blob: 9867a30ecc35b13a27039c872f1dc59acd6dbe54 [file] [log] [blame]
[email protected]529c6672012-01-04 02:18:261// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]96449d2c2009-11-25 00:01:322// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]8a837bb2010-01-05 00:21:245#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
[email protected]74470702010-01-06 18:51:166
7#include <stdio.h>
8
[email protected]1aef98132010-02-23 18:00:079#include <algorithm>
[email protected]f39f4b3f2010-05-12 17:04:0810#include <list>
[email protected]96449d2c2009-11-25 00:01:3211#include <map>
[email protected]94307712012-11-16 23:26:1112#include <stack>
[email protected]f39f4b3f2010-05-12 17:04:0813#include <string>
14#include <vector>
[email protected]5a6db6c2010-04-22 18:32:0615
[email protected]00eb49a2010-08-12 20:46:5716#include "base/at_exit.h"
[email protected]d353541f2012-05-03 22:45:4117#include "base/atomicops.h"
[email protected]9d37f062011-11-22 01:24:5218#include "base/bind.h"
[email protected]e844ae22012-01-14 03:36:2619#include "base/command_line.h"
[email protected]1078f912011-12-23 13:12:1420#include "base/debug/trace_event.h"
[email protected]e51bdf32011-11-23 22:21:4621#if defined(OS_MACOSX)
22#include "base/mac/scoped_cftyperef.h"
23#endif
[email protected]3b63f8f42011-03-28 01:54:1524#include "base/memory/scoped_ptr.h"
[email protected]f4390962013-06-11 07:29:2225#include "base/strings/string_number_conversions.h"
[email protected]d37231fa2010-04-09 21:16:0226#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3227#define GLES2_GPU_SERVICE 1
[email protected]f4390962013-06-11 07:29:2228#include "gpu/command_buffer/common/debug_marker_manager.h"
[email protected]96449d2c2009-11-25 00:01:3229#include "gpu/command_buffer/common/gles2_cmd_format.h"
30#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1031#include "gpu/command_buffer/common/id_allocator.h"
[email protected]2ad674132013-06-05 07:48:5132#include "gpu/command_buffer/common/mailbox.h"
[email protected]f4390962013-06-11 07:29:2233#include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
34#include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
[email protected]3916c97e2010-02-25 03:20:5035#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3236#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5037#include "gpu/command_buffer/service/context_group.h"
[email protected]e259eb412012-10-13 05:47:2438#include "gpu/command_buffer/service/context_state.h"
[email protected]d3eba342013-04-18 21:11:5039#include "gpu/command_buffer/service/error_state.h"
[email protected]915a59a12010-09-30 21:29:1140#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5841#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3242#include "gpu/command_buffer/service/gl_utils.h"
[email protected]43410e92012-04-20 17:06:2843#include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
[email protected]ba3176a2009-12-16 18:19:4644#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]8f9b8dd2013-09-12 18:05:1345#include "gpu/command_buffer/service/gpu_state_tracer.h"
[email protected]e844ae22012-01-14 03:36:2646#include "gpu/command_buffer/service/gpu_switches.h"
[email protected]fb97b662013-02-20 23:02:1447#include "gpu/command_buffer/service/gpu_tracer.h"
[email protected]09d50362012-10-18 20:54:3748#include "gpu/command_buffer/service/image_manager.h"
[email protected]78b514b2012-05-01 21:50:5949#include "gpu/command_buffer/service/mailbox_manager.h"
[email protected]ff6493f2012-07-31 19:52:2550#include "gpu/command_buffer/service/memory_tracking.h"
[email protected]a93bb842010-02-16 23:03:4751#include "gpu/command_buffer/service/program_manager.h"
[email protected]882ba1e22012-03-08 19:02:5352#include "gpu/command_buffer/service/query_manager.h"
[email protected]a25fa872010-03-25 02:57:5853#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4754#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4555#include "gpu/command_buffer/service/shader_translator.h"
[email protected]87fb6ab2012-06-13 22:28:0456#include "gpu/command_buffer/service/shader_translator_cache.h"
[email protected]b0af4f52011-09-28 22:04:4257#include "gpu/command_buffer/service/stream_texture.h"
58#include "gpu/command_buffer/service/stream_texture_manager.h"
[email protected]a93bb842010-02-16 23:03:4759#include "gpu/command_buffer/service/texture_manager.h"
[email protected]944b62f32012-09-27 02:20:4660#include "gpu/command_buffer/service/vertex_array_manager.h"
[email protected]f4390962013-06-11 07:29:2261#include "gpu/command_buffer/service/vertex_attrib_manager.h"
[email protected]d8bc3ec2013-03-07 06:28:4062#include "ui/gl/gl_bindings.h"
[email protected]5a36dc132013-07-23 23:17:5563#include "ui/gl/gl_fence.h"
[email protected]09d50362012-10-18 20:54:3764#include "ui/gl/gl_image.h"
[email protected]c9e2cbbb2012-05-12 21:17:2765#include "ui/gl/gl_implementation.h"
66#include "ui/gl/gl_surface.h"
[email protected]423e644f2013-06-19 00:48:2767
[email protected]e51bdf32011-11-23 22:21:4668#if defined(OS_MACOSX)
[email protected]423e644f2013-06-19 00:48:2769#include "ui/gl/io_surface_support_mac.h"
[email protected]e51bdf32011-11-23 22:21:4670#endif
[email protected]de17df392010-04-23 21:09:4171
[email protected]6eb775352013-08-27 05:57:1672#if defined(OS_WIN)
73#include "base/win/win_util.h"
74#endif
75
[email protected]693ca512012-11-13 18:09:1376// TODO(zmo): we can't include "City.h" due to type def conflicts.
77extern uint64 CityHash64(const char*, size_t);
78
[email protected]a7a27ace2009-12-12 00:11:2579namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3280namespace gles2 {
81
[email protected]f0d74742011-10-03 16:31:0482namespace {
[email protected]693ca512012-11-13 18:09:1383
[email protected]f0d74742011-10-03 16:31:0484static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
[email protected]70dc60932013-06-04 03:33:4985static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
[email protected]aff39ac82013-06-08 04:53:1386static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
[email protected]693ca512012-11-13 18:09:1387
[email protected]3d944a82013-02-12 19:09:0288#if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
[email protected]693ca512012-11-13 18:09:1389khronos_uint64_t CityHashForAngle(const char* name, unsigned int len) {
90 return static_cast<khronos_uint64_t>(
91 CityHash64(name, static_cast<size_t>(len)));
92}
[email protected]3d944a82013-02-12 19:09:0293#endif
[email protected]693ca512012-11-13 18:09:1394
[email protected]448e459e2013-06-12 17:00:4195static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
96 GLint rangeMax,
97 GLint precision) {
98 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
99}
100
[email protected]8dc1bf92013-03-12 03:58:21101static void GetShaderPrecisionFormatImpl(GLenum shader_type,
102 GLenum precision_type,
103 GLint *range, GLint *precision) {
104 switch (precision_type) {
105 case GL_LOW_INT:
106 case GL_MEDIUM_INT:
107 case GL_HIGH_INT:
108 // These values are for a 32-bit twos-complement integer format.
109 range[0] = 31;
110 range[1] = 30;
111 *precision = 0;
112 break;
113 case GL_LOW_FLOAT:
114 case GL_MEDIUM_FLOAT:
115 case GL_HIGH_FLOAT:
116 // These values are for an IEEE single-precision floating-point format.
117 range[0] = 127;
118 range[1] = 127;
119 *precision = 23;
120 break;
121 default:
122 NOTREACHED();
123 break;
124 }
125
[email protected]8af4d5e2013-03-15 23:55:33126 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
127 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
[email protected]8dc1bf92013-03-12 03:58:21128 // This function is sometimes defined even though it's really just
129 // a stub, so we need to set range and precision as if it weren't
130 // defined before calling it.
[email protected]501b57402013-03-14 22:21:44131 // On Mac OS with some GPUs, calling this generates a
132 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
133 // platforms.
[email protected]8dc1bf92013-03-12 03:58:21134 glGetShaderPrecisionFormat(shader_type, precision_type,
135 range, precision);
[email protected]448e459e2013-06-12 17:00:41136
137 // TODO(brianderson): Make the following official workarounds.
138
139 // Some drivers have bugs where they report the ranges as a negative number.
140 // Taking the absolute value here shouldn't hurt because negative numbers
141 // aren't expected anyway.
142 range[0] = abs(range[0]);
143 range[1] = abs(range[1]);
144
145 // If the driver reports a precision for highp float that isn't actually
146 // highp, don't pretend like it's supported because shader compilation will
147 // fail anyway.
148 if (precision_type == GL_HIGH_FLOAT &&
149 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
150 range[0] = 0;
151 range[1] = 0;
152 *precision = 0;
153 }
[email protected]8dc1bf92013-03-12 03:58:21154 }
155}
156
[email protected]b04e24c2013-01-08 18:35:25157} // namespace
[email protected]f0d74742011-10-03 16:31:04158
[email protected]6217d392010-03-25 22:08:35159class GLES2DecoderImpl;
160
[email protected]ab09b612013-03-11 22:11:51161// Local versions of the SET_GL_ERROR macros
162#define LOCAL_SET_GL_ERROR(error, function_name, msg) \
[email protected]d3eba342013-04-18 21:11:50163 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
[email protected]ab09b612013-03-11 22:11:51164#define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
[email protected]d3eba342013-04-18 21:11:50165 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
166 function_name, value, label)
[email protected]ab09b612013-03-11 22:11:51167#define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
[email protected]d3eba342013-04-18 21:11:50168 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
169 function_name, pname)
[email protected]ab09b612013-03-11 22:11:51170#define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
[email protected]d3eba342013-04-18 21:11:50171 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
172 function_name)
[email protected]ab09b612013-03-11 22:11:51173#define LOCAL_PEEK_GL_ERROR(function_name) \
[email protected]d3eba342013-04-18 21:11:50174 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
[email protected]ab09b612013-03-11 22:11:51175#define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
[email protected]d3eba342013-04-18 21:11:50176 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
[email protected]ab09b612013-03-11 22:11:51177#define LOCAL_PERFORMANCE_WARNING(msg) \
178 PerformanceWarning(__FILE__, __LINE__, msg)
179#define LOCAL_RENDER_WARNING(msg) \
180 RenderWarning(__FILE__, __LINE__, msg)
181
[email protected]07f54fcc2009-12-22 02:46:30182// Check that certain assumptions the code makes are true. There are places in
183// the code where shared memory is passed direclty to GL. Example, glUniformiv,
184// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
185// a few others) are 32bits. If they are not 32bits the code will have to change
186// to call those GL functions with service side memory and then copy the results
187// to shared memory, converting the sizes.
188COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
189 GLint_not_same_size_as_uint32);
190COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
191 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:37192COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
193 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:30194
[email protected]43f28f832010-02-03 02:28:48195// TODO(kbr): the use of this anonymous namespace core dumps the
196// linker on Mac OS X 10.6 when the symbol ordering file is used
197// namespace {
[email protected]96449d2c2009-11-25 00:01:32198
199// Returns the address of the first byte after a struct.
200template <typename T>
201const void* AddressAfterStruct(const T& pod) {
202 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
203}
204
[email protected]07f54fcc2009-12-22 02:46:30205// Returns the address of the frst byte after the struct or NULL if size >
206// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:32207template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:30208RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
209 uint32 size,
210 uint32 immediate_data_size) {
211 return (size <= immediate_data_size) ?
212 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
213 NULL;
[email protected]96449d2c2009-11-25 00:01:32214}
215
[email protected]07f54fcc2009-12-22 02:46:30216// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:18217bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:32218 GLuint count,
219 size_t size,
[email protected]a76b0052010-03-05 00:33:18220 unsigned int elements_per_unit,
221 uint32* dst) {
222 uint32 value;
223 if (!SafeMultiplyUint32(count, size, &value)) {
224 return false;
225 }
226 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
227 return false;
228 }
229 *dst = value;
230 return true;
[email protected]96449d2c2009-11-25 00:01:32231}
232
233// A struct to hold info about each command.
234struct CommandInfo {
235 int arg_flags; // How to handle the arguments for this command
236 int arg_count; // How many arguments are expected for this command.
237};
238
239// A table of CommandInfo for all the commands.
240const CommandInfo g_command_info[] = {
[email protected]ed9f9cd2013-02-27 21:12:35241 #define GLES2_CMD_OP(name) { \
242 cmds::name::kArgFlags, \
243 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
[email protected]96449d2c2009-11-25 00:01:32244
245 GLES2_COMMAND_LIST(GLES2_CMD_OP)
246
247 #undef GLES2_CMD_OP
248};
249
[email protected]258a3313f2011-10-18 20:13:57250// Return true if a character belongs to the ASCII subset as defined in
251// GLSL ES 1.0 spec section 3.1.
252static bool CharacterIsValidForGLES(unsigned char c) {
253 // Printing characters are valid except " $ ` @ \ ' DEL.
254 if (c >= 32 && c <= 126 &&
255 c != '"' &&
256 c != '$' &&
257 c != '`' &&
258 c != '@' &&
259 c != '\\' &&
260 c != '\'') {
261 return true;
262 }
263 // Horizontal tab, line feed, vertical tab, form feed, carriage return
264 // are also valid.
265 if (c >= 9 && c <= 13) {
266 return true;
267 }
268
269 return false;
270}
271
272static bool StringIsValidForGLES(const char* str) {
273 for (; *str; ++str) {
274 if (!CharacterIsValidForGLES(*str)) {
275 return false;
276 }
277 }
278 return true;
279}
280
[email protected]297ca1c2011-06-20 23:08:46281// Wrapper for glEnable/glDisable that doesn't suck.
282static void EnableDisable(GLenum pname, bool enable) {
283 if (enable) {
284 glEnable(pname);
285 } else {
286 glDisable(pname);
287 }
288}
289
[email protected]6217d392010-03-25 22:08:35290// This class prevents any GL errors that occur when it is in scope from
291// being reported to the client.
292class ScopedGLErrorSuppressor {
293 public:
[email protected]ab09b612013-03-11 22:11:51294 explicit ScopedGLErrorSuppressor(
[email protected]40621eb52013-10-08 15:40:30295 const char* function_name, ErrorState* error_state);
[email protected]6217d392010-03-25 22:08:35296 ~ScopedGLErrorSuppressor();
297 private:
[email protected]ab09b612013-03-11 22:11:51298 const char* function_name_;
[email protected]40621eb52013-10-08 15:40:30299 ErrorState* error_state_;
[email protected]6217d392010-03-25 22:08:35300 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
301};
302
303// Temporarily changes a decoder's bound 2D texture and restore it when this
304// object goes out of scope. Also temporarily switches to using active texture
305// unit zero in case the client has changed that to something invalid.
306class ScopedTexture2DBinder {
307 public:
308 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
309 ~ScopedTexture2DBinder();
310
311 private:
312 GLES2DecoderImpl* decoder_;
313 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
314};
315
316// Temporarily changes a decoder's bound render buffer and restore it when this
317// object goes out of scope.
318class ScopedRenderBufferBinder {
319 public:
[email protected]18e785a2013-10-09 03:29:41320 ScopedRenderBufferBinder(ContextState* state, GLuint id);
[email protected]6217d392010-03-25 22:08:35321 ~ScopedRenderBufferBinder();
322
323 private:
[email protected]18e785a2013-10-09 03:29:41324 ContextState* state_;
[email protected]6217d392010-03-25 22:08:35325 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
326};
327
328// Temporarily changes a decoder's bound frame buffer and restore it when this
329// object goes out of scope.
330class ScopedFrameBufferBinder {
331 public:
332 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
333 ~ScopedFrameBufferBinder();
334
335 private:
336 GLES2DecoderImpl* decoder_;
337 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
338};
339
[email protected]34ff8b0c2010-10-01 20:06:02340// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52341// the multisampled offscreen render buffer if that buffer is multisampled, and,
[email protected]de26b3c2011-08-03 21:54:27342// if it is bound or enforce_internal_framebuffer is true. If internal is
343// true, the resolved framebuffer is not visible to the parent.
[email protected]34ff8b0c2010-10-01 20:06:02344class ScopedResolvedFrameBufferBinder {
345 public:
[email protected]e7e38032011-07-26 17:25:25346 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
[email protected]de26b3c2011-08-03 21:54:27347 bool enforce_internal_framebuffer,
348 bool internal);
[email protected]34ff8b0c2010-10-01 20:06:02349 ~ScopedResolvedFrameBufferBinder();
350
351 private:
352 GLES2DecoderImpl* decoder_;
353 bool resolve_and_bind_;
354 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
355};
356
[email protected]6217d392010-03-25 22:08:35357// Encapsulates an OpenGL texture.
[email protected]ed9f9cd2013-02-27 21:12:35358class BackTexture {
[email protected]6217d392010-03-25 22:08:35359 public:
[email protected]ed9f9cd2013-02-27 21:12:35360 explicit BackTexture(GLES2DecoderImpl* decoder);
361 ~BackTexture();
[email protected]6217d392010-03-25 22:08:35362
363 // Create a new render texture.
364 void Create();
365
366 // Set the initial size and format of a render texture or resize it.
[email protected]678a73f2012-12-19 19:22:09367 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
[email protected]6217d392010-03-25 22:08:35368
369 // Copy the contents of the currently bound frame buffer.
[email protected]3a4d0c52011-06-29 23:11:58370 void Copy(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35371
372 // Destroy the render texture. This must be explicitly called before
373 // destroying this object.
374 void Destroy();
375
[email protected]97872062010-11-03 19:07:05376 // Invalidate the texture. This can be used when a context is lost and it is
377 // not possible to make it current in order to free the resource.
378 void Invalidate();
379
[email protected]6217d392010-03-25 22:08:35380 GLuint id() const {
381 return id_;
382 }
383
[email protected]d37231fa2010-04-09 21:16:02384 gfx::Size size() const {
385 return size_;
386 }
387
[email protected]1078f912011-12-23 13:12:14388 size_t estimated_size() const {
[email protected]ff6493f2012-07-31 19:52:25389 return memory_tracker_.GetMemRepresented();
[email protected]1078f912011-12-23 13:12:14390 }
391
[email protected]6217d392010-03-25 22:08:35392 private:
393 GLES2DecoderImpl* decoder_;
[email protected]ff6493f2012-07-31 19:52:25394 MemoryTypeTracker memory_tracker_;
[email protected]68e81a4a62012-12-13 01:16:48395 size_t bytes_allocated_;
[email protected]6217d392010-03-25 22:08:35396 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02397 gfx::Size size_;
[email protected]ed9f9cd2013-02-27 21:12:35398 DISALLOW_COPY_AND_ASSIGN(BackTexture);
[email protected]6217d392010-03-25 22:08:35399};
400
401// Encapsulates an OpenGL render buffer of any format.
[email protected]ed9f9cd2013-02-27 21:12:35402class BackRenderbuffer {
[email protected]6217d392010-03-25 22:08:35403 public:
[email protected]d5a28e452013-10-10 01:01:40404 explicit BackRenderbuffer(
405 RenderbufferManager* renderbuffer_manager,
406 MemoryTracker* memory_tracker,
407 ContextState* state);
[email protected]ed9f9cd2013-02-27 21:12:35408 ~BackRenderbuffer();
[email protected]6217d392010-03-25 22:08:35409
410 // Create a new render buffer.
411 void Create();
412
413 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02414 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35415
416 // Destroy the render buffer. This must be explicitly called before destroying
417 // this object.
418 void Destroy();
419
[email protected]97872062010-11-03 19:07:05420 // Invalidate the render buffer. This can be used when a context is lost and
421 // it is not possible to make it current in order to free the resource.
422 void Invalidate();
423
[email protected]6217d392010-03-25 22:08:35424 GLuint id() const {
425 return id_;
426 }
427
[email protected]1078f912011-12-23 13:12:14428 size_t estimated_size() const {
[email protected]ff6493f2012-07-31 19:52:25429 return memory_tracker_.GetMemRepresented();
[email protected]1078f912011-12-23 13:12:14430 }
431
[email protected]6217d392010-03-25 22:08:35432 private:
[email protected]d5a28e452013-10-10 01:01:40433 RenderbufferManager* renderbuffer_manager_;
[email protected]ff6493f2012-07-31 19:52:25434 MemoryTypeTracker memory_tracker_;
[email protected]d5a28e452013-10-10 01:01:40435 ContextState* state_;
[email protected]68e81a4a62012-12-13 01:16:48436 size_t bytes_allocated_;
[email protected]6217d392010-03-25 22:08:35437 GLuint id_;
[email protected]ed9f9cd2013-02-27 21:12:35438 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
[email protected]6217d392010-03-25 22:08:35439};
440
441// Encapsulates an OpenGL frame buffer.
[email protected]ed9f9cd2013-02-27 21:12:35442class BackFramebuffer {
[email protected]6217d392010-03-25 22:08:35443 public:
[email protected]ed9f9cd2013-02-27 21:12:35444 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
445 ~BackFramebuffer();
[email protected]6217d392010-03-25 22:08:35446
447 // Create a new frame buffer.
448 void Create();
449
450 // Attach a color render buffer to a frame buffer.
[email protected]ed9f9cd2013-02-27 21:12:35451 void AttachRenderTexture(BackTexture* texture);
[email protected]6217d392010-03-25 22:08:35452
[email protected]b9363b22010-06-09 22:06:15453 // Attach a render buffer to a frame buffer. Note that this unbinds any
454 // currently bound frame buffer.
[email protected]ed9f9cd2013-02-27 21:12:35455 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35456
[email protected]6217d392010-03-25 22:08:35457 // Destroy the frame buffer. This must be explicitly called before destroying
458 // this object.
459 void Destroy();
460
[email protected]97872062010-11-03 19:07:05461 // Invalidate the frame buffer. This can be used when a context is lost and it
462 // is not possible to make it current in order to free the resource.
463 void Invalidate();
464
[email protected]6217d392010-03-25 22:08:35465 // See glCheckFramebufferStatusEXT.
466 GLenum CheckStatus();
467
468 GLuint id() const {
469 return id_;
470 }
471
472 private:
473 GLES2DecoderImpl* decoder_;
474 GLuint id_;
[email protected]ed9f9cd2013-02-27 21:12:35475 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
[email protected]6217d392010-03-25 22:08:35476};
[email protected]34ff8b0c2010-10-01 20:06:02477
[email protected]5a36dc132013-07-23 23:17:55478struct FenceCallback {
479 explicit FenceCallback()
480 : fence(gfx::GLFence::Create()) {
481 DCHECK(fence);
482 }
483 void AddCallback(base::Closure cb) {
484 callbacks.push_back(cb);
485 }
486 std::vector<base::Closure> callbacks;
487 scoped_ptr<gfx::GLFence> fence;
488};
489
490
[email protected]43f28f832010-02-03 02:28:48491// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32492
[email protected]ddb1e5a2010-12-13 20:10:45493bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
494 uint32* service_texture_id) {
495 return false;
496}
497
[email protected]a3ded6d2010-10-19 06:44:39498GLES2Decoder::GLES2Decoder()
[email protected]55e136f2013-04-03 18:50:06499 : initialized_(false),
500 debug_(false),
[email protected]1d82e822013-04-10 21:32:32501 log_commands_(false) {
[email protected]96449d2c2009-11-25 00:01:32502}
503
[email protected]3916c97e2010-02-25 03:20:50504GLES2Decoder::~GLES2Decoder() {
505}
506
[email protected]57edfdad2012-02-07 04:57:15507bool GLES2Decoder::testing_force_is_angle_;
508
509void GLES2Decoder::set_testing_force_is_angle(bool force) {
510 testing_force_is_angle_ = force;
511}
512
513bool GLES2Decoder::IsAngle() {
514#if defined(OS_WIN)
515 return testing_force_is_angle_ ||
516 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
517#else
518 return testing_force_is_angle_;
519#endif
520}
521
[email protected]f39f4b3f2010-05-12 17:04:08522// This class implements GLES2Decoder so we don't have to expose all the GLES2
523// cmd stuff to outside this class.
[email protected]ee1e6aa2012-11-29 09:24:10524class GLES2DecoderImpl : public GLES2Decoder {
[email protected]f39f4b3f2010-05-12 17:04:08525 public:
[email protected]476ccb72012-12-06 15:52:52526 // Used by PrepForSetUniformByLocation to validate types.
527 struct BaseUniformInfo {
528 const GLenum* const valid_types;
529 size_t num_valid_types;
530 };
531
[email protected]aa7666122011-09-02 19:45:52532 explicit GLES2DecoderImpl(ContextGroup* group);
[email protected]b8e97b62012-09-30 15:09:00533 virtual ~GLES2DecoderImpl();
[email protected]f39f4b3f2010-05-12 17:04:08534
[email protected]96449d2c2009-11-25 00:01:32535 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14536 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50537 unsigned int arg_count,
[email protected]b8e97b62012-09-30 15:09:00538 const void* args) OVERRIDE;
[email protected]96449d2c2009-11-25 00:01:32539
540 // Overridden from AsyncAPIInterface.
[email protected]b8e97b62012-09-30 15:09:00541 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
[email protected]96449d2c2009-11-25 00:01:32542
543 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38544 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
545 const scoped_refptr<gfx::GLContext>& context,
[email protected]069944672012-04-25 20:52:23546 bool offscreen,
[email protected]6217d392010-03-25 22:08:35547 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:29548 const DisallowedFeatures& disallowed_features,
[email protected]b8e97b62012-09-30 15:09:00549 const std::vector<int32>& attribs) OVERRIDE;
550 virtual void Destroy(bool have_context) OVERRIDE;
[email protected]63c9b052012-05-17 18:27:38551 virtual void SetSurface(
552 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
[email protected]2ad674132013-06-05 07:48:51553 virtual bool ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
[email protected]b8e97b62012-09-30 15:09:00554 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
[email protected]9a5afa432011-07-22 18:16:39555 void UpdateParentTextureInfo();
[email protected]b8e97b62012-09-30 15:09:00556 virtual bool MakeCurrent() OVERRIDE;
557 virtual void ReleaseCurrent() OVERRIDE;
558 virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
559 virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
560 virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
[email protected]1868a342012-11-07 15:56:02561 virtual void RestoreState() const OVERRIDE;
[email protected]29a4d902013-02-26 20:18:06562
563 virtual void RestoreActiveTexture() const OVERRIDE {
564 state_.RestoreActiveTexture();
565 }
[email protected]217004512013-05-10 21:25:55566 virtual void RestoreAllTextureUnitBindings() const OVERRIDE {
567 state_.RestoreAllTextureUnitBindings();
568 }
[email protected]29a4d902013-02-26 20:18:06569 virtual void RestoreAttribute(unsigned index) const OVERRIDE {
570 state_.RestoreAttribute(index);
571 }
572 virtual void RestoreBufferBindings() const OVERRIDE {
573 state_.RestoreBufferBindings();
574 }
575 virtual void RestoreGlobalState() const OVERRIDE {
576 state_.RestoreGlobalState();
577 }
578 virtual void RestoreProgramBindings() const OVERRIDE {
579 state_.RestoreProgramBindings();
580 }
581 virtual void RestoreRenderbufferBindings() const OVERRIDE {
582 state_.RestoreRenderbufferBindings();
583 }
584 virtual void RestoreTextureUnitBindings(unsigned unit) const OVERRIDE {
585 state_.RestoreTextureUnitBindings(unit);
586 }
587 virtual void RestoreFramebufferBindings() const OVERRIDE;
588 virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
589
[email protected]b8e97b62012-09-30 15:09:00590 virtual QueryManager* GetQueryManager() OVERRIDE {
591 return query_manager_.get();
592 }
593 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
[email protected]944b62f32012-09-27 02:20:46594 return vertex_array_manager_.get();
595 }
[email protected]b8e97b62012-09-30 15:09:00596 virtual bool ProcessPendingQueries() OVERRIDE;
[email protected]2b1767cf2013-03-16 09:25:05597 virtual bool HasMoreIdleWork() OVERRIDE;
598 virtual void PerformIdleWork() OVERRIDE;
[email protected]43f28f832010-02-03 02:28:48599
[email protected]5a36dc132013-07-23 23:17:55600 virtual void WaitForReadPixels(base::Closure callback) OVERRIDE;
601
[email protected]9d37f062011-11-22 01:24:52602 virtual void SetResizeCallback(
[email protected]729c0b42013-05-26 02:05:07603 const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
[email protected]22f320a2011-08-30 01:17:00604
[email protected]1d82e822013-04-10 21:32:32605 virtual Logger* GetLogger() OVERRIDE;
[email protected]d3eba342013-04-18 21:11:50606 virtual ErrorState* GetErrorState() OVERRIDE;
[email protected]1d82e822013-04-10 21:32:32607
[email protected]e3932abb2013-03-13 00:01:37608 virtual void SetShaderCacheCallback(
609 const ShaderCacheCallback& callback) OVERRIDE;
[email protected]840a7e462013-02-27 01:29:51610 virtual void SetWaitSyncPointCallback(
611 const WaitSyncPointCallback& callback) OVERRIDE;
[email protected]22f320a2011-08-30 01:17:00612
[email protected]85a4ac22013-05-31 01:58:47613 virtual AsyncPixelTransferManager*
614 GetAsyncPixelTransferManager() OVERRIDE;
615 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
[email protected]498b5c072013-06-04 19:30:07616 virtual void SetAsyncPixelTransferManagerForTest(
617 AsyncPixelTransferManager* manager) OVERRIDE;
[email protected]69a8701e2013-03-07 21:31:09618 void ProcessFinishedAsyncTransfers();
[email protected]32145a92012-12-17 09:01:59619
[email protected]1318e922010-09-17 22:03:16620 virtual bool GetServiceTextureId(uint32 client_texture_id,
[email protected]b8e97b62012-09-30 15:09:00621 uint32* service_texture_id) OVERRIDE;
[email protected]43f28f832010-02-03 02:28:48622
[email protected]63b465922012-09-06 02:04:52623 virtual uint32 GetTextureUploadCount() OVERRIDE;
624 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
625 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
[email protected]dc25dda2012-09-27 21:36:30626 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE;
[email protected]63b465922012-09-06 02:04:52627
[email protected]8e3e0662010-08-23 18:46:30628 // Restores the current state to the user's settings.
629 void RestoreCurrentFramebufferBindings();
[email protected]8e3e0662010-08-23 18:46:30630 void RestoreCurrentTexture2DBindings();
631
[email protected]297ca1c2011-06-20 23:08:46632 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
633 void ApplyDirtyState();
634
635 // These check the state of the currently bound framebuffer or the
636 // backbuffer if no framebuffer is bound.
[email protected]f3b191b2013-06-19 03:43:54637 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
638 // check with all attached and enabled color attachments.
639 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
[email protected]297ca1c2011-06-20 23:08:46640 bool BoundFramebufferHasDepthAttachment();
641 bool BoundFramebufferHasStencilAttachment();
642
[email protected]b8e97b62012-09-30 15:09:00643 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
[email protected]38d139d2011-07-14 00:38:43644
[email protected]96449d2c2009-11-25 00:01:32645 private:
[email protected]70d34263c2013-01-09 00:27:45646 friend class ScopedFrameBufferBinder;
[email protected]34ff8b0c2010-10-01 20:06:02647 friend class ScopedResolvedFrameBufferBinder;
[email protected]ed9f9cd2013-02-27 21:12:35648 friend class BackTexture;
[email protected]ed9f9cd2013-02-27 21:12:35649 friend class BackFramebuffer;
[email protected]6217d392010-03-25 22:08:35650
[email protected]c2f8c8402010-12-06 18:07:24651 // Initialize or re-initialize the shader translator.
652 bool InitializeShaderTranslator();
653
[email protected]302ce6d2011-07-07 23:28:11654 void UpdateCapabilities();
655
[email protected]ae51d192010-04-27 00:48:03656 // Helpers for the glGen and glDelete functions.
657 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
658 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
659 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
660 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
661 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
662 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
663 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
664 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]882ba1e22012-03-08 19:02:53665 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
666 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
[email protected]944b62f32012-09-27 02:20:46667 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
668 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47669
[email protected]70d34263c2013-01-09 00:27:45670 // Workarounds
671 void OnFboChanged() const;
[email protected]28718a92013-04-04 12:12:51672 void OnUseFramebuffer() const;
[email protected]70d34263c2013-01-09 00:27:45673
[email protected]3916c97e2010-02-25 03:20:50674 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50675 BufferManager* buffer_manager() {
676 return group_->buffer_manager();
677 }
678
[email protected]a25fa872010-03-25 02:57:58679 RenderbufferManager* renderbuffer_manager() {
680 return group_->renderbuffer_manager();
681 }
682
683 FramebufferManager* framebuffer_manager() {
684 return group_->framebuffer_manager();
685 }
686
[email protected]3916c97e2010-02-25 03:20:50687 ProgramManager* program_manager() {
688 return group_->program_manager();
689 }
690
691 ShaderManager* shader_manager() {
692 return group_->shader_manager();
693 }
694
[email protected]29a4d902013-02-26 20:18:06695 const TextureManager* texture_manager() const {
696 return group_->texture_manager();
697 }
698
[email protected]3916c97e2010-02-25 03:20:50699 TextureManager* texture_manager() {
700 return group_->texture_manager();
701 }
702
[email protected]78b514b2012-05-01 21:50:59703 MailboxManager* mailbox_manager() {
704 return group_->mailbox_manager();
705 }
706
[email protected]09d50362012-10-18 20:54:37707 ImageManager* image_manager() {
708 return group_->image_manager();
709 }
710
[email protected]944b62f32012-09-27 02:20:46711 VertexArrayManager* vertex_array_manager() {
712 return vertex_array_manager_.get();
713 }
714
[email protected]7989c9e2013-01-23 06:39:26715 MemoryTracker* memory_tracker() {
716 return group_->memory_tracker();
717 }
718
[email protected]4f9958142013-07-02 03:58:07719 StreamTextureManager* stream_texture_manager() const {
720 return group_->stream_texture_manager();
721 }
722
[email protected]7989c9e2013-01-23 06:39:26723 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
724 MemoryTracker* tracker = memory_tracker();
725 if (tracker) {
726 return tracker->EnsureGPUMemoryAvailable(estimated_size);
727 }
728 return true;
729 }
730
[email protected]34ff8b0c2010-10-01 20:06:02731 bool IsOffscreenBufferMultisampled() const {
732 return offscreen_target_samples_ > 1;
733 }
734
[email protected]ed9f9cd2013-02-27 21:12:35735 // Creates a Texture for the given texture.
[email protected]370eaf12013-05-18 09:19:49736 TextureRef* CreateTexture(
[email protected]ae51d192010-04-27 00:48:03737 GLuint client_id, GLuint service_id) {
[email protected]ed9f9cd2013-02-27 21:12:35738 return texture_manager()->CreateTexture(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47739 }
740
741 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]370eaf12013-05-18 09:19:49742 TextureRef* GetTexture(GLuint client_id) const {
[email protected]02965c22013-03-09 02:40:07743 return texture_manager()->GetTexture(client_id);
[email protected]a93bb842010-02-16 23:03:47744 }
745
746 // Deletes the texture info for the given texture.
[email protected]ed9f9cd2013-02-27 21:12:35747 void RemoveTexture(GLuint client_id) {
748 texture_manager()->RemoveTexture(client_id);
[email protected]3916c97e2010-02-25 03:20:50749 }
[email protected]a93bb842010-02-16 23:03:47750
[email protected]d37231fa2010-04-09 21:16:02751 // Get the size (in pixels) of the currently bound frame buffer (either FBO
752 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30753 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02754
[email protected]9edc6b22010-12-23 02:00:26755 // Get the format of the currently bound frame buffer (either FBO or regular
756 // back buffer)
757 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46758 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26759
[email protected]a93bb842010-02-16 23:03:47760 // Wrapper for CompressedTexImage2D commands.
761 error::Error DoCompressedTexImage2D(
[email protected]09d50362012-10-18 20:54:37762 GLenum target,
763 GLint level,
764 GLenum internal_format,
765 GLsizei width,
766 GLsizei height,
767 GLint border,
768 GLsizei image_size,
769 const void* data);
[email protected]a93bb842010-02-16 23:03:47770
[email protected]cadde4a2010-07-31 17:10:43771 // Wrapper for CompressedTexSubImage2D.
772 void DoCompressedTexSubImage2D(
[email protected]09d50362012-10-18 20:54:37773 GLenum target,
774 GLint level,
775 GLint xoffset,
776 GLint yoffset,
777 GLsizei width,
778 GLsizei height,
779 GLenum format,
780 GLsizei imageSize,
781 const void * data);
[email protected]cadde4a2010-07-31 17:10:43782
783 // Wrapper for CopyTexImage2D.
784 void DoCopyTexImage2D(
[email protected]09d50362012-10-18 20:54:37785 GLenum target,
786 GLint level,
787 GLenum internal_format,
788 GLint x,
789 GLint y,
790 GLsizei width,
791 GLsizei height,
792 GLint border);
[email protected]cadde4a2010-07-31 17:10:43793
[email protected]6d792ee12013-05-15 00:40:56794 // Wrapper for SwapBuffers.
795 void DoSwapBuffers();
796
[email protected]cadde4a2010-07-31 17:10:43797 // Wrapper for CopyTexSubImage2D.
798 void DoCopyTexSubImage2D(
[email protected]09d50362012-10-18 20:54:37799 GLenum target,
800 GLint level,
801 GLint xoffset,
802 GLint yoffset,
803 GLint x,
804 GLint y,
805 GLsizei width,
806 GLsizei height);
[email protected]cadde4a2010-07-31 17:10:43807
[email protected]f598f422012-12-07 08:30:03808 // Validation for TexSubImage2D.
809 bool ValidateTexSubImage2D(
810 error::Error* error,
811 const char* function_name,
812 GLenum target,
813 GLint level,
814 GLint xoffset,
815 GLint yoffset,
816 GLsizei width,
817 GLsizei height,
818 GLenum format,
819 GLenum type,
820 const void * data);
821
[email protected]cadde4a2010-07-31 17:10:43822 // Wrapper for TexSubImage2D.
[email protected]f598f422012-12-07 08:30:03823 error::Error DoTexSubImage2D(
[email protected]09d50362012-10-18 20:54:37824 GLenum target,
825 GLint level,
826 GLint xoffset,
827 GLint yoffset,
828 GLsizei width,
829 GLsizei height,
830 GLenum format,
831 GLenum type,
832 const void * data);
[email protected]cadde4a2010-07-31 17:10:43833
[email protected]32145a92012-12-17 09:01:59834 // Extra validation for async tex(Sub)Image2D.
835 bool ValidateAsyncTransfer(
836 const char* function_name,
[email protected]85a4ac22013-05-31 01:58:47837 TextureRef* texture_ref,
[email protected]32145a92012-12-17 09:01:59838 GLenum target,
839 GLint level,
840 const void * data);
841
[email protected]e51bdf32011-11-23 22:21:46842 // Wrapper for TexImageIOSurface2DCHROMIUM.
843 void DoTexImageIOSurface2DCHROMIUM(
[email protected]09d50362012-10-18 20:54:37844 GLenum target,
845 GLsizei width,
846 GLsizei height,
847 GLuint io_surface_id,
848 GLuint plane);
[email protected]e51bdf32011-11-23 22:21:46849
[email protected]43410e92012-04-20 17:06:28850 void DoCopyTextureCHROMIUM(
[email protected]09d50362012-10-18 20:54:37851 GLenum target,
852 GLuint source_id,
853 GLuint target_id,
854 GLint level,
[email protected]a4a6bdd12013-04-19 20:46:54855 GLenum internal_format,
856 GLenum dest_type);
[email protected]43410e92012-04-20 17:06:28857
[email protected]97dc7cbe2011-12-06 17:26:17858 // Wrapper for TexStorage2DEXT.
859 void DoTexStorage2DEXT(
[email protected]09d50362012-10-18 20:54:37860 GLenum target,
861 GLint levels,
862 GLenum internal_format,
863 GLsizei width,
864 GLsizei height);
[email protected]97dc7cbe2011-12-06 17:26:17865
[email protected]78b514b2012-05-01 21:50:59866 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
867 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
868
[email protected]09d50362012-10-18 20:54:37869 void DoBindTexImage2DCHROMIUM(
870 GLenum target,
871 GLint image_id);
872 void DoReleaseTexImage2DCHROMIUM(
873 GLenum target,
874 GLint image_id);
875
[email protected]94307712012-11-16 23:26:11876 void DoTraceEndCHROMIUM(void);
877
[email protected]2f143d482013-03-14 18:04:49878 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
879
[email protected]ed9f9cd2013-02-27 21:12:35880 // Creates a Program for the given program.
881 Program* CreateProgram(
[email protected]d685a682011-04-29 16:19:57882 GLuint client_id, GLuint service_id) {
[email protected]ed9f9cd2013-02-27 21:12:35883 return program_manager()->CreateProgram(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47884 }
885
[email protected]07f54fcc2009-12-22 02:46:30886 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ed9f9cd2013-02-27 21:12:35887 Program* GetProgram(GLuint client_id) {
888 return program_manager()->GetProgram(client_id);
[email protected]1d32bc82010-01-13 22:06:46889 }
[email protected]07f54fcc2009-12-22 02:46:30890
[email protected]cae20172012-12-07 00:06:19891#if defined(NDEBUG)
892 void LogClientServiceMapping(
893 const char* /* function_name */,
894 GLuint /* client_id */,
895 GLuint /* service_id */) {
896 }
897 template<typename T>
898 void LogClientServiceForInfo(
899 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
900 }
901#else
902 void LogClientServiceMapping(
903 const char* function_name, GLuint client_id, GLuint service_id) {
[email protected]2a22fe72012-12-07 04:21:26904 if (service_logging_) {
[email protected]1d82e822013-04-10 21:32:32905 DLOG(INFO) << "[" << logger_.GetLogPrefix() << "] " << function_name
[email protected]2a22fe72012-12-07 04:21:26906 << ": client_id = " << client_id
907 << ", service_id = " << service_id;
908 }
[email protected]cae20172012-12-07 00:06:19909 }
910 template<typename T>
911 void LogClientServiceForInfo(
912 T* info, GLuint client_id, const char* function_name) {
[email protected]2a22fe72012-12-07 04:21:26913 if (info) {
[email protected]cae20172012-12-07 00:06:19914 LogClientServiceMapping(function_name, client_id, info->service_id());
915 }
916 }
917#endif
918
[email protected]6b8cf1a2010-05-06 16:13:58919 // Gets the program info for the given program. If it's not a program
920 // generates a GL error. Returns NULL if not program.
[email protected]ed9f9cd2013-02-27 21:12:35921 Program* GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:58922 GLuint client_id, const char* function_name) {
[email protected]df37b9932013-03-08 05:21:42923 Program* program = GetProgram(client_id);
924 if (!program) {
[email protected]ed9f9cd2013-02-27 21:12:35925 if (GetShader(client_id)) {
[email protected]ab09b612013-03-11 22:11:51926 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:43927 GL_INVALID_OPERATION, function_name, "shader passed for program");
[email protected]6b8cf1a2010-05-06 16:13:58928 } else {
[email protected]ab09b612013-03-11 22:11:51929 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
[email protected]6b8cf1a2010-05-06 16:13:58930 }
931 }
[email protected]df37b9932013-03-08 05:21:42932 LogClientServiceForInfo(program, client_id, function_name);
933 return program;
[email protected]6b8cf1a2010-05-06 16:13:58934 }
935
936
[email protected]ed9f9cd2013-02-27 21:12:35937 // Creates a Shader for the given shader.
938 Shader* CreateShader(
[email protected]d685a682011-04-29 16:19:57939 GLuint client_id,
940 GLuint service_id,
941 GLenum shader_type) {
[email protected]ed9f9cd2013-02-27 21:12:35942 return shader_manager()->CreateShader(
[email protected]d685a682011-04-29 16:19:57943 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31944 }
945
946 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ed9f9cd2013-02-27 21:12:35947 Shader* GetShader(GLuint client_id) {
948 return shader_manager()->GetShader(client_id);
[email protected]45bf5152010-02-12 00:11:31949 }
950
[email protected]6b8cf1a2010-05-06 16:13:58951 // Gets the shader info for the given shader. If it's not a shader generates a
952 // GL error. Returns NULL if not shader.
[email protected]ed9f9cd2013-02-27 21:12:35953 Shader* GetShaderInfoNotProgram(
[email protected]6b8cf1a2010-05-06 16:13:58954 GLuint client_id, const char* function_name) {
[email protected]df37b9932013-03-08 05:21:42955 Shader* shader = GetShader(client_id);
956 if (!shader) {
[email protected]ed9f9cd2013-02-27 21:12:35957 if (GetProgram(client_id)) {
[email protected]ab09b612013-03-11 22:11:51958 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:43959 GL_INVALID_OPERATION, function_name, "program passed for shader");
[email protected]6b8cf1a2010-05-06 16:13:58960 } else {
[email protected]ab09b612013-03-11 22:11:51961 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:43962 GL_INVALID_VALUE, function_name, "unknown shader");
[email protected]6b8cf1a2010-05-06 16:13:58963 }
964 }
[email protected]df37b9932013-03-08 05:21:42965 LogClientServiceForInfo(shader, client_id, function_name);
966 return shader;
[email protected]6b8cf1a2010-05-06 16:13:58967 }
968
[email protected]a93bb842010-02-16 23:03:47969 // Creates a buffer info for the given buffer.
[email protected]ed9f9cd2013-02-27 21:12:35970 void CreateBuffer(GLuint client_id, GLuint service_id) {
971 return buffer_manager()->CreateBuffer(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47972 }
973
[email protected]07f54fcc2009-12-22 02:46:30974 // Gets the buffer info for the given buffer.
[email protected]16ccec12013-02-28 03:40:21975 Buffer* GetBuffer(GLuint client_id) {
[email protected]b10492f2013-03-08 05:24:07976 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
977 return buffer;
[email protected]1d32bc82010-01-13 22:06:46978 }
[email protected]07f54fcc2009-12-22 02:46:30979
[email protected]a93bb842010-02-16 23:03:47980 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
981 // on glDeleteBuffers so we can make sure the user does not try to render
982 // with deleted buffers.
[email protected]ed9f9cd2013-02-27 21:12:35983 void RemoveBuffer(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47984
[email protected]a25fa872010-03-25 02:57:58985 // Creates a framebuffer info for the given framebuffer.
[email protected]ed9f9cd2013-02-27 21:12:35986 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
987 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58988 }
989
990 // Gets the framebuffer info for the given framebuffer.
[email protected]4d8f0dd2013-03-09 14:37:06991 Framebuffer* GetFramebuffer(GLuint client_id) {
992 return framebuffer_manager()->GetFramebuffer(client_id);
[email protected]a25fa872010-03-25 02:57:58993 }
994
995 // Removes the framebuffer info for the given framebuffer.
[email protected]ed9f9cd2013-02-27 21:12:35996 void RemoveFramebuffer(GLuint client_id) {
997 framebuffer_manager()->RemoveFramebuffer(client_id);
[email protected]a25fa872010-03-25 02:57:58998 }
999
1000 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ed9f9cd2013-02-27 21:12:351001 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1002 return renderbuffer_manager()->CreateRenderbuffer(
[email protected]ae51d192010-04-27 00:48:031003 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:581004 }
1005
1006 // Gets the renderbuffer info for the given renderbuffer.
[email protected]ee2a79c32013-03-10 03:50:271007 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1008 return renderbuffer_manager()->GetRenderbuffer(client_id);
[email protected]a25fa872010-03-25 02:57:581009 }
1010
1011 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ed9f9cd2013-02-27 21:12:351012 void RemoveRenderbuffer(GLuint client_id) {
1013 renderbuffer_manager()->RemoveRenderbuffer(client_id);
[email protected]a25fa872010-03-25 02:57:581014 }
1015
[email protected]944b62f32012-09-27 02:20:461016 // Gets the vertex attrib manager for the given vertex array.
1017 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1018 VertexAttribManager* info =
1019 vertex_array_manager()->GetVertexAttribManager(client_id);
1020 return info;
1021 }
1022
1023 // Removes the vertex attrib manager for the given vertex array.
1024 void RemoveVertexAttribManager(GLuint client_id) {
1025 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1026 }
1027
1028 // Creates a vertex attrib manager for the given vertex array.
1029 void CreateVertexAttribManager(GLuint client_id, GLuint service_id) {
1030 return vertex_array_manager()->CreateVertexAttribManager(
1031 client_id, service_id, group_->max_vertex_attribs());
1032 }
1033
[email protected]258a3313f2011-10-18 20:13:571034 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
[email protected]2be6abf32012-06-26 00:28:331035 void DoBindUniformLocationCHROMIUM(
1036 GLuint client_id, GLint location, const char* name);
[email protected]258a3313f2011-10-18 20:13:571037
[email protected]558847a2010-03-24 07:02:541038 error::Error GetAttribLocationHelper(
1039 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1040 const std::string& name_str);
1041
1042 error::Error GetUniformLocationHelper(
1043 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1044 const std::string& name_str);
1045
[email protected]3916c97e2010-02-25 03:20:501046 // Helper for glShaderSource.
1047 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:031048 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:301049
[email protected]0d6bfdc2011-11-02 01:32:201050 // Clear any textures used by the current program.
1051 bool ClearUnclearedTextures();
1052
1053 // Clear any uncleared level in texture.
1054 // Returns false if there was a generated GL error.
[email protected]02965c22013-03-09 02:40:071055 bool ClearTexture(Texture* texture);
[email protected]0d6bfdc2011-11-02 01:32:201056
1057 // Clears any uncleared attachments attached to the given frame buffer.
1058 // Returns false if there was a generated GL error.
[email protected]4d8f0dd2013-03-09 14:37:061059 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
[email protected]3a2e7c7b2010-08-06 01:12:281060
[email protected]0d6bfdc2011-11-02 01:32:201061 // overridden from GLES2Decoder
[email protected]b8e97b62012-09-30 15:09:001062 virtual bool ClearLevel(unsigned service_id,
1063 unsigned bind_target,
1064 unsigned target,
1065 int level,
1066 unsigned format,
1067 unsigned type,
1068 int width,
1069 int height,
1070 bool is_texture_immutable) OVERRIDE;
[email protected]0d6bfdc2011-11-02 01:32:201071
[email protected]c007aa02010-09-02 22:22:401072 // Restore all GL state that affects clearing.
1073 void RestoreClearState();
1074
[email protected]3a2e7c7b2010-08-06 01:12:281075 // Remembers the state of some capabilities.
[email protected]297ca1c2011-06-20 23:08:461076 // Returns: true if glEnable/glDisable should actually be called.
1077 bool SetCapabilityState(GLenum cap, bool enabled);
[email protected]3a2e7c7b2010-08-06 01:12:281078
[email protected]0d6bfdc2011-11-02 01:32:201079 // Check that the currently bound framebuffers are valid.
1080 // Generates GL error if not.
1081 bool CheckBoundFramebuffersValid(const char* func_name);
1082
1083 // Check if a framebuffer meets our requirements.
1084 bool CheckFramebufferValid(
[email protected]ed9f9cd2013-02-27 21:12:351085 Framebuffer* framebuffer,
[email protected]0d6bfdc2011-11-02 01:32:201086 GLenum target,
1087 const char* func_name);
[email protected]3a03a8f2011-03-19 00:51:271088
[email protected]939e7362010-05-13 20:49:101089 // Checks if the current program exists and is valid. If not generates the
1090 // appropriate GL error. Returns true if the current program is in a usable
1091 // state.
1092 bool CheckCurrentProgram(const char* function_name);
1093
1094 // Checks if the current program exists and is valid and that location is not
1095 // -1. If the current program is not valid generates the appropriate GL
1096 // error. Returns true if the current program is in a usable state and
1097 // location is not -1.
1098 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1099
1100 // Gets the type of a uniform for a location in the current program. Sets GL
1101 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:361102 // program is valid and the location exists. Adjusts count so it
1103 // does not overflow the uniform.
1104 bool PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:121105 GLint fake_location, const char* function_name,
[email protected]476ccb72012-12-06 15:52:521106 const BaseUniformInfo& base_info,
[email protected]1b0a6752012-02-22 03:44:121107 GLint* real_location, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:101108
[email protected]b177ae22011-11-01 03:29:111109 // Gets the service id for any simulated backbuffer fbo.
[email protected]1868a342012-11-07 15:56:021110 GLuint GetBackbufferServiceId() const;
[email protected]b177ae22011-11-01 03:29:111111
[email protected]b273e432010-04-12 17:23:581112 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1113 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1114
[email protected]ac77603c72013-03-08 13:52:061115 // Helper for glGetVertexAttrib
1116 void GetVertexAttribHelper(
1117 const VertexAttrib* attrib, GLenum pname, GLint* param);
1118
[email protected]96449d2c2009-11-25 00:01:321119 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:031120 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:321121
1122 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:031123 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:321124
[email protected]3916c97e2010-02-25 03:20:501125 // Wrapper for glActiveTexture
1126 void DoActiveTexture(GLenum texture_unit);
1127
[email protected]ae51d192010-04-27 00:48:031128 // Wrapper for glAttachShader
1129 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1130
[email protected]96449d2c2009-11-25 00:01:321131 // Wrapper for glBindBuffer since we need to track the current targets.
1132 void DoBindBuffer(GLenum target, GLuint buffer);
1133
[email protected]86093972010-03-11 00:13:561134 // Wrapper for glBindFramebuffer since we need to track the current targets.
1135 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1136
1137 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1138 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1139
[email protected]a93bb842010-02-16 23:03:471140 // Wrapper for glBindTexture since we need to track the current targets.
1141 void DoBindTexture(GLenum target, GLuint texture);
1142
[email protected]944b62f32012-09-27 02:20:461143 // Wrapper for glBindVertexArrayOES
1144 void DoBindVertexArrayOES(GLuint array);
[email protected]ab4fd7282012-10-12 16:25:571145 void EmulateVertexArrayState();
[email protected]944b62f32012-09-27 02:20:461146
[email protected]8e3e0662010-08-23 18:46:301147 // Wrapper for glBlitFramebufferEXT.
1148 void DoBlitFramebufferEXT(
1149 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1150 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1151 GLbitfield mask, GLenum filter);
1152
[email protected]36cef8ce2010-03-16 07:34:451153 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:111154 void DoBufferSubData(
1155 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1156
[email protected]36cef8ce2010-03-16 07:34:451157 // Wrapper for glCheckFramebufferStatus
1158 GLenum DoCheckFramebufferStatus(GLenum target);
1159
[email protected]3a03a8f2011-03-19 00:51:271160 // Wrapper for glClear
[email protected]a7266a92012-06-28 02:11:081161 error::Error DoClear(GLbitfield mask);
[email protected]3a03a8f2011-03-19 00:51:271162
[email protected]88a61bf2012-10-27 13:00:421163 // Wrappers for various state.
[email protected]88a61bf2012-10-27 13:00:421164 void DoDepthRangef(GLclampf znear, GLclampf zfar);
[email protected]b04e24c2013-01-08 18:35:251165 void DoSampleCoverage(GLclampf value, GLboolean invert);
[email protected]3a2e7c7b2010-08-06 01:12:281166
[email protected]45bf5152010-02-12 00:11:311167 // Wrapper for glCompileShader.
1168 void DoCompileShader(GLuint shader);
1169
[email protected]269200b12010-11-18 22:53:061170 // Helper for DeleteSharedIdsCHROMIUM commands.
1171 void DoDeleteSharedIdsCHROMIUM(
1172 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101173
[email protected]ae51d192010-04-27 00:48:031174 // Wrapper for glDetachShader
1175 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1176
[email protected]3a2e7c7b2010-08-06 01:12:281177 // Wrapper for glDisable
1178 void DoDisable(GLenum cap);
1179
[email protected]07f54fcc2009-12-22 02:46:301180 // Wrapper for glDisableVertexAttribArray.
1181 void DoDisableVertexAttribArray(GLuint index);
1182
[email protected]60f22d32012-12-12 00:31:581183 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1184 // attachments.
1185 void DoDiscardFramebufferEXT(GLenum target,
1186 GLsizei numAttachments,
1187 const GLenum* attachments);
1188
[email protected]3a2e7c7b2010-08-06 01:12:281189 // Wrapper for glEnable
1190 void DoEnable(GLenum cap);
1191
[email protected]07f54fcc2009-12-22 02:46:301192 // Wrapper for glEnableVertexAttribArray.
1193 void DoEnableVertexAttribArray(GLuint index);
1194
[email protected]882ba1e22012-03-08 19:02:531195 // Wrapper for glFinish.
1196 void DoFinish();
1197
1198 // Wrapper for glFlush.
1199 void DoFlush();
1200
[email protected]36cef8ce2010-03-16 07:34:451201 // Wrapper for glFramebufferRenderbufffer.
1202 void DoFramebufferRenderbuffer(
1203 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1204 GLuint renderbuffer);
1205
1206 // Wrapper for glFramebufferTexture2D.
1207 void DoFramebufferTexture2D(
1208 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1209 GLint level);
1210
[email protected]7d3c36e2013-07-12 14:13:161211 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1212 void DoFramebufferTexture2DMultisample(
1213 GLenum target, GLenum attachment, GLenum textarget,
1214 GLuint texture, GLint level, GLsizei samples);
1215
1216 // Common implementation for both DoFramebufferTexture2D wrappers.
1217 void DoFramebufferTexture2DCommon(const char* name,
1218 GLenum target, GLenum attachment, GLenum textarget,
1219 GLuint texture, GLint level, GLsizei samples);
1220
[email protected]a93bb842010-02-16 23:03:471221 // Wrapper for glGenerateMipmap
1222 void DoGenerateMipmap(GLenum target);
1223
[email protected]269200b12010-11-18 22:53:061224 // Helper for GenSharedIdsCHROMIUM commands.
1225 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:101226 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1227
[email protected]7d3c36e2013-07-12 14:13:161228 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1229 // to account for different pname values defined in different extension
1230 // variants.
1231 GLenum AdjustGetPname(GLenum pname);
1232
[email protected]b273e432010-04-12 17:23:581233 // Wrapper for DoGetBooleanv.
1234 void DoGetBooleanv(GLenum pname, GLboolean* params);
1235
1236 // Wrapper for DoGetFloatv.
1237 void DoGetFloatv(GLenum pname, GLfloat* params);
1238
[email protected]36cef8ce2010-03-16 07:34:451239 // Wrapper for glGetFramebufferAttachmentParameteriv.
1240 void DoGetFramebufferAttachmentParameteriv(
1241 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1242
[email protected]a0c3e972010-04-21 00:49:131243 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581244 void DoGetIntegerv(GLenum pname, GLint* params);
1245
[email protected]29a9eb52010-04-13 09:04:231246 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:061247 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:231248 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1249
[email protected]17cfbe0e2013-03-07 01:26:081250 // Wrapper for glGetBufferParameteriv.
1251 void DoGetBufferParameteriv(
1252 GLenum target, GLenum pname, GLint* params);
1253
[email protected]a0c3e972010-04-21 00:49:131254 // Wrapper for glGetProgramiv.
1255 void DoGetProgramiv(
1256 GLuint program_id, GLenum pname, GLint* params);
1257
[email protected]36cef8ce2010-03-16 07:34:451258 // Wrapper for glRenderbufferParameteriv.
1259 void DoGetRenderbufferParameteriv(
1260 GLenum target, GLenum pname, GLint* params);
1261
[email protected]ddd968b82010-03-02 00:44:291262 // Wrapper for glGetShaderiv
1263 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1264
[email protected]b1122982010-05-17 23:04:241265 // Wrappers for glGetVertexAttrib.
1266 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1267 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1268
[email protected]1958e0e2010-04-22 05:17:151269 // Wrappers for glIsXXX functions.
[email protected]3dc69c42012-05-12 02:29:241270 bool DoIsEnabled(GLenum cap);
[email protected]1958e0e2010-04-22 05:17:151271 bool DoIsBuffer(GLuint client_id);
1272 bool DoIsFramebuffer(GLuint client_id);
1273 bool DoIsProgram(GLuint client_id);
1274 bool DoIsRenderbuffer(GLuint client_id);
1275 bool DoIsShader(GLuint client_id);
1276 bool DoIsTexture(GLuint client_id);
[email protected]944b62f32012-09-27 02:20:461277 bool DoIsVertexArrayOES(GLuint client_id);
[email protected]1958e0e2010-04-22 05:17:151278
[email protected]07f54fcc2009-12-22 02:46:301279 // Wrapper for glLinkProgram
1280 void DoLinkProgram(GLuint program);
1281
[email protected]269200b12010-11-18 22:53:061282 // Helper for RegisterSharedIdsCHROMIUM.
1283 void DoRegisterSharedIdsCHROMIUM(
1284 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101285
[email protected]36cef8ce2010-03-16 07:34:451286 // Wrapper for glRenderbufferStorage.
1287 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031288 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451289
[email protected]8e3e0662010-08-23 18:46:301290 // Wrapper for glRenderbufferStorageMultisampleEXT.
1291 void DoRenderbufferStorageMultisample(
1292 GLenum target, GLsizei samples, GLenum internalformat,
1293 GLsizei width, GLsizei height);
1294
[email protected]4a4c18b2013-09-13 22:50:101295 // Verifies that the currently bound multisample renderbuffer is valid
1296 // Very slow! Only done on platforms with driver bugs that return invalid
1297 // buffers under memory pressure
1298 bool VerifyMultisampleRenderbufferIntegrity(
1299 GLuint renderbuffer, GLenum format);
1300
[email protected]b273e432010-04-12 17:23:581301 // Wrapper for glReleaseShaderCompiler.
1302 void DoReleaseShaderCompiler() { }
1303
[email protected]3916c97e2010-02-25 03:20:501304 // Wrappers for glTexParameter functions.
1305 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1306 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1307 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1308 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1309
1310 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1311 // spec only these 2 functions can be used to set sampler uniforms.
[email protected]1b0a6752012-02-22 03:44:121312 void DoUniform1i(GLint fake_location, GLint v0);
1313 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1314 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1315 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1316 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101317
1318 // Wrappers for glUniformfv because some drivers don't correctly accept
1319 // bool uniforms.
[email protected]1b0a6752012-02-22 03:44:121320 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1321 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1322 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1323 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501324
[email protected]43c2f1f2011-03-25 18:35:361325 void DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:121326 GLint fake_location, GLsizei count, GLboolean transpose,
1327 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361328 void DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:121329 GLint fake_location, GLsizei count, GLboolean transpose,
1330 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361331 void DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:121332 GLint fake_location, GLsizei count, GLboolean transpose,
1333 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361334
[email protected]af6380962012-11-29 23:24:131335 bool SetVertexAttribValue(
1336 const char* function_name, GLuint index, const GLfloat* value);
1337
[email protected]b1122982010-05-17 23:04:241338 // Wrappers for glVertexAttrib??
1339 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1340 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1341 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1342 void DoVertexAttrib4f(
1343 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1344 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1345 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1346 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1347 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1348
[email protected]43410e92012-04-20 17:06:281349 // Wrapper for glViewport
1350 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1351
[email protected]07f54fcc2009-12-22 02:46:301352 // Wrapper for glUseProgram
1353 void DoUseProgram(GLuint program);
1354
[email protected]ae51d192010-04-27 00:48:031355 // Wrapper for glValidateProgram.
1356 void DoValidateProgram(GLuint program_client_id);
1357
[email protected]d2a0e1a2012-08-12 02:25:011358 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1359 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1360 void DoPopGroupMarkerEXT(void);
1361
[email protected]4e8a5b122010-05-08 22:00:101362 // Gets the number of values that will be returned by glGetXXX. Returns
1363 // false if pname is unknown.
1364 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1365
[email protected]07f54fcc2009-12-22 02:46:301366 // Checks if the current program and vertex attributes are valid for drawing.
[email protected]ad84a3a2012-06-08 21:42:431367 bool IsDrawValid(
1368 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount);
[email protected]07f54fcc2009-12-22 02:46:301369
[email protected]c13e1da62011-09-09 21:48:301370 // Returns true if successful, simulated will be true if attrib0 was
1371 // simulated.
[email protected]c6aef902012-02-14 03:31:421372 bool SimulateAttrib0(
[email protected]ad84a3a2012-06-08 21:42:431373 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
[email protected]43410e92012-04-20 17:06:281374 void RestoreStateForAttrib(GLuint attrib);
[email protected]b1122982010-05-17 23:04:241375
[email protected]e56131d22013-07-28 16:14:111376 // If texture is a stream texture, this will update the stream to the newest
1377 // buffer.
1378 void UpdateStreamTextureIfNeeded(Texture* texture);
1379
1380 // Returns false if unrenderable textures were replaced.
1381 bool PrepareTexturesForRender();
[email protected]3916c97e2010-02-25 03:20:501382 void RestoreStateForNonRenderableTextures();
1383
[email protected]8fbedc02010-11-18 18:43:401384 // Returns true if GL_FIXED attribs were simulated.
[email protected]c6aef902012-02-14 03:31:421385 bool SimulateFixedAttribs(
[email protected]ad84a3a2012-06-08 21:42:431386 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421387 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
[email protected]8fbedc02010-11-18 18:43:401388 void RestoreStateForSimulatedFixedAttribs();
1389
[email protected]c6aef902012-02-14 03:31:421390 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1391 // cases (primcount is 0 for non-instanced).
1392 error::Error DoDrawArrays(
[email protected]ad84a3a2012-06-08 21:42:431393 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421394 bool instanced, GLenum mode, GLint first, GLsizei count,
1395 GLsizei primcount);
1396 error::Error DoDrawElements(
[email protected]ad84a3a2012-06-08 21:42:431397 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421398 bool instanced, GLenum mode, GLsizei count, GLenum type,
1399 int32 offset, GLsizei primcount);
1400
[email protected]61eeb33f2011-07-26 15:30:311401 GLenum GetBindTargetForSamplerType(GLenum type) {
1402 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:461403 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1404 switch (type) {
1405 case GL_SAMPLER_2D:
1406 return GL_TEXTURE_2D;
1407 case GL_SAMPLER_CUBE:
1408 return GL_TEXTURE_CUBE_MAP;
1409 case GL_SAMPLER_EXTERNAL_OES:
1410 return GL_TEXTURE_EXTERNAL_OES;
1411 case GL_SAMPLER_2D_RECT_ARB:
1412 return GL_TEXTURE_RECTANGLE_ARB;
1413 }
1414
1415 NOTREACHED();
1416 return 0;
[email protected]61eeb33f2011-07-26 15:30:311417 }
1418
[email protected]8e3e0662010-08-23 18:46:301419 // Gets the framebuffer info for a particular target.
[email protected]4d8f0dd2013-03-09 14:37:061420 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1421 Framebuffer* framebuffer = NULL;
[email protected]8e3e0662010-08-23 18:46:301422 switch (target) {
1423 case GL_FRAMEBUFFER:
[email protected]ebfb73c2012-08-15 02:37:451424 case GL_DRAW_FRAMEBUFFER_EXT:
[email protected]9d3b2e12013-10-02 01:04:341425 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
[email protected]8e3e0662010-08-23 18:46:301426 break;
[email protected]ebfb73c2012-08-15 02:37:451427 case GL_READ_FRAMEBUFFER_EXT:
[email protected]9d3b2e12013-10-02 01:04:341428 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
[email protected]8e3e0662010-08-23 18:46:301429 break;
1430 default:
1431 NOTREACHED();
1432 break;
1433 }
[email protected]4d8f0dd2013-03-09 14:37:061434 return framebuffer;
[email protected]8e3e0662010-08-23 18:46:301435 }
1436
[email protected]ed9f9cd2013-02-27 21:12:351437 Renderbuffer* GetRenderbufferInfoForTarget(
[email protected]0d6bfdc2011-11-02 01:32:201438 GLenum target) {
[email protected]ee2a79c32013-03-10 03:50:271439 Renderbuffer* renderbuffer = NULL;
[email protected]0d6bfdc2011-11-02 01:32:201440 switch (target) {
1441 case GL_RENDERBUFFER:
[email protected]7cd76fd2013-06-02 21:11:111442 renderbuffer = state_.bound_renderbuffer.get();
[email protected]0d6bfdc2011-11-02 01:32:201443 break;
1444 default:
1445 NOTREACHED();
1446 break;
1447 }
[email protected]ee2a79c32013-03-10 03:50:271448 return renderbuffer;
[email protected]0d6bfdc2011-11-02 01:32:201449 }
1450
[email protected]f7b85372010-02-03 01:11:371451 // Validates the program and location for a glGetUniform call and returns
1452 // a SizeResult setup to receive the result. Returns true if glGetUniform
1453 // should be called.
1454 bool GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:121455 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:371456 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:121457 error::Error* error, GLint* real_location, GLuint* service_id,
1458 void** result, GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371459
[email protected]1078f912011-12-23 13:12:141460 // Computes the estimated memory used for the backbuffer and passes it to
1461 // the tracing system.
[email protected]260ddc4e2012-06-28 00:01:531462 size_t GetBackbufferMemoryTotal();
[email protected]1078f912011-12-23 13:12:141463
[email protected]a10b4a02012-11-26 23:09:501464 virtual bool WasContextLost() OVERRIDE;
[email protected]93a7d98f2013-07-11 00:04:221465 virtual bool WasContextLostByRobustnessExtension() OVERRIDE;
[email protected]c4485aad62012-12-17 10:19:091466 virtual void LoseContext(uint32 reset_status) OVERRIDE;
[email protected]38d139d2011-07-14 00:38:431467
[email protected]e51bdf32011-11-23 22:21:461468#if defined(OS_MACOSX)
1469 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1470#endif
1471
[email protected]81375742012-06-08 00:04:001472 // Validates the combination of texture parameters. For example validates that
1473 // for a given format the specific type, level and targets are valid.
1474 // Synthesizes the correct GL error if invalid. Returns true if valid.
1475 bool ValidateTextureParameters(
1476 const char* function_name,
1477 GLenum target, GLenum format, GLenum type, GLint level);
1478
[email protected]ad84a3a2012-06-08 21:42:431479 bool ValidateCompressedTexDimensions(
1480 const char* function_name,
1481 GLint level, GLsizei width, GLsizei height, GLenum format);
1482 bool ValidateCompressedTexFuncData(
1483 const char* function_name,
1484 GLsizei width, GLsizei height, GLenum format, size_t size);
1485 bool ValidateCompressedTexSubDimensions(
1486 const char* function_name,
1487 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1488 GLsizei width, GLsizei height, GLenum format,
[email protected]ed9f9cd2013-02-27 21:12:351489 Texture* texture);
[email protected]ad84a3a2012-06-08 21:42:431490
[email protected]ab09b612013-03-11 22:11:511491 void RenderWarning(const char* filename, int line, const std::string& msg);
1492 void PerformanceWarning(
1493 const char* filename, int line, const std::string& msg);
[email protected]0f8afe82012-05-14 23:43:011494
[email protected]62e155e2012-10-23 22:43:151495 const FeatureInfo::FeatureFlags& features() const {
1496 return feature_info_->feature_flags();
1497 }
1498
1499 const FeatureInfo::Workarounds& workarounds() const {
1500 return feature_info_->workarounds();
1501 }
1502
[email protected]a7266a92012-06-28 02:11:081503 bool ShouldDeferDraws() {
1504 return !offscreen_target_frame_buffer_.get() &&
[email protected]9d3b2e12013-10-02 01:04:341505 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
[email protected]a7266a92012-06-28 02:11:081506 surface_->DeferDraws();
1507 }
1508
[email protected]09e17272012-11-30 10:30:441509 bool ShouldDeferReads() {
1510 return !offscreen_target_frame_buffer_.get() &&
[email protected]9d3b2e12013-10-02 01:04:341511 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
[email protected]09e17272012-11-30 10:30:441512 surface_->DeferDraws();
1513 }
1514
[email protected]5a36dc132013-07-23 23:17:551515 void ProcessPendingReadPixels();
1516 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1517
[email protected]96449d2c2009-11-25 00:01:321518 // Generate a member function prototype for each command in an automated and
1519 // typesafe way.
1520 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141521 Error Handle ## name( \
[email protected]ed9f9cd2013-02-27 21:12:351522 uint32 immediate_data_size, \
1523 const cmds::name& args); \
[email protected]96449d2c2009-11-25 00:01:321524
1525 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1526
1527 #undef GLES2_CMD_OP
1528
[email protected]2f2d7042010-04-14 21:45:581529 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381530 scoped_refptr<gfx::GLSurface> surface_;
1531 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021532
[email protected]a3ded6d2010-10-19 06:44:391533 // The ContextGroup for this decoder uses to track resources.
[email protected]ed9f9cd2013-02-27 21:12:351534 scoped_refptr<ContextGroup> group_;
[email protected]a3ded6d2010-10-19 06:44:391535
[email protected]1d82e822013-04-10 21:32:321536 DebugMarkerManager debug_marker_manager_;
1537 Logger logger_;
1538
[email protected]e259eb412012-10-13 05:47:241539 // All the state for this context.
1540 ContextState state_;
1541
[email protected]34ff8b0c2010-10-01 20:06:021542 // Current width and height of the offscreen frame buffer.
1543 gfx::Size offscreen_size_;
1544
[email protected]96449d2c2009-11-25 00:01:321545 // Util to help with GL.
1546 GLES2Util util_;
1547
[email protected]43410e92012-04-20 17:06:281548 // unpack flip y as last set by glPixelStorei
1549 bool unpack_flip_y_;
1550
[email protected]6c75c712012-06-19 15:43:171551 // unpack (un)premultiply alpha as last set by glPixelStorei
[email protected]43410e92012-04-20 17:06:281552 bool unpack_premultiply_alpha_;
[email protected]6c75c712012-06-19 15:43:171553 bool unpack_unpremultiply_alpha_;
[email protected]43410e92012-04-20 17:06:281554
[email protected]944b62f32012-09-27 02:20:461555 // Default vertex attribs manager, used when no VAOs are bound.
[email protected]ed9f9cd2013-02-27 21:12:351556 scoped_refptr<VertexAttribManager> default_vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301557
[email protected]b1122982010-05-17 23:04:241558 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1559 GLuint attrib_0_buffer_id_;
1560
1561 // The value currently in attrib_0.
[email protected]af6380962012-11-29 23:24:131562 Vec4 attrib_0_value_;
[email protected]b1122982010-05-17 23:04:241563
[email protected]fc753442011-02-04 19:49:491564 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1565 bool attrib_0_buffer_matches_value_;
1566
[email protected]b1122982010-05-17 23:04:241567 // The size of attrib 0.
1568 GLsizei attrib_0_size_;
1569
[email protected]8fbedc02010-11-18 18:43:401570 // The buffer used to simulate GL_FIXED attribs.
1571 GLuint fixed_attrib_buffer_id_;
1572
1573 // The size of fiixed attrib buffer.
1574 GLsizei fixed_attrib_buffer_size_;
1575
[email protected]b9363b22010-06-09 22:06:151576 // The offscreen frame buffer that the client renders to. With EGL, the
1577 // depth and stencil buffers are separate. With regular GL there is a single
1578 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1579 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]ed9f9cd2013-02-27 21:12:351580 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1581 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1582 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1583 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1584 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021585 GLenum offscreen_target_color_format_;
1586 GLenum offscreen_target_depth_format_;
1587 GLenum offscreen_target_stencil_format_;
1588 GLsizei offscreen_target_samples_;
[email protected]8a61d872012-01-20 12:43:561589 GLboolean offscreen_target_buffer_preserved_;
[email protected]6217d392010-03-25 22:08:351590
[email protected]de26b3c2011-08-03 21:54:271591 // The copy that is saved when SwapBuffers is called.
[email protected]ed9f9cd2013-02-27 21:12:351592 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1593 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
[email protected]370eaf12013-05-18 09:19:491594 scoped_refptr<TextureRef>
[email protected]ed9f9cd2013-02-27 21:12:351595 offscreen_saved_color_texture_info_;
[email protected]de26b3c2011-08-03 21:54:271596
1597 // The copy that is used as the destination for multi-sample resolves.
[email protected]ed9f9cd2013-02-27 21:12:351598 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1599 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051600 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351601
[email protected]882ba1e22012-03-08 19:02:531602 scoped_ptr<QueryManager> query_manager_;
[email protected]882ba1e22012-03-08 19:02:531603
[email protected]944b62f32012-09-27 02:20:461604 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1605
[email protected]729c0b42013-05-26 02:05:071606 base::Callback<void(gfx::Size, float)> resize_callback_;
[email protected]22f320a2011-08-30 01:17:001607
[email protected]840a7e462013-02-27 01:29:511608 WaitSyncPointCallback wait_sync_point_callback_;
[email protected]43f28f832010-02-03 02:28:481609
[email protected]e3932abb2013-03-13 00:01:371610 ShaderCacheCallback shader_cache_callback_;
1611
[email protected]85a4ac22013-05-31 01:58:471612 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
[email protected]b0af4f52011-09-28 22:04:421613
[email protected]32fe9aa2011-01-21 23:47:131614 // The format of the back buffer_
1615 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461616 bool back_buffer_has_depth_;
1617 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131618
[email protected]60f22d32012-12-12 00:31:581619 // Backbuffer attachments that are currently undefined.
1620 uint32 backbuffer_needs_clear_bits_;
1621
[email protected]a3a93e7b2010-08-28 00:48:561622 // The current decoder error.
1623 error::Error current_decoder_error_;
1624
[email protected]b1d2dcb2010-05-17 19:24:181625 bool use_shader_translator_;
[email protected]87fb6ab2012-06-13 22:28:041626 scoped_refptr<ShaderTranslator> vertex_translator_;
1627 scoped_refptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181628
[email protected]e82fb792011-09-22 00:33:291629 DisallowedFeatures disallowed_features_;
[email protected]c410da802011-03-14 19:17:411630
[email protected]915a59a12010-09-30 21:29:111631 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051632 const Validators* validators_;
[email protected]ed9f9cd2013-02-27 21:12:351633 scoped_refptr<FeatureInfo> feature_info_;
[email protected]9438b012010-06-15 22:55:051634
[email protected]65225772011-05-12 21:10:241635 int frame_number_;
1636
[email protected]706b69f2012-07-27 04:59:301637 bool has_robustness_extension_;
[email protected]38d139d2011-07-14 00:38:431638 GLenum reset_status_;
[email protected]93a7d98f2013-07-11 00:04:221639 bool reset_by_robustness_extension_;
[email protected]38d139d2011-07-14 00:38:431640
[email protected]f0d74742011-10-03 16:31:041641 // These flags are used to override the state of the shared feature_info_
1642 // member. Because the same FeatureInfo instance may be shared among many
1643 // contexts, the assumptions on the availablity of extensions in WebGL
1644 // contexts may be broken. These flags override the shared state to preserve
1645 // WebGL semantics.
1646 bool force_webgl_glsl_validation_;
1647 bool derivatives_explicitly_enabled_;
[email protected]70dc60932013-06-04 03:33:491648 bool frag_depth_explicitly_enabled_;
[email protected]aff39ac82013-06-08 04:53:131649 bool draw_buffers_explicitly_enabled_;
[email protected]f0d74742011-10-03 16:31:041650
[email protected]062c38b2012-01-18 03:25:101651 bool compile_shader_always_succeeds_;
1652
[email protected]cae20172012-12-07 00:06:191653 // Log extra info.
1654 bool service_logging_;
1655
[email protected]e51bdf32011-11-23 22:21:461656#if defined(OS_MACOSX)
1657 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1658 TextureToIOSurfaceMap texture_to_io_surface_map_;
1659#endif
1660
[email protected]43410e92012-04-20 17:06:281661 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1662
[email protected]1868a342012-11-07 15:56:021663 // Cached values of the currently assigned viewport dimensions.
1664 GLsizei viewport_max_width_;
1665 GLsizei viewport_max_height_;
1666
[email protected]63b465922012-09-06 02:04:521667 // Command buffer stats.
[email protected]63b465922012-09-06 02:04:521668 base::TimeDelta total_processing_commands_time_;
1669
[email protected]c986af502013-08-14 01:04:441670 // States related to each manager.
1671 DecoderTextureState texture_state_;
1672 DecoderFramebufferState framebuffer_state_;
1673
[email protected]fb97b662013-02-20 23:02:141674 scoped_ptr<GPUTracer> gpu_tracer_;
[email protected]8f9b8dd2013-09-12 18:05:131675 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
[email protected]94307712012-11-16 23:26:111676
[email protected]5a36dc132013-07-23 23:17:551677 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1678
[email protected]4a4c18b2013-09-13 22:50:101679 // Used to validate multisample renderbuffers if needed
1680 GLuint validation_texture_;
1681 GLuint validation_fbo_multisample_;
1682 GLuint validation_fbo_;
1683
[email protected]96449d2c2009-11-25 00:01:321684 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1685};
1686
[email protected]ab09b612013-03-11 22:11:511687ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
[email protected]40621eb52013-10-08 15:40:301688 const char* function_name, ErrorState* error_state)
[email protected]ab09b612013-03-11 22:11:511689 : function_name_(function_name),
[email protected]40621eb52013-10-08 15:40:301690 error_state_(error_state) {
1691 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
[email protected]6217d392010-03-25 22:08:351692}
1693
1694ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
[email protected]40621eb52013-10-08 15:40:301695 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
[email protected]6217d392010-03-25 22:08:351696}
1697
1698ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1699 GLuint id)
1700 : decoder_(decoder) {
[email protected]ab09b612013-03-11 22:11:511701 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:301702 "ScopedTexture2DBinder::ctor", decoder_->GetErrorState());
[email protected]6217d392010-03-25 22:08:351703
1704 // TODO(apatrick): Check if there are any other states that need to be reset
1705 // before binding a new texture.
1706 glActiveTexture(GL_TEXTURE0);
1707 glBindTexture(GL_TEXTURE_2D, id);
1708}
1709
1710ScopedTexture2DBinder::~ScopedTexture2DBinder() {
[email protected]ab09b612013-03-11 22:11:511711 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:301712 "ScopedTexture2DBinder::dtor", decoder_->GetErrorState());
[email protected]8e3e0662010-08-23 18:46:301713 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351714}
1715
[email protected]18e785a2013-10-09 03:29:411716ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
[email protected]6217d392010-03-25 22:08:351717 GLuint id)
[email protected]18e785a2013-10-09 03:29:411718 : state_(state) {
[email protected]ab09b612013-03-11 22:11:511719 ScopedGLErrorSuppressor suppressor(
[email protected]18e785a2013-10-09 03:29:411720 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
[email protected]6217d392010-03-25 22:08:351721 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1722}
1723
1724ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
[email protected]ab09b612013-03-11 22:11:511725 ScopedGLErrorSuppressor suppressor(
[email protected]18e785a2013-10-09 03:29:411726 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
1727 state_->RestoreRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351728}
1729
1730ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1731 GLuint id)
1732 : decoder_(decoder) {
[email protected]ab09b612013-03-11 22:11:511733 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:301734 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
[email protected]6217d392010-03-25 22:08:351735 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
[email protected]70d34263c2013-01-09 00:27:451736 decoder->OnFboChanged();
[email protected]6217d392010-03-25 22:08:351737}
1738
1739ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
[email protected]ab09b612013-03-11 22:11:511740 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:301741 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
[email protected]8e3e0662010-08-23 18:46:301742 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351743}
1744
[email protected]34ff8b0c2010-10-01 20:06:021745ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271746 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521747 : decoder_(decoder) {
[email protected]9d3b2e12013-10-02 01:04:341748 resolve_and_bind_ = (
1749 decoder_->offscreen_target_frame_buffer_.get() &&
1750 decoder_->IsOffscreenBufferMultisampled() &&
1751 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
1752 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021753 if (!resolve_and_bind_)
1754 return;
1755
[email protected]ab09b612013-03-11 22:11:511756 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:301757 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
[email protected]34ff8b0c2010-10-01 20:06:021758 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1759 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271760 GLuint targetid;
1761 if (internal) {
1762 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1763 decoder_->offscreen_resolved_frame_buffer_.reset(
[email protected]ed9f9cd2013-02-27 21:12:351764 new BackFramebuffer(decoder_));
[email protected]de26b3c2011-08-03 21:54:271765 decoder_->offscreen_resolved_frame_buffer_->Create();
[email protected]ed9f9cd2013-02-27 21:12:351766 decoder_->offscreen_resolved_color_texture_.reset(
1767 new BackTexture(decoder_));
[email protected]de26b3c2011-08-03 21:54:271768 decoder_->offscreen_resolved_color_texture_->Create();
1769
1770 DCHECK(decoder_->offscreen_saved_color_format_);
1771 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
[email protected]678a73f2012-12-19 19:22:091772 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
1773 false);
[email protected]de26b3c2011-08-03 21:54:271774 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1775 decoder_->offscreen_resolved_color_texture_.get());
1776 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1777 GL_FRAMEBUFFER_COMPLETE) {
1778 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1779 << "because offscreen resolved FBO was incomplete.";
1780 return;
1781 }
1782 }
1783 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1784 } else {
1785 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1786 }
1787 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021788 const int width = decoder_->offscreen_size_.width();
1789 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181790 glDisable(GL_SCISSOR_TEST);
[email protected]57edfdad2012-02-07 04:57:151791 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021792 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1793 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1794 } else {
1795 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1796 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1797 }
[email protected]de26b3c2011-08-03 21:54:271798 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021799}
1800
1801ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1802 if (!resolve_and_bind_)
1803 return;
1804
[email protected]ab09b612013-03-11 22:11:511805 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:301806 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
[email protected]34ff8b0c2010-10-01 20:06:021807 decoder_->RestoreCurrentFramebufferBindings();
[email protected]f731b9462012-10-30 00:35:221808 if (decoder_->state_.enable_flags.scissor_test) {
[email protected]8c3e68782010-10-27 16:41:181809 glEnable(GL_SCISSOR_TEST);
1810 }
[email protected]34ff8b0c2010-10-01 20:06:021811}
1812
[email protected]ed9f9cd2013-02-27 21:12:351813BackTexture::BackTexture(GLES2DecoderImpl* decoder)
[email protected]6217d392010-03-25 22:08:351814 : decoder_(decoder),
[email protected]7989c9e2013-01-23 06:39:261815 memory_tracker_(decoder->memory_tracker(), MemoryTracker::kUnmanaged),
[email protected]68e81a4a62012-12-13 01:16:481816 bytes_allocated_(0),
[email protected]ff6493f2012-07-31 19:52:251817 id_(0) {
[email protected]6217d392010-03-25 22:08:351818}
1819
[email protected]ed9f9cd2013-02-27 21:12:351820BackTexture::~BackTexture() {
[email protected]6217d392010-03-25 22:08:351821 // This does not destroy the render texture because that would require that
1822 // the associated GL context was current. Just check that it was explicitly
1823 // destroyed.
1824 DCHECK_EQ(id_, 0u);
1825}
1826
[email protected]ed9f9cd2013-02-27 21:12:351827void BackTexture::Create() {
[email protected]40621eb52013-10-08 15:40:301828 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
1829 decoder_->GetErrorState());
[email protected]6217d392010-03-25 22:08:351830 Destroy();
1831 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581832 ScopedTexture2DBinder binder(decoder_, id_);
1833 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1834 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1835 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1836 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]62788802011-10-03 17:57:161837
1838 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1839 // never called on an offscreen context, no data will ever be uploaded to the
1840 // saved offscreen color texture (it is deferred until to when SwapBuffers
1841 // is called). My idea is that some nvidia drivers might have a bug where
1842 // deleting a texture that has never been populated might cause a
1843 // crash.
1844 glTexImage2D(
1845 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
[email protected]68e81a4a62012-12-13 01:16:481846
1847 bytes_allocated_ = 16u * 16u * 4u;
1848 memory_tracker_.TrackMemAlloc(bytes_allocated_);
[email protected]6217d392010-03-25 22:08:351849}
1850
[email protected]ed9f9cd2013-02-27 21:12:351851bool BackTexture::AllocateStorage(
1852 const gfx::Size& size, GLenum format, bool zero) {
[email protected]6217d392010-03-25 22:08:351853 DCHECK_NE(id_, 0u);
[email protected]40621eb52013-10-08 15:40:301854 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
1855 decoder_->GetErrorState());
[email protected]6217d392010-03-25 22:08:351856 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]678a73f2012-12-19 19:22:091857 uint32 image_size = 0;
1858 GLES2Util::ComputeImageDataSizes(
1859 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
1860 NULL, NULL);
1861
[email protected]7989c9e2013-01-23 06:39:261862 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
1863 return false;
1864 }
1865
[email protected]40d90a22013-04-09 03:39:551866 scoped_ptr<char[]> zero_data;
[email protected]678a73f2012-12-19 19:22:091867 if (zero) {
1868 zero_data.reset(new char[image_size]);
1869 memset(zero_data.get(), 0, image_size);
1870 }
[email protected]6217d392010-03-25 22:08:351871
[email protected]8f1d2aa2013-05-10 23:45:381872 glTexImage2D(GL_TEXTURE_2D,
1873 0, // mip level
1874 format,
1875 size.width(),
1876 size.height(),
1877 0, // border
1878 format,
1879 GL_UNSIGNED_BYTE,
1880 zero_data.get());
[email protected]6217d392010-03-25 22:08:351881
[email protected]d37231fa2010-04-09 21:16:021882 size_ = size;
1883
[email protected]1078f912011-12-23 13:12:141884 bool success = glGetError() == GL_NO_ERROR;
1885 if (success) {
[email protected]68e81a4a62012-12-13 01:16:481886 memory_tracker_.TrackMemFree(bytes_allocated_);
1887 bytes_allocated_ = image_size;
1888 memory_tracker_.TrackMemAlloc(bytes_allocated_);
[email protected]1078f912011-12-23 13:12:141889 }
1890 return success;
[email protected]6217d392010-03-25 22:08:351891}
1892
[email protected]ed9f9cd2013-02-27 21:12:351893void BackTexture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351894 DCHECK_NE(id_, 0u);
[email protected]40621eb52013-10-08 15:40:301895 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
1896 decoder_->GetErrorState());
[email protected]6217d392010-03-25 22:08:351897 ScopedTexture2DBinder binder(decoder_, id_);
1898 glCopyTexImage2D(GL_TEXTURE_2D,
1899 0, // level
[email protected]3a4d0c52011-06-29 23:11:581900 format,
[email protected]6217d392010-03-25 22:08:351901 0, 0,
1902 size.width(),
1903 size.height(),
1904 0); // border
1905}
1906
[email protected]ed9f9cd2013-02-27 21:12:351907void BackTexture::Destroy() {
[email protected]6217d392010-03-25 22:08:351908 if (id_ != 0) {
[email protected]40621eb52013-10-08 15:40:301909 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
1910 decoder_->GetErrorState());
[email protected]6217d392010-03-25 22:08:351911 glDeleteTextures(1, &id_);
1912 id_ = 0;
1913 }
[email protected]68e81a4a62012-12-13 01:16:481914 memory_tracker_.TrackMemFree(bytes_allocated_);
1915 bytes_allocated_ = 0;
[email protected]6217d392010-03-25 22:08:351916}
1917
[email protected]ed9f9cd2013-02-27 21:12:351918void BackTexture::Invalidate() {
[email protected]97872062010-11-03 19:07:051919 id_ = 0;
1920}
1921
[email protected]d5a28e452013-10-10 01:01:401922BackRenderbuffer::BackRenderbuffer(
1923 RenderbufferManager* renderbuffer_manager,
1924 MemoryTracker* memory_tracker,
1925 ContextState* state)
1926 : renderbuffer_manager_(renderbuffer_manager),
1927 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
1928 state_(state),
[email protected]68e81a4a62012-12-13 01:16:481929 bytes_allocated_(0),
[email protected]ff6493f2012-07-31 19:52:251930 id_(0) {
[email protected]6217d392010-03-25 22:08:351931}
1932
[email protected]ed9f9cd2013-02-27 21:12:351933BackRenderbuffer::~BackRenderbuffer() {
[email protected]6217d392010-03-25 22:08:351934 // This does not destroy the render buffer because that would require that
1935 // the associated GL context was current. Just check that it was explicitly
1936 // destroyed.
1937 DCHECK_EQ(id_, 0u);
1938}
1939
[email protected]ed9f9cd2013-02-27 21:12:351940void BackRenderbuffer::Create() {
[email protected]40621eb52013-10-08 15:40:301941 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
[email protected]d5a28e452013-10-10 01:01:401942 state_->GetErrorState());
[email protected]6217d392010-03-25 22:08:351943 Destroy();
1944 glGenRenderbuffersEXT(1, &id_);
1945}
1946
[email protected]ed9f9cd2013-02-27 21:12:351947bool BackRenderbuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1948 GLsizei samples) {
[email protected]ab09b612013-03-11 22:11:511949 ScopedGLErrorSuppressor suppressor(
[email protected]d5a28e452013-10-10 01:01:401950 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
1951 ScopedRenderBufferBinder binder(state_, id_);
[email protected]7989c9e2013-01-23 06:39:261952
1953 uint32 estimated_size = 0;
[email protected]d5a28e452013-10-10 01:01:401954 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
[email protected]8e102e102013-09-20 22:50:231955 size.width(), size.height(), samples, format, &estimated_size)) {
[email protected]7989c9e2013-01-23 06:39:261956 return false;
1957 }
1958
1959 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
1960 return false;
1961 }
1962
[email protected]34ff8b0c2010-10-01 20:06:021963 if (samples <= 1) {
1964 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1965 format,
1966 size.width(),
1967 size.height());
1968 } else {
[email protected]57edfdad2012-02-07 04:57:151969 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021970 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1971 samples,
1972 format,
1973 size.width(),
1974 size.height());
1975 } else {
1976 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1977 samples,
1978 format,
1979 size.width(),
1980 size.height());
1981 }
1982 }
[email protected]1078f912011-12-23 13:12:141983 bool success = glGetError() == GL_NO_ERROR;
1984 if (success) {
[email protected]d5a28e452013-10-10 01:01:401985 // Mark the previously allocated bytes as free.
[email protected]68e81a4a62012-12-13 01:16:481986 memory_tracker_.TrackMemFree(bytes_allocated_);
[email protected]7989c9e2013-01-23 06:39:261987 bytes_allocated_ = estimated_size;
[email protected]d5a28e452013-10-10 01:01:401988 // Track the newly allocated bytes.
[email protected]68e81a4a62012-12-13 01:16:481989 memory_tracker_.TrackMemAlloc(bytes_allocated_);
[email protected]1078f912011-12-23 13:12:141990 }
1991 return success;
[email protected]6217d392010-03-25 22:08:351992}
1993
[email protected]ed9f9cd2013-02-27 21:12:351994void BackRenderbuffer::Destroy() {
[email protected]6217d392010-03-25 22:08:351995 if (id_ != 0) {
[email protected]40621eb52013-10-08 15:40:301996 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
[email protected]d5a28e452013-10-10 01:01:401997 state_->GetErrorState());
[email protected]6217d392010-03-25 22:08:351998 glDeleteRenderbuffersEXT(1, &id_);
1999 id_ = 0;
2000 }
[email protected]68e81a4a62012-12-13 01:16:482001 memory_tracker_.TrackMemFree(bytes_allocated_);
2002 bytes_allocated_ = 0;
[email protected]6217d392010-03-25 22:08:352003}
2004
[email protected]ed9f9cd2013-02-27 21:12:352005void BackRenderbuffer::Invalidate() {
[email protected]97872062010-11-03 19:07:052006 id_ = 0;
2007}
2008
[email protected]ed9f9cd2013-02-27 21:12:352009BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
[email protected]6217d392010-03-25 22:08:352010 : decoder_(decoder),
2011 id_(0) {
2012}
2013
[email protected]ed9f9cd2013-02-27 21:12:352014BackFramebuffer::~BackFramebuffer() {
[email protected]6217d392010-03-25 22:08:352015 // This does not destroy the frame buffer because that would require that
2016 // the associated GL context was current. Just check that it was explicitly
2017 // destroyed.
2018 DCHECK_EQ(id_, 0u);
2019}
2020
[email protected]ed9f9cd2013-02-27 21:12:352021void BackFramebuffer::Create() {
[email protected]40621eb52013-10-08 15:40:302022 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2023 decoder_->GetErrorState());
[email protected]6217d392010-03-25 22:08:352024 Destroy();
2025 glGenFramebuffersEXT(1, &id_);
2026}
2027
[email protected]ed9f9cd2013-02-27 21:12:352028void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
[email protected]6217d392010-03-25 22:08:352029 DCHECK_NE(id_, 0u);
[email protected]ab09b612013-03-11 22:11:512030 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:302031 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
[email protected]6217d392010-03-25 22:08:352032 ScopedFrameBufferBinder binder(decoder_, id_);
2033 GLuint attach_id = texture ? texture->id() : 0;
2034 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2035 GL_COLOR_ATTACHMENT0,
2036 GL_TEXTURE_2D,
2037 attach_id,
2038 0);
2039}
2040
[email protected]ed9f9cd2013-02-27 21:12:352041void BackFramebuffer::AttachRenderBuffer(GLenum target,
2042 BackRenderbuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:352043 DCHECK_NE(id_, 0u);
[email protected]ab09b612013-03-11 22:11:512044 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:302045 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
[email protected]6217d392010-03-25 22:08:352046 ScopedFrameBufferBinder binder(decoder_, id_);
2047 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2048 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:152049 target,
[email protected]6217d392010-03-25 22:08:352050 GL_RENDERBUFFER,
2051 attach_id);
2052}
2053
[email protected]ed9f9cd2013-02-27 21:12:352054void BackFramebuffer::Destroy() {
[email protected]6217d392010-03-25 22:08:352055 if (id_ != 0) {
[email protected]40621eb52013-10-08 15:40:302056 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2057 decoder_->GetErrorState());
[email protected]6217d392010-03-25 22:08:352058 glDeleteFramebuffersEXT(1, &id_);
2059 id_ = 0;
2060 }
2061}
2062
[email protected]ed9f9cd2013-02-27 21:12:352063void BackFramebuffer::Invalidate() {
[email protected]97872062010-11-03 19:07:052064 id_ = 0;
2065}
2066
[email protected]ed9f9cd2013-02-27 21:12:352067GLenum BackFramebuffer::CheckStatus() {
[email protected]6217d392010-03-25 22:08:352068 DCHECK_NE(id_, 0u);
[email protected]40621eb52013-10-08 15:40:302069 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2070 decoder_->GetErrorState());
[email protected]6217d392010-03-25 22:08:352071 ScopedFrameBufferBinder binder(decoder_, id_);
2072 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2073}
2074
[email protected]aa7666122011-09-02 19:45:522075GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2076 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:322077}
2078
[email protected]aa7666122011-09-02 19:45:522079GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:392080 : GLES2Decoder(),
[email protected]3b1ecc262011-08-03 22:49:572081 group_(group),
[email protected]1d82e822013-04-10 21:32:322082 logger_(&debug_marker_manager_),
[email protected]d3eba342013-04-18 21:11:502083 state_(group_->feature_info(), &logger_),
[email protected]43410e92012-04-20 17:06:282084 unpack_flip_y_(false),
2085 unpack_premultiply_alpha_(false),
[email protected]6c75c712012-06-19 15:43:172086 unpack_unpremultiply_alpha_(false),
[email protected]b1122982010-05-17 23:04:242087 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:492088 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:242089 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:402090 fixed_attrib_buffer_id_(0),
2091 fixed_attrib_buffer_size_(0),
[email protected]34ff8b0c2010-10-01 20:06:022092 offscreen_target_color_format_(0),
2093 offscreen_target_depth_format_(0),
2094 offscreen_target_stencil_format_(0),
2095 offscreen_target_samples_(0),
[email protected]8a61d872012-01-20 12:43:562096 offscreen_target_buffer_preserved_(true),
[email protected]97872062010-11-03 19:07:052097 offscreen_saved_color_format_(0),
[email protected]32fe9aa2011-01-21 23:47:132098 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:462099 back_buffer_has_depth_(false),
2100 back_buffer_has_stencil_(false),
[email protected]60f22d32012-12-12 00:31:582101 backbuffer_needs_clear_bits_(0),
[email protected]a3a93e7b2010-08-28 00:48:562102 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:052103 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:112104 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:002105 feature_info_(group_->feature_info()),
[email protected]38d139d2011-07-14 00:38:432106 frame_number_(0),
[email protected]706b69f2012-07-27 04:59:302107 has_robustness_extension_(false),
[email protected]75c023c2011-08-22 23:54:512108 reset_status_(GL_NO_ERROR),
[email protected]93a7d98f2013-07-11 00:04:222109 reset_by_robustness_extension_(false),
[email protected]f0d74742011-10-03 16:31:042110 force_webgl_glsl_validation_(false),
[email protected]062c38b2012-01-18 03:25:102111 derivatives_explicitly_enabled_(false),
[email protected]70dc60932013-06-04 03:33:492112 frag_depth_explicitly_enabled_(false),
[email protected]aff39ac82013-06-08 04:53:132113 draw_buffers_explicitly_enabled_(false),
[email protected]43410e92012-04-20 17:06:282114 compile_shader_always_succeeds_(false),
[email protected]cae20172012-12-07 00:06:192115 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2116 switches::kEnableGPUServiceLoggingGPU)),
[email protected]1868a342012-11-07 15:56:022117 viewport_max_width_(0),
[email protected]4a4c18b2013-09-13 22:50:102118 viewport_max_height_(0),
2119 validation_texture_(0),
2120 validation_fbo_multisample_(0),
2121 validation_fbo_(0) {
[email protected]3b1ecc262011-08-03 22:49:572122 DCHECK(group);
2123
[email protected]b1122982010-05-17 23:04:242124 attrib_0_value_.v[0] = 0.0f;
2125 attrib_0_value_.v[1] = 0.0f;
2126 attrib_0_value_.v[2] = 0.0f;
2127 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:152128
[email protected]c2f8c8402010-12-06 18:07:242129 // The shader translator is used for WebGL even when running on EGL
2130 // because additional restrictions are needed (like only enabling
2131 // GL_OES_standard_derivatives on demand). It is used for the unit
[email protected]4b7eba92013-01-08 02:23:562132 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2133 // the empty string to CompileShader and this is not a valid shader.
2134 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
[email protected]39ba4f02012-03-26 01:16:002135 CommandLine::ForCurrentProcess()->HasSwitch(
2136 switches::kDisableGLSLTranslator)) {
[email protected]b9363b22010-06-09 22:06:152137 use_shader_translator_ = false;
2138 }
[email protected]473c01ccb2011-06-07 01:33:302139
[email protected]a39370652012-09-25 21:52:132140 // TODO(gman): Consider setting this based on GPU and/or driver.
[email protected]473c01ccb2011-06-07 01:33:302141 if (IsAngle()) {
[email protected]c986af502013-08-14 01:04:442142 texture_state_.teximage2d_faster_than_texsubimage2d = false;
[email protected]473c01ccb2011-06-07 01:33:302143 }
[email protected]96449d2c2009-11-25 00:01:322144}
2145
[email protected]80eb6b52012-01-19 00:14:412146GLES2DecoderImpl::~GLES2DecoderImpl() {
2147}
2148
[email protected]c410da802011-03-14 19:17:412149bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:382150 const scoped_refptr<gfx::GLSurface>& surface,
2151 const scoped_refptr<gfx::GLContext>& context,
[email protected]069944672012-04-25 20:52:232152 bool offscreen,
[email protected]c410da802011-03-14 19:17:412153 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:292154 const DisallowedFeatures& disallowed_features,
[email protected]3c644d82011-06-20 19:58:242155 const std::vector<int32>& attribs) {
[email protected]3551cb202012-05-24 10:55:322156 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
[email protected]63c9b052012-05-17 18:27:382157 DCHECK(context->IsCurrent(surface.get()));
[email protected]66791e382010-07-14 20:48:302158 DCHECK(!context_.get());
2159
[email protected]55e136f2013-04-03 18:50:062160 set_initialized();
[email protected]fb97b662013-02-20 23:02:142161 gpu_tracer_ = GPUTracer::Create();
[email protected]8f9b8dd2013-09-12 18:05:132162 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
[email protected]fb97b662013-02-20 23:02:142163
[email protected]e844ae22012-01-14 03:36:262164 if (CommandLine::ForCurrentProcess()->HasSwitch(
2165 switches::kEnableGPUDebugging)) {
2166 set_debug(true);
2167 }
2168
[email protected]39ba4f02012-03-26 01:16:002169 if (CommandLine::ForCurrentProcess()->HasSwitch(
2170 switches::kEnableGPUCommandLogging)) {
2171 set_log_commands(true);
2172 }
2173
[email protected]062c38b2012-01-18 03:25:102174 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2175 switches::kCompileShaderAlwaysSucceeds);
2176
[email protected]f62a5ab2011-05-23 20:34:152177
[email protected]63c9b052012-05-17 18:27:382178 // Take ownership of the context and surface. The surface can be replaced with
2179 // SetSurface.
[email protected]fbe20372011-06-01 01:46:382180 context_ = context;
[email protected]63c9b052012-05-17 18:27:382181 surface_ = surface;
[email protected]eb54a562010-01-20 21:55:182182
[email protected]956aec52013-09-05 15:41:192183 if (!group_->Initialize(this, disallowed_features)) {
[email protected]09ddb91f2011-04-14 23:16:222184 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:392185 << "failed to initialize.";
[email protected]1871a092011-10-10 21:46:422186 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]63c9b052012-05-17 18:27:382187 Destroy(true);
[email protected]ae1741092010-11-17 19:16:032188 return false;
[email protected]a3ded6d2010-10-19 06:44:392189 }
[email protected]b64c24952012-04-19 03:20:272190 CHECK_GL_ERROR();
[email protected]43410e92012-04-20 17:06:282191
[email protected]e82fb792011-09-22 00:33:292192 disallowed_features_ = disallowed_features;
[email protected]246a70452010-03-05 21:53:502193
[email protected]af6380962012-11-29 23:24:132194 state_.attrib_values.resize(group_->max_vertex_attribs());
[email protected]944b62f32012-09-27 02:20:462195 default_vertex_attrib_manager_ = new VertexAttribManager();
2196 default_vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
2197
[email protected]ab4fd7282012-10-12 16:25:572198 // vertex_attrib_manager is set to default_vertex_attrib_manager_ by this call
2199 DoBindVertexArrayOES(0);
[email protected]876f6fee2010-08-02 23:10:322200
[email protected]7cd76fd2013-06-02 21:11:112201 query_manager_.reset(new QueryManager(this, feature_info_.get()));
[email protected]944b62f32012-09-27 02:20:462202 vertex_array_manager_.reset(new VertexArrayManager());
[email protected]882ba1e22012-03-08 19:02:532203
[email protected]302ce6d2011-07-07 23:28:112204 util_.set_num_compressed_texture_formats(
2205 validators_->compressed_texture_format.GetValues().size());
2206
[email protected]1071e572011-02-09 20:00:122207 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2208 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2209 // OpenGL ES 2.0 does not have this issue.
2210 glEnableVertexAttribArray(0);
2211 }
[email protected]b1122982010-05-17 23:04:242212 glGenBuffersARB(1, &attrib_0_buffer_id_);
2213 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2214 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2215 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:402216 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:082217
[email protected]1868a342012-11-07 15:56:022218 state_.texture_units.resize(group_->max_texture_units());
2219 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
[email protected]00f893d2010-08-24 18:55:492220 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:312221 // We want the last bind to be 2D.
[email protected]370eaf12013-05-18 09:19:492222 TextureRef* ref;
[email protected]62e155e2012-10-23 22:43:152223 if (features().oes_egl_image_external) {
[email protected]370eaf12013-05-18 09:19:492224 ref = texture_manager()->GetDefaultTextureInfo(
[email protected]02965c22013-03-09 02:40:072225 GL_TEXTURE_EXTERNAL_OES);
[email protected]370eaf12013-05-18 09:19:492226 state_.texture_units[tt].bound_texture_external_oes = ref;
2227 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref->service_id());
[email protected]61eeb33f2011-07-26 15:30:312228 }
[email protected]62e155e2012-10-23 22:43:152229 if (features().arb_texture_rectangle) {
[email protected]370eaf12013-05-18 09:19:492230 ref = texture_manager()->GetDefaultTextureInfo(
[email protected]02965c22013-03-09 02:40:072231 GL_TEXTURE_RECTANGLE_ARB);
[email protected]370eaf12013-05-18 09:19:492232 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2233 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref->service_id());
[email protected]e51bdf32011-11-23 22:21:462234 }
[email protected]370eaf12013-05-18 09:19:492235 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2236 state_.texture_units[tt].bound_texture_cube_map = ref;
2237 glBindTexture(GL_TEXTURE_CUBE_MAP, ref->service_id());
2238 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2239 state_.texture_units[tt].bound_texture_2d = ref;
2240 glBindTexture(GL_TEXTURE_2D, ref->service_id());
[email protected]1958e0e2010-04-22 05:17:152241 }
[email protected]00f893d2010-08-24 18:55:492242 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:502243 CHECK_GL_ERROR();
2244
[email protected]763eaf72013-08-16 00:58:562245 ContextCreationAttribHelper attrib_parser;
[email protected]297ca1c2011-06-20 23:08:462246 if (!attrib_parser.Parse(attribs))
2247 return false;
[email protected]41c56362011-06-14 16:47:432248
[email protected]069944672012-04-25 20:52:232249 if (offscreen) {
[email protected]34ff8b0c2010-10-01 20:06:022250 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]b0609652012-12-14 07:24:542251 features().chromium_framebuffer_multisample) {
[email protected]34ff8b0c2010-10-01 20:06:022252 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:432253 // max_sample_count must be initialized to a sane value. If
2254 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2255 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:022256 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2257 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2258 max_sample_count);
2259 } else {
2260 offscreen_target_samples_ = 1;
2261 }
[email protected]8a61d872012-01-20 12:43:562262 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
[email protected]34ff8b0c2010-10-01 20:06:022263
2264 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2265 const bool rgb8_supported =
2266 context_->HasExtension("GL_OES_rgb8_rgba8");
2267 // The only available default render buffer formats in GLES2 have very
2268 // little precision. Don't enable multisampling unless 8-bit render
2269 // buffer formats are available--instead fall back to 8-bit textures.
2270 if (rgb8_supported && offscreen_target_samples_ > 1) {
2271 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2272 GL_RGBA8 : GL_RGB8;
2273 } else {
2274 offscreen_target_samples_ = 1;
2275 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2276 GL_RGBA : GL_RGB;
2277 }
2278
2279 // ANGLE only supports packed depth/stencil formats, so use it if it is
2280 // available.
2281 const bool depth24_stencil8_supported =
2282 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272283 VLOG(1) << "GL_OES_packed_depth_stencil "
2284 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:002285 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2286 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022287 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2288 offscreen_target_stencil_format_ = 0;
2289 } else {
2290 // It may be the case that this depth/stencil combination is not
2291 // supported, but this will be checked later by CheckFramebufferStatus.
2292 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2293 GL_DEPTH_COMPONENT16 : 0;
2294 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2295 GL_STENCIL_INDEX8 : 0;
2296 }
2297 } else {
2298 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2299 GL_RGBA : GL_RGB;
2300
2301 // If depth is requested at all, use the packed depth stencil format if
2302 // it's available, as some desktop GL drivers don't support any non-packed
2303 // formats for depth attachments.
2304 const bool depth24_stencil8_supported =
2305 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272306 VLOG(1) << "GL_EXT_packed_depth_stencil "
2307 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:022308
[email protected]71ee3642010-10-14 18:08:002309 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2310 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022311 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2312 offscreen_target_stencil_format_ = 0;
2313 } else {
2314 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2315 GL_DEPTH_COMPONENT : 0;
2316 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2317 GL_STENCIL_INDEX : 0;
2318 }
2319 }
2320
[email protected]97872062010-11-03 19:07:052321 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2322 GL_RGBA : GL_RGB;
2323
[email protected]6217d392010-03-25 22:08:352324 // Create the target frame buffer. This is the one that the client renders
2325 // directly to.
[email protected]ed9f9cd2013-02-27 21:12:352326 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
[email protected]6217d392010-03-25 22:08:352327 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022328 // Due to GLES2 format limitations, either the color texture (for
2329 // non-multisampling) or the color render buffer (for multisampling) will be
2330 // attached to the offscreen frame buffer. The render buffer has more
2331 // limited formats available to it, but the texture can't do multisampling.
2332 if (IsOffscreenBufferMultisampled()) {
[email protected]d5a28e452013-10-10 01:01:402333 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2334 renderbuffer_manager(), memory_tracker(), &state_));
[email protected]34ff8b0c2010-10-01 20:06:022335 offscreen_target_color_render_buffer_->Create();
2336 } else {
[email protected]ed9f9cd2013-02-27 21:12:352337 offscreen_target_color_texture_.reset(new BackTexture(this));
[email protected]34ff8b0c2010-10-01 20:06:022338 offscreen_target_color_texture_->Create();
2339 }
[email protected]d5a28e452013-10-10 01:01:402340 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2341 renderbuffer_manager(), memory_tracker(), &state_));
[email protected]b9363b22010-06-09 22:06:152342 offscreen_target_depth_render_buffer_->Create();
[email protected]d5a28e452013-10-10 01:01:402343 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2344 renderbuffer_manager(), memory_tracker(), &state_));
[email protected]b9363b22010-06-09 22:06:152345 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:352346
2347 // Create the saved offscreen texture. The target frame buffer is copied
2348 // here when SwapBuffers is called.
[email protected]ed9f9cd2013-02-27 21:12:352349 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
[email protected]34ff8b0c2010-10-01 20:06:022350 offscreen_saved_frame_buffer_->Create();
2351 //
[email protected]ed9f9cd2013-02-27 21:12:352352 offscreen_saved_color_texture_.reset(new BackTexture(this));
[email protected]6217d392010-03-25 22:08:352353 offscreen_saved_color_texture_->Create();
2354
[email protected]6217d392010-03-25 22:08:352355 // Allocate the render buffers at their initial size and check the status
2356 // of the frame buffers is okay.
[email protected]799b4b22011-08-22 17:09:592357 if (!ResizeOffscreenFrameBuffer(size)) {
[email protected]d0498742010-09-20 20:27:012358 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]63c9b052012-05-17 18:27:382359 Destroy(true);
[email protected]6217d392010-03-25 22:08:352360 return false;
2361 }
2362
[email protected]678a73f2012-12-19 19:22:092363 // Allocate the offscreen saved color texture.
2364 DCHECK(offscreen_saved_color_format_);
2365 offscreen_saved_color_texture_->AllocateStorage(
2366 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2367
2368 offscreen_saved_frame_buffer_->AttachRenderTexture(
2369 offscreen_saved_color_texture_.get());
2370 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2371 GL_FRAMEBUFFER_COMPLETE) {
2372 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2373 Destroy(true);
2374 return false;
2375 }
2376
[email protected]6217d392010-03-25 22:08:352377 // Bind to the new default frame buffer (the offscreen target frame buffer).
2378 // This should now be associated with ID zero.
2379 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
[email protected]62e65f02013-05-29 22:28:102380 } else {
2381 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2382 // These are NOT if the back buffer has these proprorties. They are
2383 // if we want the command buffer to enforce them regardless of what
2384 // the real backbuffer is assuming the real back buffer gives us more than
2385 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2386 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2387 // can't do anything about that.
2388
2389 GLint v = 0;
2390 glGetIntegerv(GL_ALPHA_BITS, &v);
2391 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2392 // user requested RGB then RGB. If the user did not specify a preference
2393 // than use whatever we were given. Same for DEPTH and STENCIL.
2394 back_buffer_color_format_ =
2395 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2396 glGetIntegerv(GL_DEPTH_BITS, &v);
2397 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2398 glGetIntegerv(GL_STENCIL_BITS, &v);
2399 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
[email protected]6217d392010-03-25 22:08:352400 }
2401
[email protected]76a0ee102010-04-07 21:03:042402 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2403 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2404 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372405 // mailing list archives. It also implicitly enables the desktop GL
2406 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2407 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152408 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2409 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372410 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152411 }
[email protected]de17df392010-04-23 21:09:412412
[email protected]706b69f2012-07-27 04:59:302413 has_robustness_extension_ =
2414 context->HasExtension("GL_ARB_robustness") ||
2415 context->HasExtension("GL_EXT_robustness");
[email protected]38d139d2011-07-14 00:38:432416
[email protected]c2f8c8402010-12-06 18:07:242417 if (!InitializeShaderTranslator()) {
2418 return false;
[email protected]de17df392010-04-23 21:09:412419 }
[email protected]76a0ee102010-04-07 21:03:042420
[email protected]e259eb412012-10-13 05:47:242421 state_.viewport_width = size.width();
2422 state_.viewport_height = size.height();
[email protected]43410e92012-04-20 17:06:282423
[email protected]5904806b2012-05-08 18:10:222424 GLint viewport_params[4] = { 0 };
[email protected]43410e92012-04-20 17:06:282425 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
[email protected]1868a342012-11-07 15:56:022426 viewport_max_width_ = viewport_params[0];
2427 viewport_max_height_ = viewport_params[1];
[email protected]43410e92012-04-20 17:06:282428
[email protected]88a61bf2012-10-27 13:00:422429 state_.scissor_width = state_.viewport_width;
2430 state_.scissor_height = state_.viewport_height;
2431
[email protected]11f3e702012-06-19 19:00:012432 // Set all the default state because some GL drivers get it wrong.
[email protected]f731b9462012-10-30 00:35:222433 state_.InitCapabilities();
2434 state_.InitState();
[email protected]e259eb412012-10-13 05:47:242435 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
[email protected]11f3e702012-06-19 19:00:012436
2437 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2438 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2439 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2440 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2441
[email protected]88cfd132013-07-11 00:59:002442 bool call_gl_clear = true;
2443#if defined(OS_ANDROID)
2444 // Temporary workaround for Android WebView because this clear ignores the
2445 // clip and corrupts that external UI of the App. Not calling glClear is ok
2446 // because the system already clears the buffer before each draw. Proper
2447 // fix might be setting the scissor clip properly before initialize. See
2448 // crbug.com/259023 for details.
2449 call_gl_clear = surface_->GetHandle();
2450#endif
2451 if (call_gl_clear) {
2452 // Clear the backbuffer.
2453 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2454 }
[email protected]561cc0a62013-05-07 18:34:452455
[email protected]62e155e2012-10-23 22:43:152456 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
[email protected]dd289a5d62012-06-30 22:05:462457 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2458 }
[email protected]dd289a5d62012-06-30 22:05:462459
[email protected]9b753992013-04-27 02:04:412460 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2461 context_->SetUnbindFboOnMakeCurrent();
[email protected]85cb4682013-04-20 00:54:242462 }
[email protected]85cb4682013-04-20 00:54:242463
[email protected]97419c02013-04-10 02:52:382464 // Only compositor contexts are known to use only the subset of GL
2465 // that can be safely migrated between the iGPU and the dGPU. Mark
2466 // those contexts as safe to forcibly transition between the GPUs.
2467 // http://crbug.com/180876, http://crbug.com/227228
2468 if (!offscreen)
2469 context_->SetSafeToForceGpuSwitch();
2470
[email protected]85a4ac22013-05-31 01:58:472471 async_pixel_transfer_manager_.reset(
[email protected]498b5c072013-06-04 19:30:072472 AsyncPixelTransferManager::Create(context.get()));
2473 async_pixel_transfer_manager_->Initialize(texture_manager());
[email protected]32145a92012-12-17 09:01:592474
[email protected]246a70452010-03-05 21:53:502475 return true;
[email protected]96449d2c2009-11-25 00:01:322476}
2477
[email protected]302ce6d2011-07-07 23:28:112478void GLES2DecoderImpl::UpdateCapabilities() {
2479 util_.set_num_compressed_texture_formats(
2480 validators_->compressed_texture_format.GetValues().size());
2481 util_.set_num_shader_binary_formats(
2482 validators_->shader_binary_format.GetValues().size());
2483}
2484
[email protected]c2f8c8402010-12-06 18:07:242485bool GLES2DecoderImpl::InitializeShaderTranslator() {
[email protected]a5d3dad2012-05-26 04:34:442486 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2487
[email protected]c2f8c8402010-12-06 18:07:242488 if (!use_shader_translator_) {
2489 return true;
2490 }
2491 ShBuiltInResources resources;
2492 ShInitBuiltInResources(&resources);
2493 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2494 resources.MaxVertexUniformVectors =
2495 group_->max_vertex_uniform_vectors();
2496 resources.MaxVaryingVectors = group_->max_varying_vectors();
2497 resources.MaxVertexTextureImageUnits =
2498 group_->max_vertex_texture_image_units();
2499 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2500 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2501 resources.MaxFragmentUniformVectors =
2502 group_->max_fragment_uniform_vectors();
[email protected]2f143d482013-03-14 18:04:492503 resources.MaxDrawBuffers = group_->max_draw_buffers();
[email protected]a0b78142013-05-23 00:47:242504 resources.MaxExpressionComplexity = 256;
2505 resources.MaxCallStackDepth = 256;
[email protected]f0d74742011-10-03 16:31:042506
[email protected]9e98f61b2013-03-05 02:21:142507#if (ANGLE_SH_VERSION >= 110)
[email protected]46c86752013-05-21 05:08:392508 GLint range[2] = { 0, 0 };
[email protected]8dc1bf92013-03-12 03:58:212509 GLint precision = 0;
2510 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2511 range, &precision);
[email protected]448e459e2013-06-12 17:00:412512 resources.FragmentPrecisionHigh =
2513 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
[email protected]9e98f61b2013-03-05 02:21:142514#endif
2515
[email protected]f0d74742011-10-03 16:31:042516 if (force_webgl_glsl_validation_) {
2517 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
[email protected]70dc60932013-06-04 03:33:492518 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
[email protected]aff39ac82013-06-08 04:53:132519 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
[email protected]cd8f1892013-09-05 00:14:442520 if (!draw_buffers_explicitly_enabled_)
2521 resources.MaxDrawBuffers = 1;
[email protected]f0d74742011-10-03 16:31:042522 } else {
2523 resources.OES_standard_derivatives =
[email protected]62e155e2012-10-23 22:43:152524 features().oes_standard_derivatives ? 1 : 0;
[email protected]e51bdf32011-11-23 22:21:462525 resources.ARB_texture_rectangle =
[email protected]62e155e2012-10-23 22:43:152526 features().arb_texture_rectangle ? 1 : 0;
[email protected]70e7bb12012-09-29 14:01:062527 resources.OES_EGL_image_external =
[email protected]62e155e2012-10-23 22:43:152528 features().oes_egl_image_external ? 1 : 0;
[email protected]2f143d482013-03-14 18:04:492529 resources.EXT_draw_buffers =
2530 features().ext_draw_buffers ? 1 : 0;
[email protected]70dc60932013-06-04 03:33:492531 resources.EXT_frag_depth =
2532 features().ext_frag_depth ? 1 : 0;
[email protected]f0d74742011-10-03 16:31:042533 }
2534
[email protected]26b61442013-03-17 16:12:012535 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2536 : SH_GLES2_SPEC;
[email protected]6aedcdc2013-01-24 01:25:052537 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
[email protected]3d944a82013-02-12 19:09:022538#if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
[email protected]6aedcdc2013-01-24 01:25:052539 resources.HashFunction = &CityHashForAngle;
[email protected]3d944a82013-02-12 19:09:022540#else
2541 resources.HashFunction = &CityHash64;
2542#endif
[email protected]6aedcdc2013-01-24 01:25:052543 else
2544 resources.HashFunction = NULL;
[email protected]a2a0fe762011-09-20 00:59:122545 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2546 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2547 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
[email protected]a6739bc2013-09-07 04:45:212548 int driver_bug_workarounds = 0;
2549 if (workarounds().needs_glsl_built_in_function_emulation)
2550 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
[email protected]81187c62013-09-09 23:54:542551 if (workarounds().init_gl_position_in_vertex_shader)
2552 driver_bug_workarounds |= SH_INIT_GL_POSITION;
[email protected]87fb6ab2012-06-13 22:28:042553
2554 ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
2555 vertex_translator_ = cache->GetTranslator(
2556 SH_VERTEX_SHADER, shader_spec, &resources,
[email protected]a6739bc2013-09-07 04:45:212557 implementation_type,
2558 static_cast<ShCompileOptions>(driver_bug_workarounds));
[email protected]87fb6ab2012-06-13 22:28:042559 if (!vertex_translator_.get()) {
[email protected]c2f8c8402010-12-06 18:07:242560 LOG(ERROR) << "Could not initialize vertex shader translator.";
[email protected]63c9b052012-05-17 18:27:382561 Destroy(true);
[email protected]c2f8c8402010-12-06 18:07:242562 return false;
2563 }
[email protected]87fb6ab2012-06-13 22:28:042564
2565 fragment_translator_ = cache->GetTranslator(
2566 SH_FRAGMENT_SHADER, shader_spec, &resources,
[email protected]a6739bc2013-09-07 04:45:212567 implementation_type,
2568 static_cast<ShCompileOptions>(driver_bug_workarounds));
[email protected]87fb6ab2012-06-13 22:28:042569 if (!fragment_translator_.get()) {
[email protected]c2f8c8402010-12-06 18:07:242570 LOG(ERROR) << "Could not initialize fragment shader translator.";
[email protected]63c9b052012-05-17 18:27:382571 Destroy(true);
[email protected]c2f8c8402010-12-06 18:07:242572 return false;
2573 }
2574 return true;
2575}
2576
[email protected]ae51d192010-04-27 00:48:032577bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472578 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352579 if (GetBuffer(client_ids[ii])) {
[email protected]ae51d192010-04-27 00:48:032580 return false;
2581 }
2582 }
[email protected]40d90a22013-04-09 03:39:552583 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ae51d192010-04-27 00:48:032584 glGenBuffersARB(n, service_ids.get());
2585 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352586 CreateBuffer(client_ids[ii], service_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032587 }
2588 return true;
2589}
2590
2591bool GLES2DecoderImpl::GenFramebuffersHelper(
2592 GLsizei n, const GLuint* client_ids) {
2593 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352594 if (GetFramebuffer(client_ids[ii])) {
[email protected]ae51d192010-04-27 00:48:032595 return false;
2596 }
2597 }
[email protected]40d90a22013-04-09 03:39:552598 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ae51d192010-04-27 00:48:032599 glGenFramebuffersEXT(n, service_ids.get());
2600 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352601 CreateFramebuffer(client_ids[ii], service_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032602 }
2603 return true;
2604}
2605
2606bool GLES2DecoderImpl::GenRenderbuffersHelper(
2607 GLsizei n, const GLuint* client_ids) {
2608 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352609 if (GetRenderbuffer(client_ids[ii])) {
[email protected]ae51d192010-04-27 00:48:032610 return false;
2611 }
2612 }
[email protected]40d90a22013-04-09 03:39:552613 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ae51d192010-04-27 00:48:032614 glGenRenderbuffersEXT(n, service_ids.get());
2615 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352616 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032617 }
2618 return true;
2619}
2620
2621bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2622 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352623 if (GetTexture(client_ids[ii])) {
[email protected]ae51d192010-04-27 00:48:032624 return false;
2625 }
2626 }
[email protected]40d90a22013-04-09 03:39:552627 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ae51d192010-04-27 00:48:032628 glGenTextures(n, service_ids.get());
2629 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352630 CreateTexture(client_ids[ii], service_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032631 }
2632 return true;
2633}
2634
2635void GLES2DecoderImpl::DeleteBuffersHelper(
2636 GLsizei n, const GLuint* client_ids) {
2637 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]16ccec12013-02-28 03:40:212638 Buffer* buffer = GetBuffer(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102639 if (buffer && !buffer->IsDeleted()) {
[email protected]e259eb412012-10-13 05:47:242640 state_.vertex_attrib_manager->Unbind(buffer);
[email protected]7cd76fd2013-06-02 21:11:112641 if (state_.bound_array_buffer.get() == buffer) {
[email protected]e259eb412012-10-13 05:47:242642 state_.bound_array_buffer = NULL;
[email protected]a0b78dc2011-11-11 10:43:102643 }
[email protected]ed9f9cd2013-02-27 21:12:352644 RemoveBuffer(client_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032645 }
[email protected]a93bb842010-02-16 23:03:472646 }
[email protected]07f54fcc2009-12-22 02:46:302647}
2648
[email protected]ae51d192010-04-27 00:48:032649void GLES2DecoderImpl::DeleteFramebuffersHelper(
2650 GLsizei n, const GLuint* client_ids) {
[email protected]ebfb73c2012-08-15 02:37:452651 bool supports_separate_framebuffer_binds =
[email protected]62e155e2012-10-23 22:43:152652 features().chromium_framebuffer_multisample;
[email protected]b177ae22011-11-01 03:29:112653
[email protected]a25fa872010-03-25 02:57:582654 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352655 Framebuffer* framebuffer =
2656 GetFramebuffer(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102657 if (framebuffer && !framebuffer->IsDeleted()) {
[email protected]9d3b2e12013-10-02 01:04:342658 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
2659 framebuffer_state_.bound_draw_framebuffer = NULL;
[email protected]c986af502013-08-14 01:04:442660 framebuffer_state_.clear_state_dirty = true;
[email protected]ebfb73c2012-08-15 02:37:452661 GLenum target = supports_separate_framebuffer_binds ?
2662 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
[email protected]b177ae22011-11-01 03:29:112663 glBindFramebufferEXT(target, GetBackbufferServiceId());
2664 }
[email protected]9d3b2e12013-10-02 01:04:342665 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
2666 framebuffer_state_.bound_read_framebuffer = NULL;
[email protected]ebfb73c2012-08-15 02:37:452667 GLenum target = supports_separate_framebuffer_binds ?
2668 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
[email protected]b177ae22011-11-01 03:29:112669 glBindFramebufferEXT(target, GetBackbufferServiceId());
[email protected]297ca1c2011-06-20 23:08:462670 }
[email protected]70d34263c2013-01-09 00:27:452671 OnFboChanged();
[email protected]ed9f9cd2013-02-27 21:12:352672 RemoveFramebuffer(client_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032673 }
[email protected]a25fa872010-03-25 02:57:582674 }
[email protected]07f54fcc2009-12-22 02:46:302675}
2676
[email protected]ae51d192010-04-27 00:48:032677void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2678 GLsizei n, const GLuint* client_ids) {
[email protected]ebfb73c2012-08-15 02:37:452679 bool supports_separate_framebuffer_binds =
[email protected]62e155e2012-10-23 22:43:152680 features().chromium_framebuffer_multisample;
[email protected]a25fa872010-03-25 02:57:582681 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352682 Renderbuffer* renderbuffer =
2683 GetRenderbuffer(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102684 if (renderbuffer && !renderbuffer->IsDeleted()) {
[email protected]7cd76fd2013-06-02 21:11:112685 if (state_.bound_renderbuffer.get() == renderbuffer) {
[email protected]e259eb412012-10-13 05:47:242686 state_.bound_renderbuffer = NULL;
[email protected]a0b78dc2011-11-11 10:43:102687 }
2688 // Unbind from current framebuffers.
[email protected]ebfb73c2012-08-15 02:37:452689 if (supports_separate_framebuffer_binds) {
[email protected]9d3b2e12013-10-02 01:04:342690 if (framebuffer_state_.bound_read_framebuffer.get()) {
2691 framebuffer_state_.bound_read_framebuffer
[email protected]7cd76fd2013-06-02 21:11:112692 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
[email protected]a0b78dc2011-11-11 10:43:102693 }
[email protected]9d3b2e12013-10-02 01:04:342694 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2695 framebuffer_state_.bound_draw_framebuffer
[email protected]7cd76fd2013-06-02 21:11:112696 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
[email protected]a0b78dc2011-11-11 10:43:102697 }
2698 } else {
[email protected]9d3b2e12013-10-02 01:04:342699 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2700 framebuffer_state_.bound_draw_framebuffer
[email protected]7cd76fd2013-06-02 21:11:112701 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
[email protected]a0b78dc2011-11-11 10:43:102702 }
2703 }
[email protected]c986af502013-08-14 01:04:442704 framebuffer_state_.clear_state_dirty = true;
[email protected]ed9f9cd2013-02-27 21:12:352705 RemoveRenderbuffer(client_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032706 }
[email protected]a25fa872010-03-25 02:57:582707 }
[email protected]07f54fcc2009-12-22 02:46:302708}
2709
[email protected]ae51d192010-04-27 00:48:032710void GLES2DecoderImpl::DeleteTexturesHelper(
2711 GLsizei n, const GLuint* client_ids) {
[email protected]ebfb73c2012-08-15 02:37:452712 bool supports_separate_framebuffer_binds =
[email protected]62e155e2012-10-23 22:43:152713 features().chromium_framebuffer_multisample;
[email protected]a93bb842010-02-16 23:03:472714 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]370eaf12013-05-18 09:19:492715 TextureRef* texture_ref = GetTexture(client_ids[ii]);
2716 if (texture_ref) {
2717 Texture* texture = texture_ref->texture();
[email protected]a0b78dc2011-11-11 10:43:102718 if (texture->IsAttachedToFramebuffer()) {
[email protected]c986af502013-08-14 01:04:442719 framebuffer_state_.clear_state_dirty = true;
[email protected]297ca1c2011-06-20 23:08:462720 }
[email protected]370eaf12013-05-18 09:19:492721 // Unbind texture_ref from texture_ref units.
[email protected]1868a342012-11-07 15:56:022722 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
[email protected]370eaf12013-05-18 09:19:492723 state_.texture_units[jj].Unbind(texture_ref);
[email protected]a0b78dc2011-11-11 10:43:102724 }
2725 // Unbind from current framebuffers.
[email protected]ebfb73c2012-08-15 02:37:452726 if (supports_separate_framebuffer_binds) {
[email protected]9d3b2e12013-10-02 01:04:342727 if (framebuffer_state_.bound_read_framebuffer.get()) {
2728 framebuffer_state_.bound_read_framebuffer
[email protected]7cd76fd2013-06-02 21:11:112729 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
[email protected]a0b78dc2011-11-11 10:43:102730 }
[email protected]9d3b2e12013-10-02 01:04:342731 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2732 framebuffer_state_.bound_draw_framebuffer
[email protected]7cd76fd2013-06-02 21:11:112733 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
[email protected]a0b78dc2011-11-11 10:43:102734 }
2735 } else {
[email protected]9d3b2e12013-10-02 01:04:342736 if (framebuffer_state_.bound_draw_framebuffer.get()) {
2737 framebuffer_state_.bound_draw_framebuffer
[email protected]7cd76fd2013-06-02 21:11:112738 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
[email protected]a0b78dc2011-11-11 10:43:102739 }
2740 }
[email protected]e51bdf32011-11-23 22:21:462741#if defined(OS_MACOSX)
[email protected]4f9958142013-07-02 03:58:072742 GLuint service_id = texture->service_id();
[email protected]e51bdf32011-11-23 22:21:462743 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2744 ReleaseIOSurfaceForTexture(service_id);
2745 }
2746#endif
[email protected]ed9f9cd2013-02-27 21:12:352747 RemoveTexture(client_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032748 }
[email protected]a93bb842010-02-16 23:03:472749 }
[email protected]07f54fcc2009-12-22 02:46:302750}
2751
[email protected]43f28f832010-02-03 02:28:482752// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322753
[email protected]eb54a562010-01-20 21:55:182754bool GLES2DecoderImpl::MakeCurrent() {
[email protected]63c9b052012-05-17 18:27:382755 if (!context_.get() || !context_->MakeCurrent(surface_.get()))
2756 return false;
2757
2758 if (WasContextLost()) {
[email protected]38d139d2011-07-14 00:38:432759 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
[email protected]e9f0ca82013-04-01 23:52:292760
2761 // Some D3D drivers cannot recover from device lost in the GPU process
2762 // sandbox. Allow a new GPU process to launch.
2763 if (workarounds().exit_on_context_lost) {
2764 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
2765 << " a D3D device in the Chrome GPU process sandbox.";
[email protected]6eb775352013-08-27 05:57:162766#if defined(OS_WIN)
2767 base::win::SetShouldCrashOnProcessDetach(false);
2768#endif
[email protected]e9f0ca82013-04-01 23:52:292769 exit(0);
2770 }
2771
[email protected]63c9b052012-05-17 18:27:382772 return false;
[email protected]38d139d2011-07-14 00:38:432773 }
2774
[email protected]69a8701e2013-03-07 21:31:092775 ProcessFinishedAsyncTransfers();
[email protected]69a8701e2013-03-07 21:31:092776
[email protected]9b753992013-04-27 02:04:412777 // Rebind the FBO if it was unbound by the context.
2778 if (workarounds().unbind_fbo_on_context_switch)
2779 RestoreFramebufferBindings();
2780
[email protected]c986af502013-08-14 01:04:442781 framebuffer_state_.clear_state_dirty = true;
[email protected]370eaf12013-05-18 09:19:492782
[email protected]69a8701e2013-03-07 21:31:092783 return true;
2784}
2785
2786void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
[email protected]5a36dc132013-07-23 23:17:552787 ProcessPendingReadPixels();
[email protected]fe8d73c2013-02-16 22:37:322788 if (engine() && query_manager_.get())
2789 query_manager_->ProcessPendingTransferQueries();
2790
[email protected]5b3a8e02013-03-13 05:36:442791 // TODO(epenner): Is there a better place to do this?
2792 // This needs to occur before we execute any batch of commands
2793 // from the client, as the client may have recieved an async
2794 // completion while issuing those commands.
2795 // "DidFlushStart" would be ideal if we had such a callback.
[email protected]b68b100752013-06-05 08:34:482796 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
[email protected]eb54a562010-01-20 21:55:182797}
2798
[email protected]a96a6022011-11-04 00:58:122799void GLES2DecoderImpl::ReleaseCurrent() {
2800 if (context_.get())
2801 context_->ReleaseCurrent(surface_.get());
2802}
2803
[email protected]8e3e0662010-08-23 18:46:302804static void RebindCurrentFramebuffer(
2805 GLenum target,
[email protected]4d8f0dd2013-03-09 14:37:062806 Framebuffer* framebuffer,
[email protected]a3783712012-01-20 22:18:242807 GLuint back_buffer_service_id) {
[email protected]4d8f0dd2013-03-09 14:37:062808 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462809
[email protected]a3783712012-01-20 22:18:242810 if (framebuffer_id == 0) {
2811 framebuffer_id = back_buffer_service_id;
[email protected]8e3e0662010-08-23 18:46:302812 }
[email protected]297ca1c2011-06-20 23:08:462813
[email protected]8e3e0662010-08-23 18:46:302814 glBindFramebufferEXT(target, framebuffer_id);
2815}
2816
2817void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]c986af502013-08-14 01:04:442818 framebuffer_state_.clear_state_dirty = true;
[email protected]297ca1c2011-06-20 23:08:462819
[email protected]62e155e2012-10-23 22:43:152820 if (!features().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302821 RebindCurrentFramebuffer(
2822 GL_FRAMEBUFFER,
[email protected]9d3b2e12013-10-02 01:04:342823 framebuffer_state_.bound_draw_framebuffer.get(),
[email protected]a3783712012-01-20 22:18:242824 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302825 } else {
2826 RebindCurrentFramebuffer(
2827 GL_READ_FRAMEBUFFER_EXT,
[email protected]9d3b2e12013-10-02 01:04:342828 framebuffer_state_.bound_read_framebuffer.get(),
[email protected]a3783712012-01-20 22:18:242829 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302830 RebindCurrentFramebuffer(
2831 GL_DRAW_FRAMEBUFFER_EXT,
[email protected]9d3b2e12013-10-02 01:04:342832 framebuffer_state_.bound_draw_framebuffer.get(),
[email protected]a3783712012-01-20 22:18:242833 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302834 }
[email protected]70d34263c2013-01-09 00:27:452835 OnFboChanged();
[email protected]8e3e0662010-08-23 18:46:302836}
2837
2838void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
[email protected]e259eb412012-10-13 05:47:242839 TextureUnit& info = state_.texture_units[0];
[email protected]8e3e0662010-08-23 18:46:302840 GLuint last_id;
[email protected]7cd76fd2013-06-02 21:11:112841 if (info.bound_texture_2d.get()) {
[email protected]8e3e0662010-08-23 18:46:302842 last_id = info.bound_texture_2d->service_id();
2843 } else {
2844 last_id = 0;
2845 }
2846
2847 glBindTexture(GL_TEXTURE_2D, last_id);
[email protected]e259eb412012-10-13 05:47:242848 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
[email protected]8e3e0662010-08-23 18:46:302849}
2850
[email protected]0d6bfdc2011-11-02 01:32:202851bool GLES2DecoderImpl::CheckFramebufferValid(
[email protected]ed9f9cd2013-02-27 21:12:352852 Framebuffer* framebuffer,
[email protected]0d6bfdc2011-11-02 01:32:202853 GLenum target, const char* func_name) {
[email protected]a0b78dc2011-11-11 10:43:102854 if (!framebuffer) {
[email protected]60f22d32012-12-12 00:31:582855 if (backbuffer_needs_clear_bits_) {
2856 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2857 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
2858 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2859 glClearStencil(0);
2860 glStencilMask(-1);
2861 glClearDepth(1.0f);
2862 glDepthMask(true);
2863 glDisable(GL_SCISSOR_TEST);
2864 glClear(backbuffer_needs_clear_bits_);
2865 backbuffer_needs_clear_bits_ = 0;
2866 RestoreClearState();
2867 }
[email protected]0d6bfdc2011-11-02 01:32:202868 return true;
2869 }
2870
[email protected]968351b2011-12-20 08:26:512871 if (framebuffer_manager()->IsComplete(framebuffer)) {
2872 return true;
2873 }
2874
[email protected]0d6bfdc2011-11-02 01:32:202875 GLenum completeness = framebuffer->IsPossiblyComplete();
2876 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
[email protected]ab09b612013-03-11 22:11:512877 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:432878 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
[email protected]3a03a8f2011-03-19 00:51:272879 return false;
2880 }
[email protected]0d6bfdc2011-11-02 01:32:202881
2882 // Are all the attachments cleared?
2883 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2884 texture_manager()->HaveUnclearedMips()) {
2885 if (!framebuffer->IsCleared()) {
2886 // Can we clear them?
[email protected]73276522012-11-09 05:50:202887 if (framebuffer->GetStatus(texture_manager(), target) !=
2888 GL_FRAMEBUFFER_COMPLETE) {
[email protected]ab09b612013-03-11 22:11:512889 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:432890 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2891 "framebuffer incomplete (clear)");
[email protected]0d6bfdc2011-11-02 01:32:202892 return false;
2893 }
2894 ClearUnclearedAttachments(target, framebuffer);
2895 }
2896 }
2897
[email protected]968351b2011-12-20 08:26:512898 if (!framebuffer_manager()->IsComplete(framebuffer)) {
[email protected]73276522012-11-09 05:50:202899 if (framebuffer->GetStatus(texture_manager(), target) !=
2900 GL_FRAMEBUFFER_COMPLETE) {
[email protected]ab09b612013-03-11 22:11:512901 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:432902 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2903 "framebuffer incomplete (check)");
[email protected]968351b2011-12-20 08:26:512904 return false;
2905 }
2906 framebuffer_manager()->MarkAsComplete(framebuffer);
2907 }
2908
[email protected]0d6bfdc2011-11-02 01:32:202909 // NOTE: At this point we don't know if the framebuffer is complete but
2910 // we DO know that everything that needs to be cleared has been cleared.
[email protected]3a03a8f2011-03-19 00:51:272911 return true;
2912}
2913
[email protected]0d6bfdc2011-11-02 01:32:202914bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
[email protected]62e155e2012-10-23 22:43:152915 if (!features().chromium_framebuffer_multisample) {
[email protected]28718a92013-04-04 12:12:512916 bool valid = CheckFramebufferValid(
[email protected]9d3b2e12013-10-02 01:04:342917 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
2918 func_name);
[email protected]28718a92013-04-04 12:12:512919
2920 if (valid)
2921 OnUseFramebuffer();
2922
2923 return valid;
[email protected]0d6bfdc2011-11-02 01:32:202924 }
[email protected]9d3b2e12013-10-02 01:04:342925 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
[email protected]7cd76fd2013-06-02 21:11:112926 GL_DRAW_FRAMEBUFFER_EXT,
2927 func_name) &&
[email protected]9d3b2e12013-10-02 01:04:342928 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
[email protected]7cd76fd2013-06-02 21:11:112929 GL_READ_FRAMEBUFFER_EXT,
2930 func_name);
[email protected]0d6bfdc2011-11-02 01:32:202931}
2932
[email protected]8e3e0662010-08-23 18:46:302933gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
[email protected]ed9f9cd2013-02-27 21:12:352934 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:452935 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:202936 if (framebuffer != NULL) {
[email protected]ed9f9cd2013-02-27 21:12:352937 const Framebuffer::Attachment* attachment =
[email protected]0d6bfdc2011-11-02 01:32:202938 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
[email protected]9edc6b22010-12-23 02:00:262939 if (attachment) {
2940 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502941 }
[email protected]9edc6b22010-12-23 02:00:262942 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022943 } else if (offscreen_target_frame_buffer_.get()) {
2944 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352945 } else {
[email protected]f62a5ab2011-05-23 20:34:152946 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022947 }
[email protected]246a70452010-03-05 21:53:502948}
2949
[email protected]9edc6b22010-12-23 02:00:262950GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
[email protected]ed9f9cd2013-02-27 21:12:352951 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:452952 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:202953 if (framebuffer != NULL) {
2954 return framebuffer->GetColorAttachmentFormat();
[email protected]297ca1c2011-06-20 23:08:462955 } else if (offscreen_target_frame_buffer_.get()) {
2956 return offscreen_target_color_format_;
2957 } else {
2958 return back_buffer_color_format_;
2959 }
2960}
2961
2962GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
[email protected]ed9f9cd2013-02-27 21:12:352963 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:452964 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:202965 if (framebuffer != NULL) {
2966 return framebuffer->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262967 } else if (offscreen_target_frame_buffer_.get()) {
2968 return offscreen_target_color_format_;
2969 } else {
[email protected]32fe9aa2011-01-21 23:47:132970 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262971 }
2972}
2973
[email protected]9a5afa432011-07-22 18:16:392974void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]2ad674132013-06-05 07:48:512975 if (!offscreen_saved_color_texture_info_.get())
2976 return;
2977 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
2978 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
2979 texture_manager()->SetLevelInfo(
2980 offscreen_saved_color_texture_info_.get(),
2981 GL_TEXTURE_2D,
2982 0, // level
2983 GL_RGBA,
2984 offscreen_size_.width(),
2985 offscreen_size_.height(),
2986 1, // depth
2987 0, // border
2988 GL_RGBA,
2989 GL_UNSIGNED_BYTE,
2990 true);
2991 texture_manager()->SetParameter(
2992 "UpdateParentTextureInfo",
2993 GetErrorState(),
2994 offscreen_saved_color_texture_info_.get(),
2995 GL_TEXTURE_MAG_FILTER,
2996 GL_NEAREST);
2997 texture_manager()->SetParameter(
2998 "UpdateParentTextureInfo",
2999 GetErrorState(),
3000 offscreen_saved_color_texture_info_.get(),
3001 GL_TEXTURE_MIN_FILTER,
3002 GL_NEAREST);
3003 texture_manager()->SetParameter(
3004 "UpdateParentTextureInfo",
3005 GetErrorState(),
3006 offscreen_saved_color_texture_info_.get(),
3007 GL_TEXTURE_WRAP_S,
3008 GL_CLAMP_TO_EDGE);
3009 texture_manager()->SetParameter(
3010 "UpdateParentTextureInfo",
3011 GetErrorState(),
3012 offscreen_saved_color_texture_info_.get(),
3013 GL_TEXTURE_WRAP_T,
3014 GL_CLAMP_TO_EDGE);
[email protected]c986af502013-08-14 01:04:443015 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3016 &state_, target);
[email protected]2ad674132013-06-05 07:48:513017 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
[email protected]6217d392010-03-25 22:08:353018}
3019
[email protected]799b4b22011-08-22 17:09:593020void GLES2DecoderImpl::SetResizeCallback(
[email protected]729c0b42013-05-26 02:05:073021 const base::Callback<void(gfx::Size, float)>& callback) {
[email protected]9d37f062011-11-22 01:24:523022 resize_callback_ = callback;
[email protected]7ff86b92010-11-25 17:50:003023}
3024
[email protected]1d82e822013-04-10 21:32:323025Logger* GLES2DecoderImpl::GetLogger() {
3026 return &logger_;
[email protected]6b6e7ee2011-12-13 08:04:523027}
3028
[email protected]d3eba342013-04-18 21:11:503029ErrorState* GLES2DecoderImpl::GetErrorState() {
3030 return state_.GetErrorState();
3031}
3032
[email protected]e3932abb2013-03-13 00:01:373033void GLES2DecoderImpl::SetShaderCacheCallback(
3034 const ShaderCacheCallback& callback) {
3035 shader_cache_callback_ = callback;
3036}
3037
[email protected]840a7e462013-02-27 01:29:513038void GLES2DecoderImpl::SetWaitSyncPointCallback(
3039 const WaitSyncPointCallback& callback) {
3040 wait_sync_point_callback_ = callback;
3041}
3042
[email protected]85a4ac22013-05-31 01:58:473043AsyncPixelTransferManager*
3044 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3045 return async_pixel_transfer_manager_.get();
3046}
3047
3048void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3049 async_pixel_transfer_manager_.reset();
[email protected]32145a92012-12-17 09:01:593050}
3051
[email protected]498b5c072013-06-04 19:30:073052void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3053 AsyncPixelTransferManager* manager) {
3054 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3055}
3056
[email protected]1318e922010-09-17 22:03:163057bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3058 uint32* service_texture_id) {
[email protected]370eaf12013-05-18 09:19:493059 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3060 if (texture_ref) {
3061 *service_texture_id = texture_ref->service_id();
[email protected]1318e922010-09-17 22:03:163062 return true;
3063 }
3064 return false;
3065}
3066
[email protected]63b465922012-09-06 02:04:523067uint32 GLES2DecoderImpl::GetTextureUploadCount() {
[email protected]c986af502013-08-14 01:04:443068 return texture_state_.texture_upload_count +
[email protected]b68b100752013-06-05 08:34:483069 async_pixel_transfer_manager_->GetTextureUploadCount();
[email protected]63b465922012-09-06 02:04:523070}
3071
3072base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
[email protected]c986af502013-08-14 01:04:443073 return texture_state_.total_texture_upload_time +
[email protected]b68b100752013-06-05 08:34:483074 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
[email protected]63b465922012-09-06 02:04:523075}
3076
3077base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3078 return total_processing_commands_time_;
3079}
3080
[email protected]dc25dda2012-09-27 21:36:303081void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3082 total_processing_commands_time_ += time;
3083}
3084
[email protected]63c9b052012-05-17 18:27:383085void GLES2DecoderImpl::Destroy(bool have_context) {
[email protected]55e136f2013-04-03 18:50:063086 if (!initialized())
3087 return;
3088
[email protected]63c9b052012-05-17 18:27:383089 DCHECK(!have_context || context_->IsCurrent(NULL));
[email protected]97872062010-11-03 19:07:053090
[email protected]80eb6b52012-01-19 00:14:413091 // Unbind everything.
[email protected]e259eb412012-10-13 05:47:243092 state_.vertex_attrib_manager = NULL;
[email protected]944b62f32012-09-27 02:20:463093 default_vertex_attrib_manager_ = NULL;
[email protected]1868a342012-11-07 15:56:023094 state_.texture_units.clear();
[email protected]e259eb412012-10-13 05:47:243095 state_.bound_array_buffer = NULL;
3096 state_.current_query = NULL;
[email protected]9d3b2e12013-10-02 01:04:343097 framebuffer_state_.bound_read_framebuffer = NULL;
3098 framebuffer_state_.bound_draw_framebuffer = NULL;
[email protected]e259eb412012-10-13 05:47:243099 state_.bound_renderbuffer = NULL;
[email protected]80eb6b52012-01-19 00:14:413100
[email protected]cadac622013-06-11 16:46:363101 if (offscreen_saved_color_texture_info_.get()) {
[email protected]2ad674132013-06-05 07:48:513102 DCHECK(offscreen_target_color_texture_);
3103 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3104 offscreen_saved_color_texture_->id());
3105 offscreen_saved_color_texture_->Invalidate();
3106 offscreen_saved_color_texture_info_ = NULL;
3107 }
[email protected]eadc96792010-10-27 19:39:393108 if (have_context) {
[email protected]c322e882012-05-23 18:06:183109 if (copy_texture_CHROMIUM_.get()) {
3110 copy_texture_CHROMIUM_->Destroy();
3111 copy_texture_CHROMIUM_.reset();
3112 }
[email protected]43410e92012-04-20 17:06:283113
[email protected]7cd76fd2013-06-02 21:11:113114 if (state_.current_program.get()) {
3115 program_manager()->UnuseProgram(shader_manager(),
3116 state_.current_program.get());
[email protected]ca488e12010-12-13 20:06:143117 }
3118
[email protected]b1122982010-05-17 23:04:243119 if (attrib_0_buffer_id_) {
3120 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3121 }
[email protected]8fbedc02010-11-18 18:43:403122 if (fixed_attrib_buffer_id_) {
3123 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3124 }
[email protected]b1122982010-05-17 23:04:243125
[email protected]4a4c18b2013-09-13 22:50:103126 if (validation_texture_) {
3127 glDeleteTextures(1, &validation_texture_);
3128 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3129 glDeleteFramebuffersEXT(1, &validation_fbo_);
3130 }
3131
[email protected]97872062010-11-03 19:07:053132 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:543133 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053134 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:543135 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:053136 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:023137 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053138 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:153139 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053140 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:153141 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053142 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:023143 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053144 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:543145 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:273146 if (offscreen_resolved_frame_buffer_.get())
3147 offscreen_resolved_frame_buffer_->Destroy();
3148 if (offscreen_resolved_color_texture_.get())
3149 offscreen_resolved_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:053150 } else {
3151 if (offscreen_target_frame_buffer_.get())
3152 offscreen_target_frame_buffer_->Invalidate();
3153 if (offscreen_target_color_texture_.get())
3154 offscreen_target_color_texture_->Invalidate();
3155 if (offscreen_target_color_render_buffer_.get())
3156 offscreen_target_color_render_buffer_->Invalidate();
3157 if (offscreen_target_depth_render_buffer_.get())
3158 offscreen_target_depth_render_buffer_->Invalidate();
3159 if (offscreen_target_stencil_render_buffer_.get())
3160 offscreen_target_stencil_render_buffer_->Invalidate();
3161 if (offscreen_saved_frame_buffer_.get())
3162 offscreen_saved_frame_buffer_->Invalidate();
3163 if (offscreen_saved_color_texture_.get())
3164 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:273165 if (offscreen_resolved_frame_buffer_.get())
3166 offscreen_resolved_frame_buffer_->Invalidate();
3167 if (offscreen_resolved_color_texture_.get())
3168 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:023169 }
[email protected]83a52d032013-07-24 10:30:373170
3171 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3172 // Otherwise, we can leak objects. http://crbug.com/258772.
3173 // state_.current_program must be reset before group_ is reset because
3174 // the later deletes the ProgramManager object that referred by
3175 // state_.current_program object.
3176 state_.current_program = NULL;
3177
[email protected]43410e92012-04-20 17:06:283178 copy_texture_CHROMIUM_.reset();
[email protected]97872062010-11-03 19:07:053179
[email protected]882ba1e22012-03-08 19:02:533180 if (query_manager_.get()) {
3181 query_manager_->Destroy(have_context);
3182 query_manager_.reset();
3183 }
3184
[email protected]944b62f32012-09-27 02:20:463185 if (vertex_array_manager_ .get()) {
3186 vertex_array_manager_->Destroy(have_context);
3187 vertex_array_manager_.reset();
3188 }
3189
[email protected]97872062010-11-03 19:07:053190 offscreen_target_frame_buffer_.reset();
3191 offscreen_target_color_texture_.reset();
3192 offscreen_target_color_render_buffer_.reset();
3193 offscreen_target_depth_render_buffer_.reset();
3194 offscreen_target_stencil_render_buffer_.reset();
3195 offscreen_saved_frame_buffer_.reset();
3196 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:273197 offscreen_resolved_frame_buffer_.reset();
3198 offscreen_resolved_color_texture_.reset();
[email protected]e51bdf32011-11-23 22:21:463199
[email protected]85a4ac22013-05-31 01:58:473200 // Should destroy the transfer manager before the texture manager held
3201 // by the context group.
3202 async_pixel_transfer_manager_.reset();
3203
[email protected]7cd76fd2013-06-02 21:11:113204 if (group_.get()) {
[email protected]2d9d3b92013-01-18 01:07:233205 group_->Destroy(this, have_context);
3206 group_ = NULL;
3207 }
3208
3209 if (context_.get()) {
3210 context_->ReleaseCurrent(NULL);
3211 context_ = NULL;
3212 }
3213
[email protected]e51bdf32011-11-23 22:21:463214#if defined(OS_MACOSX)
3215 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3216 it != texture_to_io_surface_map_.end(); ++it) {
3217 CFRelease(it->second);
3218 }
3219 texture_to_io_surface_map_.clear();
3220#endif
[email protected]96449d2c2009-11-25 00:01:323221}
3222
[email protected]63c9b052012-05-17 18:27:383223void GLES2DecoderImpl::SetSurface(
3224 const scoped_refptr<gfx::GLSurface>& surface) {
3225 DCHECK(context_->IsCurrent(NULL));
3226 DCHECK(surface_.get());
3227 surface_ = surface;
3228 RestoreCurrentFramebufferBindings();
3229}
3230
[email protected]2ad674132013-06-05 07:48:513231bool GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
[email protected]9a5afa432011-07-22 18:16:393232 if (!offscreen_saved_color_texture_.get())
3233 return false;
[email protected]2ad674132013-06-05 07:48:513234 if (!offscreen_saved_color_texture_info_.get()) {
[email protected]3c644d82011-06-20 19:58:243235 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]f46476932013-06-08 05:36:073236 offscreen_saved_color_texture_info_ = TextureRef::Create(
3237 texture_manager(), 0, service_id);
[email protected]2ad674132013-06-05 07:48:513238 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3239 GL_TEXTURE_2D);
[email protected]9a5afa432011-07-22 18:16:393240 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:243241 }
[email protected]2ad674132013-06-05 07:48:513242 gpu::gles2::MailboxName name;
3243 memcpy(name.key, mailbox.name, sizeof(mailbox.name));
3244 return mailbox_manager()->ProduceTexture(
3245 GL_TEXTURE_2D, name, offscreen_saved_color_texture_info_->texture());
[email protected]3c644d82011-06-20 19:58:243246}
3247
[email protected]260ddc4e2012-06-28 00:01:533248size_t GLES2DecoderImpl::GetBackbufferMemoryTotal() {
[email protected]1078f912011-12-23 13:12:143249 size_t total = 0;
3250 if (offscreen_target_frame_buffer_.get()) {
3251 if (offscreen_target_color_texture_.get()) {
3252 total += offscreen_target_color_texture_->estimated_size();
3253 }
3254 if (offscreen_target_color_render_buffer_.get()) {
3255 total += offscreen_target_color_render_buffer_->estimated_size();
3256 }
3257 if (offscreen_target_depth_render_buffer_.get()) {
3258 total += offscreen_target_depth_render_buffer_->estimated_size();
3259 }
3260 if (offscreen_target_stencil_render_buffer_.get()) {
3261 total += offscreen_target_stencil_render_buffer_->estimated_size();
3262 }
3263 if (offscreen_saved_color_texture_.get()) {
3264 total += offscreen_saved_color_texture_->estimated_size();
3265 }
3266 if (offscreen_resolved_color_texture_.get()) {
3267 total += offscreen_resolved_color_texture_->estimated_size();
3268 }
3269 } else {
3270 gfx::Size size = surface_->GetSize();
3271 total += size.width() * size.height() *
3272 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_);
3273 }
[email protected]260ddc4e2012-06-28 00:01:533274 return total;
[email protected]1078f912011-12-23 13:12:143275}
3276
[email protected]799b4b22011-08-22 17:09:593277bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3278 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3279 if (!is_offscreen) {
3280 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3281 << " with an onscreen framebuffer.";
3282 return false;
3283 }
3284
3285 if (offscreen_size_ == size)
3286 return true;
3287
3288 offscreen_size_ = size;
3289 int w = offscreen_size_.width();
3290 int h = offscreen_size_.height();
3291 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3292 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3293 << "to allocate storage due to excessive dimensions.";
3294 return false;
3295 }
3296
3297 // Reallocate the offscreen target buffers.
3298 DCHECK(offscreen_target_color_format_);
3299 if (IsOffscreenBufferMultisampled()) {
3300 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3301 offscreen_size_, offscreen_target_color_format_,
3302 offscreen_target_samples_)) {
3303 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3304 << "to allocate storage for offscreen target color buffer.";
3305 return false;
3306 }
3307 } else {
3308 if (!offscreen_target_color_texture_->AllocateStorage(
[email protected]678a73f2012-12-19 19:22:093309 offscreen_size_, offscreen_target_color_format_, false)) {
[email protected]799b4b22011-08-22 17:09:593310 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3311 << "to allocate storage for offscreen target color texture.";
3312 return false;
3313 }
3314 }
3315 if (offscreen_target_depth_format_ &&
3316 !offscreen_target_depth_render_buffer_->AllocateStorage(
3317 offscreen_size_, offscreen_target_depth_format_,
3318 offscreen_target_samples_)) {
3319 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3320 << "to allocate storage for offscreen target depth buffer.";
3321 return false;
3322 }
3323 if (offscreen_target_stencil_format_ &&
3324 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3325 offscreen_size_, offscreen_target_stencil_format_,
3326 offscreen_target_samples_)) {
3327 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3328 << "to allocate storage for offscreen target stencil buffer.";
3329 return false;
3330 }
3331
3332 // Attach the offscreen target buffers to the target frame buffer.
3333 if (IsOffscreenBufferMultisampled()) {
3334 offscreen_target_frame_buffer_->AttachRenderBuffer(
3335 GL_COLOR_ATTACHMENT0,
3336 offscreen_target_color_render_buffer_.get());
3337 } else {
3338 offscreen_target_frame_buffer_->AttachRenderTexture(
3339 offscreen_target_color_texture_.get());
3340 }
3341 if (offscreen_target_depth_format_) {
3342 offscreen_target_frame_buffer_->AttachRenderBuffer(
3343 GL_DEPTH_ATTACHMENT,
3344 offscreen_target_depth_render_buffer_.get());
3345 }
3346 const bool packed_depth_stencil =
3347 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3348 if (packed_depth_stencil) {
3349 offscreen_target_frame_buffer_->AttachRenderBuffer(
3350 GL_STENCIL_ATTACHMENT,
3351 offscreen_target_depth_render_buffer_.get());
3352 } else if (offscreen_target_stencil_format_) {
3353 offscreen_target_frame_buffer_->AttachRenderBuffer(
3354 GL_STENCIL_ATTACHMENT,
3355 offscreen_target_stencil_render_buffer_.get());
3356 }
3357
3358 if (offscreen_target_frame_buffer_->CheckStatus() !=
3359 GL_FRAMEBUFFER_COMPLETE) {
3360 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3361 << "because offscreen FBO was incomplete.";
3362 return false;
3363 }
3364
3365 // Clear the target frame buffer.
3366 {
3367 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3368 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3369 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3370 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3371 glClearStencil(0);
3372 glStencilMaskSeparate(GL_FRONT, -1);
3373 glStencilMaskSeparate(GL_BACK, -1);
3374 glClearDepth(0);
3375 glDepthMask(GL_TRUE);
3376 glDisable(GL_SCISSOR_TEST);
3377 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3378 RestoreClearState();
3379 }
[email protected]d85ef76d2011-09-08 22:21:433380
3381 // Destroy the offscreen resolved framebuffers.
3382 if (offscreen_resolved_frame_buffer_.get())
3383 offscreen_resolved_frame_buffer_->Destroy();
3384 if (offscreen_resolved_color_texture_.get())
3385 offscreen_resolved_color_texture_->Destroy();
3386 offscreen_resolved_color_texture_.reset();
3387 offscreen_resolved_frame_buffer_.reset();
3388
[email protected]799b4b22011-08-22 17:09:593389 return true;
[email protected]6217d392010-03-25 22:08:353390}
3391
[email protected]799b4b22011-08-22 17:09:593392error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:353393 uint32 immediate_data_size, const cmds::ResizeCHROMIUM& c) {
[email protected]09e17272012-11-30 10:30:443394 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
[email protected]452120872012-09-27 15:21:023395 return error::kDeferCommandUntilLater;
3396
[email protected]799b4b22011-08-22 17:09:593397 GLuint width = static_cast<GLuint>(c.width);
3398 GLuint height = static_cast<GLuint>(c.height);
[email protected]729c0b42013-05-26 02:05:073399 GLfloat scale_factor = c.scale_factor;
[email protected]799b4b22011-08-22 17:09:593400 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
[email protected]d16aa4b2013-02-14 22:35:413401
3402 width = std::max(1U, width);
3403 height = std::max(1U, height);
3404
[email protected]a0d989162011-11-22 13:15:073405#if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3406 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
[email protected]7ff86b92010-11-25 17:50:003407 // Make sure that we are done drawing to the back buffer before resizing.
3408 glFinish();
3409#endif
[email protected]799b4b22011-08-22 17:09:593410 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3411 if (is_offscreen) {
[email protected]7794d512012-04-17 20:36:493412 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3413 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3414 << "ResizeOffscreenFrameBuffer failed.";
[email protected]799b4b22011-08-22 17:09:593415 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:493416 }
[email protected]7ff86b92010-11-25 17:50:003417 }
[email protected]799b4b22011-08-22 17:09:593418
[email protected]9d37f062011-11-22 01:24:523419 if (!resize_callback_.is_null()) {
[email protected]729c0b42013-05-26 02:05:073420 resize_callback_.Run(gfx::Size(width, height), scale_factor);
[email protected]0e9346b2013-03-16 16:35:443421 DCHECK(context_->IsCurrent(surface_.get()));
[email protected]7794d512012-04-17 20:36:493422 if (!context_->IsCurrent(surface_.get())) {
3423 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3424 << "current after resize callback.";
[email protected]658f7562011-09-09 05:24:053425 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:493426 }
[email protected]658f7562011-09-09 05:24:053427 }
[email protected]799b4b22011-08-22 17:09:593428
3429 return error::kNoError;
[email protected]43ecf372010-11-16 19:19:393430}
3431
[email protected]96449d2c2009-11-25 00:01:323432const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3433 if (command_id > kStartPoint && command_id < kNumCommands) {
3434 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3435 }
3436 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3437}
3438
3439// Decode command with its arguments, and call the corresponding GL function.
3440// Note: args is a pointer to the command buffer. As such, it could be changed
3441// by a (malicious) client at any time, so if validation has to happen, it
3442// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:143443error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:323444 unsigned int command,
3445 unsigned int arg_count,
3446 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:143447 error::Error result = error::kNoError;
[email protected]e844ae22012-01-14 03:36:263448 if (log_commands()) {
[email protected]39ba4f02012-03-26 01:16:003449 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3450 // LOG(INFO), tried VLOG(1), no luck.
[email protected]1d82e822013-04-10 21:32:323451 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" << "cmd: "
[email protected]d2a0e1a2012-08-12 02:25:013452 << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193453 }
[email protected]96449d2c2009-11-25 00:01:323454 unsigned int command_index = command - kStartPoint - 1;
3455 if (command_index < arraysize(g_command_info)) {
3456 const CommandInfo& info = g_command_info[command_index];
3457 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3458 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3459 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:193460 uint32 immediate_data_size =
3461 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:323462 switch (command) {
3463 #define GLES2_CMD_OP(name) \
[email protected]ed9f9cd2013-02-27 21:12:353464 case cmds::name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:193465 result = Handle ## name( \
3466 immediate_data_size, \
[email protected]ed9f9cd2013-02-27 21:12:353467 *static_cast<const gles2::cmds::name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:193468 break; \
[email protected]96449d2c2009-11-25 00:01:323469
3470 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:323471 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:383472 }
3473 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:303474 GLenum error;
3475 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]1d82e822013-04-10 21:32:323476 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
[email protected]39ba4f02012-03-26 01:16:003477 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3478 << GetCommandName(command);
[email protected]ab09b612013-03-11 22:11:513479 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
[email protected]b9849abf2009-11-25 19:13:193480 }
[email protected]96449d2c2009-11-25 00:01:323481 }
3482 } else {
[email protected]f7a64ee2010-02-01 22:24:143483 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:323484 }
[email protected]b9849abf2009-11-25 19:13:193485 } else {
3486 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:323487 }
[email protected]a3a93e7b2010-08-28 00:48:563488 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3489 result = current_decoder_error_;
3490 current_decoder_error_ = error::kNoError;
3491 }
[email protected]b9849abf2009-11-25 19:13:193492 return result;
[email protected]96449d2c2009-11-25 00:01:323493}
3494
[email protected]ed9f9cd2013-02-27 21:12:353495void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3496 buffer_manager()->RemoveBuffer(client_id);
[email protected]3916c97e2010-02-25 03:20:503497}
3498
[email protected]ae51d192010-04-27 00:48:033499bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
[email protected]ed9f9cd2013-02-27 21:12:353500 if (GetProgram(client_id)) {
[email protected]ae51d192010-04-27 00:48:033501 return false;
3502 }
[email protected]96449d2c2009-11-25 00:01:323503 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:033504 if (service_id != 0) {
[email protected]ed9f9cd2013-02-27 21:12:353505 CreateProgram(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:323506 }
[email protected]ae51d192010-04-27 00:48:033507 return true;
[email protected]96449d2c2009-11-25 00:01:323508}
3509
[email protected]ae51d192010-04-27 00:48:033510bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
[email protected]ed9f9cd2013-02-27 21:12:353511 if (GetShader(client_id)) {
[email protected]ae51d192010-04-27 00:48:033512 return false;
[email protected]96449d2c2009-11-25 00:01:323513 }
[email protected]ae51d192010-04-27 00:48:033514 GLuint service_id = glCreateShader(type);
3515 if (service_id != 0) {
[email protected]ed9f9cd2013-02-27 21:12:353516 CreateShader(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:033517 }
3518 return true;
[email protected]96449d2c2009-11-25 00:01:323519}
3520
[email protected]882ba1e22012-03-08 19:02:533521void GLES2DecoderImpl::DoFinish() {
3522 glFinish();
[email protected]5a36dc132013-07-23 23:17:553523 ProcessPendingReadPixels();
[email protected]22e3f552012-03-13 01:54:193524 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533525}
3526
3527void GLES2DecoderImpl::DoFlush() {
3528 glFlush();
[email protected]22e3f552012-03-13 01:54:193529 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533530}
3531
[email protected]3916c97e2010-02-25 03:20:503532void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:453533 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]1868a342012-11-07 15:56:023534 if (texture_index >= state_.texture_units.size()) {
[email protected]ab09b612013-03-11 22:11:513535 LOCAL_SET_GL_ERROR_INVALID_ENUM(
[email protected]f80e6e12012-08-31 00:43:533536 "glActiveTexture", texture_unit, "texture_unit");
[email protected]3916c97e2010-02-25 03:20:503537 return;
3538 }
[email protected]e259eb412012-10-13 05:47:243539 state_.active_texture_unit = texture_index;
[email protected]36cef8ce2010-03-16 07:34:453540 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:503541}
3542
[email protected]051b1372010-04-12 02:42:083543void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]b10492f2013-03-08 05:24:073544 Buffer* buffer = NULL;
[email protected]051b1372010-04-12 02:42:083545 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033546 if (client_id != 0) {
[email protected]b10492f2013-03-08 05:24:073547 buffer = GetBuffer(client_id);
3548 if (!buffer) {
[email protected]bf5a8d132011-08-16 08:39:353549 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153550 LOG(ERROR) << "glBindBuffer: id not generated by glGenBuffers";
3551 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353552 return;
3553 }
3554
[email protected]b10492f2013-03-08 05:24:073555 // It's a new id so make a buffer buffer for it.
[email protected]ae51d192010-04-27 00:48:033556 glGenBuffersARB(1, &service_id);
[email protected]ed9f9cd2013-02-27 21:12:353557 CreateBuffer(client_id, service_id);
[email protected]b10492f2013-03-08 05:24:073558 buffer = GetBuffer(client_id);
[email protected]3b1ecc262011-08-03 22:49:573559 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103560 group_->GetIdAllocator(id_namespaces::kBuffers);
3561 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033562 }
[email protected]051b1372010-04-12 02:42:083563 }
[email protected]b10492f2013-03-08 05:24:073564 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
3565 if (buffer) {
3566 if (!buffer_manager()->SetTarget(buffer, target)) {
[email protected]ab09b612013-03-11 22:11:513567 LOCAL_SET_GL_ERROR(
3568 GL_INVALID_OPERATION,
3569 "glBindBuffer", "buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:473570 return;
3571 }
[email protected]b10492f2013-03-08 05:24:073572 service_id = buffer->service_id();
[email protected]a93bb842010-02-16 23:03:473573 }
[email protected]96449d2c2009-11-25 00:01:323574 switch (target) {
3575 case GL_ARRAY_BUFFER:
[email protected]b10492f2013-03-08 05:24:073576 state_.bound_array_buffer = buffer;
[email protected]96449d2c2009-11-25 00:01:323577 break;
3578 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]b10492f2013-03-08 05:24:073579 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
[email protected]96449d2c2009-11-25 00:01:323580 break;
3581 default:
[email protected]a93bb842010-02-16 23:03:473582 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:323583 break;
3584 }
[email protected]051b1372010-04-12 02:42:083585 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:323586}
3587
[email protected]f3b191b2013-06-19 03:43:543588bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3589 bool all_draw_buffers) {
3590 Framebuffer* framebuffer =
3591 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3592 if (!all_draw_buffers || !framebuffer) {
3593 return (GLES2Util::GetChannelsForFormat(
3594 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3595 }
3596 return framebuffer->HasAlphaMRT();
[email protected]297ca1c2011-06-20 23:08:463597}
3598
3599bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
[email protected]ed9f9cd2013-02-27 21:12:353600 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:453601 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:203602 if (framebuffer) {
3603 return framebuffer->HasDepthAttachment();
[email protected]297ca1c2011-06-20 23:08:463604 }
3605 if (offscreen_target_frame_buffer_.get()) {
3606 return offscreen_target_depth_format_ != 0;
3607 }
3608 return back_buffer_has_depth_;
3609}
3610
3611bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
[email protected]ed9f9cd2013-02-27 21:12:353612 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:453613 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:203614 if (framebuffer) {
3615 return framebuffer->HasStencilAttachment();
[email protected]297ca1c2011-06-20 23:08:463616 }
3617 if (offscreen_target_frame_buffer_.get()) {
3618 return offscreen_target_stencil_format_ != 0 ||
3619 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3620 }
3621 return back_buffer_has_stencil_;
3622}
3623
3624void GLES2DecoderImpl::ApplyDirtyState() {
[email protected]c986af502013-08-14 01:04:443625 if (framebuffer_state_.clear_state_dirty) {
[email protected]297ca1c2011-06-20 23:08:463626 glColorMask(
[email protected]e259eb412012-10-13 05:47:243627 state_.color_mask_red, state_.color_mask_green, state_.color_mask_blue,
3628 state_.color_mask_alpha &&
[email protected]f3b191b2013-06-19 03:43:543629 BoundFramebufferHasColorAttachmentWithAlpha(true));
[email protected]297ca1c2011-06-20 23:08:463630 bool have_depth = BoundFramebufferHasDepthAttachment();
[email protected]e259eb412012-10-13 05:47:243631 glDepthMask(state_.depth_mask && have_depth);
[email protected]f731b9462012-10-30 00:35:223632 EnableDisable(GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
[email protected]297ca1c2011-06-20 23:08:463633 bool have_stencil = BoundFramebufferHasStencilAttachment();
[email protected]e259eb412012-10-13 05:47:243634 glStencilMaskSeparate(
[email protected]88a61bf2012-10-27 13:00:423635 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
[email protected]e259eb412012-10-13 05:47:243636 glStencilMaskSeparate(
[email protected]88a61bf2012-10-27 13:00:423637 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
[email protected]f731b9462012-10-30 00:35:223638 EnableDisable(
3639 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
3640 EnableDisable(GL_CULL_FACE, state_.enable_flags.cull_face);
3641 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
3642 EnableDisable(GL_BLEND, state_.enable_flags.blend);
[email protected]c986af502013-08-14 01:04:443643 framebuffer_state_.clear_state_dirty = false;
[email protected]297ca1c2011-06-20 23:08:463644 }
3645}
3646
[email protected]1868a342012-11-07 15:56:023647GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
[email protected]7cd76fd2013-06-02 21:11:113648 return (offscreen_target_frame_buffer_.get())
3649 ? offscreen_target_frame_buffer_->id()
3650 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
[email protected]1868a342012-11-07 15:56:023651}
3652
3653void GLES2DecoderImpl::RestoreState() const {
[email protected]962bfbe72013-05-24 11:16:143654 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3655 "context", logger_.GetLogPrefix());
[email protected]29a4d902013-02-26 20:18:063656 // Restore the Framebuffer first because of bugs in Intel drivers.
3657 // Intel drivers incorrectly clip the viewport settings to
3658 // the size of the current framebuffer object.
3659 RestoreFramebufferBindings();
3660 state_.RestoreState();
3661}
3662
3663void GLES2DecoderImpl::RestoreFramebufferBindings() const {
[email protected]9d3b2e12013-10-02 01:04:343664 GLuint service_id =
3665 framebuffer_state_.bound_draw_framebuffer.get()
3666 ? framebuffer_state_.bound_draw_framebuffer->service_id()
3667 : GetBackbufferServiceId();
[email protected]29a4d902013-02-26 20:18:063668 if (!features().chromium_framebuffer_multisample) {
3669 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
3670 } else {
3671 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
[email protected]9d3b2e12013-10-02 01:04:343672 service_id = framebuffer_state_.bound_read_framebuffer.get()
3673 ? framebuffer_state_.bound_read_framebuffer->service_id()
[email protected]7cd76fd2013-06-02 21:11:113674 : GetBackbufferServiceId();
[email protected]29a4d902013-02-26 20:18:063675 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
3676 }
[email protected]70d34263c2013-01-09 00:27:453677 OnFboChanged();
[email protected]29a4d902013-02-26 20:18:063678}
3679
3680void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
[email protected]62e65f02013-05-29 22:28:103681 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
3682 if (texture) {
[email protected]9bc9a2e82013-04-03 03:56:253683 GLenum target = texture->target();
3684 glBindTexture(target, service_id);
[email protected]29a4d902013-02-26 20:18:063685 glTexParameteri(
[email protected]9bc9a2e82013-04-03 03:56:253686 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
[email protected]29a4d902013-02-26 20:18:063687 glTexParameteri(
[email protected]9bc9a2e82013-04-03 03:56:253688 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
[email protected]29a4d902013-02-26 20:18:063689 glTexParameteri(
[email protected]9bc9a2e82013-04-03 03:56:253690 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
[email protected]29a4d902013-02-26 20:18:063691 glTexParameteri(
[email protected]9bc9a2e82013-04-03 03:56:253692 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
[email protected]29a4d902013-02-26 20:18:063693 RestoreTextureUnitBindings(state_.active_texture_unit);
3694 }
[email protected]70d34263c2013-01-09 00:27:453695}
3696
3697void GLES2DecoderImpl::OnFboChanged() const {
3698 if (workarounds().restore_scissor_on_fbo_change)
[email protected]28718a92013-04-04 12:12:513699 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
3700}
3701
3702// Called after the FBO is checked for completeness.
3703void GLES2DecoderImpl::OnUseFramebuffer() const {
3704 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
3705 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
[email protected]81fc9d02013-03-14 23:53:323706 // The driver forgets the correct scissor when modifying the FBO binding.
[email protected]28718a92013-04-04 12:12:513707 glScissor(state_.scissor_x,
3708 state_.scissor_y,
3709 state_.scissor_width,
3710 state_.scissor_height);
3711
3712 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
3713 // it's unclear how this bug works.
3714 glFlush();
3715 }
[email protected]b177ae22011-11-01 03:29:113716}
3717
[email protected]051b1372010-04-12 02:42:083718void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
[email protected]4d8f0dd2013-03-09 14:37:063719 Framebuffer* framebuffer = NULL;
[email protected]051b1372010-04-12 02:42:083720 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033721 if (client_id != 0) {
[email protected]4d8f0dd2013-03-09 14:37:063722 framebuffer = GetFramebuffer(client_id);
3723 if (!framebuffer) {
[email protected]bf5a8d132011-08-16 08:39:353724 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153725 LOG(ERROR)
3726 << "glBindFramebuffer: id not generated by glGenFramebuffers";
3727 current_decoder_error_ = error::kGenericError;
3728 return;
[email protected]bf5a8d132011-08-16 08:39:353729 }
3730
[email protected]4d8f0dd2013-03-09 14:37:063731 // It's a new id so make a framebuffer framebuffer for it.
[email protected]ae51d192010-04-27 00:48:033732 glGenFramebuffersEXT(1, &service_id);
[email protected]ed9f9cd2013-02-27 21:12:353733 CreateFramebuffer(client_id, service_id);
[email protected]4d8f0dd2013-03-09 14:37:063734 framebuffer = GetFramebuffer(client_id);
[email protected]3b1ecc262011-08-03 22:49:573735 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103736 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3737 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033738 } else {
[email protected]4d8f0dd2013-03-09 14:37:063739 service_id = framebuffer->service_id();
[email protected]051b1372010-04-12 02:42:083740 }
[email protected]4d8f0dd2013-03-09 14:37:063741 framebuffer->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083742 }
[email protected]4d8f0dd2013-03-09 14:37:063743 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
[email protected]8e3e0662010-08-23 18:46:303744
3745 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
[email protected]9d3b2e12013-10-02 01:04:343746 framebuffer_state_.bound_draw_framebuffer = framebuffer;
[email protected]8e3e0662010-08-23 18:46:303747 }
3748 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]9d3b2e12013-10-02 01:04:343749 framebuffer_state_.bound_read_framebuffer = framebuffer;
[email protected]8e3e0662010-08-23 18:46:303750 }
[email protected]6217d392010-03-25 22:08:353751
[email protected]c986af502013-08-14 01:04:443752 framebuffer_state_.clear_state_dirty = true;
[email protected]297ca1c2011-06-20 23:08:463753
[email protected]b177ae22011-11-01 03:29:113754 // If we are rendering to the backbuffer get the FBO id for any simulated
3755 // backbuffer.
[email protected]4d8f0dd2013-03-09 14:37:063756 if (framebuffer == NULL) {
[email protected]b177ae22011-11-01 03:29:113757 service_id = GetBackbufferServiceId();
[email protected]297ca1c2011-06-20 23:08:463758 }
[email protected]6217d392010-03-25 22:08:353759
[email protected]051b1372010-04-12 02:42:083760 glBindFramebufferEXT(target, service_id);
[email protected]70d34263c2013-01-09 00:27:453761 OnFboChanged();
[email protected]86093972010-03-11 00:13:563762}
3763
[email protected]051b1372010-04-12 02:42:083764void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
[email protected]ee2a79c32013-03-10 03:50:273765 Renderbuffer* renderbuffer = NULL;
[email protected]051b1372010-04-12 02:42:083766 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033767 if (client_id != 0) {
[email protected]ee2a79c32013-03-10 03:50:273768 renderbuffer = GetRenderbuffer(client_id);
3769 if (!renderbuffer) {
[email protected]bf5a8d132011-08-16 08:39:353770 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153771 LOG(ERROR)
3772 << "glBindRenderbuffer: id not generated by glGenRenderbuffers";
3773 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353774 return;
3775 }
3776
[email protected]ee2a79c32013-03-10 03:50:273777 // It's a new id so make a renderbuffer renderbuffer for it.
[email protected]ae51d192010-04-27 00:48:033778 glGenRenderbuffersEXT(1, &service_id);
[email protected]ed9f9cd2013-02-27 21:12:353779 CreateRenderbuffer(client_id, service_id);
[email protected]ee2a79c32013-03-10 03:50:273780 renderbuffer = GetRenderbuffer(client_id);
[email protected]3b1ecc262011-08-03 22:49:573781 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103782 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3783 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033784 } else {
[email protected]ee2a79c32013-03-10 03:50:273785 service_id = renderbuffer->service_id();
[email protected]051b1372010-04-12 02:42:083786 }
[email protected]ee2a79c32013-03-10 03:50:273787 renderbuffer->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083788 }
[email protected]ee2a79c32013-03-10 03:50:273789 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenerbuffer");
3790 state_.bound_renderbuffer = renderbuffer;
[email protected]051b1372010-04-12 02:42:083791 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563792}
3793
[email protected]051b1372010-04-12 02:42:083794void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]370eaf12013-05-18 09:19:493795 TextureRef* texture_ref = NULL;
[email protected]051b1372010-04-12 02:42:083796 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033797 if (client_id != 0) {
[email protected]370eaf12013-05-18 09:19:493798 texture_ref = GetTexture(client_id);
3799 if (!texture_ref) {
[email protected]bf5a8d132011-08-16 08:39:353800 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153801 LOG(ERROR) << "glBindTexture: id not generated by glGenTextures";
3802 current_decoder_error_ = error::kGenericError;
3803 return;
[email protected]bf5a8d132011-08-16 08:39:353804 }
3805
[email protected]02965c22013-03-09 02:40:073806 // It's a new id so make a texture texture for it.
[email protected]ae51d192010-04-27 00:48:033807 glGenTextures(1, &service_id);
[email protected]80eb6b52012-01-19 00:14:413808 DCHECK_NE(0u, service_id);
[email protected]ed9f9cd2013-02-27 21:12:353809 CreateTexture(client_id, service_id);
[email protected]370eaf12013-05-18 09:19:493810 texture_ref = GetTexture(client_id);
[email protected]3b1ecc262011-08-03 22:49:573811 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103812 group_->GetIdAllocator(id_namespaces::kTextures);
3813 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033814 }
3815 } else {
[email protected]370eaf12013-05-18 09:19:493816 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:083817 }
[email protected]370eaf12013-05-18 09:19:493818 Texture* texture = texture_ref->texture();
[email protected]ae51d192010-04-27 00:48:033819
[email protected]1958e0e2010-04-22 05:17:153820 // Check the texture exists
3821 // Check that we are not trying to bind it to a different target.
[email protected]02965c22013-03-09 02:40:073822 if (texture->target() != 0 && texture->target() != target) {
[email protected]ab09b612013-03-11 22:11:513823 LOCAL_SET_GL_ERROR(
3824 GL_INVALID_OPERATION,
3825 "glBindTexture", "texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:153826 return;
3827 }
[email protected]02965c22013-03-09 02:40:073828 if (texture->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
[email protected]ab09b612013-03-11 22:11:513829 LOCAL_SET_GL_ERROR(
3830 GL_INVALID_OPERATION,
3831 "glBindTexture", "illegal target for stream texture.");
[email protected]b0af4f52011-09-28 22:04:423832 return;
3833 }
[email protected]02965c22013-03-09 02:40:073834 LogClientServiceForInfo(texture, client_id, "glBindTexture");
3835 if (texture->target() == 0) {
[email protected]370eaf12013-05-18 09:19:493836 texture_manager()->SetTarget(texture_ref, target);
[email protected]a93bb842010-02-16 23:03:473837 }
[email protected]02965c22013-03-09 02:40:073838 glBindTexture(target, texture->service_id());
[email protected]32145a92012-12-17 09:01:593839
[email protected]e259eb412012-10-13 05:47:243840 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]3916c97e2010-02-25 03:20:503841 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:473842 switch (target) {
3843 case GL_TEXTURE_2D:
[email protected]370eaf12013-05-18 09:19:493844 unit.bound_texture_2d = texture_ref;
[email protected]a93bb842010-02-16 23:03:473845 break;
3846 case GL_TEXTURE_CUBE_MAP:
[email protected]370eaf12013-05-18 09:19:493847 unit.bound_texture_cube_map = texture_ref;
[email protected]a93bb842010-02-16 23:03:473848 break;
[email protected]61eeb33f2011-07-26 15:30:313849 case GL_TEXTURE_EXTERNAL_OES:
[email protected]370eaf12013-05-18 09:19:493850 unit.bound_texture_external_oes = texture_ref;
[email protected]61eeb33f2011-07-26 15:30:313851 break;
[email protected]e51bdf32011-11-23 22:21:463852 case GL_TEXTURE_RECTANGLE_ARB:
[email protected]370eaf12013-05-18 09:19:493853 unit.bound_texture_rectangle_arb = texture_ref;
[email protected]e51bdf32011-11-23 22:21:463854 break;
[email protected]a93bb842010-02-16 23:03:473855 default:
3856 NOTREACHED(); // Validation should prevent us getting here.
3857 break;
3858 }
3859}
3860
[email protected]07f54fcc2009-12-22 02:46:303861void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]e259eb412012-10-13 05:47:243862 if (state_.vertex_attrib_manager->Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:123863 if (index != 0 ||
3864 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:243865 glDisableVertexAttribArray(index);
3866 }
[email protected]07f54fcc2009-12-22 02:46:303867 } else {
[email protected]ab09b612013-03-11 22:11:513868 LOCAL_SET_GL_ERROR(
3869 GL_INVALID_VALUE,
3870 "glDisableVertexAttribArray", "index out of range");
[email protected]07f54fcc2009-12-22 02:46:303871 }
3872}
3873
[email protected]60f22d32012-12-12 00:31:583874void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
3875 GLsizei numAttachments,
3876 const GLenum* attachments) {
[email protected]ed9f9cd2013-02-27 21:12:353877 Framebuffer* framebuffer =
[email protected]60f22d32012-12-12 00:31:583878 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
3879
3880 // Validates the attachments. If one of them fails
3881 // the whole command fails.
3882 for (GLsizei i = 0; i < numAttachments; ++i) {
3883 if ((framebuffer &&
3884 !validators_->attachment.IsValid(attachments[i])) ||
3885 (!framebuffer &&
3886 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
[email protected]ab09b612013-03-11 22:11:513887 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3888 "glDiscardFramebufferEXT", attachments[i], "attachments");
[email protected]60f22d32012-12-12 00:31:583889 return;
3890 }
3891 }
3892
3893 // Marks each one of them as not cleared
3894 for (GLsizei i = 0; i < numAttachments; ++i) {
3895 if (framebuffer) {
3896 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
3897 texture_manager(),
3898 attachments[i],
3899 false);
3900 } else {
3901 switch (attachments[i]) {
3902 case GL_COLOR_EXT:
3903 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
3904 break;
3905 case GL_DEPTH_EXT:
3906 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
3907 case GL_STENCIL_EXT:
3908 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
3909 break;
3910 default:
3911 NOTREACHED();
3912 break;
3913 }
3914 }
3915 }
3916
[email protected]d49c5402013-09-11 15:39:023917 // If the default framebuffer is bound but we are still rendering to an
3918 // FBO, translate attachment names that refer to default framebuffer
3919 // channels to corresponding framebuffer attachments.
3920 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
3921 for (GLsizei i = 0; i < numAttachments; ++i) {
3922 GLenum attachment = attachments[i];
3923 if (!framebuffer && GetBackbufferServiceId()) {
3924 switch (attachment) {
3925 case GL_COLOR_EXT:
3926 attachment = GL_COLOR_ATTACHMENT0;
3927 break;
3928 case GL_DEPTH_EXT:
3929 attachment = GL_DEPTH_ATTACHMENT;
3930 break;
3931 case GL_STENCIL_EXT:
3932 attachment = GL_STENCIL_ATTACHMENT;
3933 break;
3934 default:
3935 NOTREACHED();
3936 return;
3937 }
3938 }
3939 translated_attachments[i] = attachment;
3940 }
3941
3942 glDiscardFramebufferEXT(target, numAttachments, translated_attachments.get());
[email protected]60f22d32012-12-12 00:31:583943}
3944
[email protected]07f54fcc2009-12-22 02:46:303945void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]e259eb412012-10-13 05:47:243946 if (state_.vertex_attrib_manager->Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:303947 glEnableVertexAttribArray(index);
3948 } else {
[email protected]ab09b612013-03-11 22:11:513949 LOCAL_SET_GL_ERROR(
3950 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
[email protected]07f54fcc2009-12-22 02:46:303951 }
3952}
3953
[email protected]a93bb842010-02-16 23:03:473954void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]c986af502013-08-14 01:04:443955 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3956 &state_, target);
[email protected]370eaf12013-05-18 09:19:493957 if (!texture_ref ||
3958 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
[email protected]ab09b612013-03-11 22:11:513959 LOCAL_SET_GL_ERROR(
3960 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
[email protected]a93bb842010-02-16 23:03:473961 return;
3962 }
[email protected]38c0a972012-05-12 00:48:023963
[email protected]12d95352012-12-14 07:23:543964 if (target == GL_TEXTURE_CUBE_MAP) {
3965 for (int i = 0; i < 6; ++i) {
3966 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
[email protected]370eaf12013-05-18 09:19:493967 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
[email protected]ab09b612013-03-11 22:11:513968 LOCAL_SET_GL_ERROR(
3969 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
[email protected]12d95352012-12-14 07:23:543970 return;
3971 }
3972 }
3973 } else {
[email protected]370eaf12013-05-18 09:19:493974 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
[email protected]ab09b612013-03-11 22:11:513975 LOCAL_SET_GL_ERROR(
3976 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
[email protected]12d95352012-12-14 07:23:543977 return;
3978 }
[email protected]7687479c2012-05-14 23:54:043979 }
3980
[email protected]ab09b612013-03-11 22:11:513981 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
[email protected]59f3ca02011-03-26 22:24:193982 // Workaround for Mac driver bug. In the large scheme of things setting
3983 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
[email protected]a8bad262011-10-21 18:28:563984 // hit so there's probably no need to make this conditional. The bug appears
3985 // to be that if the filtering mode is set to something that doesn't require
3986 // mipmaps for rendering, or is never set to something other than the default,
3987 // then glGenerateMipmap misbehaves.
[email protected]62e155e2012-10-23 22:43:153988 if (workarounds().set_texture_filter_before_generating_mipmap) {
[email protected]c892a4e12012-05-08 18:20:193989 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3990 }
[email protected]a93bb842010-02-16 23:03:473991 glGenerateMipmapEXT(target);
[email protected]62e155e2012-10-23 22:43:153992 if (workarounds().set_texture_filter_before_generating_mipmap) {
[email protected]370eaf12013-05-18 09:19:493993 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
3994 texture_ref->texture()->min_filter());
[email protected]c892a4e12012-05-08 18:20:193995 }
[email protected]ab09b612013-03-11 22:11:513996 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
[email protected]38c0a972012-05-12 00:48:023997 if (error == GL_NO_ERROR) {
[email protected]370eaf12013-05-18 09:19:493998 texture_manager()->MarkMipmapsGenerated(texture_ref);
[email protected]38c0a972012-05-12 00:48:023999 }
[email protected]a93bb842010-02-16 23:03:474000}
4001
[email protected]b273e432010-04-12 17:23:584002bool GLES2DecoderImpl::GetHelper(
4003 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:584004 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:154005 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4006 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:434007 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4008 *num_written = 1;
4009 if (params) {
4010 *params = GL_RGBA; // We don't support other formats.
4011 }
4012 return true;
4013 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4014 *num_written = 1;
4015 if (params) {
4016 *params = GL_UNSIGNED_BYTE; // We don't support other types.
4017 }
4018 return true;
4019 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4020 *num_written = 1;
4021 if (params) {
4022 *params = group_->max_fragment_uniform_vectors();
4023 }
4024 return true;
4025 case GL_MAX_VARYING_VECTORS:
4026 *num_written = 1;
4027 if (params) {
4028 *params = group_->max_varying_vectors();
4029 }
4030 return true;
4031 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4032 *num_written = 1;
4033 if (params) {
4034 *params = group_->max_vertex_uniform_vectors();
4035 }
4036 return true;
[email protected]4e8a5b122010-05-08 22:00:104037 }
[email protected]5cb735d2011-10-13 01:37:234038 }
4039 switch (pname) {
[email protected]5094b0f2010-11-09 19:45:244040 case GL_MAX_VIEWPORT_DIMS:
4041 if (offscreen_target_frame_buffer_.get()) {
4042 *num_written = 2;
4043 if (params) {
4044 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4045 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4046 }
4047 return true;
4048 }
[email protected]5cb735d2011-10-13 01:37:234049 return false;
[email protected]84afefa2011-10-19 21:45:534050 case GL_MAX_SAMPLES:
4051 *num_written = 1;
4052 if (params) {
4053 params[0] = renderbuffer_manager()->max_samples();
4054 }
4055 return true;
4056 case GL_MAX_RENDERBUFFER_SIZE:
4057 *num_written = 1;
4058 if (params) {
4059 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4060 }
4061 return true;
[email protected]5cb735d2011-10-13 01:37:234062 case GL_MAX_TEXTURE_SIZE:
4063 *num_written = 1;
4064 if (params) {
4065 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4066 }
4067 return true;
4068 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4069 *num_written = 1;
4070 if (params) {
4071 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4072 }
4073 return true;
[email protected]2f143d482013-03-14 18:04:494074 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4075 *num_written = 1;
4076 if (params) {
4077 params[0] = group_->max_color_attachments();
4078 }
4079 return true;
4080 case GL_MAX_DRAW_BUFFERS_ARB:
4081 *num_written = 1;
4082 if (params) {
4083 params[0] = group_->max_draw_buffers();
4084 }
4085 return true;
[email protected]297ca1c2011-06-20 23:08:464086 case GL_ALPHA_BITS:
4087 *num_written = 1;
4088 if (params) {
4089 GLint v = 0;
4090 glGetIntegerv(GL_ALPHA_BITS, &v);
[email protected]f3b191b2013-06-19 03:43:544091 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
[email protected]297ca1c2011-06-20 23:08:464092 }
4093 return true;
4094 case GL_DEPTH_BITS:
4095 *num_written = 1;
4096 if (params) {
4097 GLint v = 0;
4098 glGetIntegerv(GL_DEPTH_BITS, &v);
4099 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4100 }
4101 return true;
4102 case GL_STENCIL_BITS:
4103 *num_written = 1;
4104 if (params) {
4105 GLint v = 0;
4106 glGetIntegerv(GL_STENCIL_BITS, &v);
4107 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4108 }
4109 return true;
[email protected]656dcaad2010-05-07 17:18:374110 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:114111 *num_written = validators_->compressed_texture_format.GetValues().size();
4112 if (params) {
4113 for (GLint ii = 0; ii < *num_written; ++ii) {
4114 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4115 }
4116 }
[email protected]656dcaad2010-05-07 17:18:374117 return true;
[email protected]b273e432010-04-12 17:23:584118 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4119 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104120 if (params) {
[email protected]302ce6d2011-07-07 23:28:114121 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:104122 }
[email protected]b273e432010-04-12 17:23:584123 return true;
4124 case GL_NUM_SHADER_BINARY_FORMATS:
4125 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104126 if (params) {
[email protected]302ce6d2011-07-07 23:28:114127 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:104128 }
[email protected]b273e432010-04-12 17:23:584129 return true;
4130 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:114131 *num_written = validators_->shader_binary_format.GetValues().size();
4132 if (params) {
4133 for (GLint ii = 0; ii < *num_written; ++ii) {
4134 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4135 }
4136 }
4137 return true;
[email protected]b273e432010-04-12 17:23:584138 case GL_SHADER_COMPILER:
4139 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104140 if (params) {
4141 *params = GL_TRUE;
4142 }
[email protected]b273e432010-04-12 17:23:584143 return true;
[email protected]6b8cf1a2010-05-06 16:13:584144 case GL_ARRAY_BUFFER_BINDING:
4145 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104146 if (params) {
[email protected]7cd76fd2013-06-02 21:11:114147 if (state_.bound_array_buffer.get()) {
[email protected]4e8a5b122010-05-08 22:00:104148 GLuint client_id = 0;
[email protected]e259eb412012-10-13 05:47:244149 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
[email protected]4e8a5b122010-05-08 22:00:104150 &client_id);
4151 *params = client_id;
4152 } else {
4153 *params = 0;
4154 }
[email protected]6b8cf1a2010-05-06 16:13:584155 }
4156 return true;
4157 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4158 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104159 if (params) {
[email protected]e259eb412012-10-13 05:47:244160 if (state_.vertex_attrib_manager->element_array_buffer()) {
[email protected]4e8a5b122010-05-08 22:00:104161 GLuint client_id = 0;
4162 buffer_manager()->GetClientId(
[email protected]b04e24c2013-01-08 18:35:254163 state_.vertex_attrib_manager->element_array_buffer()->
4164 service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:104165 *params = client_id;
4166 } else {
4167 *params = 0;
4168 }
[email protected]6b8cf1a2010-05-06 16:13:584169 }
4170 return true;
4171 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:304172 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:584173 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104174 if (params) {
[email protected]ed9f9cd2013-02-27 21:12:354175 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:454176 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
[email protected]0d6bfdc2011-11-02 01:32:204177 if (framebuffer) {
[email protected]4e8a5b122010-05-08 22:00:104178 GLuint client_id = 0;
4179 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:204180 framebuffer->service_id(), &client_id);
[email protected]8e3e0662010-08-23 18:46:304181 *params = client_id;
4182 } else {
4183 *params = 0;
4184 }
4185 }
4186 return true;
[email protected]ebfb73c2012-08-15 02:37:454187 case GL_READ_FRAMEBUFFER_BINDING_EXT:
[email protected]8e3e0662010-08-23 18:46:304188 *num_written = 1;
4189 if (params) {
[email protected]ed9f9cd2013-02-27 21:12:354190 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:454191 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:204192 if (framebuffer) {
[email protected]8e3e0662010-08-23 18:46:304193 GLuint client_id = 0;
4194 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:204195 framebuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:104196 *params = client_id;
4197 } else {
4198 *params = 0;
4199 }
[email protected]6b8cf1a2010-05-06 16:13:584200 }
4201 return true;
4202 case GL_RENDERBUFFER_BINDING:
4203 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104204 if (params) {
[email protected]ed9f9cd2013-02-27 21:12:354205 Renderbuffer* renderbuffer =
[email protected]0d6bfdc2011-11-02 01:32:204206 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4207 if (renderbuffer) {
[email protected]62e65f02013-05-29 22:28:104208 *params = renderbuffer->client_id();
[email protected]4e8a5b122010-05-08 22:00:104209 } else {
4210 *params = 0;
4211 }
[email protected]6b8cf1a2010-05-06 16:13:584212 }
4213 return true;
4214 case GL_CURRENT_PROGRAM:
4215 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104216 if (params) {
[email protected]7cd76fd2013-06-02 21:11:114217 if (state_.current_program.get()) {
[email protected]4e8a5b122010-05-08 22:00:104218 GLuint client_id = 0;
4219 program_manager()->GetClientId(
[email protected]e259eb412012-10-13 05:47:244220 state_.current_program->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:104221 *params = client_id;
4222 } else {
4223 *params = 0;
4224 }
[email protected]6b8cf1a2010-05-06 16:13:584225 }
4226 return true;
[email protected]bf835842012-11-19 15:21:514227 case GL_VERTEX_ARRAY_BINDING_OES:
4228 *num_written = 1;
4229 if (params) {
[email protected]7cd76fd2013-06-02 21:11:114230 if (state_.vertex_attrib_manager.get() !=
4231 default_vertex_attrib_manager_.get()) {
[email protected]bf835842012-11-19 15:21:514232 GLuint client_id = 0;
4233 vertex_array_manager_->GetClientId(
4234 state_.vertex_attrib_manager->service_id(), &client_id);
4235 *params = client_id;
4236 } else {
4237 *params = 0;
4238 }
4239 }
4240 return true;
[email protected]4e8a5b122010-05-08 22:00:104241 case GL_TEXTURE_BINDING_2D:
4242 *num_written = 1;
4243 if (params) {
[email protected]e259eb412012-10-13 05:47:244244 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]7cd76fd2013-06-02 21:11:114245 if (unit.bound_texture_2d.get()) {
[email protected]62e65f02013-05-29 22:28:104246 *params = unit.bound_texture_2d->client_id();
[email protected]6b8cf1a2010-05-06 16:13:584247 } else {
4248 *params = 0;
4249 }
[email protected]6b8cf1a2010-05-06 16:13:584250 }
[email protected]4e8a5b122010-05-08 22:00:104251 return true;
4252 case GL_TEXTURE_BINDING_CUBE_MAP:
4253 *num_written = 1;
4254 if (params) {
[email protected]e259eb412012-10-13 05:47:244255 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]7cd76fd2013-06-02 21:11:114256 if (unit.bound_texture_cube_map.get()) {
[email protected]62e65f02013-05-29 22:28:104257 *params = unit.bound_texture_cube_map->client_id();
[email protected]6b8cf1a2010-05-06 16:13:584258 } else {
4259 *params = 0;
4260 }
[email protected]6b8cf1a2010-05-06 16:13:584261 }
[email protected]4e8a5b122010-05-08 22:00:104262 return true;
[email protected]61eeb33f2011-07-26 15:30:314263 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4264 *num_written = 1;
4265 if (params) {
[email protected]e259eb412012-10-13 05:47:244266 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]7cd76fd2013-06-02 21:11:114267 if (unit.bound_texture_external_oes.get()) {
[email protected]62e65f02013-05-29 22:28:104268 *params = unit.bound_texture_external_oes->client_id();
[email protected]61eeb33f2011-07-26 15:30:314269 } else {
4270 *params = 0;
4271 }
4272 }
4273 return true;
[email protected]e51bdf32011-11-23 22:21:464274 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4275 *num_written = 1;
4276 if (params) {
[email protected]e259eb412012-10-13 05:47:244277 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]7cd76fd2013-06-02 21:11:114278 if (unit.bound_texture_rectangle_arb.get()) {
[email protected]62e65f02013-05-29 22:28:104279 *params = unit.bound_texture_rectangle_arb->client_id();
[email protected]e51bdf32011-11-23 22:21:464280 } else {
4281 *params = 0;
4282 }
4283 }
4284 return true;
[email protected]6c75c712012-06-19 15:43:174285 case GL_UNPACK_FLIP_Y_CHROMIUM:
4286 *num_written = 1;
4287 if (params) {
4288 params[0] = unpack_flip_y_;
4289 }
4290 return true;
4291 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4292 *num_written = 1;
4293 if (params) {
4294 params[0] = unpack_premultiply_alpha_;
4295 }
4296 return true;
4297 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4298 *num_written = 1;
4299 if (params) {
4300 params[0] = unpack_unpremultiply_alpha_;
4301 }
4302 return true;
[email protected]b273e432010-04-12 17:23:584303 default:
[email protected]2f143d482013-03-14 18:04:494304 if (pname >= GL_DRAW_BUFFER0_ARB &&
4305 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4306 *num_written = 1;
4307 if (params) {
4308 Framebuffer* framebuffer =
4309 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4310 if (framebuffer) {
4311 params[0] = framebuffer->GetDrawBuffer(pname);
4312 } else { // backbuffer
4313 if (pname == GL_DRAW_BUFFER0_ARB)
4314 params[0] = group_->draw_buffer();
4315 else
4316 params[0] = GL_NONE;
4317 }
4318 }
4319 return true;
4320 }
[email protected]4e8a5b122010-05-08 22:00:104321 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:534322 return false;
[email protected]b273e432010-04-12 17:23:584323 }
4324}
4325
[email protected]4e8a5b122010-05-08 22:00:104326bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4327 GLenum pname, GLsizei* num_values) {
[email protected]d058bca2012-11-26 10:27:264328 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
[email protected]f63b1232012-10-31 07:03:534329 return true;
4330 }
[email protected]4e8a5b122010-05-08 22:00:104331 return GetHelper(pname, NULL, num_values);
4332}
4333
[email protected]7d3c36e2013-07-12 14:13:164334GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4335 if (GL_MAX_SAMPLES == pname &&
4336 features().use_img_for_multisampled_render_to_texture) {
4337 return GL_MAX_SAMPLES_IMG;
4338 }
4339 return pname;
4340}
4341
[email protected]b273e432010-04-12 17:23:584342void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4343 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:104344 GLsizei num_written = 0;
[email protected]f63b1232012-10-31 07:03:534345 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
[email protected]40d90a22013-04-09 03:39:554346 scoped_ptr<GLint[]> values(new GLint[num_written]);
[email protected]d058bca2012-11-26 10:27:264347 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
[email protected]f63b1232012-10-31 07:03:534348 GetHelper(pname, values.get(), &num_written);
4349 }
[email protected]b273e432010-04-12 17:23:584350 for (GLsizei ii = 0; ii < num_written; ++ii) {
4351 params[ii] = static_cast<GLboolean>(values[ii]);
4352 }
4353 } else {
[email protected]7d3c36e2013-07-12 14:13:164354 pname = AdjustGetPname(pname);
[email protected]b273e432010-04-12 17:23:584355 glGetBooleanv(pname, params);
4356 }
4357}
4358
4359void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4360 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:104361 GLsizei num_written = 0;
[email protected]d058bca2012-11-26 10:27:264362 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
[email protected]f63b1232012-10-31 07:03:534363 if (GetHelper(pname, NULL, &num_written)) {
[email protected]40d90a22013-04-09 03:39:554364 scoped_ptr<GLint[]> values(new GLint[num_written]);
[email protected]f63b1232012-10-31 07:03:534365 GetHelper(pname, values.get(), &num_written);
4366 for (GLsizei ii = 0; ii < num_written; ++ii) {
4367 params[ii] = static_cast<GLfloat>(values[ii]);
4368 }
4369 } else {
[email protected]7d3c36e2013-07-12 14:13:164370 pname = AdjustGetPname(pname);
[email protected]f63b1232012-10-31 07:03:534371 glGetFloatv(pname, params);
[email protected]b273e432010-04-12 17:23:584372 }
[email protected]b273e432010-04-12 17:23:584373 }
4374}
4375
4376void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4377 DCHECK(params);
4378 GLsizei num_written;
[email protected]d058bca2012-11-26 10:27:264379 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
[email protected]f63b1232012-10-31 07:03:534380 !GetHelper(pname, params, &num_written)) {
[email protected]7d3c36e2013-07-12 14:13:164381 pname = AdjustGetPname(pname);
[email protected]b273e432010-04-12 17:23:584382 glGetIntegerv(pname, params);
4383 }
4384}
4385
[email protected]a0c3e972010-04-21 00:49:134386void GLES2DecoderImpl::DoGetProgramiv(
4387 GLuint program_id, GLenum pname, GLint* params) {
[email protected]df37b9932013-03-08 05:21:424388 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4389 if (!program) {
[email protected]a0c3e972010-04-21 00:49:134390 return;
4391 }
[email protected]df37b9932013-03-08 05:21:424392 program->GetProgramiv(pname, params);
[email protected]a0c3e972010-04-21 00:49:134393}
4394
[email protected]17cfbe0e2013-03-07 01:26:084395void GLES2DecoderImpl::DoGetBufferParameteriv(
4396 GLenum target, GLenum pname, GLint* params) {
[email protected]0fbba3732013-07-17 15:40:134397 // Just delegate it. Some validation is actually done before this.
4398 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4399 &state_, target, pname, params);
[email protected]17cfbe0e2013-03-07 01:26:084400}
4401
[email protected]258a3313f2011-10-18 20:13:574402void GLES2DecoderImpl::DoBindAttribLocation(
[email protected]df37b9932013-03-08 05:21:424403 GLuint program_id, GLuint index, const char* name) {
[email protected]258a3313f2011-10-18 20:13:574404 if (!StringIsValidForGLES(name)) {
[email protected]ab09b612013-03-11 22:11:514405 LOCAL_SET_GL_ERROR(
4406 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:574407 return;
4408 }
[email protected]68dcb1f2012-04-07 00:14:564409 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
[email protected]ab09b612013-03-11 22:11:514410 LOCAL_SET_GL_ERROR(
4411 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
[email protected]68dcb1f2012-04-07 00:14:564412 return;
4413 }
4414 if (index >= group_->max_vertex_attribs()) {
[email protected]ab09b612013-03-11 22:11:514415 LOCAL_SET_GL_ERROR(
4416 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
[email protected]68dcb1f2012-04-07 00:14:564417 return;
4418 }
[email protected]df37b9932013-03-08 05:21:424419 Program* program = GetProgramInfoNotShader(
4420 program_id, "glBindAttribLocation");
4421 if (!program) {
[email protected]258a3313f2011-10-18 20:13:574422 return;
[email protected]558847a2010-03-24 07:02:544423 }
[email protected]df37b9932013-03-08 05:21:424424 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4425 glBindAttribLocation(program->service_id(), index, name);
[email protected]258a3313f2011-10-18 20:13:574426}
4427
4428error::Error GLES2DecoderImpl::HandleBindAttribLocation(
[email protected]ed9f9cd2013-02-27 21:12:354429 uint32 immediate_data_size, const cmds::BindAttribLocation& c) {
[email protected]258a3313f2011-10-18 20:13:574430 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:544431 GLuint index = static_cast<GLuint>(c.index);
4432 uint32 name_size = c.data_size;
4433 const char* name = GetSharedMemoryAs<const char*>(
4434 c.name_shm_id, c.name_shm_offset, name_size);
4435 if (name == NULL) {
4436 return error::kOutOfBounds;
4437 }
4438 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:574439 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:544440 return error::kNoError;
4441}
4442
4443error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
[email protected]ed9f9cd2013-02-27 21:12:354444 uint32 immediate_data_size, const cmds::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:584445 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:544446 GLuint index = static_cast<GLuint>(c.index);
4447 uint32 name_size = c.data_size;
4448 const char* name = GetImmediateDataAs<const char*>(
4449 c, name_size, immediate_data_size);
4450 if (name == NULL) {
4451 return error::kOutOfBounds;
4452 }
4453 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:574454 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:544455 return error::kNoError;
4456}
4457
4458error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
[email protected]ed9f9cd2013-02-27 21:12:354459 uint32 immediate_data_size, const cmds::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:584460 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:544461 GLuint index = static_cast<GLuint>(c.index);
4462 Bucket* bucket = GetBucket(c.name_bucket_id);
4463 if (!bucket || bucket->size() == 0) {
4464 return error::kInvalidArguments;
4465 }
4466 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:184467 if (!bucket->GetAsString(&name_str)) {
4468 return error::kInvalidArguments;
4469 }
[email protected]258a3313f2011-10-18 20:13:574470 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:544471 return error::kNoError;
4472}
4473
[email protected]2be6abf32012-06-26 00:28:334474void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
[email protected]df37b9932013-03-08 05:21:424475 GLuint program_id, GLint location, const char* name) {
[email protected]2be6abf32012-06-26 00:28:334476 if (!StringIsValidForGLES(name)) {
[email protected]ab09b612013-03-11 22:11:514477 LOCAL_SET_GL_ERROR(
4478 GL_INVALID_VALUE,
4479 "glBindUniformLocationCHROMIUM", "Invalid character");
[email protected]2be6abf32012-06-26 00:28:334480 return;
4481 }
4482 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
[email protected]ab09b612013-03-11 22:11:514483 LOCAL_SET_GL_ERROR(
4484 GL_INVALID_OPERATION,
4485 "glBindUniformLocationCHROMIUM", "reserved prefix");
[email protected]2be6abf32012-06-26 00:28:334486 return;
4487 }
4488 if (location < 0 || static_cast<uint32>(location) >=
4489 (group_->max_fragment_uniform_vectors() +
4490 group_->max_vertex_uniform_vectors()) * 4) {
[email protected]ab09b612013-03-11 22:11:514491 LOCAL_SET_GL_ERROR(
4492 GL_INVALID_VALUE,
4493 "glBindUniformLocationCHROMIUM", "location out of range");
[email protected]2be6abf32012-06-26 00:28:334494 return;
4495 }
[email protected]df37b9932013-03-08 05:21:424496 Program* program = GetProgramInfoNotShader(
4497 program_id, "glBindUniformLocationCHROMIUM");
4498 if (!program) {
[email protected]2be6abf32012-06-26 00:28:334499 return;
4500 }
[email protected]df37b9932013-03-08 05:21:424501 if (!program->SetUniformLocationBinding(name, location)) {
[email protected]ab09b612013-03-11 22:11:514502 LOCAL_SET_GL_ERROR(
4503 GL_INVALID_VALUE,
4504 "glBindUniformLocationCHROMIUM", "location out of range");
[email protected]2be6abf32012-06-26 00:28:334505 }
4506}
4507
4508error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:354509 uint32 immediate_data_size, const cmds::BindUniformLocationCHROMIUM& c) {
[email protected]2be6abf32012-06-26 00:28:334510 GLuint program = static_cast<GLuint>(c.program);
4511 GLint location = static_cast<GLint>(c.location);
4512 uint32 name_size = c.data_size;
4513 const char* name = GetSharedMemoryAs<const char*>(
4514 c.name_shm_id, c.name_shm_offset, name_size);
4515 if (name == NULL) {
4516 return error::kOutOfBounds;
4517 }
4518 String name_str(name, name_size);
4519 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4520 return error::kNoError;
4521}
4522
4523error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMImmediate(
4524 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:354525 const cmds::BindUniformLocationCHROMIUMImmediate& c) {
[email protected]2be6abf32012-06-26 00:28:334526 GLuint program = static_cast<GLuint>(c.program);
4527 GLint location = static_cast<GLint>(c.location);
4528 uint32 name_size = c.data_size;
4529 const char* name = GetImmediateDataAs<const char*>(
4530 c, name_size, immediate_data_size);
4531 if (name == NULL) {
4532 return error::kOutOfBounds;
4533 }
4534 String name_str(name, name_size);
4535 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4536 return error::kNoError;
4537}
4538
4539error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4540 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:354541 const cmds::BindUniformLocationCHROMIUMBucket& c) {
[email protected]2be6abf32012-06-26 00:28:334542 GLuint program = static_cast<GLuint>(c.program);
4543 GLint location = static_cast<GLint>(c.location);
4544 Bucket* bucket = GetBucket(c.name_bucket_id);
4545 if (!bucket || bucket->size() == 0) {
4546 return error::kInvalidArguments;
4547 }
4548 std::string name_str;
4549 if (!bucket->GetAsString(&name_str)) {
4550 return error::kInvalidArguments;
4551 }
4552 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4553 return error::kNoError;
4554}
4555
[email protected]f7a64ee2010-02-01 22:24:144556error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ed9f9cd2013-02-27 21:12:354557 uint32 immediate_data_size, const cmds::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:034558 GLuint client_id = c.shader;
4559 if (client_id) {
[email protected]df37b9932013-03-08 05:21:424560 Shader* shader = GetShader(client_id);
4561 if (shader) {
4562 if (!shader->IsDeleted()) {
4563 glDeleteShader(shader->service_id());
4564 shader_manager()->MarkAsDeleted(shader);
[email protected]ca488e12010-12-13 20:06:144565 }
[email protected]ae51d192010-04-27 00:48:034566 } else {
[email protected]ab09b612013-03-11 22:11:514567 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
[email protected]ae51d192010-04-27 00:48:034568 }
[email protected]96449d2c2009-11-25 00:01:324569 }
[email protected]f7a64ee2010-02-01 22:24:144570 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324571}
4572
[email protected]f7a64ee2010-02-01 22:24:144573error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ed9f9cd2013-02-27 21:12:354574 uint32 immediate_data_size, const cmds::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:034575 GLuint client_id = c.program;
4576 if (client_id) {
[email protected]df37b9932013-03-08 05:21:424577 Program* program = GetProgram(client_id);
4578 if (program) {
4579 if (!program->IsDeleted()) {
4580 program_manager()->MarkAsDeleted(shader_manager(), program);
[email protected]ca488e12010-12-13 20:06:144581 }
[email protected]ae51d192010-04-27 00:48:034582 } else {
[email protected]ab09b612013-03-11 22:11:514583 LOCAL_SET_GL_ERROR(
4584 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
[email protected]ae51d192010-04-27 00:48:034585 }
[email protected]96449d2c2009-11-25 00:01:324586 }
[email protected]f7a64ee2010-02-01 22:24:144587 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324588}
4589
[email protected]269200b12010-11-18 22:53:064590void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104591 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574592 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104593 for (GLsizei ii = 0; ii < n; ++ii) {
4594 id_allocator->FreeID(ids[ii]);
4595 }
4596}
4597
[email protected]269200b12010-11-18 22:53:064598error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:354599 uint32 immediate_data_size, const cmds::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104600 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4601 GLsizei n = static_cast<GLsizei>(c.n);
4602 uint32 data_size;
4603 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4604 return error::kOutOfBounds;
4605 }
4606 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4607 c.ids_shm_id, c.ids_shm_offset, data_size);
4608 if (n < 0) {
[email protected]ab09b612013-03-11 22:11:514609 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104610 return error::kNoError;
4611 }
4612 if (ids == NULL) {
4613 return error::kOutOfBounds;
4614 }
[email protected]269200b12010-11-18 22:53:064615 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:104616 return error::kNoError;
4617}
4618
[email protected]269200b12010-11-18 22:53:064619void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104620 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574621 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104622 if (id_offset == 0) {
4623 for (GLsizei ii = 0; ii < n; ++ii) {
4624 ids[ii] = id_allocator->AllocateID();
4625 }
4626 } else {
4627 for (GLsizei ii = 0; ii < n; ++ii) {
4628 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4629 id_offset = ids[ii] + 1;
4630 }
4631 }
4632}
4633
[email protected]269200b12010-11-18 22:53:064634error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:354635 uint32 immediate_data_size, const cmds::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104636 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4637 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4638 GLsizei n = static_cast<GLsizei>(c.n);
4639 uint32 data_size;
4640 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4641 return error::kOutOfBounds;
4642 }
4643 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4644 c.ids_shm_id, c.ids_shm_offset, data_size);
4645 if (n < 0) {
[email protected]ab09b612013-03-11 22:11:514646 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104647 return error::kNoError;
4648 }
4649 if (ids == NULL) {
4650 return error::kOutOfBounds;
4651 }
[email protected]269200b12010-11-18 22:53:064652 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:104653 return error::kNoError;
4654}
4655
[email protected]269200b12010-11-18 22:53:064656void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104657 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574658 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104659 for (GLsizei ii = 0; ii < n; ++ii) {
4660 if (!id_allocator->MarkAsUsed(ids[ii])) {
4661 for (GLsizei jj = 0; jj < ii; ++jj) {
4662 id_allocator->FreeID(ids[jj]);
4663 }
[email protected]ab09b612013-03-11 22:11:514664 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:434665 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4666 "attempt to register id that already exists");
[email protected]066849e32010-05-03 19:14:104667 return;
4668 }
4669 }
4670}
4671
[email protected]269200b12010-11-18 22:53:064672error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:354673 uint32 immediate_data_size, const cmds::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104674 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4675 GLsizei n = static_cast<GLsizei>(c.n);
4676 uint32 data_size;
4677 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4678 return error::kOutOfBounds;
4679 }
4680 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4681 c.ids_shm_id, c.ids_shm_offset, data_size);
4682 if (n < 0) {
[email protected]ab09b612013-03-11 22:11:514683 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104684 return error::kNoError;
4685 }
4686 if (ids == NULL) {
4687 return error::kOutOfBounds;
4688 }
[email protected]269200b12010-11-18 22:53:064689 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:104690 return error::kNoError;
4691}
4692
[email protected]a7266a92012-06-28 02:11:084693error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
[email protected]09e17272012-11-30 10:30:444694 DCHECK(!ShouldDeferDraws());
[email protected]0d6bfdc2011-11-02 01:32:204695 if (CheckBoundFramebuffersValid("glClear")) {
[email protected]297ca1c2011-06-20 23:08:464696 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:274697 glClear(mask);
4698 }
[email protected]a7266a92012-06-28 02:11:084699 return error::kNoError;
4700}
4701
[email protected]36cef8ce2010-03-16 07:34:454702void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4703 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:034704 GLuint client_renderbuffer_id) {
[email protected]4d8f0dd2013-03-09 14:37:064705 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4706 if (!framebuffer) {
[email protected]ab09b612013-03-11 22:11:514707 LOCAL_SET_GL_ERROR(
4708 GL_INVALID_OPERATION,
4709 "glFramebufferRenderbuffer", "no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454710 return;
4711 }
[email protected]ae51d192010-04-27 00:48:034712 GLuint service_id = 0;
[email protected]ee2a79c32013-03-10 03:50:274713 Renderbuffer* renderbuffer = NULL;
[email protected]ae51d192010-04-27 00:48:034714 if (client_renderbuffer_id) {
[email protected]ee2a79c32013-03-10 03:50:274715 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
4716 if (!renderbuffer) {
[email protected]ab09b612013-03-11 22:11:514717 LOCAL_SET_GL_ERROR(
4718 GL_INVALID_OPERATION,
4719 "glFramebufferRenderbuffer", "unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:034720 return;
4721 }
[email protected]ee2a79c32013-03-10 03:50:274722 service_id = renderbuffer->service_id();
[email protected]ae51d192010-04-27 00:48:034723 }
[email protected]ab09b612013-03-11 22:11:514724 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
[email protected]ae51d192010-04-27 00:48:034725 glFramebufferRenderbufferEXT(
4726 target, attachment, renderbuffertarget, service_id);
[email protected]ab09b612013-03-11 22:11:514727 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
[email protected]9edc6b22010-12-23 02:00:264728 if (error == GL_NO_ERROR) {
[email protected]ee2a79c32013-03-10 03:50:274729 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
[email protected]3a2e7c7b2010-08-06 01:12:284730 }
[email protected]9d3b2e12013-10-02 01:04:344731 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
[email protected]c986af502013-08-14 01:04:444732 framebuffer_state_.clear_state_dirty = true;
[email protected]297ca1c2011-06-20 23:08:464733 }
[email protected]81fc9d02013-03-14 23:53:324734 OnFboChanged();
[email protected]3a2e7c7b2010-08-06 01:12:284735}
4736
[email protected]3a2e7c7b2010-08-06 01:12:284737void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464738 if (SetCapabilityState(cap, false)) {
4739 glDisable(cap);
4740 }
[email protected]3a2e7c7b2010-08-06 01:12:284741}
4742
4743void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464744 if (SetCapabilityState(cap, true)) {
4745 glEnable(cap);
4746 }
[email protected]3a2e7c7b2010-08-06 01:12:284747}
4748
[email protected]88a61bf2012-10-27 13:00:424749void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
4750 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
4751 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
4752 glDepthRange(znear, zfar);
[email protected]3a2e7c7b2010-08-06 01:12:284753}
4754
[email protected]b04e24c2013-01-08 18:35:254755void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
[email protected]88a61bf2012-10-27 13:00:424756 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
4757 state_.sample_coverage_invert = (invert != 0);
4758 glSampleCoverage(state_.sample_coverage_value, invert);
[email protected]3a2e7c7b2010-08-06 01:12:284759}
4760
[email protected]0d6bfdc2011-11-02 01:32:204761// Assumes framebuffer is complete.
4762void GLES2DecoderImpl::ClearUnclearedAttachments(
[email protected]4d8f0dd2013-03-09 14:37:064763 GLenum target, Framebuffer* framebuffer) {
[email protected]8e3e0662010-08-23 18:46:304764 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204765 // bind this to the DRAW point, clear then bind back to READ
4766 // TODO(gman): I don't think there is any guarantee that an FBO that
4767 // is complete on the READ attachment will be complete as a DRAW
4768 // attachment.
4769 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
[email protected]4d8f0dd2013-03-09 14:37:064770 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
[email protected]8e3e0662010-08-23 18:46:304771 }
[email protected]3a2e7c7b2010-08-06 01:12:284772 GLbitfield clear_bits = 0;
[email protected]4d8f0dd2013-03-09 14:37:064773 if (framebuffer->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:464774 glClearColor(
[email protected]0d6bfdc2011-11-02 01:32:204775 0.0f, 0.0f, 0.0f,
[email protected]297ca1c2011-06-20 23:08:464776 (GLES2Util::GetChannelsForFormat(
[email protected]4d8f0dd2013-03-09 14:37:064777 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
4778 1.0f);
[email protected]3a2e7c7b2010-08-06 01:12:284779 glColorMask(true, true, true, true);
4780 clear_bits |= GL_COLOR_BUFFER_BIT;
4781 }
4782
[email protected]4d8f0dd2013-03-09 14:37:064783 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4784 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
[email protected]3a2e7c7b2010-08-06 01:12:284785 glClearStencil(0);
4786 glStencilMask(-1);
4787 clear_bits |= GL_STENCIL_BUFFER_BIT;
4788 }
4789
[email protected]4d8f0dd2013-03-09 14:37:064790 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4791 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
[email protected]3a2e7c7b2010-08-06 01:12:284792 glClearDepth(1.0f);
4793 glDepthMask(true);
4794 clear_bits |= GL_DEPTH_BUFFER_BIT;
4795 }
4796
4797 glDisable(GL_SCISSOR_TEST);
4798 glClear(clear_bits);
4799
[email protected]968351b2011-12-20 08:26:514800 framebuffer_manager()->MarkAttachmentsAsCleared(
[email protected]4d8f0dd2013-03-09 14:37:064801 framebuffer, renderbuffer_manager(), texture_manager());
[email protected]3a2e7c7b2010-08-06 01:12:284802
[email protected]c007aa02010-09-02 22:22:404803 RestoreClearState();
4804
4805 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]4d8f0dd2013-03-09 14:37:064806 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
4807 Framebuffer* draw_framebuffer =
[email protected]87d1a3fe2011-12-01 04:25:484808 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]4d8f0dd2013-03-09 14:37:064809 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
4810 GetBackbufferServiceId();
[email protected]87d1a3fe2011-12-01 04:25:484811 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
[email protected]c007aa02010-09-02 22:22:404812 }
4813}
4814
4815void GLES2DecoderImpl::RestoreClearState() {
[email protected]c986af502013-08-14 01:04:444816 framebuffer_state_.clear_state_dirty = true;
[email protected]e259eb412012-10-13 05:47:244817 glClearColor(
4818 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
4819 state_.color_clear_alpha);
4820 glClearStencil(state_.stencil_clear);
4821 glClearDepth(state_.depth_clear);
[email protected]f731b9462012-10-30 00:35:224822 if (state_.enable_flags.scissor_test) {
[email protected]3a2e7c7b2010-08-06 01:12:284823 glEnable(GL_SCISSOR_TEST);
4824 }
[email protected]36cef8ce2010-03-16 07:34:454825}
4826
4827GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]ed9f9cd2013-02-27 21:12:354828 Framebuffer* framebuffer =
[email protected]8e3e0662010-08-23 18:46:304829 GetFramebufferInfoForTarget(target);
[email protected]0d6bfdc2011-11-02 01:32:204830 if (!framebuffer) {
[email protected]36cef8ce2010-03-16 07:34:454831 return GL_FRAMEBUFFER_COMPLETE;
4832 }
[email protected]0d6bfdc2011-11-02 01:32:204833 GLenum completeness = framebuffer->IsPossiblyComplete();
4834 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4835 return completeness;
4836 }
[email protected]73276522012-11-09 05:50:204837 return framebuffer->GetStatus(texture_manager(), target);
[email protected]36cef8ce2010-03-16 07:34:454838}
4839
4840void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:034841 GLenum target, GLenum attachment, GLenum textarget,
4842 GLuint client_texture_id, GLint level) {
[email protected]7d3c36e2013-07-12 14:13:164843 DoFramebufferTexture2DCommon(
4844 "glFramebufferTexture2D", target, attachment,
4845 textarget, client_texture_id, level, 0);
4846}
4847
4848void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
4849 GLenum target, GLenum attachment, GLenum textarget,
4850 GLuint client_texture_id, GLint level, GLsizei samples) {
4851 if (!features().multisampled_render_to_texture) {
4852 LOCAL_SET_GL_ERROR(
4853 GL_INVALID_OPERATION,
4854 "glFramebufferTexture2DMultisample", "function not available");
4855 return;
4856 }
4857 DoFramebufferTexture2DCommon(
4858 "glFramebufferTexture2DMultisample", target, attachment,
4859 textarget, client_texture_id, level, samples);
4860}
4861
4862void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
4863 const char* name, GLenum target, GLenum attachment, GLenum textarget,
4864 GLuint client_texture_id, GLint level, GLsizei samples) {
4865 if (samples > renderbuffer_manager()->max_samples()) {
4866 LOCAL_SET_GL_ERROR(
4867 GL_INVALID_VALUE,
4868 "glFramebufferTexture2DMultisample", "samples too large");
4869 return;
4870 }
[email protected]4d8f0dd2013-03-09 14:37:064871 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4872 if (!framebuffer) {
[email protected]ab09b612013-03-11 22:11:514873 LOCAL_SET_GL_ERROR(
4874 GL_INVALID_OPERATION,
[email protected]7d3c36e2013-07-12 14:13:164875 name, "no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:454876 return;
4877 }
[email protected]ae51d192010-04-27 00:48:034878 GLuint service_id = 0;
[email protected]370eaf12013-05-18 09:19:494879 TextureRef* texture_ref = NULL;
[email protected]ae51d192010-04-27 00:48:034880 if (client_texture_id) {
[email protected]370eaf12013-05-18 09:19:494881 texture_ref = GetTexture(client_texture_id);
4882 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:514883 LOCAL_SET_GL_ERROR(
4884 GL_INVALID_OPERATION,
[email protected]7d3c36e2013-07-12 14:13:164885 name, "unknown texture_ref");
[email protected]ae51d192010-04-27 00:48:034886 return;
4887 }
[email protected]370eaf12013-05-18 09:19:494888 service_id = texture_ref->service_id();
[email protected]ae51d192010-04-27 00:48:034889 }
[email protected]0d6bfdc2011-11-02 01:32:204890
[email protected]80eb6b52012-01-19 00:14:414891 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
[email protected]ab09b612013-03-11 22:11:514892 LOCAL_SET_GL_ERROR(
4893 GL_INVALID_VALUE,
[email protected]7d3c36e2013-07-12 14:13:164894 name, "level out of range");
[email protected]0d6bfdc2011-11-02 01:32:204895 return;
4896 }
4897
[email protected]7d3c36e2013-07-12 14:13:164898 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
4899 if (0 == samples) {
4900 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
4901 } else {
4902 if (features().use_img_for_multisampled_render_to_texture) {
4903 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
4904 service_id, level, samples);
4905 } else {
4906 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
4907 service_id, level, samples);
4908 }
4909 }
4910 GLenum error = LOCAL_PEEK_GL_ERROR(name);
[email protected]9edc6b22010-12-23 02:00:264911 if (error == GL_NO_ERROR) {
[email protected]7d3c36e2013-07-12 14:13:164912 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
4913 samples);
[email protected]3a2e7c7b2010-08-06 01:12:284914 }
[email protected]9d3b2e12013-10-02 01:04:344915 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
[email protected]c986af502013-08-14 01:04:444916 framebuffer_state_.clear_state_dirty = true;
[email protected]297ca1c2011-06-20 23:08:464917 }
[email protected]81fc9d02013-03-14 23:53:324918 OnFboChanged();
[email protected]36cef8ce2010-03-16 07:34:454919}
4920
4921void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4922 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]4d8f0dd2013-03-09 14:37:064923 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4924 if (!framebuffer) {
[email protected]ab09b612013-03-11 22:11:514925 LOCAL_SET_GL_ERROR(
4926 GL_INVALID_OPERATION,
4927 "glFramebufferAttachmentParameteriv", "no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454928 return;
4929 }
[email protected]74c1ec42010-08-12 01:55:574930 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
[email protected]62e65f02013-05-29 22:28:104931 const Framebuffer::Attachment* attachment_object =
4932 framebuffer->GetAttachment(attachment);
4933 *params = attachment_object ? attachment_object->object_name() : 0;
4934 } else {
[email protected]7d3c36e2013-07-12 14:13:164935 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
4936 features().use_img_for_multisampled_render_to_texture) {
4937 pname = GL_TEXTURE_SAMPLES_IMG;
4938 }
[email protected]62e65f02013-05-29 22:28:104939 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:574940 }
[email protected]36cef8ce2010-03-16 07:34:454941}
4942
4943void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4944 GLenum target, GLenum pname, GLint* params) {
[email protected]ed9f9cd2013-02-27 21:12:354945 Renderbuffer* renderbuffer =
[email protected]0d6bfdc2011-11-02 01:32:204946 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4947 if (!renderbuffer) {
[email protected]ab09b612013-03-11 22:11:514948 LOCAL_SET_GL_ERROR(
4949 GL_INVALID_OPERATION,
4950 "glGetRenderbufferParameteriv", "no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454951 return;
4952 }
[email protected]3a03a8f2011-03-19 00:51:274953 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:434954 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4955 *params = renderbuffer->internal_format();
4956 break;
4957 case GL_RENDERBUFFER_WIDTH:
4958 *params = renderbuffer->width();
4959 break;
4960 case GL_RENDERBUFFER_HEIGHT:
4961 *params = renderbuffer->height();
4962 break;
[email protected]7d3c36e2013-07-12 14:13:164963 case GL_RENDERBUFFER_SAMPLES_EXT:
4964 if (features().use_img_for_multisampled_render_to_texture) {
4965 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
4966 params);
4967 } else {
4968 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
4969 params);
4970 }
[email protected]ad84a3a2012-06-08 21:42:434971 default:
4972 glGetRenderbufferParameterivEXT(target, pname, params);
4973 break;
[email protected]b71f52c2010-06-18 22:20:204974 }
[email protected]36cef8ce2010-03-16 07:34:454975}
4976
[email protected]8e3e0662010-08-23 18:46:304977void GLES2DecoderImpl::DoBlitFramebufferEXT(
4978 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
4979 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
4980 GLbitfield mask, GLenum filter) {
[email protected]09e17272012-11-30 10:30:444981 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
[email protected]62e155e2012-10-23 22:43:154982 if (!features().chromium_framebuffer_multisample) {
[email protected]ab09b612013-03-11 22:11:514983 LOCAL_SET_GL_ERROR(
4984 GL_INVALID_OPERATION,
4985 "glBlitFramebufferEXT", "function not available");
[email protected]8e3e0662010-08-23 18:46:304986 }
[email protected]0c16343f2013-03-08 20:40:164987
4988 if (!CheckBoundFramebuffersValid("glBlitFramebufferEXT")) {
4989 return;
4990 }
4991
[email protected]d058bca2012-11-26 10:27:264992 glDisable(GL_SCISSOR_TEST);
[email protected]5094b0f2010-11-09 19:45:244993 if (IsAngle()) {
4994 glBlitFramebufferANGLE(
4995 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4996 } else {
4997 glBlitFramebufferEXT(
4998 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4999 }
[email protected]d058bca2012-11-26 10:27:265000 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
[email protected]8e3e0662010-08-23 18:46:305001}
5002
5003void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
5004 GLenum target, GLsizei samples, GLenum internalformat,
5005 GLsizei width, GLsizei height) {
[email protected]7d3c36e2013-07-12 14:13:165006 if (!features().chromium_framebuffer_multisample &&
5007 !features().multisampled_render_to_texture) {
[email protected]ab09b612013-03-11 22:11:515008 LOCAL_SET_GL_ERROR(
5009 GL_INVALID_OPERATION,
5010 "glRenderbufferStorageMultisample", "function not available");
[email protected]8e3e0662010-08-23 18:46:305011 return;
5012 }
[email protected]8e3e0662010-08-23 18:46:305013
[email protected]ed9f9cd2013-02-27 21:12:355014 Renderbuffer* renderbuffer =
[email protected]0d6bfdc2011-11-02 01:32:205015 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5016 if (!renderbuffer) {
[email protected]ab09b612013-03-11 22:11:515017 LOCAL_SET_GL_ERROR(
5018 GL_INVALID_OPERATION,
5019 "glRenderbufferStorageMultisample", "no renderbuffer bound");
[email protected]0d6bfdc2011-11-02 01:32:205020 return;
5021 }
5022
[email protected]84afefa2011-10-19 21:45:535023 if (samples > renderbuffer_manager()->max_samples()) {
[email protected]ab09b612013-03-11 22:11:515024 LOCAL_SET_GL_ERROR(
5025 GL_INVALID_VALUE,
5026 "glRenderbufferStorageMultisample", "samples too large");
[email protected]84afefa2011-10-19 21:45:535027 return;
5028 }
5029
5030 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5031 height > renderbuffer_manager()->max_renderbuffer_size()) {
[email protected]ab09b612013-03-11 22:11:515032 LOCAL_SET_GL_ERROR(
5033 GL_INVALID_VALUE,
5034 "glRenderbufferStorageMultisample", "dimensions too large");
[email protected]84afefa2011-10-19 21:45:535035 return;
5036 }
5037
[email protected]7989c9e2013-01-23 06:39:265038 uint32 estimated_size = 0;
[email protected]8e102e102013-09-20 22:50:235039 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5040 width, height, samples, internalformat, &estimated_size)) {
[email protected]ab09b612013-03-11 22:11:515041 LOCAL_SET_GL_ERROR(
5042 GL_OUT_OF_MEMORY,
5043 "glRenderbufferStorageMultsample", "dimensions too large");
[email protected]7989c9e2013-01-23 06:39:265044 return;
[email protected]8e3e0662010-08-23 18:46:305045 }
5046
[email protected]7989c9e2013-01-23 06:39:265047 if (!EnsureGPUMemoryAvailable(estimated_size)) {
[email protected]ab09b612013-03-11 22:11:515048 LOCAL_SET_GL_ERROR(
5049 GL_OUT_OF_MEMORY,
5050 "glRenderbufferStorageMultsample", "out of memory");
[email protected]7989c9e2013-01-23 06:39:265051 return;
5052 }
5053
[email protected]8e102e102013-09-20 22:50:235054 GLenum impl_format =
5055 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5056 internalformat);
[email protected]ab09b612013-03-11 22:11:515057 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisample");
[email protected]866b91c52011-03-23 14:38:085058 if (IsAngle()) {
5059 glRenderbufferStorageMultisampleANGLE(
5060 target, samples, impl_format, width, height);
[email protected]7d3c36e2013-07-12 14:13:165061 } else if (features().use_img_for_multisampled_render_to_texture) {
5062 glRenderbufferStorageMultisampleIMG(
5063 target, samples, impl_format, width, height);
[email protected]866b91c52011-03-23 14:38:085064 } else {
5065 glRenderbufferStorageMultisampleEXT(
5066 target, samples, impl_format, width, height);
5067 }
[email protected]ab09b612013-03-11 22:11:515068 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisample");
[email protected]9edc6b22010-12-23 02:00:265069 if (error == GL_NO_ERROR) {
[email protected]4a4c18b2013-09-13 22:50:105070
5071 if (workarounds().validate_multisample_buffer_allocation) {
5072 if (!VerifyMultisampleRenderbufferIntegrity(
5073 renderbuffer->service_id(), impl_format)) {
5074 LOCAL_SET_GL_ERROR(
5075 GL_OUT_OF_MEMORY,
5076 "glRenderbufferStorageMultisample", "out of memory");
5077 return;
5078 }
5079 }
5080
[email protected]968351b2011-12-20 08:26:515081 // TODO(gman): If renderbuffers tracked which framebuffers they were
5082 // attached to we could just mark those framebuffers as not complete.
5083 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:205084 renderbuffer_manager()->SetInfo(
5085 renderbuffer, samples, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:265086 }
[email protected]8e3e0662010-08-23 18:46:305087}
5088
[email protected]4a4c18b2013-09-13 22:50:105089// This function validates the allocation of a multisampled renderbuffer
5090// by clearing it to a key color, blitting the contents to a texture, and
5091// reading back the color to ensure it matches the key.
5092bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
5093 GLuint renderbuffer, GLenum format) {
5094
5095 // Only validate color buffers.
5096 // These formats have been selected because they are very common or are known
5097 // to be used by the WebGL backbuffer. If problems are observed with other
5098 // color formats they can be added here.
5099 switch(format) {
5100 case GL_RGB:
5101 case GL_RGB8:
5102 case GL_RGBA:
5103 case GL_RGBA8:
5104 break;
5105 default:
5106 return true;
5107 }
5108
5109 GLint draw_framebuffer, read_framebuffer;
5110
5111 // Cache framebuffer and texture bindings.
5112 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
5113 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
5114
5115 if (!validation_texture_) {
5116 GLint bound_texture;
5117 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
5118
5119 // Create additional resources needed for the verification.
5120 glGenTextures(1, &validation_texture_);
5121 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
5122 glGenFramebuffersEXT(1, &validation_fbo_);
5123
5124 // Texture only needs to be 1x1.
5125 glBindTexture(GL_TEXTURE_2D, validation_texture_);
5126 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB,
5127 GL_UNSIGNED_BYTE, NULL);
5128
5129 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5130 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5131 GL_TEXTURE_2D, validation_texture_, 0);
5132
5133 glBindTexture(GL_TEXTURE_2D, bound_texture);
5134 }
5135
5136 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5137 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5138 GL_RENDERBUFFER, renderbuffer);
5139
5140 // Cache current state and reset it to the values we require.
5141 GLboolean scissor_enabled = false;
5142 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
5143 if (scissor_enabled)
5144 glDisable(GL_SCISSOR_TEST);
5145
5146 GLboolean color_mask[4] = {true, true, true, true};
5147 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
5148 glColorMask(true, true, true, true);
5149
5150 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5151 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
5152 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
5153
5154 // Clear the buffer to the desired key color.
5155 glClear(GL_COLOR_BUFFER_BIT);
5156
5157 // Blit from the multisample buffer to a standard texture.
5158 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
5159 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
5160
5161 glBlitFramebufferEXT(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5162
5163 // Read a pixel from the buffer.
5164 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
5165
5166 unsigned char pixel[3] = {0, 0, 0};
5167 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
5168
5169 // Detach the renderbuffer.
5170 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
5171 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5172 GL_RENDERBUFFER, 0);
5173
5174 // Restore cached state.
5175 if (scissor_enabled)
5176 glEnable(GL_SCISSOR_TEST);
5177
5178 glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
5179 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
5180 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
5181 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
5182
5183 // Return true if the pixel matched the desired key color.
5184 return (pixel[0] == 0xFF &&
5185 pixel[1] == 0x00 &&
5186 pixel[2] == 0xFF);
5187}
5188
[email protected]36cef8ce2010-03-16 07:34:455189void GLES2DecoderImpl::DoRenderbufferStorage(
5190 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]ed9f9cd2013-02-27 21:12:355191 Renderbuffer* renderbuffer =
[email protected]0d6bfdc2011-11-02 01:32:205192 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5193 if (!renderbuffer) {
[email protected]ab09b612013-03-11 22:11:515194 LOCAL_SET_GL_ERROR(
5195 GL_INVALID_OPERATION,
5196 "glRenderbufferStorage", "no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:455197 return;
5198 }
[email protected]876f6fee2010-08-02 23:10:325199
[email protected]84afefa2011-10-19 21:45:535200 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5201 height > renderbuffer_manager()->max_renderbuffer_size()) {
[email protected]ab09b612013-03-11 22:11:515202 LOCAL_SET_GL_ERROR(
5203 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
[email protected]84afefa2011-10-19 21:45:535204 return;
5205 }
5206
[email protected]7989c9e2013-01-23 06:39:265207 uint32 estimated_size = 0;
[email protected]8e102e102013-09-20 22:50:235208 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
5209 width, height, 1, internalformat, &estimated_size)) {
[email protected]ab09b612013-03-11 22:11:515210 LOCAL_SET_GL_ERROR(
5211 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
[email protected]7989c9e2013-01-23 06:39:265212 return;
5213 }
5214
5215 if (!EnsureGPUMemoryAvailable(estimated_size)) {
[email protected]ab09b612013-03-11 22:11:515216 LOCAL_SET_GL_ERROR(
5217 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
[email protected]7989c9e2013-01-23 06:39:265218 return;
[email protected]b71f52c2010-06-18 22:20:205219 }
[email protected]876f6fee2010-08-02 23:10:325220
[email protected]ab09b612013-03-11 22:11:515221 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
[email protected]7989c9e2013-01-23 06:39:265222 glRenderbufferStorageEXT(
[email protected]8e102e102013-09-20 22:50:235223 target,
5224 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
5225 internalformat),
5226 width,
5227 height);
[email protected]ab09b612013-03-11 22:11:515228 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
[email protected]9edc6b22010-12-23 02:00:265229 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:515230 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5231 // we could just mark those framebuffers as not complete.
5232 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:205233 renderbuffer_manager()->SetInfo(
[email protected]7989c9e2013-01-23 06:39:265234 renderbuffer, 1, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:265235 }
[email protected]36cef8ce2010-03-16 07:34:455236}
5237
[email protected]df37b9932013-03-08 05:21:425238void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
[email protected]43ed3a72012-05-30 22:55:385239 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]df37b9932013-03-08 05:21:425240 Program* program = GetProgramInfoNotShader(
5241 program_id, "glLinkProgram");
5242 if (!program) {
[email protected]a93bb842010-02-16 23:03:475243 return;
5244 }
[email protected]05afda12011-01-20 00:17:345245
[email protected]df37b9932013-03-08 05:21:425246 LogClientServiceForInfo(program, program_id, "glLinkProgram");
[email protected]65dfc602012-07-23 20:39:395247 ShaderTranslator* vertex_translator = NULL;
5248 ShaderTranslator* fragment_translator = NULL;
5249 if (use_shader_translator_) {
[email protected]7cd76fd2013-06-02 21:11:115250 vertex_translator = vertex_translator_.get();
5251 fragment_translator = fragment_translator_.get();
[email protected]65dfc602012-07-23 20:39:395252 }
[email protected]df37b9932013-03-08 05:21:425253 if (program->Link(shader_manager(),
[email protected]7cd76fd2013-06-02 21:11:115254 vertex_translator,
5255 fragment_translator,
5256 feature_info_.get(),
5257 shader_cache_callback_)) {
[email protected]df37b9932013-03-08 05:21:425258 if (program == state_.current_program.get()) {
[email protected]62e155e2012-10-23 22:43:155259 if (workarounds().use_current_program_after_successful_link) {
[email protected]df37b9932013-03-08 05:21:425260 glUseProgram(program->service_id());
[email protected]c2a3caf12012-10-23 19:32:005261 }
[email protected]df37b9932013-03-08 05:21:425262 program_manager()->ClearUniforms(program);
[email protected]2df73892012-04-28 01:09:545263 }
5264 }
[email protected]07f54fcc2009-12-22 02:46:305265};
5266
[email protected]3916c97e2010-02-25 03:20:505267void GLES2DecoderImpl::DoTexParameterf(
5268 GLenum target, GLenum pname, GLfloat param) {
[email protected]c986af502013-08-14 01:04:445269 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5270 &state_, target);
[email protected]02965c22013-03-09 02:40:075271 if (!texture) {
[email protected]ab09b612013-03-11 22:11:515272 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:245273 return;
[email protected]07f54fcc2009-12-22 02:46:305274 }
[email protected]cbb22e42011-05-12 23:36:245275
[email protected]02965c22013-03-09 02:40:075276 texture_manager()->SetParameter(
[email protected]d3eba342013-04-18 21:11:505277 "glTexParameterf", GetErrorState(), texture, pname,
5278 static_cast<GLint>(param));
[email protected]07f54fcc2009-12-22 02:46:305279}
5280
[email protected]3916c97e2010-02-25 03:20:505281void GLES2DecoderImpl::DoTexParameteri(
5282 GLenum target, GLenum pname, GLint param) {
[email protected]c986af502013-08-14 01:04:445283 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5284 &state_, target);
[email protected]02965c22013-03-09 02:40:075285 if (!texture) {
[email protected]ab09b612013-03-11 22:11:515286 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:245287 return;
[email protected]3916c97e2010-02-25 03:20:505288 }
[email protected]cbb22e42011-05-12 23:36:245289
[email protected]02965c22013-03-09 02:40:075290 texture_manager()->SetParameter(
[email protected]d3eba342013-04-18 21:11:505291 "glTexParameteri", GetErrorState(), texture, pname, param);
[email protected]3916c97e2010-02-25 03:20:505292}
5293
5294void GLES2DecoderImpl::DoTexParameterfv(
5295 GLenum target, GLenum pname, const GLfloat* params) {
[email protected]c986af502013-08-14 01:04:445296 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5297 &state_, target);
[email protected]02965c22013-03-09 02:40:075298 if (!texture) {
[email protected]ab09b612013-03-11 22:11:515299 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:245300 return;
[email protected]3916c97e2010-02-25 03:20:505301 }
[email protected]cbb22e42011-05-12 23:36:245302
[email protected]02965c22013-03-09 02:40:075303 texture_manager()->SetParameter(
[email protected]d3eba342013-04-18 21:11:505304 "glTexParameterfv", GetErrorState(), texture, pname,
5305 static_cast<GLint>(params[0]));
[email protected]3916c97e2010-02-25 03:20:505306}
5307
5308void GLES2DecoderImpl::DoTexParameteriv(
5309 GLenum target, GLenum pname, const GLint* params) {
[email protected]c986af502013-08-14 01:04:445310 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5311 &state_, target);
[email protected]02965c22013-03-09 02:40:075312 if (!texture) {
[email protected]ab09b612013-03-11 22:11:515313 LOCAL_SET_GL_ERROR(
5314 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:245315 return;
[email protected]3916c97e2010-02-25 03:20:505316 }
[email protected]cbb22e42011-05-12 23:36:245317
[email protected]02965c22013-03-09 02:40:075318 texture_manager()->SetParameter(
[email protected]d3eba342013-04-18 21:11:505319 "glTexParameteriv", GetErrorState(), texture, pname, *params);
[email protected]3916c97e2010-02-25 03:20:505320}
5321
[email protected]939e7362010-05-13 20:49:105322bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]7cd76fd2013-06-02 21:11:115323 if (!state_.current_program.get()) {
[email protected]ad84a3a2012-06-08 21:42:435324 // The program does not exist.
[email protected]ab09b612013-03-11 22:11:515325 LOCAL_SET_GL_ERROR(
5326 GL_INVALID_OPERATION, function_name, "no program in use");
[email protected]ad84a3a2012-06-08 21:42:435327 return false;
[email protected]939e7362010-05-13 20:49:105328 }
[email protected]e259eb412012-10-13 05:47:245329 if (!state_.current_program->InUse()) {
[email protected]ab09b612013-03-11 22:11:515330 LOCAL_SET_GL_ERROR(
5331 GL_INVALID_OPERATION, function_name, "program not linked");
[email protected]939e7362010-05-13 20:49:105332 return false;
5333 }
5334 return true;
5335}
5336
5337bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5338 GLint location, const char* function_name) {
5339 if (!CheckCurrentProgram(function_name)) {
5340 return false;
5341 }
5342 return location != -1;
5343}
5344
[email protected]476ccb72012-12-06 15:52:525345namespace {
5346
5347static const GLenum valid_int_vec1_types_list[] = {
5348 GL_INT,
5349 GL_BOOL,
5350 GL_SAMPLER_2D,
5351 GL_SAMPLER_2D_RECT_ARB,
5352 GL_SAMPLER_CUBE,
5353 GL_SAMPLER_EXTERNAL_OES,
5354};
5355
5356static const GLenum valid_int_vec2_types_list[] = {
5357 GL_INT_VEC2,
5358 GL_BOOL_VEC2,
5359};
5360
5361static const GLenum valid_int_vec3_types_list[] = {
5362 GL_INT_VEC3,
5363 GL_BOOL_VEC3,
5364};
5365
5366static const GLenum valid_int_vec4_types_list[] = {
5367 GL_INT_VEC4,
5368 GL_BOOL_VEC4,
5369};
5370
5371static const GLenum valid_float_vec1_types_list[] = {
5372 GL_FLOAT,
5373 GL_BOOL,
5374};
5375
5376static const GLenum valid_float_vec2_types_list[] = {
5377 GL_FLOAT_VEC2,
5378 GL_BOOL_VEC2,
5379};
5380
5381static const GLenum valid_float_vec3_types_list[] = {
5382 GL_FLOAT_VEC3,
5383 GL_BOOL_VEC3,
5384};
5385
5386static const GLenum valid_float_vec4_types_list[] = {
5387 GL_FLOAT_VEC4,
5388 GL_BOOL_VEC4,
5389};
5390
5391static const GLenum valid_float_mat2_types_list[] = {
5392 GL_FLOAT_MAT2,
5393};
5394
5395static const GLenum valid_float_mat3_types_list[] = {
5396 GL_FLOAT_MAT3,
5397};
5398
5399static const GLenum valid_float_mat4_types_list[] = {
5400 GL_FLOAT_MAT4,
5401};
5402
5403static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec1_base_info = {
5404 valid_int_vec1_types_list,
5405 arraysize(valid_int_vec1_types_list),
5406};
5407
5408static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec2_base_info = {
5409 valid_int_vec2_types_list,
5410 arraysize(valid_int_vec2_types_list),
5411};
5412
5413static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec3_base_info = {
5414 valid_int_vec3_types_list,
5415 arraysize(valid_int_vec3_types_list),
5416};
5417
5418static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec4_base_info = {
5419 valid_int_vec4_types_list,
5420 arraysize(valid_int_vec4_types_list),
5421};
5422
5423static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec1_base_info = {
5424 valid_float_vec1_types_list,
5425 arraysize(valid_float_vec1_types_list),
5426};
5427
5428static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec2_base_info = {
5429 valid_float_vec2_types_list,
5430 arraysize(valid_float_vec2_types_list),
5431};
5432
5433static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec3_base_info = {
5434 valid_float_vec3_types_list,
5435 arraysize(valid_float_vec3_types_list),
5436};
5437
5438static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec4_base_info = {
5439 valid_float_vec4_types_list,
5440 arraysize(valid_float_vec4_types_list),
5441};
5442
5443static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat2_base_info = {
5444 valid_float_mat2_types_list,
5445 arraysize(valid_float_mat2_types_list),
5446};
5447
5448static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat3_base_info = {
5449 valid_float_mat3_types_list,
5450 arraysize(valid_float_mat3_types_list),
5451};
5452
5453static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat4_base_info = {
5454 valid_float_mat4_types_list,
5455 arraysize(valid_float_mat4_types_list),
5456};
5457
5458} // anonymous namespace.
5459
[email protected]43c2f1f2011-03-25 18:35:365460bool GLES2DecoderImpl::PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:125461 GLint fake_location, const char* function_name,
[email protected]476ccb72012-12-06 15:52:525462 const GLES2DecoderImpl::BaseUniformInfo& base_info,
[email protected]1b0a6752012-02-22 03:44:125463 GLint* real_location, GLenum* type, GLsizei* count) {
[email protected]43c2f1f2011-03-25 18:35:365464 DCHECK(type);
5465 DCHECK(count);
[email protected]1b0a6752012-02-22 03:44:125466 DCHECK(real_location);
[email protected]476ccb72012-12-06 15:52:525467
[email protected]1b0a6752012-02-22 03:44:125468 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
[email protected]939e7362010-05-13 20:49:105469 return false;
5470 }
[email protected]43c2f1f2011-03-25 18:35:365471 GLint array_index = -1;
[email protected]ed9f9cd2013-02-27 21:12:355472 const Program::UniformInfo* info =
[email protected]e259eb412012-10-13 05:47:245473 state_.current_program->GetUniformInfoByFakeLocation(
[email protected]1b0a6752012-02-22 03:44:125474 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:365475 if (!info) {
[email protected]ab09b612013-03-11 22:11:515476 LOCAL_SET_GL_ERROR(
5477 GL_INVALID_OPERATION, function_name, "unknown location");
[email protected]939e7362010-05-13 20:49:105478 return false;
5479 }
[email protected]476ccb72012-12-06 15:52:525480 bool okay = false;
5481 for (size_t ii = 0; ii < base_info.num_valid_types; ++ii) {
5482 if (base_info.valid_types[ii] == info->type) {
5483 okay = true;
5484 break;
5485 }
5486 }
5487 if (!okay) {
[email protected]ab09b612013-03-11 22:11:515488 LOCAL_SET_GL_ERROR(
5489 GL_INVALID_OPERATION, function_name,
5490 "wrong uniform function for type");
[email protected]476ccb72012-12-06 15:52:525491 return false;
5492 }
[email protected]43c2f1f2011-03-25 18:35:365493 if (*count > 1 && !info->is_array) {
[email protected]ab09b612013-03-11 22:11:515494 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:435495 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
[email protected]43c2f1f2011-03-25 18:35:365496 return false;
5497 }
5498 *count = std::min(info->size - array_index, *count);
5499 if (*count <= 0) {
5500 return false;
5501 }
5502 *type = info->type;
[email protected]939e7362010-05-13 20:49:105503 return true;
5504}
5505
[email protected]1b0a6752012-02-22 03:44:125506void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5507 GLenum type = 0;
5508 GLsizei count = 1;
5509 GLint real_location = -1;
5510 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525511 fake_location, "glUniform1iv", valid_int_vec1_base_info,
5512 &real_location, &type, &count)) {
[email protected]3916c97e2010-02-25 03:20:505513 return;
5514 }
[email protected]e259eb412012-10-13 05:47:245515 if (!state_.current_program->SetSamplers(
[email protected]1868a342012-11-07 15:56:025516 state_.texture_units.size(), fake_location, 1, &v0)) {
[email protected]ab09b612013-03-11 22:11:515517 LOCAL_SET_GL_ERROR(
5518 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
[email protected]d20a6512012-05-02 20:17:465519 return;
5520 }
[email protected]1b0a6752012-02-22 03:44:125521 glUniform1i(real_location, v0);
[email protected]3916c97e2010-02-25 03:20:505522}
5523
5524void GLES2DecoderImpl::DoUniform1iv(
[email protected]1b0a6752012-02-22 03:44:125525 GLint fake_location, GLsizei count, const GLint *value) {
[email protected]43c2f1f2011-03-25 18:35:365526 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125527 GLint real_location = -1;
5528 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525529 fake_location, "glUniform1iv", valid_int_vec1_base_info,
5530 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365531 return;
5532 }
[email protected]74727112012-06-13 21:18:085533 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5534 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]e259eb412012-10-13 05:47:245535 if (!state_.current_program->SetSamplers(
[email protected]1868a342012-11-07 15:56:025536 state_.texture_units.size(), fake_location, count, value)) {
[email protected]ab09b612013-03-11 22:11:515537 LOCAL_SET_GL_ERROR(
5538 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
[email protected]d20a6512012-05-02 20:17:465539 return;
5540 }
[email protected]43c2f1f2011-03-25 18:35:365541 }
[email protected]1b0a6752012-02-22 03:44:125542 glUniform1iv(real_location, count, value);
[email protected]3916c97e2010-02-25 03:20:505543}
5544
[email protected]939e7362010-05-13 20:49:105545void GLES2DecoderImpl::DoUniform1fv(
[email protected]1b0a6752012-02-22 03:44:125546 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365547 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125548 GLint real_location = -1;
5549 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525550 fake_location, "glUniform1fv", valid_float_vec1_base_info,
5551 &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:105552 return;
5553 }
5554 if (type == GL_BOOL) {
[email protected]40d90a22013-04-09 03:39:555555 scoped_ptr<GLint[]> temp(new GLint[count]);
[email protected]939e7362010-05-13 20:49:105556 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:535557 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:105558 }
[email protected]1b0a6752012-02-22 03:44:125559 DoUniform1iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:105560 } else {
[email protected]1b0a6752012-02-22 03:44:125561 glUniform1fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:105562 }
5563}
5564
5565void GLES2DecoderImpl::DoUniform2fv(
[email protected]1b0a6752012-02-22 03:44:125566 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365567 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125568 GLint real_location = -1;
5569 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525570 fake_location, "glUniform2fv", valid_float_vec2_base_info,
5571 &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:105572 return;
5573 }
5574 if (type == GL_BOOL_VEC2) {
5575 GLsizei num_values = count * 2;
[email protected]40d90a22013-04-09 03:39:555576 scoped_ptr<GLint[]> temp(new GLint[num_values]);
[email protected]939e7362010-05-13 20:49:105577 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:535578 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:105579 }
[email protected]1b0a6752012-02-22 03:44:125580 glUniform2iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:105581 } else {
[email protected]1b0a6752012-02-22 03:44:125582 glUniform2fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:105583 }
5584}
5585
5586void GLES2DecoderImpl::DoUniform3fv(
[email protected]1b0a6752012-02-22 03:44:125587 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365588 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125589 GLint real_location = -1;
5590 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525591 fake_location, "glUniform3fv", valid_float_vec3_base_info,
5592 &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:105593 return;
5594 }
5595 if (type == GL_BOOL_VEC3) {
5596 GLsizei num_values = count * 3;
[email protected]40d90a22013-04-09 03:39:555597 scoped_ptr<GLint[]> temp(new GLint[num_values]);
[email protected]939e7362010-05-13 20:49:105598 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:535599 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:105600 }
[email protected]1b0a6752012-02-22 03:44:125601 glUniform3iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:105602 } else {
[email protected]1b0a6752012-02-22 03:44:125603 glUniform3fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:105604 }
5605}
5606
5607void GLES2DecoderImpl::DoUniform4fv(
[email protected]1b0a6752012-02-22 03:44:125608 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365609 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125610 GLint real_location = -1;
5611 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525612 fake_location, "glUniform4fv", valid_float_vec4_base_info,
5613 &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:105614 return;
5615 }
5616 if (type == GL_BOOL_VEC4) {
5617 GLsizei num_values = count * 4;
[email protected]40d90a22013-04-09 03:39:555618 scoped_ptr<GLint[]> temp(new GLint[num_values]);
[email protected]939e7362010-05-13 20:49:105619 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:535620 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:105621 }
[email protected]1b0a6752012-02-22 03:44:125622 glUniform4iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:105623 } else {
[email protected]1b0a6752012-02-22 03:44:125624 glUniform4fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:105625 }
5626}
5627
[email protected]43c2f1f2011-03-25 18:35:365628void GLES2DecoderImpl::DoUniform2iv(
[email protected]1b0a6752012-02-22 03:44:125629 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:365630 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125631 GLint real_location = -1;
5632 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525633 fake_location, "glUniform2iv", valid_int_vec2_base_info,
5634 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365635 return;
5636 }
[email protected]1b0a6752012-02-22 03:44:125637 glUniform2iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:365638}
5639
5640void GLES2DecoderImpl::DoUniform3iv(
[email protected]1b0a6752012-02-22 03:44:125641 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:365642 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125643 GLint real_location = -1;
5644 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525645 fake_location, "glUniform3iv", valid_int_vec3_base_info,
5646 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365647 return;
5648 }
[email protected]1b0a6752012-02-22 03:44:125649 glUniform3iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:365650}
5651
5652void GLES2DecoderImpl::DoUniform4iv(
[email protected]1b0a6752012-02-22 03:44:125653 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:365654 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125655 GLint real_location = -1;
5656 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525657 fake_location, "glUniform4iv", valid_int_vec4_base_info,
5658 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365659 return;
5660 }
[email protected]1b0a6752012-02-22 03:44:125661 glUniform4iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:365662}
5663
5664void GLES2DecoderImpl::DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:125665 GLint fake_location, GLsizei count, GLboolean transpose,
5666 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365667 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125668 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:365669 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525670 fake_location, "glUniformMatrix2fv", valid_float_mat2_base_info,
5671 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365672 return;
5673 }
[email protected]1b0a6752012-02-22 03:44:125674 glUniformMatrix2fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:365675}
5676
5677void GLES2DecoderImpl::DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:125678 GLint fake_location, GLsizei count, GLboolean transpose,
5679 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365680 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125681 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:365682 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525683 fake_location, "glUniformMatrix3fv", valid_float_mat3_base_info,
5684 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365685 return;
5686 }
[email protected]1b0a6752012-02-22 03:44:125687 glUniformMatrix3fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:365688}
5689
5690void GLES2DecoderImpl::DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:125691 GLint fake_location, GLsizei count, GLboolean transpose,
5692 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365693 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125694 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:365695 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525696 fake_location, "glUniformMatrix4fv", valid_float_mat4_base_info,
5697 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365698 return;
5699 }
[email protected]1b0a6752012-02-22 03:44:125700 glUniformMatrix4fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:365701}
5702
[email protected]df37b9932013-03-08 05:21:425703void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
[email protected]ae51d192010-04-27 00:48:035704 GLuint service_id = 0;
[email protected]df37b9932013-03-08 05:21:425705 Program* program = NULL;
5706 if (program_id) {
5707 program = GetProgramInfoNotShader(program_id, "glUseProgram");
5708 if (!program) {
[email protected]ae51d192010-04-27 00:48:035709 return;
5710 }
[email protected]df37b9932013-03-08 05:21:425711 if (!program->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:505712 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]ab09b612013-03-11 22:11:515713 LOCAL_SET_GL_ERROR(
5714 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
[email protected]3916c97e2010-02-25 03:20:505715 return;
5716 }
[email protected]df37b9932013-03-08 05:21:425717 service_id = program->service_id();
[email protected]3916c97e2010-02-25 03:20:505718 }
[email protected]7cd76fd2013-06-02 21:11:115719 if (state_.current_program.get()) {
5720 program_manager()->UnuseProgram(shader_manager(),
5721 state_.current_program.get());
[email protected]ca488e12010-12-13 20:06:145722 }
[email protected]df37b9932013-03-08 05:21:425723 state_.current_program = program;
5724 LogClientServiceMapping("glUseProgram", program_id, service_id);
[email protected]2df73892012-04-28 01:09:545725 glUseProgram(service_id);
[email protected]7cd76fd2013-06-02 21:11:115726 if (state_.current_program.get()) {
5727 program_manager()->UseProgram(state_.current_program.get());
[email protected]ca488e12010-12-13 20:06:145728 }
[email protected]3916c97e2010-02-25 03:20:505729}
5730
[email protected]ab09b612013-03-11 22:11:515731void GLES2DecoderImpl::RenderWarning(
5732 const char* filename, int line, const std::string& msg) {
[email protected]1d82e822013-04-10 21:32:325733 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
[email protected]0f8afe82012-05-14 23:43:015734}
5735
[email protected]ab09b612013-03-11 22:11:515736void GLES2DecoderImpl::PerformanceWarning(
5737 const char* filename, int line, const std::string& msg) {
[email protected]d3eba342013-04-18 21:11:505738 logger_.LogMessage(filename, line,
5739 std::string("PERFORMANCE WARNING: ") + msg);
[email protected]0f8afe82012-05-14 23:43:015740}
5741
[email protected]e56131d22013-07-28 16:14:115742void GLES2DecoderImpl::UpdateStreamTextureIfNeeded(Texture* texture) {
5743 if (texture && texture->IsStreamTexture()) {
5744 DCHECK(stream_texture_manager());
5745 StreamTexture* stream_tex =
5746 stream_texture_manager()->LookupStreamTexture(texture->service_id());
5747 if (stream_tex)
5748 stream_tex->Update();
5749 }
5750}
5751
5752bool GLES2DecoderImpl::PrepareTexturesForRender() {
[email protected]7cd76fd2013-06-02 21:11:115753 DCHECK(state_.current_program.get());
[email protected]e56131d22013-07-28 16:14:115754 bool have_unrenderable_textures =
5755 texture_manager()->HaveUnrenderableTextures();
5756 if (!have_unrenderable_textures && !features().oes_egl_image_external) {
5757 return true;
[email protected]ef526492010-06-02 23:12:255758 }
[email protected]e2367b42013-05-31 03:37:215759
[email protected]ef526492010-06-02 23:12:255760 bool textures_set = false;
[email protected]ed9f9cd2013-02-27 21:12:355761 const Program::SamplerIndices& sampler_indices =
[email protected]e259eb412012-10-13 05:47:245762 state_.current_program->sampler_indices();
[email protected]3916c97e2010-02-25 03:20:505763 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:355764 const Program::UniformInfo* uniform_info =
[email protected]e259eb412012-10-13 05:47:245765 state_.current_program->GetUniformInfo(sampler_indices[ii]);
[email protected]3916c97e2010-02-25 03:20:505766 DCHECK(uniform_info);
5767 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5768 GLuint texture_unit_index = uniform_info->texture_units[jj];
[email protected]1868a342012-11-07 15:56:025769 if (texture_unit_index < state_.texture_units.size()) {
[email protected]e259eb412012-10-13 05:47:245770 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
[email protected]370eaf12013-05-18 09:19:495771 TextureRef* texture =
[email protected]cadac622013-06-11 16:46:365772 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
[email protected]79dc5b32013-07-30 20:08:295773 if (texture)
5774 UpdateStreamTextureIfNeeded(texture->texture());
[email protected]e56131d22013-07-28 16:14:115775 if (have_unrenderable_textures &&
5776 (!texture || !texture_manager()->CanRender(texture))) {
[email protected]ef526492010-06-02 23:12:255777 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:505778 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5779 glBindTexture(
[email protected]61eeb33f2011-07-26 15:30:315780 GetBindTargetForSamplerType(uniform_info->type),
[email protected]00f893d2010-08-24 18:55:495781 texture_manager()->black_texture_id(uniform_info->type));
[email protected]ab09b612013-03-11 22:11:515782 LOCAL_RENDER_WARNING(
[email protected]0f8afe82012-05-14 23:43:015783 std::string("texture bound to texture unit ") +
5784 base::IntToString(texture_unit_index) +
[email protected]ad9b7f8b2013-06-17 07:36:295785 " is not renderable. It maybe non-power-of-2 and have"
5786 " incompatible texture filtering or is not"
5787 " 'texture complete'");
[email protected]3916c97e2010-02-25 03:20:505788 }
5789 }
5790 // else: should this be an error?
5791 }
5792 }
[email protected]e56131d22013-07-28 16:14:115793 return !textures_set;
[email protected]3916c97e2010-02-25 03:20:505794}
5795
5796void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
[email protected]7cd76fd2013-06-02 21:11:115797 DCHECK(state_.current_program.get());
[email protected]ed9f9cd2013-02-27 21:12:355798 const Program::SamplerIndices& sampler_indices =
[email protected]7cd76fd2013-06-02 21:11:115799 state_.current_program->sampler_indices();
[email protected]3916c97e2010-02-25 03:20:505800 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:355801 const Program::UniformInfo* uniform_info =
[email protected]e259eb412012-10-13 05:47:245802 state_.current_program->GetUniformInfo(sampler_indices[ii]);
[email protected]3916c97e2010-02-25 03:20:505803 DCHECK(uniform_info);
5804 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5805 GLuint texture_unit_index = uniform_info->texture_units[jj];
[email protected]1868a342012-11-07 15:56:025806 if (texture_unit_index < state_.texture_units.size()) {
[email protected]e259eb412012-10-13 05:47:245807 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
[email protected]7cd76fd2013-06-02 21:11:115808 TextureRef* texture_ref =
5809 uniform_info->type == GL_SAMPLER_2D
5810 ? texture_unit.bound_texture_2d.get()
5811 : texture_unit.bound_texture_cube_map.get();
[email protected]370eaf12013-05-18 09:19:495812 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
[email protected]3916c97e2010-02-25 03:20:505813 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
[email protected]370eaf12013-05-18 09:19:495814 // Get the texture_ref info that was previously bound here.
[email protected]7cd76fd2013-06-02 21:11:115815 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
5816 ? texture_unit.bound_texture_2d.get()
5817 : texture_unit.bound_texture_cube_map.get();
[email protected]3916c97e2010-02-25 03:20:505818 glBindTexture(texture_unit.bind_target,
[email protected]370eaf12013-05-18 09:19:495819 texture_ref ? texture_ref->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:505820 }
5821 }
5822 }
5823 }
5824 // Set the active texture back to whatever the user had it as.
[email protected]e259eb412012-10-13 05:47:245825 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
[email protected]07f54fcc2009-12-22 02:46:305826}
5827
[email protected]0d6bfdc2011-11-02 01:32:205828bool GLES2DecoderImpl::ClearUnclearedTextures() {
5829 // Only check if there are some uncleared textures.
5830 if (!texture_manager()->HaveUnsafeTextures()) {
5831 return true;
5832 }
5833
5834 // 1: Check all textures we are about to render with.
[email protected]7cd76fd2013-06-02 21:11:115835 if (state_.current_program.get()) {
[email protected]ed9f9cd2013-02-27 21:12:355836 const Program::SamplerIndices& sampler_indices =
[email protected]7cd76fd2013-06-02 21:11:115837 state_.current_program->sampler_indices();
[email protected]0d6bfdc2011-11-02 01:32:205838 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:355839 const Program::UniformInfo* uniform_info =
[email protected]e259eb412012-10-13 05:47:245840 state_.current_program->GetUniformInfo(sampler_indices[ii]);
[email protected]0d6bfdc2011-11-02 01:32:205841 DCHECK(uniform_info);
5842 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5843 GLuint texture_unit_index = uniform_info->texture_units[jj];
[email protected]1868a342012-11-07 15:56:025844 if (texture_unit_index < state_.texture_units.size()) {
[email protected]e259eb412012-10-13 05:47:245845 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
[email protected]370eaf12013-05-18 09:19:495846 TextureRef* texture_ref =
[email protected]cadac622013-06-11 16:46:365847 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
[email protected]370eaf12013-05-18 09:19:495848 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
5849 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
[email protected]0d6bfdc2011-11-02 01:32:205850 return false;
5851 }
5852 }
5853 }
5854 }
5855 }
5856 }
5857 return true;
5858}
5859
[email protected]c6aef902012-02-14 03:31:425860bool GLES2DecoderImpl::IsDrawValid(
[email protected]ad84a3a2012-06-08 21:42:435861 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount) {
[email protected]689fa1c52010-06-09 18:35:035862 // NOTE: We specifically do not check current_program->IsValid() because
5863 // it could never be invalid since glUseProgram would have failed. While
5864 // glLinkProgram could later mark the program as invalid the previous
5865 // valid program will still function if it is still the current program.
[email protected]7cd76fd2013-06-02 21:11:115866 if (!state_.current_program.get()) {
[email protected]3916c97e2010-02-25 03:20:505867 // The program does not exist.
5868 // But GL says no ERROR.
[email protected]ab09b612013-03-11 22:11:515869 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
[email protected]3916c97e2010-02-25 03:20:505870 return false;
5871 }
[email protected]c6aef902012-02-14 03:31:425872
[email protected]7cd76fd2013-06-02 21:11:115873 return state_.vertex_attrib_manager
5874 ->ValidateBindings(function_name,
5875 this,
5876 feature_info_.get(),
5877 state_.current_program.get(),
5878 max_vertex_accessed,
5879 primcount);
[email protected]b1122982010-05-17 23:04:245880}
5881
[email protected]c13e1da62011-09-09 21:48:305882bool GLES2DecoderImpl::SimulateAttrib0(
[email protected]ad84a3a2012-06-08 21:42:435883 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
[email protected]c13e1da62011-09-09 21:48:305884 DCHECK(simulated);
5885 *simulated = false;
5886
[email protected]876f6fee2010-08-02 23:10:325887 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
[email protected]c13e1da62011-09-09 21:48:305888 return true;
[email protected]876f6fee2010-08-02 23:10:325889
[email protected]ac77603c72013-03-08 13:52:065890 const VertexAttrib* attrib =
[email protected]ed9f9cd2013-02-27 21:12:355891 state_.vertex_attrib_manager->GetVertexAttrib(0);
[email protected]b1122982010-05-17 23:04:245892 // If it's enabled or it's not used then we don't need to do anything.
[email protected]e259eb412012-10-13 05:47:245893 bool attrib_0_used =
5894 state_.current_program->GetAttribInfoByLocation(0) != NULL;
[email protected]ac77603c72013-03-08 13:52:065895 if (attrib->enabled() && attrib_0_used) {
[email protected]c13e1da62011-09-09 21:48:305896 return true;
[email protected]b1122982010-05-17 23:04:245897 }
5898
[email protected]b1122982010-05-17 23:04:245899 // Make a buffer with a single repeated vec4 value enough to
5900 // simulate the constant value that is supposed to be here.
5901 // This is required to emulate GLES2 on GL.
[email protected]c13e1da62011-09-09 21:48:305902 GLuint num_vertices = max_vertex_accessed + 1;
[email protected]3aad1a32012-09-07 20:54:475903 uint32 size_needed = 0;
[email protected]c13e1da62011-09-09 21:48:305904
5905 if (num_vertices == 0 ||
[email protected]3aad1a32012-09-07 20:54:475906 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
[email protected]c13e1da62011-09-09 21:48:305907 size_needed > 0x7FFFFFFFU) {
[email protected]ab09b612013-03-11 22:11:515908 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c13e1da62011-09-09 21:48:305909 return false;
5910 }
5911
[email protected]ab09b612013-03-11 22:11:515912 LOCAL_PERFORMANCE_WARNING(
[email protected]0f8afe82012-05-14 23:43:015913 "Attribute 0 is disabled. This has signficant performance penalty");
5914
[email protected]ab09b612013-03-11 22:11:515915 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
[email protected]c13e1da62011-09-09 21:48:305916 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
5917
[email protected]8f0b86c2f2012-04-10 05:48:285918 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
5919 if (new_buffer) {
[email protected]fc753442011-02-04 19:49:495920 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305921 GLenum error = glGetError();
5922 if (error != GL_NO_ERROR) {
[email protected]ab09b612013-03-11 22:11:515923 LOCAL_SET_GL_ERROR(
5924 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c13e1da62011-09-09 21:48:305925 return false;
5926 }
[email protected]fc753442011-02-04 19:49:495927 }
[email protected]af6380962012-11-29 23:24:135928
5929 const Vec4& value = state_.attrib_values[0];
[email protected]8f0b86c2f2012-04-10 05:48:285930 if (new_buffer ||
5931 (attrib_0_used &&
5932 (!attrib_0_buffer_matches_value_ ||
[email protected]af6380962012-11-29 23:24:135933 (value.v[0] != attrib_0_value_.v[0] ||
5934 value.v[1] != attrib_0_value_.v[1] ||
5935 value.v[2] != attrib_0_value_.v[2] ||
5936 value.v[3] != attrib_0_value_.v[3])))) {
5937 std::vector<Vec4> temp(num_vertices, value);
[email protected]fc753442011-02-04 19:49:495938 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
5939 attrib_0_buffer_matches_value_ = true;
[email protected]af6380962012-11-29 23:24:135940 attrib_0_value_ = value;
[email protected]b1122982010-05-17 23:04:245941 attrib_0_size_ = size_needed;
5942 }
5943
5944 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5945
[email protected]ac77603c72013-03-08 13:52:065946 if (attrib->divisor())
[email protected]c6aef902012-02-14 03:31:425947 glVertexAttribDivisorANGLE(0, 0);
5948
[email protected]c13e1da62011-09-09 21:48:305949 *simulated = true;
[email protected]b1122982010-05-17 23:04:245950 return true;
[email protected]b1122982010-05-17 23:04:245951}
5952
[email protected]ac77603c72013-03-08 13:52:065953void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib_index) {
5954 const VertexAttrib* attrib =
5955 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
5956 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
5957 Buffer* buffer = attrib->buffer();
[email protected]b10492f2013-03-08 05:24:075958 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
[email protected]b1122982010-05-17 23:04:245959 glVertexAttribPointer(
[email protected]ac77603c72013-03-08 13:52:065960 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
5961 attrib->gl_stride(), ptr);
5962 if (attrib->divisor())
5963 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
[email protected]e259eb412012-10-13 05:47:245964 glBindBuffer(
5965 GL_ARRAY_BUFFER,
[email protected]7cd76fd2013-06-02 21:11:115966 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
5967 : 0);
[email protected]43410e92012-04-20 17:06:285968
[email protected]265f8992012-07-20 01:03:145969 // Never touch vertex attribute 0's state (in particular, never
5970 // disable it) when running on desktop GL because it will never be
5971 // re-enabled.
[email protected]ac77603c72013-03-08 13:52:065972 if (attrib_index != 0 ||
[email protected]265f8992012-07-20 01:03:145973 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]ac77603c72013-03-08 13:52:065974 if (attrib->enabled()) {
5975 glEnableVertexAttribArray(attrib_index);
[email protected]265f8992012-07-20 01:03:145976 } else {
[email protected]ac77603c72013-03-08 13:52:065977 glDisableVertexAttribArray(attrib_index);
[email protected]265f8992012-07-20 01:03:145978 }
[email protected]43410e92012-04-20 17:06:285979 }
[email protected]b1122982010-05-17 23:04:245980}
[email protected]07f54fcc2009-12-22 02:46:305981
[email protected]8fbedc02010-11-18 18:43:405982bool GLES2DecoderImpl::SimulateFixedAttribs(
[email protected]ad84a3a2012-06-08 21:42:435983 const char* function_name,
[email protected]c6aef902012-02-14 03:31:425984 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
[email protected]8fbedc02010-11-18 18:43:405985 DCHECK(simulated);
5986 *simulated = false;
5987 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
5988 return true;
5989
[email protected]e259eb412012-10-13 05:47:245990 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
[email protected]8fbedc02010-11-18 18:43:405991 return true;
5992 }
5993
[email protected]ab09b612013-03-11 22:11:515994 LOCAL_PERFORMANCE_WARNING(
[email protected]0f8afe82012-05-14 23:43:015995 "GL_FIXED attributes have a signficant performance penalty");
5996
[email protected]8fbedc02010-11-18 18:43:405997 // NOTE: we could be smart and try to check if a buffer is used
5998 // twice in 2 different attribs, find the overlapping parts and therefore
5999 // duplicate the minimum amount of data but this whole code path is not meant
6000 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
6001 // tests so we just add to the buffer attrib used.
6002
[email protected]c13e1da62011-09-09 21:48:306003 GLuint elements_needed = 0;
[email protected]ac77603c72013-03-08 13:52:066004 const VertexAttribManager::VertexAttribList& enabled_attribs =
6005 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
6006 for (VertexAttribManager::VertexAttribList::const_iterator it =
6007 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6008 const VertexAttrib* attrib = *it;
[email protected]ed9f9cd2013-02-27 21:12:356009 const Program::VertexAttrib* attrib_info =
[email protected]ac77603c72013-03-08 13:52:066010 state_.current_program->GetAttribInfoByLocation(attrib->index());
6011 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
6012 max_vertex_accessed);
[email protected]c6aef902012-02-14 03:31:426013 GLuint num_vertices = max_accessed + 1;
6014 if (num_vertices == 0) {
[email protected]ab09b612013-03-11 22:11:516015 LOCAL_SET_GL_ERROR(
6016 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c6aef902012-02-14 03:31:426017 return false;
6018 }
[email protected]8fbedc02010-11-18 18:43:406019 if (attrib_info &&
[email protected]ac77603c72013-03-08 13:52:066020 attrib->CanAccess(max_accessed) &&
6021 attrib->type() == GL_FIXED) {
[email protected]3aad1a32012-09-07 20:54:476022 uint32 elements_used = 0;
[email protected]ac77603c72013-03-08 13:52:066023 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
[email protected]3aad1a32012-09-07 20:54:476024 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
[email protected]ab09b612013-03-11 22:11:516025 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:436026 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]8fbedc02010-11-18 18:43:406027 return false;
6028 }
6029 }
6030 }
6031
[email protected]3aad1a32012-09-07 20:54:476032 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
6033 uint32 size_needed = 0;
6034 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
[email protected]c13e1da62011-09-09 21:48:306035 size_needed > 0x7FFFFFFFU) {
[email protected]ab09b612013-03-11 22:11:516036 LOCAL_SET_GL_ERROR(
6037 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]8fbedc02010-11-18 18:43:406038 return false;
6039 }
6040
[email protected]ab09b612013-03-11 22:11:516041 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
[email protected]8fbedc02010-11-18 18:43:406042
6043 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
[email protected]c13e1da62011-09-09 21:48:306044 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
[email protected]8fbedc02010-11-18 18:43:406045 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:306046 GLenum error = glGetError();
6047 if (error != GL_NO_ERROR) {
[email protected]ab09b612013-03-11 22:11:516048 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:436049 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]c13e1da62011-09-09 21:48:306050 return false;
6051 }
[email protected]8fbedc02010-11-18 18:43:406052 }
6053
6054 // Copy the elements and convert to float
6055 GLintptr offset = 0;
[email protected]ac77603c72013-03-08 13:52:066056 for (VertexAttribManager::VertexAttribList::const_iterator it =
6057 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
6058 const VertexAttrib* attrib = *it;
[email protected]ed9f9cd2013-02-27 21:12:356059 const Program::VertexAttrib* attrib_info =
[email protected]ac77603c72013-03-08 13:52:066060 state_.current_program->GetAttribInfoByLocation(attrib->index());
6061 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
[email protected]c6aef902012-02-14 03:31:426062 max_vertex_accessed);
6063 GLuint num_vertices = max_accessed + 1;
6064 if (num_vertices == 0) {
[email protected]ab09b612013-03-11 22:11:516065 LOCAL_SET_GL_ERROR(
6066 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c6aef902012-02-14 03:31:426067 return false;
6068 }
[email protected]8fbedc02010-11-18 18:43:406069 if (attrib_info &&
[email protected]ac77603c72013-03-08 13:52:066070 attrib->CanAccess(max_accessed) &&
6071 attrib->type() == GL_FIXED) {
6072 int num_elements = attrib->size() * kSizeOfFloat;
[email protected]8fbedc02010-11-18 18:43:406073 int size = num_elements * num_vertices;
[email protected]40d90a22013-04-09 03:39:556074 scoped_ptr<float[]> data(new float[size]);
[email protected]8fbedc02010-11-18 18:43:406075 const int32* src = reinterpret_cast<const int32 *>(
[email protected]ac77603c72013-03-08 13:52:066076 attrib->buffer()->GetRange(attrib->offset(), size));
[email protected]8fbedc02010-11-18 18:43:406077 const int32* end = src + num_elements;
6078 float* dst = data.get();
6079 while (src != end) {
6080 *dst++ = static_cast<float>(*src++) / 65536.0f;
6081 }
6082 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
6083 glVertexAttribPointer(
[email protected]ac77603c72013-03-08 13:52:066084 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
[email protected]8fbedc02010-11-18 18:43:406085 reinterpret_cast<GLvoid*>(offset));
6086 offset += size;
6087 }
6088 }
6089 *simulated = true;
6090 return true;
6091}
6092
6093void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6094 // There's no need to call glVertexAttribPointer because we shadow all the
6095 // settings and passing GL_FIXED to it will not work.
[email protected]e259eb412012-10-13 05:47:246096 glBindBuffer(
6097 GL_ARRAY_BUFFER,
[email protected]7cd76fd2013-06-02 21:11:116098 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6099 : 0);
[email protected]8fbedc02010-11-18 18:43:406100}
6101
[email protected]ad84a3a2012-06-08 21:42:436102error::Error GLES2DecoderImpl::DoDrawArrays(
6103 const char* function_name,
6104 bool instanced,
6105 GLenum mode,
6106 GLint first,
6107 GLsizei count,
6108 GLsizei primcount) {
[email protected]a7266a92012-06-28 02:11:086109 if (ShouldDeferDraws())
6110 return error::kDeferCommandUntilLater;
[email protected]38d139d2011-07-14 00:38:436111 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]ab09b612013-03-11 22:11:516112 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
[email protected]38d139d2011-07-14 00:38:436113 return error::kNoError;
6114 }
6115 if (count < 0) {
[email protected]ab09b612013-03-11 22:11:516116 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
[email protected]38d139d2011-07-14 00:38:436117 return error::kNoError;
6118 }
[email protected]c6aef902012-02-14 03:31:426119 if (primcount < 0) {
[email protected]ab09b612013-03-11 22:11:516120 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
[email protected]c6aef902012-02-14 03:31:426121 return error::kNoError;
6122 }
[email protected]ad84a3a2012-06-08 21:42:436123 if (!CheckBoundFramebuffersValid(function_name)) {
[email protected]38d139d2011-07-14 00:38:436124 return error::kNoError;
6125 }
6126 // We have to check this here because the prototype for glDrawArrays
6127 // is GLint not GLsizei.
6128 if (first < 0) {
[email protected]ab09b612013-03-11 22:11:516129 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
[email protected]38d139d2011-07-14 00:38:436130 return error::kNoError;
6131 }
6132
[email protected]c6aef902012-02-14 03:31:426133 if (count == 0 || (instanced && primcount == 0)) {
[email protected]ab09b612013-03-11 22:11:516134 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
[email protected]38d139d2011-07-14 00:38:436135 return error::kNoError;
6136 }
6137
6138 GLuint max_vertex_accessed = first + count - 1;
[email protected]ad84a3a2012-06-08 21:42:436139 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:206140 if (!ClearUnclearedTextures()) {
[email protected]ab09b612013-03-11 22:11:516141 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
[email protected]0d6bfdc2011-11-02 01:32:206142 return error::kNoError;
6143 }
[email protected]c13e1da62011-09-09 21:48:306144 bool simulated_attrib_0 = false;
[email protected]ad84a3a2012-06-08 21:42:436145 if (!SimulateAttrib0(
6146 function_name, max_vertex_accessed, &simulated_attrib_0)) {
[email protected]c13e1da62011-09-09 21:48:306147 return error::kNoError;
6148 }
[email protected]38d139d2011-07-14 00:38:436149 bool simulated_fixed_attribs = false;
[email protected]ad84a3a2012-06-08 21:42:436150 if (SimulateFixedAttribs(
6151 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6152 primcount)) {
[email protected]e56131d22013-07-28 16:14:116153 bool textures_set = !PrepareTexturesForRender();
[email protected]38d139d2011-07-14 00:38:436154 ApplyDirtyState();
[email protected]c6aef902012-02-14 03:31:426155 if (!instanced) {
6156 glDrawArrays(mode, first, count);
6157 } else {
6158 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6159 }
[email protected]22e3f552012-03-13 01:54:196160 ProcessPendingQueries();
[email protected]38d139d2011-07-14 00:38:436161 if (textures_set) {
6162 RestoreStateForNonRenderableTextures();
6163 }
6164 if (simulated_fixed_attribs) {
6165 RestoreStateForSimulatedFixedAttribs();
6166 }
6167 }
6168 if (simulated_attrib_0) {
[email protected]43410e92012-04-20 17:06:286169 RestoreStateForAttrib(0);
[email protected]38d139d2011-07-14 00:38:436170 }
[email protected]38d139d2011-07-14 00:38:436171 }
6172 return error::kNoError;
6173}
6174
[email protected]c6aef902012-02-14 03:31:426175error::Error GLES2DecoderImpl::HandleDrawArrays(
[email protected]ed9f9cd2013-02-27 21:12:356176 uint32 immediate_data_size, const cmds::DrawArrays& c) {
[email protected]ad84a3a2012-06-08 21:42:436177 return DoDrawArrays("glDrawArrays",
6178 false,
[email protected]c6aef902012-02-14 03:31:426179 static_cast<GLenum>(c.mode),
6180 static_cast<GLint>(c.first),
6181 static_cast<GLsizei>(c.count),
6182 0);
6183}
6184
6185error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
[email protected]ed9f9cd2013-02-27 21:12:356186 uint32 immediate_data_size, const cmds::DrawArraysInstancedANGLE& c) {
[email protected]62e155e2012-10-23 22:43:156187 if (!features().angle_instanced_arrays) {
[email protected]ab09b612013-03-11 22:11:516188 LOCAL_SET_GL_ERROR(
6189 GL_INVALID_OPERATION,
6190 "glDrawArraysInstancedANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:426191 return error::kNoError;
6192 }
[email protected]ad84a3a2012-06-08 21:42:436193 return DoDrawArrays("glDrawArraysIntancedANGLE",
6194 true,
[email protected]c6aef902012-02-14 03:31:426195 static_cast<GLenum>(c.mode),
6196 static_cast<GLint>(c.first),
6197 static_cast<GLsizei>(c.count),
6198 static_cast<GLsizei>(c.primcount));
6199}
6200
[email protected]ad84a3a2012-06-08 21:42:436201error::Error GLES2DecoderImpl::DoDrawElements(
6202 const char* function_name,
6203 bool instanced,
6204 GLenum mode,
6205 GLsizei count,
6206 GLenum type,
6207 int32 offset,
6208 GLsizei primcount) {
[email protected]a7266a92012-06-28 02:11:086209 if (ShouldDeferDraws())
6210 return error::kDeferCommandUntilLater;
[email protected]e259eb412012-10-13 05:47:246211 if (!state_.vertex_attrib_manager->element_array_buffer()) {
[email protected]ab09b612013-03-11 22:11:516212 LOCAL_SET_GL_ERROR(
6213 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
[email protected]8eee29c2010-04-29 03:38:296214 return error::kNoError;
6215 }
6216
[email protected]8eee29c2010-04-29 03:38:296217 if (count < 0) {
[email protected]ab09b612013-03-11 22:11:516218 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
[email protected]8eee29c2010-04-29 03:38:296219 return error::kNoError;
6220 }
6221 if (offset < 0) {
[email protected]ab09b612013-03-11 22:11:516222 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
[email protected]8eee29c2010-04-29 03:38:296223 return error::kNoError;
6224 }
[email protected]9438b012010-06-15 22:55:056225 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]ab09b612013-03-11 22:11:516226 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
[email protected]8eee29c2010-04-29 03:38:296227 return error::kNoError;
6228 }
[email protected]9438b012010-06-15 22:55:056229 if (!validators_->index_type.IsValid(type)) {
[email protected]ab09b612013-03-11 22:11:516230 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
[email protected]8eee29c2010-04-29 03:38:296231 return error::kNoError;
6232 }
[email protected]c6aef902012-02-14 03:31:426233 if (primcount < 0) {
[email protected]ab09b612013-03-11 22:11:516234 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
[email protected]c6aef902012-02-14 03:31:426235 return error::kNoError;
6236 }
[email protected]8eee29c2010-04-29 03:38:296237
[email protected]ad84a3a2012-06-08 21:42:436238 if (!CheckBoundFramebuffersValid(function_name)) {
[email protected]3a03a8f2011-03-19 00:51:276239 return error::kNoError;
6240 }
6241
[email protected]c6aef902012-02-14 03:31:426242 if (count == 0 || (instanced && primcount == 0)) {
[email protected]6c788fb72010-08-26 02:16:316243 return error::kNoError;
6244 }
6245
[email protected]8eee29c2010-04-29 03:38:296246 GLuint max_vertex_accessed;
[email protected]17cfbe0e2013-03-07 01:26:086247 Buffer* element_array_buffer =
6248 state_.vertex_attrib_manager->element_array_buffer();
6249
6250 if (!element_array_buffer->GetMaxValueForRange(
6251 offset, count, type, &max_vertex_accessed)) {
[email protected]ab09b612013-03-11 22:11:516252 LOCAL_SET_GL_ERROR(
6253 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
[email protected]8eee29c2010-04-29 03:38:296254 return error::kNoError;
6255 }
6256
[email protected]ad84a3a2012-06-08 21:42:436257 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:206258 if (!ClearUnclearedTextures()) {
[email protected]ab09b612013-03-11 22:11:516259 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
[email protected]0d6bfdc2011-11-02 01:32:206260 return error::kNoError;
6261 }
[email protected]c13e1da62011-09-09 21:48:306262 bool simulated_attrib_0 = false;
[email protected]ad84a3a2012-06-08 21:42:436263 if (!SimulateAttrib0(
6264 function_name, max_vertex_accessed, &simulated_attrib_0)) {
[email protected]c13e1da62011-09-09 21:48:306265 return error::kNoError;
6266 }
[email protected]8fbedc02010-11-18 18:43:406267 bool simulated_fixed_attribs = false;
[email protected]ad84a3a2012-06-08 21:42:436268 if (SimulateFixedAttribs(
6269 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6270 primcount)) {
[email protected]e56131d22013-07-28 16:14:116271 bool textures_set = !PrepareTexturesForRender();
[email protected]297ca1c2011-06-20 23:08:466272 ApplyDirtyState();
[email protected]17cfbe0e2013-03-07 01:26:086273 // TODO(gman): Refactor to hide these details in BufferManager or
6274 // VertexAttribManager.
[email protected]8fbedc02010-11-18 18:43:406275 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
[email protected]17cfbe0e2013-03-07 01:26:086276 bool used_client_side_array = false;
6277 if (element_array_buffer->IsClientSideArray()) {
6278 used_client_side_array = true;
6279 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6280 indices = element_array_buffer->GetRange(offset, 0);
6281 }
6282
[email protected]c6aef902012-02-14 03:31:426283 if (!instanced) {
6284 glDrawElements(mode, count, type, indices);
6285 } else {
6286 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6287 }
[email protected]17cfbe0e2013-03-07 01:26:086288
6289 if (used_client_side_array) {
6290 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6291 element_array_buffer->service_id());
6292 }
6293
[email protected]22e3f552012-03-13 01:54:196294 ProcessPendingQueries();
[email protected]8fbedc02010-11-18 18:43:406295 if (textures_set) {
6296 RestoreStateForNonRenderableTextures();
6297 }
6298 if (simulated_fixed_attribs) {
6299 RestoreStateForSimulatedFixedAttribs();
6300 }
[email protected]ba3176a2009-12-16 18:19:466301 }
[email protected]b1122982010-05-17 23:04:246302 if (simulated_attrib_0) {
[email protected]43410e92012-04-20 17:06:286303 RestoreStateForAttrib(0);
[email protected]b1122982010-05-17 23:04:246304 }
[email protected]96449d2c2009-11-25 00:01:326305 }
[email protected]f7a64ee2010-02-01 22:24:146306 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326307}
6308
[email protected]c6aef902012-02-14 03:31:426309error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]ed9f9cd2013-02-27 21:12:356310 uint32 immediate_data_size, const cmds::DrawElements& c) {
[email protected]ad84a3a2012-06-08 21:42:436311 return DoDrawElements("glDrawElements",
6312 false,
[email protected]c6aef902012-02-14 03:31:426313 static_cast<GLenum>(c.mode),
6314 static_cast<GLsizei>(c.count),
6315 static_cast<GLenum>(c.type),
6316 static_cast<int32>(c.index_offset),
6317 0);
6318}
6319
6320error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
[email protected]ed9f9cd2013-02-27 21:12:356321 uint32 immediate_data_size, const cmds::DrawElementsInstancedANGLE& c) {
[email protected]62e155e2012-10-23 22:43:156322 if (!features().angle_instanced_arrays) {
[email protected]ab09b612013-03-11 22:11:516323 LOCAL_SET_GL_ERROR(
6324 GL_INVALID_OPERATION,
6325 "glDrawElementsInstancedANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:426326 return error::kNoError;
6327 }
[email protected]ad84a3a2012-06-08 21:42:436328 return DoDrawElements("glDrawElementsInstancedANGLE",
6329 true,
[email protected]c6aef902012-02-14 03:31:426330 static_cast<GLenum>(c.mode),
6331 static_cast<GLsizei>(c.count),
6332 static_cast<GLenum>(c.type),
6333 static_cast<int32>(c.index_offset),
6334 static_cast<GLsizei>(c.primcount));
6335}
6336
[email protected]269200b12010-11-18 22:53:066337GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:236338 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
6339 GLuint max_vertex_accessed = 0;
[email protected]b10492f2013-03-08 05:24:076340 Buffer* buffer = GetBuffer(buffer_id);
6341 if (!buffer) {
[email protected]ae51d192010-04-27 00:48:036342 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]ab09b612013-03-11 22:11:516343 LOCAL_SET_GL_ERROR(
6344 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
[email protected]29a9eb52010-04-13 09:04:236345 } else {
[email protected]b10492f2013-03-08 05:24:076346 if (!buffer->GetMaxValueForRange(
6347 offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:036348 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]ab09b612013-03-11 22:11:516349 LOCAL_SET_GL_ERROR(
[email protected]269200b12010-11-18 22:53:066350 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436351 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:236352 }
6353 }
6354 return max_vertex_accessed;
6355}
6356
[email protected]96449d2c2009-11-25 00:01:326357// Calls glShaderSource for the various versions of the ShaderSource command.
6358// Assumes that data / data_size points to a piece of memory that is in range
6359// of whatever context it came from (shared memory, immediate memory, bucket
6360// memory.)
[email protected]45bf5152010-02-12 00:11:316361error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:036362 GLuint client_id, const char* data, uint32 data_size) {
[email protected]258a3313f2011-10-18 20:13:576363 std::string str(data, data + data_size);
[email protected]df37b9932013-03-08 05:21:426364 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
6365 if (!shader) {
[email protected]45bf5152010-02-12 00:11:316366 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326367 }
[email protected]45bf5152010-02-12 00:11:316368 // Note: We don't actually call glShaderSource here. We wait until
6369 // the call to glCompileShader.
[email protected]df37b9932013-03-08 05:21:426370 shader->UpdateSource(str.c_str());
[email protected]f7a64ee2010-02-01 22:24:146371 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326372}
6373
[email protected]f7a64ee2010-02-01 22:24:146374error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]ed9f9cd2013-02-27 21:12:356375 uint32 immediate_data_size, const cmds::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:326376 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:316377 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:326378 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:466379 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146380 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:326381 }
[email protected]ae51d192010-04-27 00:48:036382 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:326383}
6384
[email protected]f7a64ee2010-02-01 22:24:146385error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]ed9f9cd2013-02-27 21:12:356386 uint32 immediate_data_size, const cmds::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:326387 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:316388 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:306389 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466390 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146391 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:326392 }
[email protected]ae51d192010-04-27 00:48:036393 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:316394}
6395
[email protected]558847a2010-03-24 07:02:546396error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
[email protected]ed9f9cd2013-02-27 21:12:356397 uint32 immediate_data_size, const cmds::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:546398 Bucket* bucket = GetBucket(c.data_bucket_id);
6399 if (!bucket || bucket->size() == 0) {
6400 return error::kInvalidArguments;
6401 }
6402 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:036403 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:546404 bucket->size() - 1);
6405}
6406
[email protected]ae51d192010-04-27 00:48:036407void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]43ed3a72012-05-30 22:55:386408 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]df37b9932013-03-08 05:21:426409 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
6410 if (!shader) {
[email protected]45bf5152010-02-12 00:11:316411 return;
6412 }
[email protected]f57bb282010-11-12 00:51:346413 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:186414 if (use_shader_translator_) {
[email protected]df37b9932013-03-08 05:21:426415 translator = shader->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:456416 vertex_translator_.get() : fragment_translator_.get();
[email protected]de17df392010-04-23 21:09:416417 }
[email protected]de17df392010-04-23 21:09:416418
[email protected]7cd76fd2013-06-02 21:11:116419 program_manager()->DoCompileShader(shader, translator, feature_info_.get());
[email protected]45bf5152010-02-12 00:11:316420};
6421
[email protected]ddd968b82010-03-02 00:44:296422void GLES2DecoderImpl::DoGetShaderiv(
[email protected]df37b9932013-03-08 05:21:426423 GLuint shader_id, GLenum pname, GLint* params) {
6424 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
6425 if (!shader) {
[email protected]ddd968b82010-03-02 00:44:296426 return;
6427 }
[email protected]8f1ccdac2010-05-19 21:01:486428 switch (pname) {
6429 case GL_SHADER_SOURCE_LENGTH:
[email protected]df37b9932013-03-08 05:21:426430 *params = shader->source() ? shader->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:486431 return;
6432 case GL_COMPILE_STATUS:
[email protected]df37b9932013-03-08 05:21:426433 *params = compile_shader_always_succeeds_ ? true : shader->IsValid();
[email protected]e5186162010-06-14 18:54:416434 return;
[email protected]8f1ccdac2010-05-19 21:01:486435 case GL_INFO_LOG_LENGTH:
[email protected]df37b9932013-03-08 05:21:426436 *params = shader->log_info() ? shader->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:416437 return;
[email protected]d6a53e42011-10-05 00:09:366438 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
[email protected]df37b9932013-03-08 05:21:426439 *params = shader->translated_source() ?
6440 shader->translated_source()->size() + 1 : 0;
[email protected]d6a53e42011-10-05 00:09:366441 return;
[email protected]8f1ccdac2010-05-19 21:01:486442 default:
6443 break;
[email protected]ddd968b82010-03-02 00:44:296444 }
[email protected]df37b9932013-03-08 05:21:426445 glGetShaderiv(shader->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:296446}
6447
[email protected]ae51d192010-04-27 00:48:036448error::Error GLES2DecoderImpl::HandleGetShaderSource(
[email protected]ed9f9cd2013-02-27 21:12:356449 uint32 immediate_data_size, const cmds::GetShaderSource& c) {
[email protected]df37b9932013-03-08 05:21:426450 GLuint shader_id = c.shader;
[email protected]ae51d192010-04-27 00:48:036451 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6452 Bucket* bucket = CreateBucket(bucket_id);
[email protected]df37b9932013-03-08 05:21:426453 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
6454 if (!shader || !shader->source()) {
[email protected]8eee29c2010-04-29 03:38:296455 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:296456 return error::kNoError;
6457 }
[email protected]df37b9932013-03-08 05:21:426458 bucket->SetFromString(shader->source()->c_str());
[email protected]ae51d192010-04-27 00:48:036459 return error::kNoError;
6460}
6461
[email protected]d6a53e42011-10-05 00:09:366462error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6463 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:356464 const cmds::GetTranslatedShaderSourceANGLE& c) {
[email protected]df37b9932013-03-08 05:21:426465 GLuint shader_id = c.shader;
[email protected]d6a53e42011-10-05 00:09:366466 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6467 Bucket* bucket = CreateBucket(bucket_id);
[email protected]df37b9932013-03-08 05:21:426468 Shader* shader = GetShaderInfoNotProgram(
6469 shader_id, "glTranslatedGetShaderSourceANGLE");
6470 if (!shader) {
[email protected]d6a53e42011-10-05 00:09:366471 bucket->SetSize(0);
6472 return error::kNoError;
6473 }
[email protected]d6a53e42011-10-05 00:09:366474
[email protected]df37b9932013-03-08 05:21:426475 bucket->SetFromString(shader->translated_source() ?
6476 shader->translated_source()->c_str() : NULL);
[email protected]d6a53e42011-10-05 00:09:366477 return error::kNoError;
6478}
6479
[email protected]ae51d192010-04-27 00:48:036480error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
[email protected]ed9f9cd2013-02-27 21:12:356481 uint32 immediate_data_size, const cmds::GetProgramInfoLog& c) {
[email protected]df37b9932013-03-08 05:21:426482 GLuint program_id = c.program;
[email protected]6b8cf1a2010-05-06 16:13:586483 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6484 Bucket* bucket = CreateBucket(bucket_id);
[email protected]df37b9932013-03-08 05:21:426485 Program* program = GetProgramInfoNotShader(
6486 program_id, "glGetProgramInfoLog");
6487 if (!program || !program->log_info()) {
[email protected]9a14ae612011-08-08 17:51:466488 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:036489 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:316490 }
[email protected]df37b9932013-03-08 05:21:426491 bucket->SetFromString(program->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:036492 return error::kNoError;
6493}
6494
6495error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
[email protected]ed9f9cd2013-02-27 21:12:356496 uint32 immediate_data_size, const cmds::GetShaderInfoLog& c) {
[email protected]df37b9932013-03-08 05:21:426497 GLuint shader_id = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:586498 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6499 Bucket* bucket = CreateBucket(bucket_id);
[email protected]df37b9932013-03-08 05:21:426500 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
6501 if (!shader || !shader->log_info()) {
[email protected]9a14ae612011-08-08 17:51:466502 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:036503 return error::kNoError;
6504 }
[email protected]df37b9932013-03-08 05:21:426505 bucket->SetFromString(shader->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:036506 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326507}
6508
[email protected]d058bca2012-11-26 10:27:266509bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
6510 return state_.GetEnabled(cap);
6511}
6512
[email protected]1958e0e2010-04-22 05:17:156513bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]16ccec12013-02-28 03:40:216514 const Buffer* buffer = GetBuffer(client_id);
[email protected]a0b78dc2011-11-11 10:43:106515 return buffer && buffer->IsValid() && !buffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156516}
6517
6518bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]ed9f9cd2013-02-27 21:12:356519 const Framebuffer* framebuffer =
6520 GetFramebuffer(client_id);
[email protected]a0b78dc2011-11-11 10:43:106521 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156522}
6523
6524bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:366525 // IsProgram is true for programs as soon as they are created, until they are
6526 // deleted and no longer in use.
[email protected]ed9f9cd2013-02-27 21:12:356527 const Program* program = GetProgram(client_id);
[email protected]a0b78dc2011-11-11 10:43:106528 return program != NULL && !program->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156529}
6530
6531bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]ed9f9cd2013-02-27 21:12:356532 const Renderbuffer* renderbuffer =
6533 GetRenderbuffer(client_id);
[email protected]a0b78dc2011-11-11 10:43:106534 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156535}
6536
6537bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:366538 // IsShader is true for shaders as soon as they are created, until they
6539 // are deleted and not attached to any programs.
[email protected]ed9f9cd2013-02-27 21:12:356540 const Shader* shader = GetShader(client_id);
[email protected]a0b78dc2011-11-11 10:43:106541 return shader != NULL && !shader->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156542}
6543
6544bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]370eaf12013-05-18 09:19:496545 const TextureRef* texture_ref = GetTexture(client_id);
6546 return texture_ref && texture_ref->texture()->IsValid();
[email protected]ae51d192010-04-27 00:48:036547}
6548
6549void GLES2DecoderImpl::DoAttachShader(
6550 GLuint program_client_id, GLint shader_client_id) {
[email protected]df37b9932013-03-08 05:21:426551 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:586552 program_client_id, "glAttachShader");
[email protected]df37b9932013-03-08 05:21:426553 if (!program) {
[email protected]ae51d192010-04-27 00:48:036554 return;
[email protected]1958e0e2010-04-22 05:17:156555 }
[email protected]df37b9932013-03-08 05:21:426556 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
6557 if (!shader) {
[email protected]ae51d192010-04-27 00:48:036558 return;
6559 }
[email protected]df37b9932013-03-08 05:21:426560 if (!program->AttachShader(shader_manager(), shader)) {
[email protected]ab09b612013-03-11 22:11:516561 LOCAL_SET_GL_ERROR(
6562 GL_INVALID_OPERATION,
6563 "glAttachShader",
6564 "can not attach more than one shader of the same type.");
[email protected]fb96c8e2010-08-12 04:10:316565 return;
6566 }
[email protected]df37b9932013-03-08 05:21:426567 glAttachShader(program->service_id(), shader->service_id());
[email protected]ae51d192010-04-27 00:48:036568}
6569
6570void GLES2DecoderImpl::DoDetachShader(
6571 GLuint program_client_id, GLint shader_client_id) {
[email protected]df37b9932013-03-08 05:21:426572 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:586573 program_client_id, "glDetachShader");
[email protected]df37b9932013-03-08 05:21:426574 if (!program) {
[email protected]ae51d192010-04-27 00:48:036575 return;
6576 }
[email protected]df37b9932013-03-08 05:21:426577 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
6578 if (!shader) {
[email protected]ae51d192010-04-27 00:48:036579 return;
6580 }
[email protected]df37b9932013-03-08 05:21:426581 if (!program->DetachShader(shader_manager(), shader)) {
[email protected]ab09b612013-03-11 22:11:516582 LOCAL_SET_GL_ERROR(
6583 GL_INVALID_OPERATION,
6584 "glDetachShader", "shader not attached to program");
[email protected]9a0ccd42011-03-16 23:58:226585 return;
6586 }
[email protected]df37b9932013-03-08 05:21:426587 glDetachShader(program->service_id(), shader->service_id());
[email protected]ae51d192010-04-27 00:48:036588}
6589
6590void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]df37b9932013-03-08 05:21:426591 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:586592 program_client_id, "glValidateProgram");
[email protected]df37b9932013-03-08 05:21:426593 if (!program) {
[email protected]ae51d192010-04-27 00:48:036594 return;
6595 }
[email protected]df37b9932013-03-08 05:21:426596 program->Validate();
[email protected]1958e0e2010-04-22 05:17:156597}
6598
[email protected]ac77603c72013-03-08 13:52:066599void GLES2DecoderImpl::GetVertexAttribHelper(
6600 const VertexAttrib* attrib, GLenum pname, GLint* params) {
[email protected]b1122982010-05-17 23:04:246601 switch (pname) {
6602 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
[email protected]ac77603c72013-03-08 13:52:066603 Buffer* buffer = attrib->buffer();
[email protected]b1122982010-05-17 23:04:246604 if (buffer && !buffer->IsDeleted()) {
6605 GLuint client_id;
6606 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
6607 *params = client_id;
6608 }
6609 break;
6610 }
6611 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
[email protected]ac77603c72013-03-08 13:52:066612 *params = attrib->enabled();
[email protected]b1122982010-05-17 23:04:246613 break;
6614 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
[email protected]ac77603c72013-03-08 13:52:066615 *params = attrib->size();
[email protected]b1122982010-05-17 23:04:246616 break;
6617 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
[email protected]ac77603c72013-03-08 13:52:066618 *params = attrib->gl_stride();
[email protected]b1122982010-05-17 23:04:246619 break;
6620 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
[email protected]ac77603c72013-03-08 13:52:066621 *params = attrib->type();
[email protected]b1122982010-05-17 23:04:246622 break;
6623 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
[email protected]ac77603c72013-03-08 13:52:066624 *params = attrib->normalized();
[email protected]b1122982010-05-17 23:04:246625 break;
[email protected]c6aef902012-02-14 03:31:426626 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
[email protected]ac77603c72013-03-08 13:52:066627 *params = attrib->divisor();
[email protected]c6aef902012-02-14 03:31:426628 break;
[email protected]ac77603c72013-03-08 13:52:066629 default:
6630 NOTREACHED();
6631 break;
6632 }
6633}
6634
6635void GLES2DecoderImpl::DoGetVertexAttribfv(
6636 GLuint index, GLenum pname, GLfloat* params) {
6637 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6638 if (!attrib) {
[email protected]ab09b612013-03-11 22:11:516639 LOCAL_SET_GL_ERROR(
6640 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
[email protected]ac77603c72013-03-08 13:52:066641 return;
6642 }
6643 switch (pname) {
6644 case GL_CURRENT_VERTEX_ATTRIB: {
6645 const Vec4& value = state_.attrib_values[index];
6646 params[0] = value.v[0];
6647 params[1] = value.v[1];
6648 params[2] = value.v[2];
6649 params[3] = value.v[3];
6650 break;
6651 }
6652 default: {
6653 GLint value = 0;
6654 GetVertexAttribHelper(attrib, pname, &value);
6655 *params = static_cast<GLfloat>(value);
6656 break;
6657 }
6658 }
6659}
6660
6661void GLES2DecoderImpl::DoGetVertexAttribiv(
6662 GLuint index, GLenum pname, GLint* params) {
6663 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6664 if (!attrib) {
[email protected]ab09b612013-03-11 22:11:516665 LOCAL_SET_GL_ERROR(
6666 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
[email protected]ac77603c72013-03-08 13:52:066667 return;
6668 }
6669 switch (pname) {
[email protected]af6380962012-11-29 23:24:136670 case GL_CURRENT_VERTEX_ATTRIB: {
6671 const Vec4& value = state_.attrib_values[index];
6672 params[0] = static_cast<GLint>(value.v[0]);
6673 params[1] = static_cast<GLint>(value.v[1]);
6674 params[2] = static_cast<GLint>(value.v[2]);
6675 params[3] = static_cast<GLint>(value.v[3]);
[email protected]b1122982010-05-17 23:04:246676 break;
[email protected]af6380962012-11-29 23:24:136677 }
[email protected]b1122982010-05-17 23:04:246678 default:
[email protected]ac77603c72013-03-08 13:52:066679 GetVertexAttribHelper(attrib, pname, params);
[email protected]b1122982010-05-17 23:04:246680 break;
6681 }
6682}
6683
[email protected]af6380962012-11-29 23:24:136684bool GLES2DecoderImpl::SetVertexAttribValue(
6685 const char* function_name, GLuint index, const GLfloat* value) {
6686 if (index >= state_.attrib_values.size()) {
[email protected]ab09b612013-03-11 22:11:516687 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
[email protected]af6380962012-11-29 23:24:136688 return false;
[email protected]b1122982010-05-17 23:04:246689 }
[email protected]af6380962012-11-29 23:24:136690 Vec4& v = state_.attrib_values[index];
6691 v.v[0] = value[0];
6692 v.v[1] = value[1];
6693 v.v[2] = value[2];
6694 v.v[3] = value[3];
6695 return true;
6696}
6697
6698void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
6699 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
6700 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
6701 glVertexAttrib1f(index, v0);
6702 }
[email protected]b1122982010-05-17 23:04:246703}
6704
6705void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
[email protected]af6380962012-11-29 23:24:136706 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
6707 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
6708 glVertexAttrib2f(index, v0, v1);
[email protected]b1122982010-05-17 23:04:246709 }
[email protected]b1122982010-05-17 23:04:246710}
6711
6712void GLES2DecoderImpl::DoVertexAttrib3f(
6713 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
[email protected]af6380962012-11-29 23:24:136714 GLfloat v[4] = { v0, v1, v2, 1.0f, };
6715 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
6716 glVertexAttrib3f(index, v0, v1, v2);
[email protected]b1122982010-05-17 23:04:246717 }
[email protected]b1122982010-05-17 23:04:246718}
6719
6720void GLES2DecoderImpl::DoVertexAttrib4f(
6721 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
[email protected]af6380962012-11-29 23:24:136722 GLfloat v[4] = { v0, v1, v2, v3, };
6723 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
6724 glVertexAttrib4f(index, v0, v1, v2, v3);
[email protected]b1122982010-05-17 23:04:246725 }
[email protected]b1122982010-05-17 23:04:246726}
6727
6728void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136729 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
6730 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
6731 glVertexAttrib1fv(index, v);
[email protected]b1122982010-05-17 23:04:246732 }
[email protected]b1122982010-05-17 23:04:246733}
6734
6735void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136736 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
6737 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
6738 glVertexAttrib2fv(index, v);
[email protected]b1122982010-05-17 23:04:246739 }
[email protected]b1122982010-05-17 23:04:246740}
6741
6742void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136743 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
6744 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
6745 glVertexAttrib3fv(index, v);
[email protected]b1122982010-05-17 23:04:246746 }
[email protected]b1122982010-05-17 23:04:246747}
6748
6749void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136750 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
6751 glVertexAttrib4fv(index, v);
[email protected]b1122982010-05-17 23:04:246752 }
[email protected]b1122982010-05-17 23:04:246753}
6754
[email protected]f7a64ee2010-02-01 22:24:146755error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]ed9f9cd2013-02-27 21:12:356756 uint32 immediate_data_size, const cmds::VertexAttribPointer& c) {
[email protected]944b62f32012-09-27 02:20:466757
[email protected]7cd76fd2013-06-02 21:11:116758 if (!state_.bound_array_buffer.get() ||
6759 state_.bound_array_buffer->IsDeleted()) {
6760 if (state_.vertex_attrib_manager.get() ==
6761 default_vertex_attrib_manager_.get()) {
[email protected]ab09b612013-03-11 22:11:516762 LOCAL_SET_GL_ERROR(
6763 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
[email protected]944b62f32012-09-27 02:20:466764 return error::kNoError;
6765 } else if (c.offset != 0) {
[email protected]ab09b612013-03-11 22:11:516766 LOCAL_SET_GL_ERROR(
6767 GL_INVALID_VALUE,
6768 "glVertexAttribPointer", "client side arrays are not allowed");
[email protected]944b62f32012-09-27 02:20:466769 return error::kNoError;
6770 }
[email protected]96449d2c2009-11-25 00:01:326771 }
[email protected]8eee29c2010-04-29 03:38:296772
6773 GLuint indx = c.indx;
6774 GLint size = c.size;
6775 GLenum type = c.type;
6776 GLboolean normalized = c.normalized;
6777 GLsizei stride = c.stride;
6778 GLsizei offset = c.offset;
6779 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:056780 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]ab09b612013-03-11 22:11:516781 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
[email protected]8eee29c2010-04-29 03:38:296782 return error::kNoError;
6783 }
[email protected]9438b012010-06-15 22:55:056784 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ab09b612013-03-11 22:11:516785 LOCAL_SET_GL_ERROR(
6786 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
[email protected]8eee29c2010-04-29 03:38:296787 return error::kNoError;
6788 }
6789 if (indx >= group_->max_vertex_attribs()) {
[email protected]ab09b612013-03-11 22:11:516790 LOCAL_SET_GL_ERROR(
6791 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
[email protected]8eee29c2010-04-29 03:38:296792 return error::kNoError;
6793 }
6794 if (stride < 0) {
[email protected]ab09b612013-03-11 22:11:516795 LOCAL_SET_GL_ERROR(
6796 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
[email protected]8eee29c2010-04-29 03:38:296797 return error::kNoError;
6798 }
6799 if (stride > 255) {
[email protected]ab09b612013-03-11 22:11:516800 LOCAL_SET_GL_ERROR(
6801 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
[email protected]8eee29c2010-04-29 03:38:296802 return error::kNoError;
6803 }
6804 if (offset < 0) {
[email protected]ab09b612013-03-11 22:11:516805 LOCAL_SET_GL_ERROR(
6806 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
[email protected]8eee29c2010-04-29 03:38:296807 return error::kNoError;
6808 }
6809 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:316810 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:296811 if (offset % component_size > 0) {
[email protected]ab09b612013-03-11 22:11:516812 LOCAL_SET_GL_ERROR(
6813 GL_INVALID_OPERATION,
6814 "glVertexAttribPointer", "offset not valid for type");
[email protected]ff81c192011-01-07 23:04:316815 return error::kNoError;
6816 }
6817 if (stride % component_size > 0) {
[email protected]ab09b612013-03-11 22:11:516818 LOCAL_SET_GL_ERROR(
6819 GL_INVALID_OPERATION,
6820 "glVertexAttribPointer", "stride not valid for type");
[email protected]8eee29c2010-04-29 03:38:296821 return error::kNoError;
6822 }
[email protected]7cd76fd2013-06-02 21:11:116823 state_.vertex_attrib_manager
6824 ->SetAttribInfo(indx,
6825 state_.bound_array_buffer.get(),
6826 size,
6827 type,
6828 normalized,
6829 stride,
6830 stride != 0 ? stride : component_size * size,
6831 offset);
[email protected]8fbedc02010-11-18 18:43:406832 if (type != GL_FIXED) {
6833 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
6834 }
[email protected]f7a64ee2010-02-01 22:24:146835 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326836}
6837
[email protected]43410e92012-04-20 17:06:286838void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
6839 GLsizei height) {
[email protected]e259eb412012-10-13 05:47:246840 state_.viewport_x = x;
6841 state_.viewport_y = y;
[email protected]1868a342012-11-07 15:56:026842 state_.viewport_width = std::min(width, viewport_max_width_);
6843 state_.viewport_height = std::min(height, viewport_max_height_);
[email protected]43410e92012-04-20 17:06:286844 glViewport(x, y, width, height);
6845}
6846
[email protected]c6aef902012-02-14 03:31:426847error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
[email protected]ed9f9cd2013-02-27 21:12:356848 uint32 immediate_data_size, const cmds::VertexAttribDivisorANGLE& c) {
[email protected]62e155e2012-10-23 22:43:156849 if (!features().angle_instanced_arrays) {
[email protected]ab09b612013-03-11 22:11:516850 LOCAL_SET_GL_ERROR(
6851 GL_INVALID_OPERATION,
6852 "glVertexAttribDivisorANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:426853 }
6854 GLuint index = c.index;
6855 GLuint divisor = c.divisor;
6856 if (index >= group_->max_vertex_attribs()) {
[email protected]ab09b612013-03-11 22:11:516857 LOCAL_SET_GL_ERROR(
6858 GL_INVALID_VALUE,
6859 "glVertexAttribDivisorANGLE", "index out of range");
[email protected]c6aef902012-02-14 03:31:426860 return error::kNoError;
6861 }
6862
[email protected]e259eb412012-10-13 05:47:246863 state_.vertex_attrib_manager->SetDivisor(
[email protected]c6aef902012-02-14 03:31:426864 index,
6865 divisor);
6866 glVertexAttribDivisorANGLE(index, divisor);
6867 return error::kNoError;
6868}
6869
[email protected]5a36dc132013-07-23 23:17:556870void GLES2DecoderImpl::FinishReadPixels(
6871 const cmds::ReadPixels& c,
6872 GLuint buffer) {
6873 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
6874 GLsizei width = c.width;
6875 GLsizei height = c.height;
6876 GLenum format = c.format;
6877 GLenum type = c.type;
6878 typedef cmds::ReadPixels::Result Result;
6879 uint32 pixels_size;
6880 Result* result = NULL;
6881 if (c.result_shm_id != 0) {
6882 result = GetSharedMemoryAs<Result*>(
6883 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6884 if (!result) {
6885 if (buffer != 0) {
6886 glDeleteBuffersARB(1, &buffer);
6887 }
6888 return;
6889 }
6890 }
6891 GLES2Util::ComputeImageDataSizes(
6892 width, height, format, type, state_.pack_alignment, &pixels_size,
6893 NULL, NULL);
6894 void* pixels = GetSharedMemoryAs<void*>(
6895 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
6896 if (!pixels) {
6897 if (buffer != 0) {
6898 glDeleteBuffersARB(1, &buffer);
6899 }
6900 return;
6901 }
6902
6903 if (buffer != 0) {
6904 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
[email protected]e585f9e22013-08-27 02:50:336905 void* data;
6906 if (features().map_buffer_range) {
6907 data = glMapBufferRange(
6908 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
6909 } else {
6910 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
6911 }
[email protected]5a36dc132013-07-23 23:17:556912 memcpy(pixels, data, pixels_size);
6913 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
6914 // have to restore the state.
6915 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
6916 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
6917 glDeleteBuffersARB(1, &buffer);
6918 }
6919
6920 if (result != NULL) {
6921 *result = true;
6922 }
6923
6924 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6925 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6926 if ((channels_exist & 0x0008) == 0 &&
6927 workarounds().clear_alpha_in_readpixels) {
6928 // Set the alpha to 255 because some drivers are buggy in this regard.
6929 uint32 temp_size;
6930
6931 uint32 unpadded_row_size;
6932 uint32 padded_row_size;
6933 if (!GLES2Util::ComputeImageDataSizes(
6934 width, 2, format, type, state_.pack_alignment, &temp_size,
6935 &unpadded_row_size, &padded_row_size)) {
6936 return;
6937 }
6938 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
6939 // of this implementation.
6940 if (type != GL_UNSIGNED_BYTE) {
6941 return;
6942 }
6943 switch (format) {
6944 case GL_RGBA:
6945 case GL_BGRA_EXT:
6946 case GL_ALPHA: {
6947 int offset = (format == GL_ALPHA) ? 0 : 3;
6948 int step = (format == GL_ALPHA) ? 1 : 4;
6949 uint8* dst = static_cast<uint8*>(pixels) + offset;
6950 for (GLint yy = 0; yy < height; ++yy) {
6951 uint8* end = dst + unpadded_row_size;
6952 for (uint8* d = dst; d < end; d += step) {
6953 *d = 255;
6954 }
6955 dst += padded_row_size;
6956 }
6957 break;
6958 }
6959 default:
6960 break;
6961 }
6962 }
6963}
6964
6965
[email protected]f7a64ee2010-02-01 22:24:146966error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]ed9f9cd2013-02-27 21:12:356967 uint32 immediate_data_size, const cmds::ReadPixels& c) {
[email protected]09e17272012-11-30 10:30:446968 if (ShouldDeferReads())
6969 return error::kDeferCommandUntilLater;
[email protected]612d2f82009-12-08 20:49:316970 GLint x = c.x;
6971 GLint y = c.y;
6972 GLsizei width = c.width;
6973 GLsizei height = c.height;
6974 GLenum format = c.format;
6975 GLenum type = c.type;
[email protected]5a36dc132013-07-23 23:17:556976 GLboolean async = c.async;
[email protected]57f223832010-03-19 01:57:566977 if (width < 0 || height < 0) {
[email protected]ab09b612013-03-11 22:11:516978 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
[email protected]57f223832010-03-19 01:57:566979 return error::kNoError;
6980 }
[email protected]ed9f9cd2013-02-27 21:12:356981 typedef cmds::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:186982 uint32 pixels_size;
[email protected]3458a64a2012-04-10 17:39:346983 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:246984 width, height, format, type, state_.pack_alignment, &pixels_size,
6985 NULL, NULL)) {
[email protected]a76b0052010-03-05 00:33:186986 return error::kOutOfBounds;
6987 }
[email protected]612d2f82009-12-08 20:49:316988 void* pixels = GetSharedMemoryAs<void*>(
6989 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]de43f082013-04-02 01:16:106990 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146991 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466992 }
[email protected]de43f082013-04-02 01:16:106993 Result* result = NULL;
6994 if (c.result_shm_id != 0) {
6995 result = GetSharedMemoryAs<Result*>(
6996 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6997 if (!result) {
6998 return error::kOutOfBounds;
6999 }
7000 }
[email protected]a51788e2010-02-24 21:54:257001
[email protected]9438b012010-06-15 22:55:057002 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]ab09b612013-03-11 22:11:517003 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
[email protected]8eee29c2010-04-29 03:38:297004 return error::kNoError;
7005 }
[email protected]9438b012010-06-15 22:55:057006 if (!validators_->pixel_type.IsValid(type)) {
[email protected]ab09b612013-03-11 22:11:517007 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
[email protected]d2cf0a2d2010-02-25 21:36:127008 return error::kNoError;
7009 }
[email protected]57f223832010-03-19 01:57:567010 if (width == 0 || height == 0) {
7011 return error::kNoError;
7012 }
7013
[email protected]57f223832010-03-19 01:57:567014 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:307015 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:567016
[email protected]3aad1a32012-09-07 20:54:477017 int32 max_x;
7018 int32 max_y;
7019 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
[email protected]ab09b612013-03-11 22:11:517020 LOCAL_SET_GL_ERROR(
7021 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:147022 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:317023 }
[email protected]57f223832010-03-19 01:57:567024
[email protected]0d6bfdc2011-11-02 01:32:207025 if (!CheckBoundFramebuffersValid("glReadPixels")) {
7026 return error::kNoError;
7027 }
7028
[email protected]ab09b612013-03-11 22:11:517029 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixel");
[email protected]a0b78dc2011-11-11 10:43:107030
7031 ScopedResolvedFrameBufferBinder binder(this, false, true);
7032
[email protected]d37231fa2010-04-09 21:16:027033 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:567034 // The user requested an out of range area. Get the results 1 line
7035 // at a time.
7036 uint32 temp_size;
[email protected]3458a64a2012-04-10 17:39:347037 uint32 unpadded_row_size;
7038 uint32 padded_row_size;
7039 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247040 width, 2, format, type, state_.pack_alignment, &temp_size,
[email protected]3458a64a2012-04-10 17:39:347041 &unpadded_row_size, &padded_row_size)) {
[email protected]ab09b612013-03-11 22:11:517042 LOCAL_SET_GL_ERROR(
7043 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]57f223832010-03-19 01:57:567044 return error::kNoError;
7045 }
7046
7047 GLint dest_x_offset = std::max(-x, 0);
7048 uint32 dest_row_offset;
[email protected]3458a64a2012-04-10 17:39:347049 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247050 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
7051 NULL, NULL)) {
[email protected]ab09b612013-03-11 22:11:517052 LOCAL_SET_GL_ERROR(
7053 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]57f223832010-03-19 01:57:567054 return error::kNoError;
7055 }
7056
7057 // Copy each row into the larger dest rect.
7058 int8* dst = static_cast<int8*>(pixels);
7059 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:027060 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:567061 GLint read_width = read_end_x - read_x;
7062 for (GLint yy = 0; yy < height; ++yy) {
7063 GLint ry = y + yy;
7064
7065 // Clear the row.
7066 memset(dst, 0, unpadded_row_size);
7067
7068 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:027069 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:567070 glReadPixels(
7071 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
7072 }
7073 dst += padded_row_size;
7074 }
7075 } else {
[email protected]5a36dc132013-07-23 23:17:557076 if (async && features().use_async_readpixels) {
7077 GLuint buffer;
7078 glGenBuffersARB(1, &buffer);
7079 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
7080 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
7081 GLenum error = glGetError();
7082 if (error == GL_NO_ERROR) {
7083 glReadPixels(x, y, width, height, format, type, 0);
7084 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
7085 new FenceCallback()));
7086 WaitForReadPixels(base::Bind(
7087 &GLES2DecoderImpl::FinishReadPixels,
7088 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
7089 <GLES2DecoderImpl>(this),
7090 c, buffer));
7091 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
7092 return error::kNoError;
7093 }
7094 }
[email protected]57f223832010-03-19 01:57:567095 glReadPixels(x, y, width, height, format, type, pixels);
7096 }
[email protected]ab09b612013-03-11 22:11:517097 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
[email protected]a51788e2010-02-24 21:54:257098 if (error == GL_NO_ERROR) {
[email protected]de43f082013-04-02 01:16:107099 if (result != NULL) {
7100 *result = true;
7101 }
[email protected]5a36dc132013-07-23 23:17:557102 FinishReadPixels(c, 0);
[email protected]a51788e2010-02-24 21:54:257103 }
[email protected]4848b9f82011-03-10 18:37:567104
[email protected]f7a64ee2010-02-01 22:24:147105 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327106}
7107
[email protected]f7a64ee2010-02-01 22:24:147108error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]ed9f9cd2013-02-27 21:12:357109 uint32 immediate_data_size, const cmds::PixelStorei& c) {
[email protected]b9849abf2009-11-25 19:13:197110 GLenum pname = c.pname;
7111 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:057112 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]ab09b612013-03-11 22:11:517113 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
[email protected]d2cf0a2d2010-02-25 21:36:127114 return error::kNoError;
7115 }
[email protected]222471d2011-11-30 18:06:397116 switch (pname) {
7117 case GL_PACK_ALIGNMENT:
7118 case GL_UNPACK_ALIGNMENT:
7119 if (!validators_->pixel_store_alignment.IsValid(param)) {
[email protected]ab09b612013-03-11 22:11:517120 LOCAL_SET_GL_ERROR(
7121 GL_INVALID_VALUE, "glPixelStore", "param GL_INVALID_VALUE");
[email protected]222471d2011-11-30 18:06:397122 return error::kNoError;
7123 }
[email protected]164d6d52012-05-05 00:55:037124 break;
[email protected]0a1e9ad2012-05-04 21:13:037125 case GL_UNPACK_FLIP_Y_CHROMIUM:
7126 unpack_flip_y_ = (param != 0);
7127 return error::kNoError;
7128 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
7129 unpack_premultiply_alpha_ = (param != 0);
7130 return error::kNoError;
[email protected]6c75c712012-06-19 15:43:177131 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
7132 unpack_unpremultiply_alpha_ = (param != 0);
7133 return error::kNoError;
[email protected]222471d2011-11-30 18:06:397134 default:
7135 break;
[email protected]b9849abf2009-11-25 19:13:197136 }
7137 glPixelStorei(pname, param);
7138 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:437139 case GL_PACK_ALIGNMENT:
[email protected]e259eb412012-10-13 05:47:247140 state_.pack_alignment = param;
[email protected]ad84a3a2012-06-08 21:42:437141 break;
7142 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
[email protected]88a61bf2012-10-27 13:00:427143 state_.pack_reverse_row_order = (param != 0);
[email protected]ad84a3a2012-06-08 21:42:437144 break;
7145 case GL_UNPACK_ALIGNMENT:
[email protected]e259eb412012-10-13 05:47:247146 state_.unpack_alignment = param;
[email protected]ad84a3a2012-06-08 21:42:437147 break;
7148 default:
7149 // Validation should have prevented us from getting here.
7150 NOTREACHED();
7151 break;
[email protected]b9849abf2009-11-25 19:13:197152 }
[email protected]f7a64ee2010-02-01 22:24:147153 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197154}
7155
[email protected]1c75a3702011-11-11 14:15:287156error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:357157 uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
[email protected]43ed3a72012-05-30 22:55:387158 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
[email protected]6f5fac9d12012-06-26 21:02:457159 if (!surface_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
[email protected]ab09b612013-03-11 22:11:517160 LOCAL_SET_GL_ERROR(
7161 GL_INVALID_OPERATION,
7162 "glPostSubBufferCHROMIUM", "command not supported by surface");
[email protected]1c75a3702011-11-11 14:15:287163 return error::kNoError;
7164 }
[email protected]8f9b8dd2013-09-12 18:05:137165 bool is_tracing;
7166 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
7167 &is_tracing);
7168 if (is_tracing) {
7169 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7170 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
7171 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
7172 is_offscreen ? offscreen_size_ : surface_->GetSize());
7173 }
[email protected]7794d512012-04-17 20:36:497174 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
[email protected]1c75a3702011-11-11 14:15:287175 return error::kNoError;
[email protected]7794d512012-04-17 20:36:497176 } else {
7177 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
[email protected]1c75a3702011-11-11 14:15:287178 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:497179 }
[email protected]1c75a3702011-11-11 14:15:287180}
7181
[email protected]558847a2010-03-24 07:02:547182error::Error GLES2DecoderImpl::GetAttribLocationHelper(
7183 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7184 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:577185 if (!StringIsValidForGLES(name_str.c_str())) {
[email protected]ab09b612013-03-11 22:11:517186 LOCAL_SET_GL_ERROR(
7187 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:577188 return error::kNoError;
7189 }
[email protected]df37b9932013-03-08 05:21:427190 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:587191 client_id, "glGetAttribLocation");
[email protected]df37b9932013-03-08 05:21:427192 if (!program) {
[email protected]f7a64ee2010-02-01 22:24:147193 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197194 }
[email protected]df37b9932013-03-08 05:21:427195 if (!program->IsValid()) {
[email protected]ab09b612013-03-11 22:11:517196 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437197 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
[email protected]0bfd9882010-02-05 23:02:257198 return error::kNoError;
7199 }
[email protected]b9849abf2009-11-25 19:13:197200 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:547201 location_shm_id, location_shm_offset, sizeof(GLint));
7202 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:147203 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197204 }
[email protected]558847a2010-03-24 07:02:547205 // Require the client to init this incase the context is lost and we are no
7206 // longer executing commands.
7207 if (*location != -1) {
7208 return error::kGenericError;
7209 }
[email protected]df37b9932013-03-08 05:21:427210 *location = program->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:147211 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197212}
7213
[email protected]558847a2010-03-24 07:02:547214error::Error GLES2DecoderImpl::HandleGetAttribLocation(
[email protected]ed9f9cd2013-02-27 21:12:357215 uint32 immediate_data_size, const cmds::GetAttribLocation& c) {
[email protected]558847a2010-03-24 07:02:547216 uint32 name_size = c.data_size;
7217 const char* name = GetSharedMemoryAs<const char*>(
7218 c.name_shm_id, c.name_shm_offset, name_size);
7219 if (!name) {
7220 return error::kOutOfBounds;
7221 }
7222 String name_str(name, name_size);
7223 return GetAttribLocationHelper(
7224 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7225}
7226
[email protected]558847a2010-03-24 07:02:547227error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
[email protected]ed9f9cd2013-02-27 21:12:357228 uint32 immediate_data_size, const cmds::GetAttribLocationBucket& c) {
[email protected]558847a2010-03-24 07:02:547229 Bucket* bucket = GetBucket(c.name_bucket_id);
7230 if (!bucket) {
7231 return error::kInvalidArguments;
7232 }
7233 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:187234 if (!bucket->GetAsString(&name_str)) {
7235 return error::kInvalidArguments;
7236 }
[email protected]558847a2010-03-24 07:02:547237 return GetAttribLocationHelper(
7238 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7239}
7240
7241error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7242 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7243 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:577244 if (!StringIsValidForGLES(name_str.c_str())) {
[email protected]ab09b612013-03-11 22:11:517245 LOCAL_SET_GL_ERROR(
7246 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:577247 return error::kNoError;
7248 }
[email protected]df37b9932013-03-08 05:21:427249 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:587250 client_id, "glUniformLocation");
[email protected]df37b9932013-03-08 05:21:427251 if (!program) {
[email protected]f7a64ee2010-02-01 22:24:147252 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197253 }
[email protected]df37b9932013-03-08 05:21:427254 if (!program->IsValid()) {
[email protected]ab09b612013-03-11 22:11:517255 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437256 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
[email protected]0bfd9882010-02-05 23:02:257257 return error::kNoError;
7258 }
[email protected]b9849abf2009-11-25 19:13:197259 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:547260 location_shm_id, location_shm_offset, sizeof(GLint));
7261 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:147262 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197263 }
[email protected]558847a2010-03-24 07:02:547264 // Require the client to init this incase the context is lost an we are no
7265 // longer executing commands.
7266 if (*location != -1) {
7267 return error::kGenericError;
7268 }
[email protected]df37b9932013-03-08 05:21:427269 *location = program->GetUniformFakeLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:147270 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197271}
7272
[email protected]f7a64ee2010-02-01 22:24:147273error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]ed9f9cd2013-02-27 21:12:357274 uint32 immediate_data_size, const cmds::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:197275 uint32 name_size = c.data_size;
7276 const char* name = GetSharedMemoryAs<const char*>(
7277 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:547278 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:147279 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197280 }
7281 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:547282 return GetUniformLocationHelper(
7283 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:197284}
7285
[email protected]558847a2010-03-24 07:02:547286error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
[email protected]ed9f9cd2013-02-27 21:12:357287 uint32 immediate_data_size, const cmds::GetUniformLocationBucket& c) {
[email protected]558847a2010-03-24 07:02:547288 Bucket* bucket = GetBucket(c.name_bucket_id);
7289 if (!bucket) {
7290 return error::kInvalidArguments;
7291 }
7292 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:187293 if (!bucket->GetAsString(&name_str)) {
7294 return error::kInvalidArguments;
7295 }
[email protected]558847a2010-03-24 07:02:547296 return GetUniformLocationHelper(
7297 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:197298}
7299
[email protected]ddd968b82010-03-02 00:44:297300error::Error GLES2DecoderImpl::HandleGetString(
[email protected]ed9f9cd2013-02-27 21:12:357301 uint32 immediate_data_size, const cmds::GetString& c) {
[email protected]ddd968b82010-03-02 00:44:297302 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:057303 if (!validators_->string_type.IsValid(name)) {
[email protected]ab09b612013-03-11 22:11:517304 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
[email protected]ddd968b82010-03-02 00:44:297305 return error::kNoError;
7306 }
[email protected]959e9072013-09-20 16:58:387307 const char* str = reinterpret_cast<const char*>(glGetString(name));
[email protected]f0d74742011-10-03 16:31:047308 std::string extensions;
[email protected]1958e0e2010-04-22 05:17:157309 switch (name) {
7310 case GL_VERSION:
7311 str = "OpenGL ES 2.0 Chromium";
7312 break;
7313 case GL_SHADING_LANGUAGE_VERSION:
7314 str = "OpenGL ES GLSL ES 1.0 Chromium";
7315 break;
[email protected]32939602012-05-09 06:25:167316 case GL_RENDERER:
[email protected]32939602012-05-09 06:25:167317 case GL_VENDOR:
[email protected]959e9072013-09-20 16:58:387318 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
7319 // They are used by WEBGL_debug_renderer_info.
7320 if (!force_webgl_glsl_validation_)
7321 str = "Chromium";
[email protected]32939602012-05-09 06:25:167322 break;
[email protected]1958e0e2010-04-22 05:17:157323 case GL_EXTENSIONS:
[email protected]f0d74742011-10-03 16:31:047324 {
[email protected]70dc60932013-06-04 03:33:497325 // For WebGL contexts, strip out the OES derivatives and
7326 // EXT frag depth extensions if they have not been enabled.
7327 if (force_webgl_glsl_validation_) {
[email protected]f0d74742011-10-03 16:31:047328 extensions = feature_info_->extensions();
[email protected]70dc60932013-06-04 03:33:497329 if (!derivatives_explicitly_enabled_) {
7330 size_t offset = extensions.find(kOESDerivativeExtension);
7331 if (std::string::npos != offset) {
[email protected]f16cc9f2013-06-14 01:04:097332 extensions.replace(offset, arraysize(kOESDerivativeExtension),
[email protected]70dc60932013-06-04 03:33:497333 std::string());
7334 }
7335 }
7336 if (!frag_depth_explicitly_enabled_) {
7337 size_t offset = extensions.find(kEXTFragDepthExtension);
7338 if (std::string::npos != offset) {
[email protected]f16cc9f2013-06-14 01:04:097339 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
[email protected]70dc60932013-06-04 03:33:497340 std::string());
7341 }
[email protected]f0d74742011-10-03 16:31:047342 }
[email protected]aff39ac82013-06-08 04:53:137343 if (!draw_buffers_explicitly_enabled_) {
7344 size_t offset = extensions.find(kEXTDrawBuffersExtension);
7345 if (std::string::npos != offset) {
[email protected]f16cc9f2013-06-14 01:04:097346 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
[email protected]aff39ac82013-06-08 04:53:137347 std::string());
7348 }
7349 }
[email protected]f0d74742011-10-03 16:31:047350 } else {
[email protected]6f5fac9d12012-06-26 21:02:457351 extensions = feature_info_->extensions().c_str();
[email protected]f0d74742011-10-03 16:31:047352 }
[email protected]6f5fac9d12012-06-26 21:02:457353 std::string surface_extensions = surface_->GetExtensions();
7354 if (!surface_extensions.empty())
7355 extensions += " " + surface_extensions;
7356 str = extensions.c_str();
[email protected]f0d74742011-10-03 16:31:047357 }
[email protected]1958e0e2010-04-22 05:17:157358 break;
7359 default:
[email protected]1958e0e2010-04-22 05:17:157360 break;
7361 }
[email protected]ddd968b82010-03-02 00:44:297362 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:157363 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:297364 return error::kNoError;
7365}
7366
[email protected]0c86dbf2010-03-05 08:14:117367error::Error GLES2DecoderImpl::HandleBufferData(
[email protected]ed9f9cd2013-02-27 21:12:357368 uint32 immediate_data_size, const cmds::BufferData& c) {
[email protected]0c86dbf2010-03-05 08:14:117369 GLenum target = static_cast<GLenum>(c.target);
7370 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
7371 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7372 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7373 GLenum usage = static_cast<GLenum>(c.usage);
7374 const void* data = NULL;
7375 if (data_shm_id != 0 || data_shm_offset != 0) {
7376 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
7377 if (!data) {
7378 return error::kOutOfBounds;
7379 }
7380 }
[email protected]0fbba3732013-07-17 15:40:137381 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:147382 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197383}
7384
[email protected]f7a64ee2010-02-01 22:24:147385error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]ed9f9cd2013-02-27 21:12:357386 uint32 immediate_data_size, const cmds::BufferDataImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:197387 GLenum target = static_cast<GLenum>(c.target);
7388 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:307389 const void* data = GetImmediateDataAs<const void*>(
7390 c, size, immediate_data_size);
7391 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:147392 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:307393 }
[email protected]b9849abf2009-11-25 19:13:197394 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0fbba3732013-07-17 15:40:137395 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
[email protected]0c86dbf2010-03-05 08:14:117396 return error::kNoError;
7397}
7398
7399void GLES2DecoderImpl::DoBufferSubData(
7400 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]0fbba3732013-07-17 15:40:137401 // Just delegate it. Some validation is actually done before this.
7402 buffer_manager()->ValidateAndDoBufferSubData(
7403 &state_, target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:197404}
7405
[email protected]0d6bfdc2011-11-02 01:32:207406bool GLES2DecoderImpl::ClearLevel(
7407 unsigned service_id,
7408 unsigned bind_target,
7409 unsigned target,
7410 int level,
7411 unsigned format,
7412 unsigned type,
7413 int width,
[email protected]4502e6492011-12-14 19:39:157414 int height,
7415 bool is_texture_immutable) {
[email protected]81375742012-06-08 00:04:007416 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7417 if (IsAngle() && (channels & GLES2Util::kDepth) != 0) {
7418 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7419 // on depth formats.
7420 GLuint fb = 0;
7421 glGenFramebuffersEXT(1, &fb);
7422 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
7423
7424 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
7425 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
7426 GL_DEPTH_ATTACHMENT;
7427
7428 glFramebufferTexture2DEXT(
7429 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
7430 // ANGLE promises a depth only attachment ok.
7431 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
7432 GL_FRAMEBUFFER_COMPLETE) {
7433 return false;
7434 }
7435 glClearStencil(0);
7436 glStencilMask(-1);
7437 glClearDepth(1.0f);
7438 glDepthMask(true);
7439 glDisable(GL_SCISSOR_TEST);
7440 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
7441
7442 RestoreClearState();
7443
7444 glDeleteFramebuffersEXT(1, &fb);
[email protected]ed9f9cd2013-02-27 21:12:357445 Framebuffer* framebuffer =
[email protected]81375742012-06-08 00:04:007446 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
7447 GLuint fb_service_id =
7448 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
7449 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
7450 return true;
7451 }
7452
[email protected]45d15a62012-04-18 14:33:177453 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
7454
7455 uint32 size;
7456 uint32 padded_row_size;
[email protected]3458a64a2012-04-10 17:39:347457 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247458 width, height, format, type, state_.unpack_alignment, &size,
[email protected]45d15a62012-04-18 14:33:177459 NULL, &padded_row_size)) {
[email protected]0d6bfdc2011-11-02 01:32:207460 return false;
7461 }
[email protected]45d15a62012-04-18 14:33:177462
[email protected]a5d3dad2012-05-26 04:34:447463 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
7464
[email protected]45d15a62012-04-18 14:33:177465 int tile_height;
7466
7467 if (size > kMaxZeroSize) {
7468 if (kMaxZeroSize < padded_row_size) {
7469 // That'd be an awfully large texture.
7470 return false;
7471 }
7472 // We should never have a large total size with a zero row size.
7473 DCHECK_GT(padded_row_size, 0U);
7474 tile_height = kMaxZeroSize / padded_row_size;
7475 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247476 width, tile_height, format, type, state_.unpack_alignment, &size,
7477 NULL, NULL)) {
[email protected]45d15a62012-04-18 14:33:177478 return false;
7479 }
[email protected]4502e6492011-12-14 19:39:157480 } else {
[email protected]45d15a62012-04-18 14:33:177481 tile_height = height;
7482 }
7483
7484 // Assumes the size has already been checked.
[email protected]40d90a22013-04-09 03:39:557485 scoped_ptr<char[]> zero(new char[size]);
[email protected]45d15a62012-04-18 14:33:177486 memset(zero.get(), 0, size);
7487 glBindTexture(bind_target, service_id);
7488
7489 GLint y = 0;
7490 while (y < height) {
7491 GLint h = y + tile_height > height ? height - y : tile_height;
7492 if (is_texture_immutable || h != height) {
7493 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
7494 } else {
[email protected]8f1d2aa2013-05-10 23:45:387495 glTexImage2D(
[email protected]45d15a62012-04-18 14:33:177496 target, level, format, width, h, 0, format, type, zero.get());
7497 }
7498 y += tile_height;
[email protected]4502e6492011-12-14 19:39:157499 }
[email protected]c986af502013-08-14 01:04:447500 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
7501 &state_, bind_target);
[email protected]02965c22013-03-09 02:40:077502 glBindTexture(bind_target, texture ? texture->service_id() : 0);
[email protected]0d6bfdc2011-11-02 01:32:207503 return true;
7504}
7505
[email protected]ad84a3a2012-06-08 21:42:437506namespace {
7507
7508const int kS3TCBlockWidth = 4;
7509const int kS3TCBlockHeight = 4;
7510const int kS3TCDXT1BlockSize = 8;
7511const int kS3TCDXT3AndDXT5BlockSize = 16;
[email protected]2d3765b2012-10-03 00:31:077512const int kETC1BlockWidth = 4;
7513const int kETC1BlockHeight = 4;
7514const int kETC1BlockSize = 8;
[email protected]ad84a3a2012-06-08 21:42:437515
7516bool IsValidDXTSize(GLint level, GLsizei size) {
[email protected]10b56de2012-07-14 02:09:517517 return (size == 1) ||
7518 (size == 2) || !(size % kS3TCBlockWidth);
[email protected]ad84a3a2012-06-08 21:42:437519}
7520
7521} // anonymous namespace.
7522
7523bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
7524 const char* function_name,
7525 GLsizei width, GLsizei height, GLenum format, size_t size) {
7526 unsigned int bytes_required = 0;
7527
7528 switch (format) {
7529 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7530 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: {
7531 int num_blocks_across =
7532 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7533 int num_blocks_down =
7534 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7535 int num_blocks = num_blocks_across * num_blocks_down;
7536 bytes_required = num_blocks * kS3TCDXT1BlockSize;
7537 break;
7538 }
7539 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7540 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7541 int num_blocks_across =
7542 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7543 int num_blocks_down =
7544 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7545 int num_blocks = num_blocks_across * num_blocks_down;
7546 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
7547 break;
7548 }
[email protected]2d3765b2012-10-03 00:31:077549 case GL_ETC1_RGB8_OES: {
7550 int num_blocks_across =
7551 (width + kETC1BlockWidth - 1) / kETC1BlockWidth;
7552 int num_blocks_down =
7553 (height + kETC1BlockHeight - 1) / kETC1BlockHeight;
7554 int num_blocks = num_blocks_across * num_blocks_down;
7555 bytes_required = num_blocks * kETC1BlockSize;
7556 break;
7557 }
[email protected]ad84a3a2012-06-08 21:42:437558 default:
[email protected]ab09b612013-03-11 22:11:517559 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
[email protected]ad84a3a2012-06-08 21:42:437560 return false;
7561 }
7562
7563 if (size != bytes_required) {
[email protected]ab09b612013-03-11 22:11:517564 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437565 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
7566 return false;
7567 }
7568
7569 return true;
7570}
7571
7572bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7573 const char* function_name,
7574 GLint level, GLsizei width, GLsizei height, GLenum format) {
7575 switch (format) {
7576 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7577 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7578 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7579 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7580 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
[email protected]ab09b612013-03-11 22:11:517581 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437582 GL_INVALID_OPERATION, function_name,
7583 "width or height invalid for level");
7584 return false;
7585 }
7586 return true;
7587 }
[email protected]2d3765b2012-10-03 00:31:077588 case GL_ETC1_RGB8_OES:
7589 if (width <= 0 || height <= 0) {
[email protected]ab09b612013-03-11 22:11:517590 LOCAL_SET_GL_ERROR(
[email protected]2d3765b2012-10-03 00:31:077591 GL_INVALID_OPERATION, function_name,
7592 "width or height invalid for level");
7593 return false;
7594 }
7595 return true;
[email protected]ad84a3a2012-06-08 21:42:437596 default:
7597 return false;
7598 }
7599}
7600
7601bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
7602 const char* function_name,
7603 GLenum target, GLint level, GLint xoffset, GLint yoffset,
7604 GLsizei width, GLsizei height, GLenum format,
[email protected]ed9f9cd2013-02-27 21:12:357605 Texture* texture) {
[email protected]ad84a3a2012-06-08 21:42:437606 if (xoffset < 0 || yoffset < 0) {
[email protected]ab09b612013-03-11 22:11:517607 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437608 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
7609 return false;
7610 }
7611
7612 switch (format) {
7613 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7614 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7615 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7616 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7617 const int kBlockWidth = 4;
7618 const int kBlockHeight = 4;
7619 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
[email protected]ab09b612013-03-11 22:11:517620 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437621 GL_INVALID_OPERATION, function_name,
7622 "xoffset or yoffset not multiple of 4");
7623 return false;
7624 }
7625 GLsizei tex_width = 0;
7626 GLsizei tex_height = 0;
7627 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
7628 width - xoffset > tex_width ||
7629 height - yoffset > tex_height) {
[email protected]ab09b612013-03-11 22:11:517630 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437631 GL_INVALID_OPERATION, function_name, "dimensions out of range");
7632 return false;
7633 }
7634 return ValidateCompressedTexDimensions(
7635 function_name, level, width, height, format);
7636 }
[email protected]2d3765b2012-10-03 00:31:077637 case GL_ETC1_RGB8_OES: {
[email protected]ab09b612013-03-11 22:11:517638 LOCAL_SET_GL_ERROR(
[email protected]2d3765b2012-10-03 00:31:077639 GL_INVALID_OPERATION, function_name,
7640 "TexsubImage2d not supported for ECT1_RGB8_OES textures");
7641 return false;
7642 }
[email protected]ad84a3a2012-06-08 21:42:437643 default:
7644 return false;
7645 }
7646}
7647
[email protected]a93bb842010-02-16 23:03:477648error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
7649 GLenum target,
7650 GLint level,
7651 GLenum internal_format,
7652 GLsizei width,
7653 GLsizei height,
7654 GLint border,
7655 GLsizei image_size,
7656 const void* data) {
[email protected]a93bb842010-02-16 23:03:477657 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:057658 if (!validators_->texture_target.IsValid(target)) {
[email protected]ab09b612013-03-11 22:11:517659 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7660 "glCompressedTexImage2D", target, "target");
[email protected]8eee29c2010-04-29 03:38:297661 return error::kNoError;
7662 }
[email protected]9438b012010-06-15 22:55:057663 if (!validators_->compressed_texture_format.IsValid(
7664 internal_format)) {
[email protected]ab09b612013-03-11 22:11:517665 LOCAL_SET_GL_ERROR_INVALID_ENUM(
[email protected]f80e6e12012-08-31 00:43:537666 "glCompressedTexImage2D", internal_format, "internal_format");
[email protected]a93bb842010-02-16 23:03:477667 return error::kNoError;
7668 }
[email protected]80eb6b52012-01-19 00:14:417669 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:477670 border != 0) {
[email protected]ab09b612013-03-11 22:11:517671 LOCAL_SET_GL_ERROR(
7672 GL_INVALID_VALUE,
7673 "glCompressedTexImage2D", "dimensions out of range");
[email protected]a93bb842010-02-16 23:03:477674 return error::kNoError;
7675 }
[email protected]c986af502013-08-14 01:04:447676 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7677 &state_, target);
[email protected]370eaf12013-05-18 09:19:497678 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:517679 LOCAL_SET_GL_ERROR(
7680 GL_INVALID_VALUE,
7681 "glCompressedTexImage2D", "unknown texture target");
[email protected]a93bb842010-02-16 23:03:477682 return error::kNoError;
7683 }
[email protected]370eaf12013-05-18 09:19:497684 Texture* texture = texture_ref->texture();
[email protected]02965c22013-03-09 02:40:077685 if (texture->IsImmutable()) {
[email protected]ab09b612013-03-11 22:11:517686 LOCAL_SET_GL_ERROR(
7687 GL_INVALID_OPERATION,
7688 "glCompressedTexImage2D", "texture is immutable");
[email protected]ad84a3a2012-06-08 21:42:437689 return error::kNoError;
7690 }
7691
7692 if (!ValidateCompressedTexDimensions(
7693 "glCompressedTexImage2D", level, width, height, internal_format) ||
7694 !ValidateCompressedTexFuncData(
7695 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
[email protected]97dc7cbe2011-12-06 17:26:177696 return error::kNoError;
7697 }
[email protected]968351b2011-12-20 08:26:517698
[email protected]7989c9e2013-01-23 06:39:267699 if (!EnsureGPUMemoryAvailable(image_size)) {
[email protected]ab09b612013-03-11 22:11:517700 LOCAL_SET_GL_ERROR(
7701 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
[email protected]7989c9e2013-01-23 06:39:267702 return error::kNoError;
7703 }
7704
[email protected]02965c22013-03-09 02:40:077705 if (texture->IsAttachedToFramebuffer()) {
[email protected]c986af502013-08-14 01:04:447706 framebuffer_state_.clear_state_dirty = true;
[email protected]968351b2011-12-20 08:26:517707 }
7708
[email protected]40d90a22013-04-09 03:39:557709 scoped_ptr<int8[]> zero;
[email protected]a93bb842010-02-16 23:03:477710 if (!data) {
7711 zero.reset(new int8[image_size]);
7712 memset(zero.get(), 0, image_size);
7713 data = zero.get();
7714 }
[email protected]ab09b612013-03-11 22:11:517715 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
[email protected]a93bb842010-02-16 23:03:477716 glCompressedTexImage2D(
7717 target, level, internal_format, width, height, border, image_size, data);
[email protected]ab09b612013-03-11 22:11:517718 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
[email protected]cadde4a2010-07-31 17:10:437719 if (error == GL_NO_ERROR) {
7720 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:497721 texture_ref, target, level, internal_format,
7722 width, height, 1, border, 0, 0, true);
[email protected]cadde4a2010-07-31 17:10:437723 }
[email protected]a93bb842010-02-16 23:03:477724 return error::kNoError;
7725}
7726
[email protected]f7a64ee2010-02-01 22:24:147727error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]ed9f9cd2013-02-27 21:12:357728 uint32 immediate_data_size, const cmds::CompressedTexImage2D& c) {
[email protected]b9849abf2009-11-25 19:13:197729 GLenum target = static_cast<GLenum>(c.target);
7730 GLint level = static_cast<GLint>(c.level);
7731 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7732 GLsizei width = static_cast<GLsizei>(c.width);
7733 GLsizei height = static_cast<GLsizei>(c.height);
7734 GLint border = static_cast<GLint>(c.border);
7735 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
7736 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7737 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7738 const void* data = NULL;
7739 if (data_shm_id != 0 || data_shm_offset != 0) {
7740 data = GetSharedMemoryAs<const void*>(
7741 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:467742 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:147743 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197744 }
7745 }
[email protected]a93bb842010-02-16 23:03:477746 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:197747 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:197748}
7749
[email protected]b6140d02010-05-17 14:47:167750error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
[email protected]ed9f9cd2013-02-27 21:12:357751 uint32 immediate_data_size, const cmds::CompressedTexImage2DBucket& c) {
[email protected]b6140d02010-05-17 14:47:167752 GLenum target = static_cast<GLenum>(c.target);
7753 GLint level = static_cast<GLint>(c.level);
7754 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7755 GLsizei width = static_cast<GLsizei>(c.width);
7756 GLsizei height = static_cast<GLsizei>(c.height);
7757 GLint border = static_cast<GLint>(c.border);
7758 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287759 if (!bucket) {
7760 return error::kInvalidArguments;
7761 }
7762 uint32 data_size = bucket->size();
7763 GLsizei imageSize = data_size;
7764 const void* data = bucket->GetData(0, data_size);
7765 if (!data) {
7766 return error::kInvalidArguments;
7767 }
[email protected]b6140d02010-05-17 14:47:167768 return DoCompressedTexImage2D(
7769 target, level, internal_format, width, height, border,
[email protected]12f93d82011-10-17 21:16:287770 imageSize, data);
[email protected]b6140d02010-05-17 14:47:167771}
7772
7773error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
7774 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:357775 const cmds::CompressedTexSubImage2DBucket& c) {
[email protected]b6140d02010-05-17 14:47:167776 GLenum target = static_cast<GLenum>(c.target);
7777 GLint level = static_cast<GLint>(c.level);
7778 GLint xoffset = static_cast<GLint>(c.xoffset);
7779 GLint yoffset = static_cast<GLint>(c.yoffset);
7780 GLsizei width = static_cast<GLsizei>(c.width);
7781 GLsizei height = static_cast<GLsizei>(c.height);
7782 GLenum format = static_cast<GLenum>(c.format);
7783 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287784 if (!bucket) {
7785 return error::kInvalidArguments;
7786 }
[email protected]b6140d02010-05-17 14:47:167787 uint32 data_size = bucket->size();
7788 GLsizei imageSize = data_size;
7789 const void* data = bucket->GetData(0, data_size);
[email protected]12f93d82011-10-17 21:16:287790 if (!data) {
7791 return error::kInvalidArguments;
7792 }
[email protected]9438b012010-06-15 22:55:057793 if (!validators_->texture_target.IsValid(target)) {
[email protected]ab09b612013-03-11 22:11:517794 LOCAL_SET_GL_ERROR(
[email protected]f80e6e12012-08-31 00:43:537795 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
[email protected]b6140d02010-05-17 14:47:167796 return error::kNoError;
7797 }
[email protected]9438b012010-06-15 22:55:057798 if (!validators_->compressed_texture_format.IsValid(format)) {
[email protected]ab09b612013-03-11 22:11:517799 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7800 "glCompressedTexSubImage2D", format, "format");
[email protected]9438b012010-06-15 22:55:057801 return error::kNoError;
7802 }
[email protected]b6140d02010-05-17 14:47:167803 if (width < 0) {
[email protected]ab09b612013-03-11 22:11:517804 LOCAL_SET_GL_ERROR(
7805 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
[email protected]b6140d02010-05-17 14:47:167806 return error::kNoError;
7807 }
7808 if (height < 0) {
[email protected]ab09b612013-03-11 22:11:517809 LOCAL_SET_GL_ERROR(
7810 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
[email protected]b6140d02010-05-17 14:47:167811 return error::kNoError;
7812 }
7813 if (imageSize < 0) {
[email protected]ab09b612013-03-11 22:11:517814 LOCAL_SET_GL_ERROR(
7815 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
[email protected]b6140d02010-05-17 14:47:167816 return error::kNoError;
7817 }
[email protected]cadde4a2010-07-31 17:10:437818 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:167819 target, level, xoffset, yoffset, width, height, format, imageSize, data);
7820 return error::kNoError;
7821}
7822
[email protected]f7a64ee2010-02-01 22:24:147823error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]ed9f9cd2013-02-27 21:12:357824 uint32 immediate_data_size, const cmds::TexImage2D& c) {
[email protected]43ed3a72012-05-30 22:55:387825 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]c986af502013-08-14 01:04:447826 // Set as failed for now, but if it successed, this will be set to not failed.
7827 texture_state_.tex_image_2d_failed = true;
[email protected]b9849abf2009-11-25 19:13:197828 GLenum target = static_cast<GLenum>(c.target);
7829 GLint level = static_cast<GLint>(c.level);
[email protected]c986af502013-08-14 01:04:447830 // TODO(kloveless): Change TexImage2D command to use unsigned integer
7831 // for internalformat.
7832 GLenum internal_format = static_cast<GLenum>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:197833 GLsizei width = static_cast<GLsizei>(c.width);
7834 GLsizei height = static_cast<GLsizei>(c.height);
7835 GLint border = static_cast<GLint>(c.border);
7836 GLenum format = static_cast<GLenum>(c.format);
7837 GLenum type = static_cast<GLenum>(c.type);
7838 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
7839 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:187840 uint32 pixels_size;
[email protected]3458a64a2012-04-10 17:39:347841 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247842 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
[email protected]3458a64a2012-04-10 17:39:347843 NULL)) {
[email protected]a76b0052010-03-05 00:33:187844 return error::kOutOfBounds;
7845 }
[email protected]b9849abf2009-11-25 19:13:197846 const void* pixels = NULL;
7847 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
7848 pixels = GetSharedMemoryAs<const void*>(
7849 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:467850 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:147851 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197852 }
7853 }
[email protected]f598f422012-12-07 08:30:037854
[email protected]c986af502013-08-14 01:04:447855 TextureManager::DoTextImage2DArguments args = {
7856 target, level, internal_format, width, height, border, format, type,
7857 pixels, pixels_size};
7858 texture_manager()->ValidateAndDoTexImage2D(
7859 &texture_state_, &state_, &framebuffer_state_, args);
[email protected]f598f422012-12-07 08:30:037860 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197861}
7862
[email protected]cadde4a2010-07-31 17:10:437863void GLES2DecoderImpl::DoCompressedTexSubImage2D(
7864 GLenum target,
7865 GLint level,
7866 GLint xoffset,
7867 GLint yoffset,
7868 GLsizei width,
7869 GLsizei height,
7870 GLenum format,
7871 GLsizei image_size,
7872 const void * data) {
[email protected]c986af502013-08-14 01:04:447873 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7874 &state_, target);
[email protected]370eaf12013-05-18 09:19:497875 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:517876 LOCAL_SET_GL_ERROR(
7877 GL_INVALID_OPERATION,
7878 "glCompressedTexSubImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:437879 return;
7880 }
[email protected]370eaf12013-05-18 09:19:497881 Texture* texture = texture_ref->texture();
[email protected]cadde4a2010-07-31 17:10:437882 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:527883 GLenum internal_format = 0;
[email protected]02965c22013-03-09 02:40:077884 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
[email protected]ab09b612013-03-11 22:11:517885 LOCAL_SET_GL_ERROR(
[email protected]df6cf1ad2011-01-29 01:20:527886 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437887 "glCompressedTexSubImage2D", "level does not exist.");
[email protected]df6cf1ad2011-01-29 01:20:527888 return;
7889 }
7890 if (internal_format != format) {
[email protected]ab09b612013-03-11 22:11:517891 LOCAL_SET_GL_ERROR(
[email protected]df6cf1ad2011-01-29 01:20:527892 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437893 "glCompressedTexSubImage2D", "format does not match internal format.");
[email protected]df6cf1ad2011-01-29 01:20:527894 return;
7895 }
[email protected]02965c22013-03-09 02:40:077896 if (!texture->ValidForTexture(
[email protected]df6cf1ad2011-01-29 01:20:527897 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]ab09b612013-03-11 22:11:517898 LOCAL_SET_GL_ERROR(
7899 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:437900 return;
7901 }
[email protected]ad84a3a2012-06-08 21:42:437902
7903 if (!ValidateCompressedTexFuncData(
7904 "glCompressedTexSubImage2D", width, height, format, image_size) ||
7905 !ValidateCompressedTexSubDimensions(
7906 "glCompressedTexSubImage2D",
[email protected]02965c22013-03-09 02:40:077907 target, level, xoffset, yoffset, width, height, format, texture)) {
[email protected]ad84a3a2012-06-08 21:42:437908 return;
7909 }
7910
7911
[email protected]0d6bfdc2011-11-02 01:32:207912 // Note: There is no need to deal with texture cleared tracking here
7913 // because the validation above means you can only get here if the level
7914 // is already a matching compressed format and in that case
7915 // CompressedTexImage2D already cleared the texture.
[email protected]cadde4a2010-07-31 17:10:437916 glCompressedTexSubImage2D(
7917 target, level, xoffset, yoffset, width, height, format, image_size, data);
7918}
7919
[email protected]6e288612010-12-21 20:45:037920static void Clip(
7921 GLint start, GLint range, GLint sourceRange,
7922 GLint* out_start, GLint* out_range) {
7923 DCHECK(out_start);
7924 DCHECK(out_range);
7925 if (start < 0) {
7926 range += start;
7927 start = 0;
7928 }
7929 GLint end = start + range;
7930 if (end > sourceRange) {
7931 range -= end - sourceRange;
7932 }
7933 *out_start = start;
7934 *out_range = range;
7935}
7936
[email protected]cadde4a2010-07-31 17:10:437937void GLES2DecoderImpl::DoCopyTexImage2D(
[email protected]a5d3dad2012-05-26 04:34:447938 GLenum target,
7939 GLint level,
7940 GLenum internal_format,
7941 GLint x,
7942 GLint y,
7943 GLsizei width,
7944 GLsizei height,
7945 GLint border) {
[email protected]09e17272012-11-30 10:30:447946 DCHECK(!ShouldDeferReads());
[email protected]c986af502013-08-14 01:04:447947 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7948 &state_, target);
[email protected]370eaf12013-05-18 09:19:497949 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:517950 LOCAL_SET_GL_ERROR(
7951 GL_INVALID_OPERATION,
7952 "glCopyTexImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:437953 return;
7954 }
[email protected]370eaf12013-05-18 09:19:497955 Texture* texture = texture_ref->texture();
[email protected]02965c22013-03-09 02:40:077956 if (texture->IsImmutable()) {
[email protected]ab09b612013-03-11 22:11:517957 LOCAL_SET_GL_ERROR(
7958 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
[email protected]97dc7cbe2011-12-06 17:26:177959 }
[email protected]80eb6b52012-01-19 00:14:417960 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:187961 border != 0) {
[email protected]ab09b612013-03-11 22:11:517962 LOCAL_SET_GL_ERROR(
7963 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
[email protected]f5719fb2010-08-04 18:27:187964 return;
7965 }
[email protected]c986af502013-08-14 01:04:447966 if (!texture_manager()->ValidateTextureParameters(
7967 state_.GetErrorState(), "glCopyTexImage2D", target, internal_format,
7968 GL_UNSIGNED_BYTE, level)) {
[email protected]81375742012-06-08 00:04:007969 return;
7970 }
[email protected]f5719fb2010-08-04 18:27:187971
[email protected]9edc6b22010-12-23 02:00:267972 // Check we have compatible formats.
7973 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7974 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7975 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
7976
7977 if ((channels_needed & channels_exist) != channels_needed) {
[email protected]ab09b612013-03-11 22:11:517978 LOCAL_SET_GL_ERROR(
7979 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
[email protected]9edc6b22010-12-23 02:00:267980 return;
7981 }
7982
[email protected]81375742012-06-08 00:04:007983 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
[email protected]ab09b612013-03-11 22:11:517984 LOCAL_SET_GL_ERROR(
[email protected]81375742012-06-08 00:04:007985 GL_INVALID_OPERATION,
[email protected]7989c9e2013-01-23 06:39:267986 "glCopyTexImage2D", "can not be used with depth or stencil textures");
7987 return;
7988 }
7989
7990 uint32 estimated_size = 0;
7991 if (!GLES2Util::ComputeImageDataSizes(
7992 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
7993 &estimated_size, NULL, NULL)) {
[email protected]ab09b612013-03-11 22:11:517994 LOCAL_SET_GL_ERROR(
7995 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
[email protected]7989c9e2013-01-23 06:39:267996 return;
7997 }
7998
7999 if (!EnsureGPUMemoryAvailable(estimated_size)) {
[email protected]ab09b612013-03-11 22:11:518000 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
[email protected]81375742012-06-08 00:04:008001 return;
8002 }
8003
[email protected]a0b78dc2011-11-11 10:43:108004 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8005 return;
8006 }
8007
[email protected]ab09b612013-03-11 22:11:518008 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
[email protected]de26b3c2011-08-03 21:54:278009 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:038010 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:268011
[email protected]02965c22013-03-09 02:40:078012 if (texture->IsAttachedToFramebuffer()) {
[email protected]c986af502013-08-14 01:04:448013 framebuffer_state_.clear_state_dirty = true;
[email protected]297ca1c2011-06-20 23:08:468014 }
8015
[email protected]9edc6b22010-12-23 02:00:268016 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:038017 GLint copyX = 0;
8018 GLint copyY = 0;
8019 GLint copyWidth = 0;
8020 GLint copyHeight = 0;
8021 Clip(x, width, size.width(), &copyX, &copyWidth);
8022 Clip(y, height, size.height(), &copyY, &copyHeight);
8023
8024 if (copyX != x ||
8025 copyY != y ||
8026 copyWidth != width ||
8027 copyHeight != height) {
8028 // some part was clipped so clear the texture.
[email protected]0d6bfdc2011-11-02 01:32:208029 if (!ClearLevel(
[email protected]02965c22013-03-09 02:40:078030 texture->service_id(), texture->target(),
[email protected]4502e6492011-12-14 19:39:158031 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
[email protected]02965c22013-03-09 02:40:078032 texture->IsImmutable())) {
[email protected]ab09b612013-03-11 22:11:518033 LOCAL_SET_GL_ERROR(
8034 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
[email protected]6e288612010-12-21 20:45:038035 return;
8036 }
[email protected]6e288612010-12-21 20:45:038037 if (copyHeight > 0 && copyWidth > 0) {
8038 GLint dx = copyX - x;
8039 GLint dy = copyY - y;
8040 GLint destX = dx;
8041 GLint destY = dy;
8042 glCopyTexSubImage2D(target, level,
8043 destX, destY, copyX, copyY,
8044 copyWidth, copyHeight);
8045 }
8046 } else {
8047 glCopyTexImage2D(target, level, internal_format,
8048 copyX, copyY, copyWidth, copyHeight, border);
8049 }
[email protected]ab09b612013-03-11 22:11:518050 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
[email protected]cadde4a2010-07-31 17:10:438051 if (error == GL_NO_ERROR) {
8052 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:498053 texture_ref, target, level, internal_format, width, height, 1,
[email protected]0d6bfdc2011-11-02 01:32:208054 border, internal_format, GL_UNSIGNED_BYTE, true);
[email protected]cadde4a2010-07-31 17:10:438055 }
8056}
8057
8058void GLES2DecoderImpl::DoCopyTexSubImage2D(
[email protected]a5d3dad2012-05-26 04:34:448059 GLenum target,
8060 GLint level,
8061 GLint xoffset,
8062 GLint yoffset,
8063 GLint x,
8064 GLint y,
8065 GLsizei width,
8066 GLsizei height) {
[email protected]09e17272012-11-30 10:30:448067 DCHECK(!ShouldDeferReads());
[email protected]c986af502013-08-14 01:04:448068 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8069 &state_, target);
[email protected]370eaf12013-05-18 09:19:498070 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:518071 LOCAL_SET_GL_ERROR(
8072 GL_INVALID_OPERATION,
8073 "glCopyTexSubImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:438074 return;
8075 }
[email protected]370eaf12013-05-18 09:19:498076 Texture* texture = texture_ref->texture();
[email protected]cadde4a2010-07-31 17:10:438077 GLenum type = 0;
8078 GLenum format = 0;
[email protected]02965c22013-03-09 02:40:078079 if (!texture->GetLevelType(target, level, &type, &format) ||
8080 !texture->ValidForTexture(
[email protected]cadde4a2010-07-31 17:10:438081 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]ab09b612013-03-11 22:11:518082 LOCAL_SET_GL_ERROR(
8083 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:438084 return;
8085 }
[email protected]85a4ac22013-05-31 01:58:478086 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
[email protected]ab09b612013-03-11 22:11:518087 LOCAL_SET_GL_ERROR(
8088 GL_INVALID_OPERATION,
8089 "glCopyTexSubImage2D", "async upload pending for texture");
[email protected]32145a92012-12-17 09:01:598090 return;
8091 }
[email protected]9edc6b22010-12-23 02:00:268092
8093 // Check we have compatible formats.
8094 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8095 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8096 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
8097
[email protected]2d3765b2012-10-03 00:31:078098 if (!channels_needed ||
8099 (channels_needed & channels_exist) != channels_needed) {
[email protected]ab09b612013-03-11 22:11:518100 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:438101 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
[email protected]9edc6b22010-12-23 02:00:268102 return;
8103 }
8104
[email protected]81375742012-06-08 00:04:008105 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
[email protected]ab09b612013-03-11 22:11:518106 LOCAL_SET_GL_ERROR(
[email protected]81375742012-06-08 00:04:008107 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438108 "glCopySubImage2D", "can not be used with depth or stencil textures");
[email protected]81375742012-06-08 00:04:008109 return;
8110 }
8111
[email protected]a0b78dc2011-11-11 10:43:108112 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8113 return;
8114 }
8115
[email protected]de26b3c2011-08-03 21:54:278116 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:038117 gfx::Size size = GetBoundReadFrameBufferSize();
8118 GLint copyX = 0;
8119 GLint copyY = 0;
8120 GLint copyWidth = 0;
8121 GLint copyHeight = 0;
8122 Clip(x, width, size.width(), &copyX, &copyWidth);
8123 Clip(y, height, size.height(), &copyY, &copyHeight);
[email protected]0d6bfdc2011-11-02 01:32:208124
[email protected]370eaf12013-05-18 09:19:498125 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
[email protected]ab09b612013-03-11 22:11:518126 LOCAL_SET_GL_ERROR(
8127 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
[email protected]0d6bfdc2011-11-02 01:32:208128 return;
8129 }
8130
[email protected]6e288612010-12-21 20:45:038131 if (copyX != x ||
8132 copyY != y ||
8133 copyWidth != width ||
8134 copyHeight != height) {
[email protected]0d6bfdc2011-11-02 01:32:208135 // some part was clipped so clear the sub rect.
[email protected]6e288612010-12-21 20:45:038136 uint32 pixels_size = 0;
[email protected]3458a64a2012-04-10 17:39:348137 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:248138 width, height, format, type, state_.unpack_alignment, &pixels_size,
8139 NULL, NULL)) {
[email protected]ab09b612013-03-11 22:11:518140 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:438141 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
[email protected]6e288612010-12-21 20:45:038142 return;
8143 }
[email protected]40d90a22013-04-09 03:39:558144 scoped_ptr<char[]> zero(new char[pixels_size]);
[email protected]6e288612010-12-21 20:45:038145 memset(zero.get(), 0, pixels_size);
8146 glTexSubImage2D(
8147 target, level, xoffset, yoffset, width, height,
8148 format, type, zero.get());
8149 }
[email protected]0d6bfdc2011-11-02 01:32:208150
[email protected]6e288612010-12-21 20:45:038151 if (copyHeight > 0 && copyWidth > 0) {
8152 GLint dx = copyX - x;
8153 GLint dy = copyY - y;
8154 GLint destX = xoffset + dx;
8155 GLint destY = yoffset + dy;
8156 glCopyTexSubImage2D(target, level,
8157 destX, destY, copyX, copyY,
8158 copyWidth, copyHeight);
8159 }
[email protected]cadde4a2010-07-31 17:10:438160}
8161
[email protected]f598f422012-12-07 08:30:038162bool GLES2DecoderImpl::ValidateTexSubImage2D(
8163 error::Error* error,
8164 const char* function_name,
8165 GLenum target,
8166 GLint level,
8167 GLint xoffset,
8168 GLint yoffset,
8169 GLsizei width,
8170 GLsizei height,
8171 GLenum format,
8172 GLenum type,
8173 const void * data) {
8174 (*error) = error::kNoError;
8175 if (!validators_->texture_target.IsValid(target)) {
[email protected]ab09b612013-03-11 22:11:518176 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
[email protected]f598f422012-12-07 08:30:038177 return false;
8178 }
8179 if (width < 0) {
[email protected]ab09b612013-03-11 22:11:518180 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
[email protected]f598f422012-12-07 08:30:038181 return false;
8182 }
8183 if (height < 0) {
[email protected]ab09b612013-03-11 22:11:518184 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
[email protected]f598f422012-12-07 08:30:038185 return false;
8186 }
8187 if (!validators_->texture_format.IsValid(format)) {
[email protected]ab09b612013-03-11 22:11:518188 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
[email protected]f598f422012-12-07 08:30:038189 return false;
8190 }
8191 if (!validators_->pixel_type.IsValid(type)) {
[email protected]ab09b612013-03-11 22:11:518192 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
[email protected]f598f422012-12-07 08:30:038193 return false;
8194 }
[email protected]c986af502013-08-14 01:04:448195 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8196 &state_, target);
[email protected]370eaf12013-05-18 09:19:498197 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:518198 LOCAL_SET_GL_ERROR(
8199 GL_INVALID_OPERATION,
8200 function_name, "unknown texture for target");
[email protected]f598f422012-12-07 08:30:038201 return false;
[email protected]cadde4a2010-07-31 17:10:438202 }
[email protected]370eaf12013-05-18 09:19:498203 Texture* texture = texture_ref->texture();
[email protected]df6cf1ad2011-01-29 01:20:528204 GLenum current_type = 0;
8205 GLenum internal_format = 0;
[email protected]02965c22013-03-09 02:40:078206 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
[email protected]ab09b612013-03-11 22:11:518207 LOCAL_SET_GL_ERROR(
[email protected]f598f422012-12-07 08:30:038208 GL_INVALID_OPERATION, function_name, "level does not exist.");
8209 return false;
[email protected]df6cf1ad2011-01-29 01:20:528210 }
8211 if (format != internal_format) {
[email protected]ab09b612013-03-11 22:11:518212 LOCAL_SET_GL_ERROR(
8213 GL_INVALID_OPERATION,
8214 function_name, "format does not match internal format.");
[email protected]f598f422012-12-07 08:30:038215 return false;
[email protected]df6cf1ad2011-01-29 01:20:528216 }
8217 if (type != current_type) {
[email protected]ab09b612013-03-11 22:11:518218 LOCAL_SET_GL_ERROR(
8219 GL_INVALID_OPERATION,
8220 function_name, "type does not match type of texture.");
[email protected]f598f422012-12-07 08:30:038221 return false;
[email protected]df6cf1ad2011-01-29 01:20:528222 }
[email protected]85a4ac22013-05-31 01:58:478223 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
[email protected]ab09b612013-03-11 22:11:518224 LOCAL_SET_GL_ERROR(
8225 GL_INVALID_OPERATION,
8226 function_name, "async upload pending for texture");
[email protected]32145a92012-12-17 09:01:598227 return false;
8228 }
[email protected]02965c22013-03-09 02:40:078229 if (!texture->ValidForTexture(
[email protected]cadde4a2010-07-31 17:10:438230 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]ab09b612013-03-11 22:11:518231 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
[email protected]f598f422012-12-07 08:30:038232 return false;
[email protected]cadde4a2010-07-31 17:10:438233 }
[email protected]81375742012-06-08 00:04:008234 if ((GLES2Util::GetChannelsForFormat(format) &
8235 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
[email protected]ab09b612013-03-11 22:11:518236 LOCAL_SET_GL_ERROR(
[email protected]81375742012-06-08 00:04:008237 GL_INVALID_OPERATION,
[email protected]f598f422012-12-07 08:30:038238 function_name, "can not supply data for depth or stencil textures");
8239 return false;
[email protected]81375742012-06-08 00:04:008240 }
[email protected]f598f422012-12-07 08:30:038241 if (data == NULL) {
8242 (*error) = error::kOutOfBounds;
8243 return false;
8244 }
8245 return true;
8246}
[email protected]81375742012-06-08 00:04:008247
[email protected]f598f422012-12-07 08:30:038248error::Error GLES2DecoderImpl::DoTexSubImage2D(
8249 GLenum target,
8250 GLint level,
8251 GLint xoffset,
8252 GLint yoffset,
8253 GLsizei width,
8254 GLsizei height,
8255 GLenum format,
8256 GLenum type,
8257 const void * data) {
8258 error::Error error = error::kNoError;
8259 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
8260 xoffset, yoffset, width, height, format, type, data)) {
8261 return error;
8262 }
[email protected]c986af502013-08-14 01:04:448263 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8264 &state_, target);
[email protected]370eaf12013-05-18 09:19:498265 Texture* texture = texture_ref->texture();
[email protected]4502e6492011-12-14 19:39:158266 GLsizei tex_width = 0;
8267 GLsizei tex_height = 0;
[email protected]02965c22013-03-09 02:40:078268 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
[email protected]4502e6492011-12-14 19:39:158269 DCHECK(ok);
8270 if (xoffset != 0 || yoffset != 0 ||
8271 width != tex_width || height != tex_height) {
[email protected]370eaf12013-05-18 09:19:498272 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
8273 target, level)) {
[email protected]ab09b612013-03-11 22:11:518274 LOCAL_SET_GL_ERROR(
8275 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
[email protected]f598f422012-12-07 08:30:038276 return error::kNoError;
[email protected]473c01ccb2011-06-07 01:33:308277 }
[email protected]c986af502013-08-14 01:04:448278 ScopedTextureUploadTimer timer(&texture_state_);
[email protected]4502e6492011-12-14 19:39:158279 glTexSubImage2D(
8280 target, level, xoffset, yoffset, width, height, format, type, data);
[email protected]f598f422012-12-07 08:30:038281 return error::kNoError;
[email protected]0d6bfdc2011-11-02 01:32:208282 }
[email protected]4502e6492011-12-14 19:39:158283
[email protected]c986af502013-08-14 01:04:448284 if (texture_state_.teximage2d_faster_than_texsubimage2d &&
8285 !texture->IsImmutable()) {
8286 ScopedTextureUploadTimer timer(&texture_state_);
[email protected]4502e6492011-12-14 19:39:158287 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
8288 // same as internal_foramt. If that changes we'll need to look them up.
[email protected]8f1d2aa2013-05-10 23:45:388289 glTexImage2D(
[email protected]4502e6492011-12-14 19:39:158290 target, level, format, width, height, 0, format, type, data);
8291 } else {
[email protected]c986af502013-08-14 01:04:448292 ScopedTextureUploadTimer timer(&texture_state_);
[email protected]4502e6492011-12-14 19:39:158293 glTexSubImage2D(
8294 target, level, xoffset, yoffset, width, height, format, type, data);
8295 }
[email protected]370eaf12013-05-18 09:19:498296 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
[email protected]f598f422012-12-07 08:30:038297 return error::kNoError;
[email protected]cadde4a2010-07-31 17:10:438298}
8299
[email protected]b493ee622011-04-13 23:52:008300error::Error GLES2DecoderImpl::HandleTexSubImage2D(
[email protected]ed9f9cd2013-02-27 21:12:358301 uint32 immediate_data_size, const cmds::TexSubImage2D& c) {
[email protected]43ed3a72012-05-30 22:55:388302 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:008303 GLboolean internal = static_cast<GLboolean>(c.internal);
[email protected]c986af502013-08-14 01:04:448304 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
[email protected]b493ee622011-04-13 23:52:008305 return error::kNoError;
8306
8307 GLenum target = static_cast<GLenum>(c.target);
8308 GLint level = static_cast<GLint>(c.level);
8309 GLint xoffset = static_cast<GLint>(c.xoffset);
8310 GLint yoffset = static_cast<GLint>(c.yoffset);
8311 GLsizei width = static_cast<GLsizei>(c.width);
8312 GLsizei height = static_cast<GLsizei>(c.height);
8313 GLenum format = static_cast<GLenum>(c.format);
8314 GLenum type = static_cast<GLenum>(c.type);
8315 uint32 data_size;
[email protected]3458a64a2012-04-10 17:39:348316 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:248317 width, height, format, type, state_.unpack_alignment, &data_size,
8318 NULL, NULL)) {
[email protected]b493ee622011-04-13 23:52:008319 return error::kOutOfBounds;
8320 }
8321 const void* pixels = GetSharedMemoryAs<const void*>(
8322 c.pixels_shm_id, c.pixels_shm_offset, data_size);
[email protected]f598f422012-12-07 08:30:038323 return DoTexSubImage2D(
[email protected]b493ee622011-04-13 23:52:008324 target, level, xoffset, yoffset, width, height, format, type, pixels);
[email protected]b493ee622011-04-13 23:52:008325}
8326
[email protected]f7a64ee2010-02-01 22:24:148327error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]ed9f9cd2013-02-27 21:12:358328 uint32 immediate_data_size, const cmds::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:368329 GLuint index = static_cast<GLuint>(c.index);
8330 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]ed9f9cd2013-02-27 21:12:358331 typedef cmds::GetVertexAttribPointerv::Result Result;
[email protected]0bfd9882010-02-05 23:02:258332 Result* result = GetSharedMemoryAs<Result*>(
8333 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:368334 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:148335 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:368336 }
[email protected]07d0cc82010-02-17 04:51:408337 // Check that the client initialized the result.
8338 if (result->size != 0) {
8339 return error::kInvalidArguments;
8340 }
[email protected]9438b012010-06-15 22:55:058341 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]ab09b612013-03-11 22:11:518342 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8343 "glGetVertexAttribPointerv", pname, "pname");
[email protected]f7a64ee2010-02-01 22:24:148344 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:368345 }
[email protected]3916c97e2010-02-25 03:20:508346 if (index >= group_->max_vertex_attribs()) {
[email protected]ab09b612013-03-11 22:11:518347 LOCAL_SET_GL_ERROR(
8348 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
[email protected]f7a64ee2010-02-01 22:24:148349 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:368350 }
[email protected]0bfd9882010-02-05 23:02:258351 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:088352 *result->GetData() =
[email protected]ed9f9cd2013-02-27 21:12:358353 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:148354 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328355}
8356
[email protected]f7b85372010-02-03 01:11:378357bool GLES2DecoderImpl::GetUniformSetup(
[email protected]df37b9932013-03-08 05:21:428358 GLuint program_id, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:378359 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:128360 error::Error* error, GLint* real_location,
8361 GLuint* service_id, void** result_pointer, GLenum* result_type) {
[email protected]939e7362010-05-13 20:49:108362 DCHECK(error);
8363 DCHECK(service_id);
8364 DCHECK(result_pointer);
8365 DCHECK(result_type);
[email protected]1b0a6752012-02-22 03:44:128366 DCHECK(real_location);
[email protected]f7b85372010-02-03 01:11:378367 *error = error::kNoError;
8368 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:258369 SizedResult<GLint>* result;
8370 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8371 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
8372 if (!result) {
[email protected]f7b85372010-02-03 01:11:378373 *error = error::kOutOfBounds;
8374 return false;
8375 }
[email protected]0bfd9882010-02-05 23:02:258376 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:378377 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:258378 result->SetNumResults(0);
[email protected]df37b9932013-03-08 05:21:428379 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
8380 if (!program) {
[email protected]ae51d192010-04-27 00:48:038381 return false;
8382 }
[email protected]df37b9932013-03-08 05:21:428383 if (!program->IsValid()) {
[email protected]f7b85372010-02-03 01:11:378384 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]ab09b612013-03-11 22:11:518385 LOCAL_SET_GL_ERROR(
8386 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
[email protected]f7b85372010-02-03 01:11:378387 return false;
8388 }
[email protected]df37b9932013-03-08 05:21:428389 *service_id = program->service_id();
[email protected]43c2f1f2011-03-25 18:35:368390 GLint array_index = -1;
[email protected]ed9f9cd2013-02-27 21:12:358391 const Program::UniformInfo* uniform_info =
[email protected]df37b9932013-03-08 05:21:428392 program->GetUniformInfoByFakeLocation(
[email protected]1b0a6752012-02-22 03:44:128393 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:368394 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:378395 // No such location.
[email protected]ab09b612013-03-11 22:11:518396 LOCAL_SET_GL_ERROR(
8397 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
[email protected]f7b85372010-02-03 01:11:378398 return false;
8399 }
[email protected]43c2f1f2011-03-25 18:35:368400 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:508401 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:378402 if (size == 0) {
[email protected]ab09b612013-03-11 22:11:518403 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
[email protected]f7b85372010-02-03 01:11:378404 return false;
8405 }
[email protected]0bfd9882010-02-05 23:02:258406 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8407 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
8408 if (!result) {
[email protected]f7b85372010-02-03 01:11:378409 *error = error::kOutOfBounds;
8410 return false;
8411 }
[email protected]0bfd9882010-02-05 23:02:258412 result->size = size;
[email protected]939e7362010-05-13 20:49:108413 *result_type = type;
[email protected]f7b85372010-02-03 01:11:378414 return true;
8415}
8416
[email protected]f7a64ee2010-02-01 22:24:148417error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]ed9f9cd2013-02-27 21:12:358418 uint32 immediate_data_size, const cmds::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:378419 GLuint program = c.program;
[email protected]2be6abf32012-06-26 00:28:338420 GLint fake_location = c.location;
[email protected]f7b85372010-02-03 01:11:378421 GLuint service_id;
[email protected]939e7362010-05-13 20:49:108422 GLenum result_type;
[email protected]1b0a6752012-02-22 03:44:128423 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:378424 Error error;
[email protected]0bfd9882010-02-05 23:02:258425 void* result;
[email protected]f7b85372010-02-03 01:11:378426 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:128427 program, fake_location, c.params_shm_id, c.params_shm_offset,
8428 &error, &real_location, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:258429 glGetUniformiv(
[email protected]1b0a6752012-02-22 03:44:128430 service_id, real_location,
[email protected]ed9f9cd2013-02-27 21:12:358431 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:378432 }
8433 return error;
[email protected]96449d2c2009-11-25 00:01:328434}
8435
[email protected]f7a64ee2010-02-01 22:24:148436error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]ed9f9cd2013-02-27 21:12:358437 uint32 immediate_data_size, const cmds::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:378438 GLuint program = c.program;
[email protected]2be6abf32012-06-26 00:28:338439 GLint fake_location = c.location;
[email protected]f7b85372010-02-03 01:11:378440 GLuint service_id;
[email protected]1b0a6752012-02-22 03:44:128441 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:378442 Error error;
[email protected]ed9f9cd2013-02-27 21:12:358443 typedef cmds::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:108444 Result* result;
8445 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:378446 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:128447 program, fake_location, c.params_shm_id, c.params_shm_offset,
8448 &error, &real_location, &service_id,
8449 reinterpret_cast<void**>(&result), &result_type)) {
[email protected]939e7362010-05-13 20:49:108450 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
8451 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
8452 GLsizei num_values = result->GetNumResults();
[email protected]40d90a22013-04-09 03:39:558453 scoped_ptr<GLint[]> temp(new GLint[num_values]);
[email protected]1b0a6752012-02-22 03:44:128454 glGetUniformiv(service_id, real_location, temp.get());
[email protected]939e7362010-05-13 20:49:108455 GLfloat* dst = result->GetData();
8456 for (GLsizei ii = 0; ii < num_values; ++ii) {
8457 dst[ii] = (temp[ii] != 0);
8458 }
8459 } else {
[email protected]1b0a6752012-02-22 03:44:128460 glGetUniformfv(service_id, real_location, result->GetData());
[email protected]939e7362010-05-13 20:49:108461 }
[email protected]f7b85372010-02-03 01:11:378462 }
8463 return error;
[email protected]96449d2c2009-11-25 00:01:328464}
8465
[email protected]f7a64ee2010-02-01 22:24:148466error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]ed9f9cd2013-02-27 21:12:358467 uint32 immediate_data_size, const cmds::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:258468 GLenum shader_type = static_cast<GLenum>(c.shadertype);
8469 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
[email protected]ed9f9cd2013-02-27 21:12:358470 typedef cmds::GetShaderPrecisionFormat::Result Result;
[email protected]0bfd9882010-02-05 23:02:258471 Result* result = GetSharedMemoryAs<Result*>(
8472 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8473 if (!result) {
8474 return error::kOutOfBounds;
8475 }
[email protected]07d0cc82010-02-17 04:51:408476 // Check that the client initialized the result.
8477 if (result->success != 0) {
8478 return error::kInvalidArguments;
8479 }
[email protected]9438b012010-06-15 22:55:058480 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]ab09b612013-03-11 22:11:518481 LOCAL_SET_GL_ERROR_INVALID_ENUM(
[email protected]f80e6e12012-08-31 00:43:538482 "glGetShaderPrecisionFormat", shader_type, "shader_type");
[email protected]8eee29c2010-04-29 03:38:298483 return error::kNoError;
8484 }
[email protected]9438b012010-06-15 22:55:058485 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]ab09b612013-03-11 22:11:518486 LOCAL_SET_GL_ERROR_INVALID_ENUM(
[email protected]f80e6e12012-08-31 00:43:538487 "glGetShaderPrecisionFormat", precision_type, "precision_type");
[email protected]8eee29c2010-04-29 03:38:298488 return error::kNoError;
8489 }
8490
8491 result->success = 1; // true
[email protected]d8bc3ec2013-03-07 06:28:408492
[email protected]46c86752013-05-21 05:08:398493 GLint range[2] = { 0, 0 };
[email protected]d8bc3ec2013-03-07 06:28:408494 GLint precision = 0;
[email protected]8dc1bf92013-03-12 03:58:218495 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
[email protected]d8bc3ec2013-03-07 06:28:408496
8497 result->min_range = range[0];
8498 result->max_range = range[1];
8499 result->precision = precision;
8500
[email protected]f7a64ee2010-02-01 22:24:148501 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328502}
8503
[email protected]f7a64ee2010-02-01 22:24:148504error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]ed9f9cd2013-02-27 21:12:358505 uint32 immediate_data_size, const cmds::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:258506 uint32 result_size = c.result_size;
[email protected]df37b9932013-03-08 05:21:428507 GLuint program_id = static_cast<GLuint>(c.program);
8508 Program* program = GetProgramInfoNotShader(
8509 program_id, "glGetAttachedShaders");
8510 if (!program) {
[email protected]0bfd9882010-02-05 23:02:258511 return error::kNoError;
8512 }
[email protected]ed9f9cd2013-02-27 21:12:358513 typedef cmds::GetAttachedShaders::Result Result;
[email protected]0bfd9882010-02-05 23:02:258514 uint32 max_count = Result::ComputeMaxResults(result_size);
8515 Result* result = GetSharedMemoryAs<Result*>(
8516 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
8517 if (!result) {
8518 return error::kOutOfBounds;
8519 }
[email protected]07d0cc82010-02-17 04:51:408520 // Check that the client initialized the result.
8521 if (result->size != 0) {
8522 return error::kInvalidArguments;
8523 }
[email protected]0bfd9882010-02-05 23:02:258524 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:038525 glGetAttachedShaders(
[email protected]df37b9932013-03-08 05:21:428526 program->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:258527 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:038528 if (!shader_manager()->GetClientId(result->GetData()[ii],
8529 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:258530 NOTREACHED();
8531 return error::kGenericError;
8532 }
8533 }
8534 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:148535 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328536}
8537
[email protected]f7a64ee2010-02-01 22:24:148538error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]ed9f9cd2013-02-27 21:12:358539 uint32 immediate_data_size, const cmds::GetActiveUniform& c) {
[email protected]df37b9932013-03-08 05:21:428540 GLuint program_id = c.program;
[email protected]0bfd9882010-02-05 23:02:258541 GLuint index = c.index;
8542 uint32 name_bucket_id = c.name_bucket_id;
[email protected]ed9f9cd2013-02-27 21:12:358543 typedef cmds::GetActiveUniform::Result Result;
[email protected]0bfd9882010-02-05 23:02:258544 Result* result = GetSharedMemoryAs<Result*>(
8545 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8546 if (!result) {
8547 return error::kOutOfBounds;
8548 }
[email protected]07d0cc82010-02-17 04:51:408549 // Check that the client initialized the result.
8550 if (result->success != 0) {
8551 return error::kInvalidArguments;
8552 }
[email protected]df37b9932013-03-08 05:21:428553 Program* program = GetProgramInfoNotShader(
8554 program_id, "glGetActiveUniform");
8555 if (!program) {
[email protected]0bfd9882010-02-05 23:02:258556 return error::kNoError;
8557 }
[email protected]ed9f9cd2013-02-27 21:12:358558 const Program::UniformInfo* uniform_info =
[email protected]df37b9932013-03-08 05:21:428559 program->GetUniformInfo(index);
[email protected]0bfd9882010-02-05 23:02:258560 if (!uniform_info) {
[email protected]ab09b612013-03-11 22:11:518561 LOCAL_SET_GL_ERROR(
8562 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
[email protected]0bfd9882010-02-05 23:02:258563 return error::kNoError;
8564 }
8565 result->success = 1; // true.
8566 result->size = uniform_info->size;
8567 result->type = uniform_info->type;
8568 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:298569 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:148570 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328571}
8572
[email protected]f7a64ee2010-02-01 22:24:148573error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]ed9f9cd2013-02-27 21:12:358574 uint32 immediate_data_size, const cmds::GetActiveAttrib& c) {
[email protected]df37b9932013-03-08 05:21:428575 GLuint program_id = c.program;
[email protected]0bfd9882010-02-05 23:02:258576 GLuint index = c.index;
8577 uint32 name_bucket_id = c.name_bucket_id;
[email protected]ed9f9cd2013-02-27 21:12:358578 typedef cmds::GetActiveAttrib::Result Result;
[email protected]0bfd9882010-02-05 23:02:258579 Result* result = GetSharedMemoryAs<Result*>(
8580 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8581 if (!result) {
8582 return error::kOutOfBounds;
8583 }
[email protected]07d0cc82010-02-17 04:51:408584 // Check that the client initialized the result.
8585 if (result->success != 0) {
8586 return error::kInvalidArguments;
8587 }
[email protected]df37b9932013-03-08 05:21:428588 Program* program = GetProgramInfoNotShader(
8589 program_id, "glGetActiveAttrib");
8590 if (!program) {
[email protected]0bfd9882010-02-05 23:02:258591 return error::kNoError;
8592 }
[email protected]ed9f9cd2013-02-27 21:12:358593 const Program::VertexAttrib* attrib_info =
[email protected]df37b9932013-03-08 05:21:428594 program->GetAttribInfo(index);
[email protected]0bfd9882010-02-05 23:02:258595 if (!attrib_info) {
[email protected]ab09b612013-03-11 22:11:518596 LOCAL_SET_GL_ERROR(
8597 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
[email protected]0bfd9882010-02-05 23:02:258598 return error::kNoError;
8599 }
8600 result->success = 1; // true.
8601 result->size = attrib_info->size;
8602 result->type = attrib_info->type;
8603 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:298604 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:148605 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328606}
8607
[email protected]b273e432010-04-12 17:23:588608error::Error GLES2DecoderImpl::HandleShaderBinary(
[email protected]ed9f9cd2013-02-27 21:12:358609 uint32 immediate_data_size, const cmds::ShaderBinary& c) {
[email protected]b273e432010-04-12 17:23:588610#if 1 // No binary shader support.
[email protected]ab09b612013-03-11 22:11:518611 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
[email protected]b273e432010-04-12 17:23:588612 return error::kNoError;
8613#else
8614 GLsizei n = static_cast<GLsizei>(c.n);
8615 if (n < 0) {
[email protected]ab09b612013-03-11 22:11:518616 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
[email protected]b273e432010-04-12 17:23:588617 return error::kNoError;
8618 }
8619 GLsizei length = static_cast<GLsizei>(c.length);
8620 if (length < 0) {
[email protected]ab09b612013-03-11 22:11:518621 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
[email protected]b273e432010-04-12 17:23:588622 return error::kNoError;
8623 }
8624 uint32 data_size;
8625 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
8626 return error::kOutOfBounds;
8627 }
8628 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
8629 c.shaders_shm_id, c.shaders_shm_offset, data_size);
8630 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
8631 const void* binary = GetSharedMemoryAs<const void*>(
8632 c.binary_shm_id, c.binary_shm_offset, length);
8633 if (shaders == NULL || binary == NULL) {
8634 return error::kOutOfBounds;
8635 }
8636 scoped_array<GLuint> service_ids(new GLuint[n]);
8637 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]df37b9932013-03-08 05:21:428638 Shader* shader = GetShader(shaders[ii]);
8639 if (!shader) {
[email protected]ab09b612013-03-11 22:11:518640 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
[email protected]b273e432010-04-12 17:23:588641 return error::kNoError;
8642 }
[email protected]df37b9932013-03-08 05:21:428643 service_ids[ii] = shader->service_id();
[email protected]b273e432010-04-12 17:23:588644 }
8645 // TODO(gman): call glShaderBinary
8646 return error::kNoError;
8647#endif
8648}
8649
[email protected]6d792ee12013-05-15 00:40:568650void GLES2DecoderImpl::DoSwapBuffers() {
[email protected]64ace852011-05-19 21:49:498651 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
[email protected]a7266a92012-06-28 02:11:088652
[email protected]64ace852011-05-19 21:49:498653 int this_frame_number = frame_number_++;
[email protected]2ac620e52012-07-23 20:31:428654 // TRACE_EVENT for gpu tests:
8655 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
[email protected]c76faea2013-03-26 07:42:428656 TRACE_EVENT_SCOPE_THREAD,
[email protected]2ac620e52012-07-23 20:31:428657 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
8658 "width", (is_offscreen ? offscreen_size_.width() :
8659 surface_->GetSize().width()));
[email protected]6d792ee12013-05-15 00:40:568660 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
[email protected]64ace852011-05-19 21:49:498661 "offscreen", is_offscreen,
8662 "frame", this_frame_number);
[email protected]8f9b8dd2013-09-12 18:05:138663 bool is_tracing;
8664 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8665 &is_tracing);
8666 if (is_tracing) {
8667 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8668 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8669 is_offscreen ? offscreen_size_ : surface_->GetSize());
8670 }
8671
[email protected]6217d392010-03-25 22:08:358672 // If offscreen then don't actually SwapBuffers to the display. Just copy
8673 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:498674 if (is_offscreen) {
[email protected]111975c62012-09-06 01:37:318675 TRACE_EVENT2("gpu", "Offscreen",
8676 "width", offscreen_size_.width(), "height", offscreen_size_.height());
[email protected]1fb8c482011-08-31 01:01:538677 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
8678 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
8679 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
8680 // fix this.
[email protected]62e155e2012-10-23 22:43:158681 if (workarounds().needs_offscreen_buffer_workaround) {
[email protected]1fb8c482011-08-31 01:01:538682 offscreen_saved_frame_buffer_->Create();
8683 glFinish();
8684 }
8685
8686 // Allocate the offscreen saved color texture.
8687 DCHECK(offscreen_saved_color_format_);
8688 offscreen_saved_color_texture_->AllocateStorage(
[email protected]678a73f2012-12-19 19:22:098689 offscreen_size_, offscreen_saved_color_format_, false);
[email protected]1fb8c482011-08-31 01:01:538690
8691 offscreen_saved_frame_buffer_->AttachRenderTexture(
8692 offscreen_saved_color_texture_.get());
[email protected]f0cfe752013-01-14 01:09:058693 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
8694 if (offscreen_saved_frame_buffer_->CheckStatus() !=
8695 GL_FRAMEBUFFER_COMPLETE) {
8696 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
8697 << "because offscreen saved FBO was incomplete.";
[email protected]6d792ee12013-05-15 00:40:568698 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
8699 return;
[email protected]f0cfe752013-01-14 01:09:058700 }
[email protected]1fb8c482011-08-31 01:01:538701
[email protected]f0cfe752013-01-14 01:09:058702 // Clear the offscreen color texture.
8703 // TODO(piman): Is this still necessary?
8704 {
8705 ScopedFrameBufferBinder binder(this,
8706 offscreen_saved_frame_buffer_->id());
8707 glClearColor(0, 0, 0, 0);
8708 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
8709 glDisable(GL_SCISSOR_TEST);
8710 glClear(GL_COLOR_BUFFER_BIT);
8711 RestoreClearState();
8712 }
[email protected]1fb8c482011-08-31 01:01:538713 }
8714
8715 UpdateParentTextureInfo();
8716 }
8717
[email protected]f0cfe752013-01-14 01:09:058718 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
[email protected]6d792ee12013-05-15 00:40:568719 return;
[email protected]ab09b612013-03-11 22:11:518720 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:308721 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
[email protected]6217d392010-03-25 22:08:358722
[email protected]34ff8b0c2010-10-01 20:06:028723 if (IsOffscreenBufferMultisampled()) {
[email protected]51411e32012-01-19 20:21:138724 // For multisampled buffers, resolve the frame buffer.
[email protected]de26b3c2011-08-03 21:54:278725 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]b86b14982010-10-11 18:45:488726 } else {
[email protected]069944672012-04-25 20:52:238727 ScopedFrameBufferBinder binder(this,
8728 offscreen_target_frame_buffer_->id());
[email protected]51411e32012-01-19 20:21:138729
[email protected]069944672012-04-25 20:52:238730 if (offscreen_target_buffer_preserved_) {
8731 // Copy the target frame buffer to the saved offscreen texture.
8732 offscreen_saved_color_texture_->Copy(
8733 offscreen_saved_color_texture_->size(),
8734 offscreen_saved_color_format_);
8735 } else {
8736 // Flip the textures in the parent context via the texture manager.
8737 if (!!offscreen_saved_color_texture_info_.get())
[email protected]370eaf12013-05-18 09:19:498738 offscreen_saved_color_texture_info_->texture()->
[email protected]069944672012-04-25 20:52:238739 SetServiceId(offscreen_target_color_texture_->id());
[email protected]8a61d872012-01-20 12:43:568740
[email protected]069944672012-04-25 20:52:238741 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
8742 offscreen_target_frame_buffer_->AttachRenderTexture(
8743 offscreen_target_color_texture_.get());
[email protected]b86b14982010-10-11 18:45:488744 }
[email protected]069944672012-04-25 20:52:238745
8746 // Ensure the side effects of the copy are visible to the parent
8747 // context. There is no need to do this for ANGLE because it uses a
8748 // single D3D device for all contexts.
8749 if (!IsAngle())
8750 glFlush();
[email protected]0c8c9d22010-06-25 17:36:398751 }
[email protected]6217d392010-03-25 22:08:358752 } else {
[email protected]111975c62012-09-06 01:37:318753 TRACE_EVENT2("gpu", "Onscreen",
8754 "width", surface_->GetSize().width(),
8755 "height", surface_->GetSize().height());
[email protected]f62a5ab2011-05-23 20:34:158756 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:018757 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]6d792ee12013-05-15 00:40:568758 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
[email protected]d0498742010-09-20 20:27:018759 }
[email protected]6217d392010-03-25 22:08:358760 }
[email protected]6217d392010-03-25 22:08:358761}
8762
[email protected]d4239852011-08-12 04:51:228763error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:358764 uint32 immediate_data_size, const cmds::EnableFeatureCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:188765 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:288766 if (!bucket || bucket->size() == 0) {
8767 return error::kInvalidArguments;
8768 }
[email protected]ed9f9cd2013-02-27 21:12:358769 typedef cmds::EnableFeatureCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:188770 Result* result = GetSharedMemoryAs<Result*>(
8771 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8772 if (!result) {
8773 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:108774 }
[email protected]b1d2dcb2010-05-17 19:24:188775 // Check that the client initialized the result.
8776 if (*result != 0) {
8777 return error::kInvalidArguments;
8778 }
8779 std::string feature_str;
8780 if (!bucket->GetAsString(&feature_str)) {
8781 return error::kInvalidArguments;
8782 }
8783
8784 // TODO(gman): make this some kind of table to function pointer thingy.
[email protected]d4239852011-08-12 04:51:228785 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
[email protected]b1d2dcb2010-05-17 19:24:188786 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]d4239852011-08-12 04:51:228787 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
[email protected]8fbedc02010-11-18 18:43:408788 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
8789 // TODO(gman): decide how to remove the need for this const_cast.
8790 // I could make validators_ non const but that seems bad as this is the only
8791 // place it is needed. I could make some special friend class of validators
8792 // just to allow this to set them. That seems silly. I could refactor this
8793 // code to use the extension mechanism or the initialization attributes to
8794 // turn this feature on. Given that the only real point of this is to make
8795 // the conformance tests pass and given that there is lots of real work that
8796 // needs to be done it seems like refactoring for one to one of those
8797 // methods is a very low priority.
8798 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]f0d74742011-10-03 16:31:048799 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
8800 force_webgl_glsl_validation_ = true;
8801 InitializeShaderTranslator();
[email protected]b1d2dcb2010-05-17 19:24:188802 } else {
8803 return error::kNoError;
8804 }
8805
8806 *result = 1; // true.
8807 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:108808}
8809
[email protected]c2f8c8402010-12-06 18:07:248810error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
8811 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:358812 const cmds::GetRequestableExtensionsCHROMIUM& c) {
[email protected]c2f8c8402010-12-06 18:07:248813 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]ed9f9cd2013-02-27 21:12:358814 scoped_refptr<FeatureInfo> info(new FeatureInfo());
[email protected]956aec52013-09-05 15:41:198815 info->Initialize(disallowed_features_);
[email protected]c2f8c8402010-12-06 18:07:248816 bucket->SetFromString(info->extensions().c_str());
8817 return error::kNoError;
8818}
8819
8820error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:358821 uint32 immediate_data_size, const cmds::RequestExtensionCHROMIUM& c) {
[email protected]c2f8c8402010-12-06 18:07:248822 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:288823 if (!bucket || bucket->size() == 0) {
8824 return error::kInvalidArguments;
8825 }
[email protected]c2f8c8402010-12-06 18:07:248826 std::string feature_str;
8827 if (!bucket->GetAsString(&feature_str)) {
8828 return error::kInvalidArguments;
8829 }
8830
[email protected]4b7eba92013-01-08 02:23:568831 bool desire_webgl_glsl_validation =
8832 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
8833 bool desire_standard_derivatives = false;
[email protected]70dc60932013-06-04 03:33:498834 bool desire_frag_depth = false;
[email protected]aff39ac82013-06-08 04:53:138835 bool desire_draw_buffers = false;
[email protected]4b7eba92013-01-08 02:23:568836 if (force_webgl_glsl_validation_) {
8837 desire_standard_derivatives =
8838 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
[email protected]70dc60932013-06-04 03:33:498839 desire_frag_depth =
8840 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
[email protected]aff39ac82013-06-08 04:53:138841 desire_draw_buffers =
8842 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
[email protected]f0d74742011-10-03 16:31:048843 }
8844
[email protected]4b7eba92013-01-08 02:23:568845 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
[email protected]70dc60932013-06-04 03:33:498846 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
[email protected]aff39ac82013-06-08 04:53:138847 desire_frag_depth != frag_depth_explicitly_enabled_ ||
8848 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
[email protected]70dc60932013-06-04 03:33:498849 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
8850 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
8851 frag_depth_explicitly_enabled_ |= desire_frag_depth;
[email protected]aff39ac82013-06-08 04:53:138852 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
[email protected]c2f8c8402010-12-06 18:07:248853 InitializeShaderTranslator();
8854 }
8855
[email protected]302ce6d2011-07-07 23:28:118856 UpdateCapabilities();
8857
[email protected]c2f8c8402010-12-06 18:07:248858 return error::kNoError;
8859}
8860
[email protected]372e0412011-06-28 16:08:568861error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:358862 uint32 immediate_data_size, const cmds::GetMultipleIntegervCHROMIUM& c) {
[email protected]372e0412011-06-28 16:08:568863 GLuint count = c.count;
8864 uint32 pnames_size;
8865 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
8866 return error::kOutOfBounds;
8867 }
8868 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
8869 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
8870 if (pnames == NULL) {
8871 return error::kOutOfBounds;
8872 }
8873
8874 // We have to copy them since we use them twice so the client
8875 // can't change them between the time we validate them and the time we use
8876 // them.
[email protected]40d90a22013-04-09 03:39:558877 scoped_ptr<GLenum[]> enums(new GLenum[count]);
[email protected]372e0412011-06-28 16:08:568878 memcpy(enums.get(), pnames, pnames_size);
8879
8880 // Count up the space needed for the result.
8881 uint32 num_results = 0;
8882 for (GLuint ii = 0; ii < count; ++ii) {
8883 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
8884 if (num == 0) {
[email protected]ab09b612013-03-11 22:11:518885 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8886 "glGetMulitpleCHROMIUM", enums[ii], "pname");
[email protected]372e0412011-06-28 16:08:568887 return error::kNoError;
8888 }
8889 // Num will never be more than 4.
8890 DCHECK_LE(num, 4u);
[email protected]3aad1a32012-09-07 20:54:478891 if (!SafeAddUint32(num_results, num, &num_results)) {
[email protected]372e0412011-06-28 16:08:568892 return error::kOutOfBounds;
8893 }
8894 }
8895
8896 uint32 result_size = 0;
8897 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
8898 return error::kOutOfBounds;
8899 }
8900
8901 if (result_size != static_cast<uint32>(c.size)) {
[email protected]ab09b612013-03-11 22:11:518902 LOCAL_SET_GL_ERROR(
8903 GL_INVALID_VALUE,
8904 "glGetMulitpleCHROMIUM", "bad size GL_INVALID_VALUE");
[email protected]372e0412011-06-28 16:08:568905 return error::kNoError;
8906 }
8907
8908 GLint* results = GetSharedMemoryAs<GLint*>(
8909 c.results_shm_id, c.results_shm_offset, result_size);
8910 if (results == NULL) {
8911 return error::kOutOfBounds;
8912 }
8913
8914 // Check the results have been cleared in case the context was lost.
8915 for (uint32 ii = 0; ii < num_results; ++ii) {
8916 if (results[ii]) {
8917 return error::kInvalidArguments;
8918 }
8919 }
8920
8921 // Get each result.
8922 GLint* start = results;
8923 for (GLuint ii = 0; ii < count; ++ii) {
8924 GLsizei num_written = 0;
[email protected]d058bca2012-11-26 10:27:268925 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
[email protected]f63b1232012-10-31 07:03:538926 !GetHelper(enums[ii], results, &num_written)) {
[email protected]b0ce0982013-05-13 18:51:488927 DoGetIntegerv(enums[ii], results);
[email protected]372e0412011-06-28 16:08:568928 }
8929 results += num_written;
8930 }
8931
8932 // Just to verify. Should this be a DCHECK?
8933 if (static_cast<uint32>(results - start) != num_results) {
8934 return error::kOutOfBounds;
8935 }
8936
8937 return error::kNoError;
8938}
8939
[email protected]2318d342011-07-11 22:27:428940error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:358941 uint32 immediate_data_size, const cmds::GetProgramInfoCHROMIUM& c) {
[email protected]df37b9932013-03-08 05:21:428942 GLuint program_id = static_cast<GLuint>(c.program);
[email protected]2318d342011-07-11 22:27:428943 uint32 bucket_id = c.bucket_id;
8944 Bucket* bucket = CreateBucket(bucket_id);
8945 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
[email protected]df37b9932013-03-08 05:21:428946 Program* program = NULL;
8947 program = GetProgram(program_id);
8948 if (!program || !program->IsValid()) {
[email protected]9a14ae612011-08-08 17:51:468949 return error::kNoError;
[email protected]2318d342011-07-11 22:27:428950 }
[email protected]df37b9932013-03-08 05:21:428951 program->GetProgramInfo(program_manager(), bucket);
[email protected]2318d342011-07-11 22:27:428952 return error::kNoError;
8953}
8954
[email protected]38d139d2011-07-14 00:38:438955error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
8956 switch (reset_status_) {
[email protected]ad84a3a2012-06-08 21:42:438957 case GL_NO_ERROR:
8958 // TODO(kbr): improve the precision of the error code in this case.
8959 // Consider delegating to context for error code if MakeCurrent fails.
8960 return error::kUnknown;
8961 case GL_GUILTY_CONTEXT_RESET_ARB:
8962 return error::kGuilty;
8963 case GL_INNOCENT_CONTEXT_RESET_ARB:
8964 return error::kInnocent;
8965 case GL_UNKNOWN_CONTEXT_RESET_ARB:
8966 return error::kUnknown;
[email protected]38d139d2011-07-14 00:38:438967 }
8968
8969 NOTREACHED();
8970 return error::kUnknown;
8971}
8972
8973bool GLES2DecoderImpl::WasContextLost() {
[email protected]c4485aad62012-12-17 10:19:098974 if (reset_status_ != GL_NO_ERROR) {
8975 return true;
8976 }
[email protected]706b69f2012-07-27 04:59:308977 if (context_->WasAllocatedUsingRobustnessExtension()) {
8978 GLenum status = GL_NO_ERROR;
8979 if (has_robustness_extension_)
8980 status = glGetGraphicsResetStatusARB();
[email protected]38d139d2011-07-14 00:38:438981 if (status != GL_NO_ERROR) {
8982 // The graphics card was reset. Signal a lost context to the application.
8983 reset_status_ = status;
[email protected]93a7d98f2013-07-11 00:04:228984 reset_by_robustness_extension_ = true;
[email protected]38d139d2011-07-14 00:38:438985 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
[email protected]c4485aad62012-12-17 10:19:098986 << " context lost via ARB/EXT_robustness. Reset status = "
8987 << GLES2Util::GetStringEnum(status);
[email protected]38d139d2011-07-14 00:38:438988 return true;
8989 }
8990 }
8991 return false;
8992}
8993
[email protected]93a7d98f2013-07-11 00:04:228994bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
8995 return WasContextLost() && reset_by_robustness_extension_;
8996}
8997
[email protected]c4485aad62012-12-17 10:19:098998void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
8999 // Only loses the context once.
9000 if (reset_status_ != GL_NO_ERROR) {
9001 return;
9002 }
9003
9004 // Marks this context as lost.
9005 reset_status_ = reset_status;
9006 current_decoder_error_ = error::kLostContext;
[email protected]c4485aad62012-12-17 10:19:099007}
9008
9009error::Error GLES2DecoderImpl::HandleLoseContextCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:359010 uint32 immediate_data_size, const cmds::LoseContextCHROMIUM& c) {
[email protected]c4485aad62012-12-17 10:19:099011 GLenum current = static_cast<GLenum>(c.current);
9012 GLenum other = static_cast<GLenum>(c.other);
9013 if (!validators_->reset_status.IsValid(current)) {
[email protected]ab09b612013-03-11 22:11:519014 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9015 "glLoseContextCHROMIUM", current, "current");
[email protected]c4485aad62012-12-17 10:19:099016 }
9017 if (!validators_->reset_status.IsValid(other)) {
[email protected]ab09b612013-03-11 22:11:519018 LOCAL_SET_GL_ERROR_INVALID_ENUM("glLoseContextCHROMIUM", other, "other");
[email protected]c4485aad62012-12-17 10:19:099019 }
9020 group_->LoseContexts(other);
9021 reset_status_ = current;
9022 current_decoder_error_ = error::kLostContext;
9023 return error::kLostContext;
9024}
9025
[email protected]b096d032013-03-08 03:08:019026error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9027 uint32 immediate_data_size, const cmds::InsertSyncPointCHROMIUM& c) {
9028 return error::kUnknownCommand;
9029}
9030
[email protected]840a7e462013-02-27 01:29:519031error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:359032 uint32 immediate_data_size, const cmds::WaitSyncPointCHROMIUM& c) {
[email protected]840a7e462013-02-27 01:29:519033 if (wait_sync_point_callback_.is_null())
9034 return error::kNoError;
9035
9036 return wait_sync_point_callback_.Run(c.sync_point) ?
9037 error::kNoError : error::kDeferCommandUntilLater;
9038}
9039
[email protected]882ba1e22012-03-08 19:02:539040bool GLES2DecoderImpl::GenQueriesEXTHelper(
9041 GLsizei n, const GLuint* client_ids) {
9042 for (GLsizei ii = 0; ii < n; ++ii) {
9043 if (query_manager_->GetQuery(client_ids[ii])) {
9044 return false;
9045 }
9046 }
[email protected]c45f1972012-03-14 07:27:369047 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
[email protected]882ba1e22012-03-08 19:02:539048 return true;
9049}
9050
9051void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9052 GLsizei n, const GLuint* client_ids) {
9053 for (GLsizei ii = 0; ii < n; ++ii) {
9054 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
9055 if (query && !query->IsDeleted()) {
[email protected]7cd76fd2013-06-02 21:11:119056 if (query == state_.current_query.get()) {
[email protected]e259eb412012-10-13 05:47:249057 state_.current_query = NULL;
[email protected]882ba1e22012-03-08 19:02:539058 }
[email protected]c45f1972012-03-14 07:27:369059 query->Destroy(true);
[email protected]882ba1e22012-03-08 19:02:539060 query_manager_->RemoveQuery(client_ids[ii]);
9061 }
9062 }
9063}
9064
[email protected]22e3f552012-03-13 01:54:199065bool GLES2DecoderImpl::ProcessPendingQueries() {
9066 if (query_manager_.get() == NULL) {
9067 return false;
9068 }
[email protected]c45f1972012-03-14 07:27:369069 if (!query_manager_->ProcessPendingQueries()) {
[email protected]22e3f552012-03-13 01:54:199070 current_decoder_error_ = error::kOutOfBounds;
9071 }
9072 return query_manager_->HavePendingQueries();
9073}
9074
[email protected]5a36dc132013-07-23 23:17:559075// Note that if there are no pending readpixels right now,
9076// this function will call the callback immediately.
9077void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
9078 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
9079 pending_readpixel_fences_.back()->callbacks.push_back(callback);
9080 } else {
9081 callback.Run();
9082 }
9083}
9084
9085void GLES2DecoderImpl::ProcessPendingReadPixels() {
9086 while (!pending_readpixel_fences_.empty() &&
9087 pending_readpixel_fences_.front()->fence->HasCompleted()) {
9088 std::vector<base::Closure> callbacks =
9089 pending_readpixel_fences_.front()->callbacks;
9090 pending_readpixel_fences_.pop();
9091 for (size_t i = 0; i < callbacks.size(); i++) {
9092 callbacks[i].Run();
9093 }
9094 }
9095}
9096
[email protected]2b1767cf2013-03-16 09:25:059097bool GLES2DecoderImpl::HasMoreIdleWork() {
[email protected]5a36dc132013-07-23 23:17:559098 return !pending_readpixel_fences_.empty() ||
9099 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
[email protected]2b1767cf2013-03-16 09:25:059100}
9101
9102void GLES2DecoderImpl::PerformIdleWork() {
[email protected]5a36dc132013-07-23 23:17:559103 ProcessPendingReadPixels();
[email protected]b68b100752013-06-05 08:34:489104 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
[email protected]2b1767cf2013-03-16 09:25:059105 return;
[email protected]b68b100752013-06-05 08:34:489106 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
[email protected]2b1767cf2013-03-16 09:25:059107 ProcessFinishedAsyncTransfers();
9108}
9109
[email protected]882ba1e22012-03-08 19:02:539110error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
[email protected]ed9f9cd2013-02-27 21:12:359111 uint32 immediate_data_size, const cmds::BeginQueryEXT& c) {
[email protected]882ba1e22012-03-08 19:02:539112 GLenum target = static_cast<GLenum>(c.target);
9113 GLuint client_id = static_cast<GLuint>(c.id);
9114 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
9115 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
9116
[email protected]c45f1972012-03-14 07:27:369117 switch (target) {
9118 case GL_COMMANDS_ISSUED_CHROMIUM:
[email protected]fb4bf5822012-10-23 21:25:559119 case GL_LATENCY_QUERY_CHROMIUM:
[email protected]5537605d2013-08-27 05:22:319120 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
9121 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
[email protected]620b0db02013-03-20 15:47:009122 case GL_GET_ERROR_QUERY_CHROMIUM:
[email protected]c45f1972012-03-14 07:27:369123 break;
9124 default:
[email protected]62e155e2012-10-23 22:43:159125 if (!features().occlusion_query_boolean) {
[email protected]ab09b612013-03-11 22:11:519126 LOCAL_SET_GL_ERROR(
[email protected]620b0db02013-03-20 15:47:009127 GL_INVALID_OPERATION, "glBeginQueryEXT",
9128 "not enabled for occlusion queries");
[email protected]c45f1972012-03-14 07:27:369129 return error::kNoError;
9130 }
9131 break;
[email protected]882ba1e22012-03-08 19:02:539132 }
9133
[email protected]5a36dc132013-07-23 23:17:559134 // TODO(hubbe): Make it possible to have one query per type running at the
9135 // same time.
[email protected]7cd76fd2013-06-02 21:11:119136 if (state_.current_query.get()) {
[email protected]ab09b612013-03-11 22:11:519137 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439138 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
[email protected]882ba1e22012-03-08 19:02:539139 return error::kNoError;
9140 }
9141
9142 if (client_id == 0) {
[email protected]ab09b612013-03-11 22:11:519143 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
[email protected]882ba1e22012-03-08 19:02:539144 return error::kNoError;
9145 }
9146
9147 QueryManager::Query* query = query_manager_->GetQuery(client_id);
9148 if (!query) {
[email protected]c45f1972012-03-14 07:27:369149 // TODO(gman): Decide if we need this check.
9150 //
[email protected]882ba1e22012-03-08 19:02:539151 // Checks id was made by glGenQueries
[email protected]c45f1972012-03-14 07:27:369152 //
9153 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
9154 // for all Query ids but from the POV of the command buffer service maybe
9155 // you don't.
9156 //
9157 // The client can enforce this. I don't think the service cares.
9158 //
9159 // IdAllocatorInterface* id_allocator =
9160 // group_->GetIdAllocator(id_namespaces::kQueries);
9161 // if (!id_allocator->InUse(client_id)) {
[email protected]ab09b612013-03-11 22:11:519162 // LOCAL_SET_GL_ERROR(
9163 // GL_INVALID_OPERATION,
9164 // "glBeginQueryEXT", "id not made by glGenQueriesEXT");
[email protected]c45f1972012-03-14 07:27:369165 // return error::kNoError;
9166 // }
9167 query = query_manager_->CreateQuery(
9168 target, client_id, sync_shm_id, sync_shm_offset);
[email protected]882ba1e22012-03-08 19:02:539169 }
9170
[email protected]c45f1972012-03-14 07:27:369171 if (query->target() != target) {
[email protected]ab09b612013-03-11 22:11:519172 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439173 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
[email protected]882ba1e22012-03-08 19:02:539174 return error::kNoError;
9175 } else if (query->shm_id() != sync_shm_id ||
9176 query->shm_offset() != sync_shm_offset) {
9177 DLOG(ERROR) << "Shared memory used by query not the same as before";
9178 return error::kInvalidArguments;
9179 }
9180
[email protected]c45f1972012-03-14 07:27:369181 if (!query_manager_->BeginQuery(query)) {
9182 return error::kOutOfBounds;
9183 }
[email protected]882ba1e22012-03-08 19:02:539184
[email protected]e259eb412012-10-13 05:47:249185 state_.current_query = query;
[email protected]882ba1e22012-03-08 19:02:539186 return error::kNoError;
9187}
9188
9189error::Error GLES2DecoderImpl::HandleEndQueryEXT(
[email protected]ed9f9cd2013-02-27 21:12:359190 uint32 immediate_data_size, const cmds::EndQueryEXT& c) {
[email protected]882ba1e22012-03-08 19:02:539191 GLenum target = static_cast<GLenum>(c.target);
9192 uint32 submit_count = static_cast<GLuint>(c.submit_count);
9193
[email protected]7cd76fd2013-06-02 21:11:119194 if (!state_.current_query.get()) {
[email protected]ab09b612013-03-11 22:11:519195 LOCAL_SET_GL_ERROR(
9196 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
[email protected]882ba1e22012-03-08 19:02:539197 return error::kNoError;
9198 }
[email protected]e259eb412012-10-13 05:47:249199 if (state_.current_query->target() != target) {
[email protected]ab09b612013-03-11 22:11:519200 LOCAL_SET_GL_ERROR(
9201 GL_INVALID_OPERATION,
9202 "glEndQueryEXT", "target does not match active query");
[email protected]882ba1e22012-03-08 19:02:539203 return error::kNoError;
9204 }
[email protected]882ba1e22012-03-08 19:02:539205
[email protected]7cd76fd2013-06-02 21:11:119206 if (!query_manager_->EndQuery(state_.current_query.get(), submit_count)) {
[email protected]c45f1972012-03-14 07:27:369207 return error::kOutOfBounds;
9208 }
9209
[email protected]fe8d73c2013-02-16 22:37:329210 query_manager_->ProcessPendingTransferQueries();
9211
[email protected]e259eb412012-10-13 05:47:249212 state_.current_query = NULL;
[email protected]882ba1e22012-03-08 19:02:539213 return error::kNoError;
9214}
9215
[email protected]944b62f32012-09-27 02:20:469216bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9217 GLsizei n, const GLuint* client_ids) {
[email protected]944b62f32012-09-27 02:20:469218 for (GLsizei ii = 0; ii < n; ++ii) {
9219 if (GetVertexAttribManager(client_ids[ii])) {
9220 return false;
9221 }
9222 }
[email protected]ab4fd7282012-10-12 16:25:579223
[email protected]62e155e2012-10-23 22:43:159224 if (!features().native_vertex_array_object) {
[email protected]ab4fd7282012-10-12 16:25:579225 // Emulated VAO
9226 for (GLsizei ii = 0; ii < n; ++ii) {
9227 CreateVertexAttribManager(client_ids[ii], 0);
9228 }
9229 } else {
[email protected]40d90a22013-04-09 03:39:559230 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ab4fd7282012-10-12 16:25:579231
9232 glGenVertexArraysOES(n, service_ids.get());
9233 for (GLsizei ii = 0; ii < n; ++ii) {
9234 CreateVertexAttribManager(client_ids[ii], service_ids[ii]);
9235 }
[email protected]944b62f32012-09-27 02:20:469236 }
[email protected]ab4fd7282012-10-12 16:25:579237
[email protected]944b62f32012-09-27 02:20:469238 return true;
9239}
9240
9241void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9242 GLsizei n, const GLuint* client_ids) {
[email protected]944b62f32012-09-27 02:20:469243 for (GLsizei ii = 0; ii < n; ++ii) {
9244 VertexAttribManager* vao =
9245 GetVertexAttribManager(client_ids[ii]);
9246 if (vao && !vao->IsDeleted()) {
[email protected]7cd76fd2013-06-02 21:11:119247 if (state_.vertex_attrib_manager.get() == vao) {
[email protected]e259eb412012-10-13 05:47:249248 state_.vertex_attrib_manager = default_vertex_attrib_manager_;
[email protected]944b62f32012-09-27 02:20:469249 }
9250 RemoveVertexAttribManager(client_ids[ii]);
9251 }
9252 }
9253}
9254
9255void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
[email protected]944b62f32012-09-27 02:20:469256 VertexAttribManager* vao = NULL;
9257 GLuint service_id = 0;
9258 if (client_id != 0) {
9259 vao = GetVertexAttribManager(client_id);
9260 if (!vao) {
9261 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9262 // only allows names that have been previously generated. As such, we do
9263 // not generate new names here.
[email protected]ab09b612013-03-11 22:11:519264 LOCAL_SET_GL_ERROR(
9265 GL_INVALID_OPERATION,
9266 "glBindVertexArrayOES", "bad vertex array id.");
[email protected]944b62f32012-09-27 02:20:469267 current_decoder_error_ = error::kNoError;
9268 return;
9269 } else {
9270 service_id = vao->service_id();
9271 }
[email protected]944b62f32012-09-27 02:20:469272 } else {
[email protected]7cd76fd2013-06-02 21:11:119273 vao = default_vertex_attrib_manager_.get();
[email protected]944b62f32012-09-27 02:20:469274 }
9275
[email protected]ab4fd7282012-10-12 16:25:579276 // Only set the VAO state if it's changed
[email protected]7cd76fd2013-06-02 21:11:119277 if (state_.vertex_attrib_manager.get() != vao) {
[email protected]e259eb412012-10-13 05:47:249278 state_.vertex_attrib_manager = vao;
[email protected]62e155e2012-10-23 22:43:159279 if (!features().native_vertex_array_object) {
[email protected]ab4fd7282012-10-12 16:25:579280 EmulateVertexArrayState();
9281 } else {
9282 glBindVertexArrayOES(service_id);
9283 }
9284 }
9285}
9286
9287// Used when OES_vertex_array_object isn't natively supported
9288void GLES2DecoderImpl::EmulateVertexArrayState() {
9289 // Setup the Vertex attribute state
9290 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
9291 RestoreStateForAttrib(vv);
9292 }
9293
9294 // Setup the element buffer
[email protected]16ccec12013-02-28 03:40:219295 Buffer* element_array_buffer =
[email protected]e259eb412012-10-13 05:47:249296 state_.vertex_attrib_manager->element_array_buffer();
[email protected]ab4fd7282012-10-12 16:25:579297 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
9298 element_array_buffer ? element_array_buffer->service_id() : 0);
[email protected]944b62f32012-09-27 02:20:469299}
9300
9301bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
[email protected]944b62f32012-09-27 02:20:469302 const VertexAttribManager* vao =
9303 GetVertexAttribManager(client_id);
9304 return vao && vao->IsValid() && !vao->IsDeleted();
9305}
9306
[email protected]b0af4f52011-09-28 22:04:429307error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
9308 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:359309 const cmds::CreateStreamTextureCHROMIUM& c) {
[email protected]62e155e2012-10-23 22:43:159310 if (!features().chromium_stream_texture) {
[email protected]ab09b612013-03-11 22:11:519311 LOCAL_SET_GL_ERROR(
9312 GL_INVALID_OPERATION,
9313 "glOpenStreamTextureCHROMIUM", "not supported.");
[email protected]b0af4f52011-09-28 22:04:429314 return error::kNoError;
9315 }
9316
9317 uint32 client_id = c.client_id;
[email protected]ed9f9cd2013-02-27 21:12:359318 typedef cmds::CreateStreamTextureCHROMIUM::Result Result;
[email protected]b0af4f52011-09-28 22:04:429319 Result* result = GetSharedMemoryAs<Result*>(
9320 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9321
[email protected]e5081262012-01-05 23:09:039322 if (!result)
9323 return error::kOutOfBounds;
[email protected]b0af4f52011-09-28 22:04:429324 *result = GL_ZERO;
[email protected]370eaf12013-05-18 09:19:499325 TextureRef* texture_ref = texture_manager()->GetTexture(client_id);
9326 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519327 LOCAL_SET_GL_ERROR(
9328 GL_INVALID_VALUE,
9329 "glCreateStreamTextureCHROMIUM", "bad texture id.");
[email protected]b0af4f52011-09-28 22:04:429330 return error::kNoError;
9331 }
9332
[email protected]370eaf12013-05-18 09:19:499333 Texture* texture = texture_ref->texture();
[email protected]02965c22013-03-09 02:40:079334 if (texture->IsStreamTexture()) {
[email protected]ab09b612013-03-11 22:11:519335 LOCAL_SET_GL_ERROR(
9336 GL_INVALID_OPERATION,
9337 "glCreateStreamTextureCHROMIUM", "is already a stream texture.");
[email protected]b0af4f52011-09-28 22:04:429338 return error::kNoError;
9339 }
9340
[email protected]02965c22013-03-09 02:40:079341 if (texture->target() && texture->target() != GL_TEXTURE_EXTERNAL_OES) {
[email protected]ab09b612013-03-11 22:11:519342 LOCAL_SET_GL_ERROR(
9343 GL_INVALID_OPERATION,
9344 "glCreateStreamTextureCHROMIUM",
9345 "is already bound to incompatible target.");
[email protected]b0af4f52011-09-28 22:04:429346 return error::kNoError;
9347 }
9348
[email protected]4f9958142013-07-02 03:58:079349 if (!stream_texture_manager())
[email protected]b0af4f52011-09-28 22:04:429350 return error::kInvalidArguments;
9351
[email protected]4f9958142013-07-02 03:58:079352 GLuint object_id = stream_texture_manager()->CreateStreamTexture(
[email protected]02965c22013-03-09 02:40:079353 texture->service_id(), client_id);
[email protected]b0af4f52011-09-28 22:04:429354
9355 if (object_id) {
[email protected]370eaf12013-05-18 09:19:499356 texture_manager()->SetStreamTexture(texture_ref, true);
[email protected]b0af4f52011-09-28 22:04:429357 } else {
[email protected]ab09b612013-03-11 22:11:519358 LOCAL_SET_GL_ERROR(
9359 GL_OUT_OF_MEMORY,
9360 "glCreateStreamTextureCHROMIUM", "failed to create platform texture.");
[email protected]b0af4f52011-09-28 22:04:429361 }
9362
9363 *result = object_id;
9364 return error::kNoError;
9365}
9366
9367error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
9368 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:359369 const cmds::DestroyStreamTextureCHROMIUM& c) {
[email protected]b0af4f52011-09-28 22:04:429370 GLuint client_id = c.texture;
[email protected]370eaf12013-05-18 09:19:499371 TextureRef* texture_ref = texture_manager()->GetTexture(client_id);
[email protected]4f9958142013-07-02 03:58:079372 if (texture_ref && texture_manager()->IsStreamTextureOwner(texture_ref)) {
9373 if (!stream_texture_manager())
[email protected]b0af4f52011-09-28 22:04:429374 return error::kInvalidArguments;
9375
[email protected]4f9958142013-07-02 03:58:079376 stream_texture_manager()->DestroyStreamTexture(texture_ref->service_id());
[email protected]370eaf12013-05-18 09:19:499377 texture_manager()->SetStreamTexture(texture_ref, false);
[email protected]b0af4f52011-09-28 22:04:429378 } else {
[email protected]ab09b612013-03-11 22:11:519379 LOCAL_SET_GL_ERROR(
9380 GL_INVALID_VALUE,
9381 "glDestroyStreamTextureCHROMIUM", "bad texture id.");
[email protected]b0af4f52011-09-28 22:04:429382 }
9383
9384 return error::kNoError;
9385}
9386
[email protected]e51bdf32011-11-23 22:21:469387#if defined(OS_MACOSX)
9388void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
9389 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
9390 texture_id);
9391 if (it != texture_to_io_surface_map_.end()) {
9392 // Found a previous IOSurface bound to this texture; release it.
9393 CFTypeRef surface = it->second;
9394 CFRelease(surface);
9395 texture_to_io_surface_map_.erase(it);
9396 }
9397}
9398#endif
9399
9400void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9401 GLenum target, GLsizei width, GLsizei height,
9402 GLuint io_surface_id, GLuint plane) {
9403#if defined(OS_MACOSX)
9404 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
[email protected]ab09b612013-03-11 22:11:519405 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439406 GL_INVALID_OPERATION,
9407 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
[email protected]e51bdf32011-11-23 22:21:469408 return;
9409 }
9410
9411 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
9412 if (!surface_support) {
[email protected]ab09b612013-03-11 22:11:519413 LOCAL_SET_GL_ERROR(
9414 GL_INVALID_OPERATION,
9415 "glTexImageIOSurface2DCHROMIUM", "only supported on 10.6.");
[email protected]e51bdf32011-11-23 22:21:469416 return;
9417 }
9418
9419 if (target != GL_TEXTURE_RECTANGLE_ARB) {
9420 // This might be supported in the future, and if we could require
9421 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9422 // could delete a lot of code. For now, perform strict validation so we
9423 // know what's going on.
[email protected]ab09b612013-03-11 22:11:519424 LOCAL_SET_GL_ERROR(
[email protected]e51bdf32011-11-23 22:21:469425 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439426 "glTexImageIOSurface2DCHROMIUM",
9427 "requires TEXTURE_RECTANGLE_ARB target");
[email protected]e51bdf32011-11-23 22:21:469428 return;
9429 }
9430
[email protected]09d50362012-10-18 20:54:379431 // Default target might be conceptually valid, but disallow it to avoid
9432 // accidents.
[email protected]c986af502013-08-14 01:04:449433 TextureRef* texture_ref =
9434 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
[email protected]370eaf12013-05-18 09:19:499435 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519436 LOCAL_SET_GL_ERROR(
9437 GL_INVALID_OPERATION,
9438 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
[email protected]e51bdf32011-11-23 22:21:469439 return;
9440 }
[email protected]e51bdf32011-11-23 22:21:469441
9442 // Look up the new IOSurface. Note that because of asynchrony
9443 // between processes this might fail; during live resizing the
9444 // plugin process might allocate and release an IOSurface before
9445 // this process gets a chance to look it up. Hold on to any old
9446 // IOSurface in this case.
9447 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
9448 if (!surface) {
[email protected]ab09b612013-03-11 22:11:519449 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439450 GL_INVALID_OPERATION,
9451 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
[email protected]e51bdf32011-11-23 22:21:469452 return;
9453 }
9454
9455 // Release any IOSurface previously bound to this texture.
[email protected]370eaf12013-05-18 09:19:499456 ReleaseIOSurfaceForTexture(texture_ref->service_id());
[email protected]e51bdf32011-11-23 22:21:469457
9458 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9459 texture_to_io_surface_map_.insert(
[email protected]370eaf12013-05-18 09:19:499460 std::make_pair(texture_ref->service_id(), surface));
[email protected]e51bdf32011-11-23 22:21:469461
9462 CGLContextObj context =
9463 static_cast<CGLContextObj>(context_->GetHandle());
9464
9465 CGLError err = surface_support->CGLTexImageIOSurface2D(
9466 context,
9467 target,
9468 GL_RGBA,
9469 width,
9470 height,
9471 GL_BGRA,
9472 GL_UNSIGNED_INT_8_8_8_8_REV,
9473 surface,
9474 plane);
9475
9476 if (err != kCGLNoError) {
[email protected]ab09b612013-03-11 22:11:519477 LOCAL_SET_GL_ERROR(
[email protected]e51bdf32011-11-23 22:21:469478 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439479 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
[email protected]e51bdf32011-11-23 22:21:469480 return;
9481 }
9482
9483 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:499484 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
[email protected]e51bdf32011-11-23 22:21:469485 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
9486
9487#else
[email protected]ab09b612013-03-11 22:11:519488 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439489 "glTexImageIOSurface2DCHROMIUM", "not supported.");
[email protected]e51bdf32011-11-23 22:21:469490#endif
9491}
9492
[email protected]97dc7cbe2011-12-06 17:26:179493static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
9494 switch (internalformat) {
9495 case GL_RGB565:
9496 return GL_RGB;
9497 case GL_RGBA4:
9498 return GL_RGBA;
9499 case GL_RGB5_A1:
9500 return GL_RGBA;
9501 case GL_RGB8_OES:
9502 return GL_RGB;
9503 case GL_RGBA8_OES:
9504 return GL_RGBA;
9505 case GL_LUMINANCE8_ALPHA8_EXT:
9506 return GL_LUMINANCE_ALPHA;
9507 case GL_LUMINANCE8_EXT:
9508 return GL_LUMINANCE;
9509 case GL_ALPHA8_EXT:
9510 return GL_ALPHA;
9511 case GL_RGBA32F_EXT:
9512 return GL_RGBA;
9513 case GL_RGB32F_EXT:
9514 return GL_RGB;
9515 case GL_ALPHA32F_EXT:
9516 return GL_ALPHA;
9517 case GL_LUMINANCE32F_EXT:
9518 return GL_LUMINANCE;
9519 case GL_LUMINANCE_ALPHA32F_EXT:
9520 return GL_LUMINANCE_ALPHA;
9521 case GL_RGBA16F_EXT:
9522 return GL_RGBA;
9523 case GL_RGB16F_EXT:
9524 return GL_RGB;
9525 case GL_ALPHA16F_EXT:
9526 return GL_ALPHA;
9527 case GL_LUMINANCE16F_EXT:
9528 return GL_LUMINANCE;
9529 case GL_LUMINANCE_ALPHA16F_EXT:
9530 return GL_LUMINANCE_ALPHA;
9531 case GL_BGRA8_EXT:
9532 return GL_BGRA_EXT;
9533 default:
9534 return GL_NONE;
9535 }
9536}
9537
[email protected]43410e92012-04-20 17:06:289538void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
[email protected]0a1e9ad2012-05-04 21:13:039539 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
[email protected]a4a6bdd12013-04-19 20:46:549540 GLenum internal_format, GLenum dest_type) {
[email protected]370eaf12013-05-18 09:19:499541 TextureRef* dest_texture_ref = GetTexture(dest_id);
9542 TextureRef* source_texture_ref = GetTexture(source_id);
[email protected]43410e92012-04-20 17:06:289543
[email protected]370eaf12013-05-18 09:19:499544 if (!source_texture_ref || !dest_texture_ref) {
[email protected]ab09b612013-03-11 22:11:519545 LOCAL_SET_GL_ERROR(
9546 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
[email protected]43410e92012-04-20 17:06:289547 return;
9548 }
9549
9550 if (GL_TEXTURE_2D != target) {
[email protected]ab09b612013-03-11 22:11:519551 LOCAL_SET_GL_ERROR(
9552 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
[email protected]43410e92012-04-20 17:06:289553 return;
9554 }
9555
[email protected]370eaf12013-05-18 09:19:499556 Texture* source_texture = source_texture_ref->texture();
9557 Texture* dest_texture = dest_texture_ref->texture();
[email protected]02965c22013-03-09 02:40:079558 if (dest_texture->target() != GL_TEXTURE_2D ||
[email protected]9bc9a2e82013-04-03 03:56:259559 (source_texture->target() != GL_TEXTURE_2D &&
9560 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
[email protected]3ecc1052013-09-26 08:59:009561 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9562 "glCopyTextureCHROMIUM",
9563 "invalid texture target binding");
[email protected]0a1e9ad2012-05-04 21:13:039564 return;
9565 }
9566
[email protected]43410e92012-04-20 17:06:289567 int source_width, source_height, dest_width, dest_height;
[email protected]43410e92012-04-20 17:06:289568
[email protected]3ecc1052013-09-26 08:59:009569 if (source_texture->IsStreamTexture()) {
9570 DCHECK_EQ(source_texture->target(),
9571 static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES));
[email protected]4f9958142013-07-02 03:58:079572 DCHECK(stream_texture_manager());
[email protected]377976552013-05-14 23:32:569573 StreamTexture* stream_tex =
[email protected]4f9958142013-07-02 03:58:079574 stream_texture_manager()->LookupStreamTexture(
[email protected]377976552013-05-14 23:32:569575 source_texture->service_id());
9576 if (!stream_tex) {
9577 LOCAL_SET_GL_ERROR(
9578 GL_INVALID_VALUE,
9579 "glCopyTextureChromium", "Stream texture lookup failed");
9580 return;
9581 }
9582 gfx::Size size = stream_tex->GetSize();
9583 source_width = size.width();
9584 source_height = size.height();
9585 if (source_width <= 0 || source_height <= 0) {
9586 LOCAL_SET_GL_ERROR(
9587 GL_INVALID_VALUE,
9588 "glCopyTextureChromium", "invalid streamtexture size");
9589 return;
9590 }
[email protected]3ecc1052013-09-26 08:59:009591 } else {
9592 if (!source_texture->GetLevelSize(
9593 source_texture->target(), 0, &source_width, &source_height)) {
9594 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
9595 "glCopyTextureChromium",
9596 "source texture has no level 0");
9597 return;
9598 }
9599
9600 // Check that this type of texture is allowed.
9601 if (!texture_manager()->ValidForTarget(
9602 source_texture->target(), level, source_width, source_height, 1)) {
9603 LOCAL_SET_GL_ERROR(
9604 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
9605 return;
9606 }
[email protected]377976552013-05-14 23:32:569607 }
9608
[email protected]cf6b8f62012-05-25 21:43:379609 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
9610 // needed because it takes 10s of milliseconds to initialize.
9611 if (!copy_texture_CHROMIUM_.get()) {
[email protected]ab09b612013-03-11 22:11:519612 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
[email protected]cf6b8f62012-05-25 21:43:379613 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
[email protected]07a0cc32013-02-28 00:36:279614 copy_texture_CHROMIUM_->Initialize(this);
[email protected]cf6b8f62012-05-25 21:43:379615 RestoreCurrentFramebufferBindings();
[email protected]ab09b612013-03-11 22:11:519616 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
[email protected]cf6b8f62012-05-25 21:43:379617 return;
9618 }
9619
[email protected]a4a6bdd12013-04-19 20:46:549620 GLenum dest_type_previous;
[email protected]0a1e9ad2012-05-04 21:13:039621 GLenum dest_internal_format;
[email protected]02965c22013-03-09 02:40:079622 bool dest_level_defined = dest_texture->GetLevelSize(
9623 GL_TEXTURE_2D, level, &dest_width, &dest_height);
[email protected]43410e92012-04-20 17:06:289624
[email protected]0a1e9ad2012-05-04 21:13:039625 if (dest_level_defined) {
[email protected]a4a6bdd12013-04-19 20:46:549626 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
[email protected]02965c22013-03-09 02:40:079627 &dest_internal_format);
[email protected]0a1e9ad2012-05-04 21:13:039628 }
9629
9630 // Resize the destination texture to the dimensions of the source texture.
9631 if (!dest_level_defined || dest_width != source_width ||
9632 dest_height != source_height ||
[email protected]a4a6bdd12013-04-19 20:46:549633 dest_internal_format != internal_format ||
9634 dest_type_previous != dest_type) {
[email protected]43410e92012-04-20 17:06:289635 // Ensure that the glTexImage2D succeeds.
[email protected]ab09b612013-03-11 22:11:519636 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
[email protected]02965c22013-03-09 02:40:079637 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
[email protected]8f1d2aa2013-05-10 23:45:389638 glTexImage2D(
[email protected]43410e92012-04-20 17:06:289639 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
[email protected]0a1e9ad2012-05-04 21:13:039640 0, internal_format, dest_type, NULL);
[email protected]ab09b612013-03-11 22:11:519641 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
[email protected]0a1e9ad2012-05-04 21:13:039642 if (error != GL_NO_ERROR) {
9643 RestoreCurrentTexture2DBindings();
[email protected]43410e92012-04-20 17:06:289644 return;
[email protected]0a1e9ad2012-05-04 21:13:039645 }
[email protected]43410e92012-04-20 17:06:289646
9647 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:499648 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
[email protected]0a1e9ad2012-05-04 21:13:039649 source_height, 1, 0, internal_format, dest_type, true);
[email protected]f7024712012-05-15 21:30:259650 } else {
[email protected]02965c22013-03-09 02:40:079651 texture_manager()->SetLevelCleared(
[email protected]370eaf12013-05-18 09:19:499652 dest_texture_ref, GL_TEXTURE_2D, level, true);
[email protected]43410e92012-04-20 17:06:289653 }
9654
[email protected]5394a4102013-04-18 05:41:379655 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
9656 // before presenting.
9657 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
9658 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
9659 // instead of using default matrix crbug.com/226218.
9660 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
9661 0.0f, 1.0f, 0.0f, 0.0f,
9662 0.0f, 0.0f, 1.0f, 0.0f,
9663 0.0f, 0.0f, 0.0f, 1.0f};
9664 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
9665 this,
9666 source_texture->target(),
9667 dest_texture->target(),
9668 source_texture->service_id(),
9669 dest_texture->service_id(), level,
9670 source_width, source_height,
9671 unpack_flip_y_,
9672 unpack_premultiply_alpha_,
9673 unpack_unpremultiply_alpha_,
9674 default_matrix);
9675 } else {
9676 copy_texture_CHROMIUM_->DoCopyTexture(
9677 this,
9678 source_texture->target(),
9679 dest_texture->target(),
9680 source_texture->service_id(),
9681 dest_texture->service_id(), level,
9682 source_width, source_height,
9683 unpack_flip_y_,
9684 unpack_premultiply_alpha_,
9685 unpack_unpremultiply_alpha_);
9686 }
[email protected]43410e92012-04-20 17:06:289687}
9688
[email protected]97dc7cbe2011-12-06 17:26:179689static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
9690 switch (internalformat) {
9691 case GL_RGB565:
9692 return GL_UNSIGNED_SHORT_5_6_5;
9693 case GL_RGBA4:
9694 return GL_UNSIGNED_SHORT_4_4_4_4;
9695 case GL_RGB5_A1:
9696 return GL_UNSIGNED_SHORT_5_5_5_1;
9697 case GL_RGB8_OES:
9698 return GL_UNSIGNED_BYTE;
9699 case GL_RGBA8_OES:
9700 return GL_UNSIGNED_BYTE;
9701 case GL_LUMINANCE8_ALPHA8_EXT:
9702 return GL_UNSIGNED_BYTE;
9703 case GL_LUMINANCE8_EXT:
9704 return GL_UNSIGNED_BYTE;
9705 case GL_ALPHA8_EXT:
9706 return GL_UNSIGNED_BYTE;
9707 case GL_RGBA32F_EXT:
9708 return GL_FLOAT;
9709 case GL_RGB32F_EXT:
9710 return GL_FLOAT;
9711 case GL_ALPHA32F_EXT:
9712 return GL_FLOAT;
9713 case GL_LUMINANCE32F_EXT:
9714 return GL_FLOAT;
9715 case GL_LUMINANCE_ALPHA32F_EXT:
9716 return GL_FLOAT;
9717 case GL_RGBA16F_EXT:
9718 return GL_HALF_FLOAT_OES;
9719 case GL_RGB16F_EXT:
9720 return GL_HALF_FLOAT_OES;
9721 case GL_ALPHA16F_EXT:
9722 return GL_HALF_FLOAT_OES;
9723 case GL_LUMINANCE16F_EXT:
9724 return GL_HALF_FLOAT_OES;
9725 case GL_LUMINANCE_ALPHA16F_EXT:
9726 return GL_HALF_FLOAT_OES;
9727 case GL_BGRA8_EXT:
9728 return GL_UNSIGNED_BYTE;
9729 default:
9730 return GL_NONE;
9731 }
9732}
9733
9734void GLES2DecoderImpl::DoTexStorage2DEXT(
[email protected]a5d3dad2012-05-26 04:34:449735 GLenum target,
9736 GLint levels,
9737 GLenum internal_format,
9738 GLsizei width,
9739 GLsizei height) {
[email protected]43ed3a72012-05-30 22:55:389740 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
[email protected]80eb6b52012-01-19 00:14:419741 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
[email protected]3ecc1052013-09-26 08:59:009742 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
[email protected]ab09b612013-03-11 22:11:519743 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439744 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
[email protected]97dc7cbe2011-12-06 17:26:179745 return;
9746 }
[email protected]c986af502013-08-14 01:04:449747 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9748 &state_, target);
[email protected]370eaf12013-05-18 09:19:499749 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519750 LOCAL_SET_GL_ERROR(
9751 GL_INVALID_OPERATION,
9752 "glTexStorage2DEXT", "unknown texture for target");
[email protected]97dc7cbe2011-12-06 17:26:179753 return;
9754 }
[email protected]370eaf12013-05-18 09:19:499755 Texture* texture = texture_ref->texture();
[email protected]02965c22013-03-09 02:40:079756 if (texture->IsAttachedToFramebuffer()) {
[email protected]c986af502013-08-14 01:04:449757 framebuffer_state_.clear_state_dirty = true;
[email protected]97dc7cbe2011-12-06 17:26:179758 }
[email protected]02965c22013-03-09 02:40:079759 if (texture->IsImmutable()) {
[email protected]ab09b612013-03-11 22:11:519760 LOCAL_SET_GL_ERROR(
9761 GL_INVALID_OPERATION,
9762 "glTexStorage2DEXT", "texture is immutable");
[email protected]97dc7cbe2011-12-06 17:26:179763 return;
9764 }
[email protected]7989c9e2013-01-23 06:39:269765
9766 GLenum format = ExtractFormatFromStorageFormat(internal_format);
9767 GLenum type = ExtractTypeFromStorageFormat(internal_format);
9768
9769 {
9770 GLsizei level_width = width;
9771 GLsizei level_height = height;
9772 uint32 estimated_size = 0;
9773 for (int ii = 0; ii < levels; ++ii) {
9774 uint32 level_size = 0;
9775 if (!GLES2Util::ComputeImageDataSizes(
9776 level_width, level_height, format, type, state_.unpack_alignment,
9777 &estimated_size, NULL, NULL) ||
9778 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
[email protected]ab09b612013-03-11 22:11:519779 LOCAL_SET_GL_ERROR(
9780 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
[email protected]7989c9e2013-01-23 06:39:269781 return;
9782 }
9783 level_width = std::max(1, level_width >> 1);
9784 level_height = std::max(1, level_height >> 1);
9785 }
9786 if (!EnsureGPUMemoryAvailable(estimated_size)) {
[email protected]ab09b612013-03-11 22:11:519787 LOCAL_SET_GL_ERROR(
9788 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
[email protected]7989c9e2013-01-23 06:39:269789 return;
9790 }
9791 }
9792
[email protected]ab09b612013-03-11 22:11:519793 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
[email protected]8f1d2aa2013-05-10 23:45:389794 glTexStorage2DEXT(target, levels, internal_format, width, height);
[email protected]ab09b612013-03-11 22:11:519795 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
[email protected]97dc7cbe2011-12-06 17:26:179796 if (error == GL_NO_ERROR) {
[email protected]4502e6492011-12-14 19:39:159797 GLsizei level_width = width;
9798 GLsizei level_height = height;
9799 for (int ii = 0; ii < levels; ++ii) {
9800 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:499801 texture_ref, target, ii, format,
9802 level_width, level_height, 1, 0, format, type, false);
[email protected]4502e6492011-12-14 19:39:159803 level_width = std::max(1, level_width >> 1);
9804 level_height = std::max(1, level_height >> 1);
9805 }
[email protected]02965c22013-03-09 02:40:079806 texture->SetImmutable(true);
[email protected]97dc7cbe2011-12-06 17:26:179807 }
[email protected]97dc7cbe2011-12-06 17:26:179808}
[email protected]e51bdf32011-11-23 22:21:469809
[email protected]78b514b2012-05-01 21:50:599810error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:359811 uint32 immediate_data_size, const cmds::GenMailboxCHROMIUM& c) {
[email protected]baed42c2013-10-01 05:06:359812 return error::kUnknownCommand;
[email protected]78b514b2012-05-01 21:50:599813}
9814
9815void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
9816 const GLbyte* mailbox) {
[email protected]987b9c02013-03-23 00:58:029817 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
[email protected]1d82e822013-04-10 21:32:329818 "context", logger_.GetLogPrefix(),
[email protected]987b9c02013-03-23 00:58:029819 "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
9820
[email protected]c986af502013-08-14 01:04:449821 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9822 &state_, target);
[email protected]370eaf12013-05-18 09:19:499823 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519824 LOCAL_SET_GL_ERROR(
9825 GL_INVALID_OPERATION,
9826 "glProduceTextureCHROMIUM", "unknown texture for target");
[email protected]78b514b2012-05-01 21:50:599827 return;
9828 }
9829
[email protected]62e65f02013-05-29 22:28:109830 Texture* produced = texture_manager()->Produce(texture_ref);
9831 if (!produced) {
[email protected]ab09b612013-03-11 22:11:519832 LOCAL_SET_GL_ERROR(
9833 GL_INVALID_OPERATION,
9834 "glProduceTextureCHROMIUM", "invalid texture");
[email protected]78b514b2012-05-01 21:50:599835 return;
9836 }
9837
9838 if (!group_->mailbox_manager()->ProduceTexture(
9839 target,
9840 *reinterpret_cast<const MailboxName*>(mailbox),
[email protected]62e65f02013-05-29 22:28:109841 produced)) {
[email protected]ab09b612013-03-11 22:11:519842 LOCAL_SET_GL_ERROR(
9843 GL_INVALID_OPERATION,
9844 "glProduceTextureCHROMIUM", "invalid mailbox name");
[email protected]78b514b2012-05-01 21:50:599845 return;
9846 }
[email protected]78b514b2012-05-01 21:50:599847}
9848
9849void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
9850 const GLbyte* mailbox) {
[email protected]987b9c02013-03-23 00:58:029851 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
[email protected]1d82e822013-04-10 21:32:329852 "context", logger_.GetLogPrefix(),
[email protected]987b9c02013-03-23 00:58:029853 "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
9854
[email protected]62e65f02013-05-29 22:28:109855 scoped_refptr<TextureRef> texture_ref =
[email protected]c986af502013-08-14 01:04:449856 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
[email protected]7cd76fd2013-06-02 21:11:119857 if (!texture_ref.get()) {
9858 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9859 "glConsumeTextureCHROMIUM",
9860 "unknown texture for target");
[email protected]78b514b2012-05-01 21:50:599861 return;
9862 }
[email protected]62e65f02013-05-29 22:28:109863 GLuint client_id = texture_ref->client_id();
9864 if (!client_id) {
9865 LOCAL_SET_GL_ERROR(
9866 GL_INVALID_OPERATION,
9867 "glConsumeTextureCHROMIUM", "unknown texture for target");
9868 return;
9869 }
9870 Texture* texture =
[email protected]78b514b2012-05-01 21:50:599871 group_->mailbox_manager()->ConsumeTexture(
9872 target,
[email protected]62e65f02013-05-29 22:28:109873 *reinterpret_cast<const MailboxName*>(mailbox));
9874 if (!texture) {
[email protected]ab09b612013-03-11 22:11:519875 LOCAL_SET_GL_ERROR(
9876 GL_INVALID_OPERATION,
9877 "glConsumeTextureCHROMIUM", "invalid mailbox name");
[email protected]78b514b2012-05-01 21:50:599878 return;
9879 }
[email protected]62e65f02013-05-29 22:28:109880 if (texture->target() != target) {
[email protected]ab09b612013-03-11 22:11:519881 LOCAL_SET_GL_ERROR(
9882 GL_INVALID_OPERATION,
[email protected]62e65f02013-05-29 22:28:109883 "glConsumeTextureCHROMIUM", "invalid target");
[email protected]78b514b2012-05-01 21:50:599884 return;
9885 }
[email protected]62e65f02013-05-29 22:28:109886
9887 DeleteTexturesHelper(1, &client_id);
9888 texture_ref = texture_manager()->Consume(client_id, texture);
9889 glBindTexture(target, texture_ref->service_id());
9890
9891 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
9892 unit.bind_target = target;
9893 switch (target) {
9894 case GL_TEXTURE_2D:
9895 unit.bound_texture_2d = texture_ref;
9896 break;
9897 case GL_TEXTURE_CUBE_MAP:
9898 unit.bound_texture_cube_map = texture_ref;
9899 break;
9900 case GL_TEXTURE_EXTERNAL_OES:
9901 unit.bound_texture_external_oes = texture_ref;
9902 break;
9903 case GL_TEXTURE_RECTANGLE_ARB:
9904 unit.bound_texture_rectangle_arb = texture_ref;
9905 break;
9906 default:
9907 NOTREACHED(); // Validation should prevent us getting here.
9908 break;
9909 }
[email protected]78b514b2012-05-01 21:50:599910}
9911
[email protected]d2a0e1a2012-08-12 02:25:019912void GLES2DecoderImpl::DoInsertEventMarkerEXT(
9913 GLsizei length, const GLchar* marker) {
9914 if (!marker) {
9915 marker = "";
9916 }
9917 debug_marker_manager_.SetMarker(
9918 length ? std::string(marker, length) : std::string(marker));
9919}
9920
9921void GLES2DecoderImpl::DoPushGroupMarkerEXT(
9922 GLsizei length, const GLchar* marker) {
9923 if (!marker) {
9924 marker = "";
9925 }
9926 debug_marker_manager_.PushGroup(
9927 length ? std::string(marker, length) : std::string(marker));
9928}
9929
9930void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
9931 debug_marker_manager_.PopGroup();
9932}
9933
[email protected]09d50362012-10-18 20:54:379934void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
9935 GLenum target, GLint image_id) {
9936 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
9937 if (target != GL_TEXTURE_2D) {
9938 // This might be supported in the future.
[email protected]ab09b612013-03-11 22:11:519939 LOCAL_SET_GL_ERROR(
[email protected]09d50362012-10-18 20:54:379940 GL_INVALID_OPERATION,
9941 "glBindTexImage2DCHROMIUM", "requires TEXTURE_2D target");
9942 return;
9943 }
9944
9945 // Default target might be conceptually valid, but disallow it to avoid
9946 // accidents.
[email protected]c986af502013-08-14 01:04:449947 TextureRef* texture_ref =
9948 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
[email protected]370eaf12013-05-18 09:19:499949 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519950 LOCAL_SET_GL_ERROR(
9951 GL_INVALID_OPERATION,
9952 "glBindTexImage2DCHROMIUM", "no texture bound");
[email protected]09d50362012-10-18 20:54:379953 return;
9954 }
9955
9956 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
9957 if (!gl_image) {
[email protected]ab09b612013-03-11 22:11:519958 LOCAL_SET_GL_ERROR(
9959 GL_INVALID_OPERATION,
9960 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
[email protected]09d50362012-10-18 20:54:379961 return;
9962 }
9963
[email protected]b8160812013-04-09 00:41:049964 {
9965 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:309966 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
[email protected]b8160812013-04-09 00:41:049967 if (!gl_image->BindTexImage()) {
9968 LOCAL_SET_GL_ERROR(
9969 GL_INVALID_OPERATION,
9970 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
9971 return;
9972 }
[email protected]09d50362012-10-18 20:54:379973 }
9974
9975 gfx::Size size = gl_image->GetSize();
9976 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:499977 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
[email protected]09d50362012-10-18 20:54:379978 GL_RGBA, GL_UNSIGNED_BYTE, true);
[email protected]370eaf12013-05-18 09:19:499979 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
[email protected]09d50362012-10-18 20:54:379980}
9981
9982void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
9983 GLenum target, GLint image_id) {
9984 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
9985 if (target != GL_TEXTURE_2D) {
9986 // This might be supported in the future.
[email protected]ab09b612013-03-11 22:11:519987 LOCAL_SET_GL_ERROR(
[email protected]09d50362012-10-18 20:54:379988 GL_INVALID_OPERATION,
9989 "glReleaseTexImage2DCHROMIUM", "requires TEXTURE_2D target");
9990 return;
9991 }
9992
9993 // Default target might be conceptually valid, but disallow it to avoid
9994 // accidents.
[email protected]c986af502013-08-14 01:04:449995 TextureRef* texture_ref =
9996 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
[email protected]370eaf12013-05-18 09:19:499997 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519998 LOCAL_SET_GL_ERROR(
9999 GL_INVALID_OPERATION,
10000 "glReleaseTexImage2DCHROMIUM", "no texture bound");
[email protected]09d50362012-10-18 20:54:3710001 return;
10002 }
10003
10004 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10005 if (!gl_image) {
[email protected]ab09b612013-03-11 22:11:5110006 LOCAL_SET_GL_ERROR(
10007 GL_INVALID_OPERATION,
10008 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
[email protected]09d50362012-10-18 20:54:3710009 return;
10010 }
10011
10012 // Do nothing when image is not currently bound.
[email protected]370eaf12013-05-18 09:19:4910013 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
[email protected]09d50362012-10-18 20:54:3710014 return;
10015
[email protected]b8160812013-04-09 00:41:0410016 {
10017 ScopedGLErrorSuppressor suppressor(
[email protected]40621eb52013-10-08 15:40:3010018 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
[email protected]b8160812013-04-09 00:41:0410019 gl_image->ReleaseTexImage();
10020 }
[email protected]09d50362012-10-18 20:54:3710021
10022 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:4910023 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
[email protected]09d50362012-10-18 20:54:3710024 GL_RGBA, GL_UNSIGNED_BYTE, false);
10025}
[email protected]d2a0e1a2012-08-12 02:25:0110026
[email protected]94307712012-11-16 23:26:1110027error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:3510028 uint32 immediate_data_size, const cmds::TraceBeginCHROMIUM& c) {
[email protected]94307712012-11-16 23:26:1110029 Bucket* bucket = GetBucket(c.bucket_id);
10030 if (!bucket || bucket->size() == 0) {
10031 return error::kInvalidArguments;
10032 }
10033 std::string command_name;
10034 if (!bucket->GetAsString(&command_name)) {
10035 return error::kInvalidArguments;
10036 }
[email protected]fb97b662013-02-20 23:02:1410037 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
10038 if (!gpu_tracer_->Begin(command_name)) {
[email protected]ab09b612013-03-11 22:11:5110039 LOCAL_SET_GL_ERROR(
10040 GL_INVALID_OPERATION,
10041 "glTraceBeginCHROMIUM", "unable to create begin trace");
[email protected]fb97b662013-02-20 23:02:1410042 return error::kNoError;
10043 }
[email protected]94307712012-11-16 23:26:1110044 return error::kNoError;
10045}
10046
10047void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
[email protected]fb97b662013-02-20 23:02:1410048 if (gpu_tracer_->CurrentName().empty()) {
[email protected]ab09b612013-03-11 22:11:5110049 LOCAL_SET_GL_ERROR(
10050 GL_INVALID_OPERATION,
10051 "glTraceEndCHROMIUM", "no trace begin found");
[email protected]94307712012-11-16 23:26:1110052 return;
10053 }
[email protected]fb97b662013-02-20 23:02:1410054 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
10055 gpu_tracer_->End();
[email protected]94307712012-11-16 23:26:1110056}
10057
[email protected]2f143d482013-03-14 18:04:4910058void GLES2DecoderImpl::DoDrawBuffersEXT(
10059 GLsizei count, const GLenum* bufs) {
10060 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
10061 LOCAL_SET_GL_ERROR(
10062 GL_INVALID_VALUE,
10063 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10064 return;
10065 }
10066
10067 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
10068 if (framebuffer) {
10069 for (GLsizei i = 0; i < count; ++i) {
10070 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
10071 bufs[i] != GL_NONE) {
10072 LOCAL_SET_GL_ERROR(
10073 GL_INVALID_OPERATION,
10074 "glDrawBuffersEXT",
10075 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10076 return;
10077 }
10078 }
10079 glDrawBuffersARB(count, bufs);
10080 framebuffer->SetDrawBuffers(count, bufs);
10081 } else { // backbuffer
10082 if (count > 1 ||
10083 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
10084 LOCAL_SET_GL_ERROR(
10085 GL_INVALID_OPERATION,
10086 "glDrawBuffersEXT",
10087 "more than one buffer or bufs not GL_NONE or GL_BACK");
10088 return;
10089 }
10090 GLenum mapped_buf = bufs[0];
10091 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10092 bufs[0] == GL_BACK) {
10093 mapped_buf = GL_COLOR_ATTACHMENT0;
10094 }
10095 glDrawBuffersARB(count, &mapped_buf);
10096 group_->set_draw_buffer(bufs[0]);
10097 }
10098}
10099
[email protected]32145a92012-12-17 09:01:5910100bool GLES2DecoderImpl::ValidateAsyncTransfer(
10101 const char* function_name,
[email protected]85a4ac22013-05-31 01:58:4710102 TextureRef* texture_ref,
[email protected]32145a92012-12-17 09:01:5910103 GLenum target,
10104 GLint level,
10105 const void * data) {
10106 // We only support async uploads to 2D textures for now.
10107 if (GL_TEXTURE_2D != target) {
[email protected]ab09b612013-03-11 22:11:5110108 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
[email protected]32145a92012-12-17 09:01:5910109 return false;
10110 }
10111 // We only support uploads to level zero for now.
10112 if (level != 0) {
[email protected]ab09b612013-03-11 22:11:5110113 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
[email protected]32145a92012-12-17 09:01:5910114 return false;
10115 }
10116 // A transfer buffer must be bound, even for asyncTexImage2D.
10117 if (data == NULL) {
[email protected]ab09b612013-03-11 22:11:5110118 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
[email protected]32145a92012-12-17 09:01:5910119 return false;
10120 }
10121 // We only support one async transfer in progress.
[email protected]85a4ac22013-05-31 01:58:4710122 if (!texture_ref ||
10123 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
[email protected]ab09b612013-03-11 22:11:5110124 LOCAL_SET_GL_ERROR(
10125 GL_INVALID_OPERATION,
[email protected]32145a92012-12-17 09:01:5910126 function_name, "transfer already in progress");
10127 return false;
10128 }
10129 return true;
10130}
10131
[email protected]69023942012-11-30 19:57:1610132error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:3510133 uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) {
[email protected]69023942012-11-30 19:57:1610134 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
[email protected]69023942012-11-30 19:57:1610135 GLenum target = static_cast<GLenum>(c.target);
10136 GLint level = static_cast<GLint>(c.level);
[email protected]c986af502013-08-14 01:04:4410137 // TODO(kloveless): Change HandleAsyncTexImage2DCHROMIUM command to use
10138 // unsigned integer for internalformat.
10139 GLenum internal_format = static_cast<GLenum>(c.internalformat);
[email protected]69023942012-11-30 19:57:1610140 GLsizei width = static_cast<GLsizei>(c.width);
10141 GLsizei height = static_cast<GLsizei>(c.height);
10142 GLint border = static_cast<GLint>(c.border);
10143 GLenum format = static_cast<GLenum>(c.format);
10144 GLenum type = static_cast<GLenum>(c.type);
10145 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10146 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10147 uint32 pixels_size;
[email protected]32145a92012-12-17 09:01:5910148
10149 // TODO(epenner): Move this and copies of this memory validation
10150 // into ValidateTexImage2D step.
[email protected]69023942012-11-30 19:57:1610151 if (!GLES2Util::ComputeImageDataSizes(
10152 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
10153 NULL)) {
10154 return error::kOutOfBounds;
10155 }
10156 const void* pixels = NULL;
10157 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10158 pixels = GetSharedMemoryAs<const void*>(
10159 pixels_shm_id, pixels_shm_offset, pixels_size);
10160 if (!pixels) {
10161 return error::kOutOfBounds;
10162 }
10163 }
10164
[email protected]c986af502013-08-14 01:04:4410165 TextureManager::DoTextImage2DArguments args = {
10166 target, level, internal_format, width, height, border, format, type,
10167 pixels, pixels_size};
10168 TextureRef* texture_ref;
[email protected]32145a92012-12-17 09:01:5910169 // All the normal glTexSubImage2D validation.
[email protected]c986af502013-08-14 01:04:4410170 if (!texture_manager()->ValidateTexImage2D(
10171 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
[email protected]32145a92012-12-17 09:01:5910172 return error::kNoError;
10173 }
10174
10175 // Extra async validation.
[email protected]370eaf12013-05-18 09:19:4910176 Texture* texture = texture_ref->texture();
[email protected]32145a92012-12-17 09:01:5910177 if (!ValidateAsyncTransfer(
[email protected]85a4ac22013-05-31 01:58:4710178 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
[email protected]32145a92012-12-17 09:01:5910179 return error::kNoError;
10180
10181 // Don't allow async redefinition of a textures.
[email protected]02965c22013-03-09 02:40:0710182 if (texture->IsDefined()) {
[email protected]ab09b612013-03-11 22:11:5110183 LOCAL_SET_GL_ERROR(
10184 GL_INVALID_OPERATION,
[email protected]32145a92012-12-17 09:01:5910185 "glAsyncTexImage2DCHROMIUM", "already defined");
10186 return error::kNoError;
10187 }
10188
[email protected]7989c9e2013-01-23 06:39:2610189 if (!EnsureGPUMemoryAvailable(pixels_size)) {
[email protected]ab09b612013-03-11 22:11:5110190 LOCAL_SET_GL_ERROR(
10191 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
[email protected]7989c9e2013-01-23 06:39:2610192 return error::kNoError;
10193 }
10194
[email protected]32145a92012-12-17 09:01:5910195 // We know the memory/size is safe, so get the real shared memory since
10196 // it might need to be duped to prevent use-after-free of the memory.
[email protected]16ccec12013-02-28 03:40:2110197 gpu::Buffer buffer = GetSharedMemoryBuffer(c.pixels_shm_id);
[email protected]32145a92012-12-17 09:01:5910198 base::SharedMemory* shared_memory = buffer.shared_memory;
10199 uint32 shm_size = buffer.size;
10200 uint32 shm_data_offset = c.pixels_shm_offset;
10201 uint32 shm_data_size = pixels_size;
10202
[email protected]5b3a8e02013-03-13 05:36:4410203 // Setup the parameters.
[email protected]8f1d2aa2013-05-10 23:45:3810204 AsyncTexImage2DParams tex_params = {
10205 target, level, static_cast<GLenum>(internal_format),
10206 width, height, border, format, type};
10207 AsyncMemoryParams mem_params = {
10208 shared_memory, shm_size, shm_data_offset, shm_data_size};
[email protected]32145a92012-12-17 09:01:5910209
[email protected]5b3a8e02013-03-13 05:36:4410210 // Set up the async state if needed, and make the texture
10211 // immutable so the async state stays valid. The level info
10212 // is set up lazily when the transfer completes.
[email protected]896425e2013-06-12 17:27:1810213 AsyncPixelTransferDelegate* delegate =
10214 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
10215 tex_params);
[email protected]5b3a8e02013-03-13 05:36:4410216 texture->SetImmutable(true);
[email protected]32145a92012-12-17 09:01:5910217
[email protected]896425e2013-06-12 17:27:1810218 delegate->AsyncTexImage2D(
[email protected]5b3a8e02013-03-13 05:36:4410219 tex_params,
10220 mem_params,
10221 base::Bind(&TextureManager::SetLevelInfoFromParams,
[email protected]370eaf12013-05-18 09:19:4910222 // The callback is only invoked if the transfer delegate still
10223 // exists, which implies through manager->texture_ref->state
[email protected]5b3a8e02013-03-13 05:36:4410224 // ownership that both of these pointers are valid.
10225 base::Unretained(texture_manager()),
[email protected]370eaf12013-05-18 09:19:4910226 base::Unretained(texture_ref),
[email protected]5b3a8e02013-03-13 05:36:4410227 tex_params));
[email protected]f598f422012-12-07 08:30:0310228 return error::kNoError;
[email protected]69023942012-11-30 19:57:1610229}
10230
10231error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:3510232 uint32 immediate_data_size, const cmds::AsyncTexSubImage2DCHROMIUM& c) {
[email protected]69023942012-11-30 19:57:1610233 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
[email protected]69023942012-11-30 19:57:1610234 GLenum target = static_cast<GLenum>(c.target);
10235 GLint level = static_cast<GLint>(c.level);
10236 GLint xoffset = static_cast<GLint>(c.xoffset);
10237 GLint yoffset = static_cast<GLint>(c.yoffset);
10238 GLsizei width = static_cast<GLsizei>(c.width);
10239 GLsizei height = static_cast<GLsizei>(c.height);
10240 GLenum format = static_cast<GLenum>(c.format);
10241 GLenum type = static_cast<GLenum>(c.type);
[email protected]32145a92012-12-17 09:01:5910242
10243 // TODO(epenner): Move this and copies of this memory validation
10244 // into ValidateTexSubImage2D step.
[email protected]69023942012-11-30 19:57:1610245 uint32 data_size;
10246 if (!GLES2Util::ComputeImageDataSizes(
10247 width, height, format, type, state_.unpack_alignment, &data_size,
10248 NULL, NULL)) {
10249 return error::kOutOfBounds;
10250 }
10251 const void* pixels = GetSharedMemoryAs<const void*>(
10252 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]32145a92012-12-17 09:01:5910253
10254 // All the normal glTexSubImage2D validation.
10255 error::Error error = error::kNoError;
10256 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
10257 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
10258 return error;
[email protected]69023942012-11-30 19:57:1610259 }
10260
[email protected]32145a92012-12-17 09:01:5910261 // Extra async validation.
[email protected]c986af502013-08-14 01:04:4410262 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10263 &state_, target);
[email protected]370eaf12013-05-18 09:19:4910264 Texture* texture = texture_ref->texture();
[email protected]32145a92012-12-17 09:01:5910265 if (!ValidateAsyncTransfer(
[email protected]85a4ac22013-05-31 01:58:4710266 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
[email protected]32145a92012-12-17 09:01:5910267 return error::kNoError;
10268
10269 // Guarantee async textures are always 'cleared' as follows:
10270 // - AsyncTexImage2D can not redefine an existing texture
10271 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10272 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10273 // - Textures become immutable after an async call.
10274 // This way we know in all cases that an async texture is always clear.
[email protected]02965c22013-03-09 02:40:0710275 if (!texture->SafeToRenderFrom()) {
[email protected]370eaf12013-05-18 09:19:4910276 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10277 target, level)) {
[email protected]ab09b612013-03-11 22:11:5110278 LOCAL_SET_GL_ERROR(
10279 GL_OUT_OF_MEMORY,
[email protected]b04e24c2013-01-08 18:35:2510280 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
[email protected]32145a92012-12-17 09:01:5910281 return error::kNoError;
10282 }
10283 }
10284
10285 // We know the memory/size is safe, so get the real shared memory since
10286 // it might need to be duped to prevent use-after-free of the memory.
[email protected]16ccec12013-02-28 03:40:2110287 gpu::Buffer buffer = GetSharedMemoryBuffer(c.data_shm_id);
[email protected]32145a92012-12-17 09:01:5910288 base::SharedMemory* shared_memory = buffer.shared_memory;
10289 uint32 shm_size = buffer.size;
10290 uint32 shm_data_offset = c.data_shm_offset;
10291 uint32 shm_data_size = data_size;
10292
[email protected]5b3a8e02013-03-13 05:36:4410293 // Setup the parameters.
[email protected]2a7568a2013-05-09 23:12:0310294 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
[email protected]32145a92012-12-17 09:01:5910295 width, height, format, type};
[email protected]2a7568a2013-05-09 23:12:0310296 AsyncMemoryParams mem_params = {shared_memory, shm_size,
[email protected]32145a92012-12-17 09:01:5910297 shm_data_offset, shm_data_size};
[email protected]896425e2013-06-12 17:27:1810298 AsyncPixelTransferDelegate* delegate =
10299 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10300 if (!delegate) {
[email protected]5b3a8e02013-03-13 05:36:4410301 // TODO(epenner): We may want to enforce exclusive use
10302 // of async APIs in which case this should become an error,
10303 // (the texture should have been async defined).
[email protected]2a7568a2013-05-09 23:12:0310304 AsyncTexImage2DParams define_params = {target, level,
[email protected]5b3a8e02013-03-13 05:36:4410305 0, 0, 0, 0, 0, 0};
10306 texture->GetLevelSize(target, level, &define_params.width,
10307 &define_params.height);
10308 texture->GetLevelType(target, level, &define_params.type,
10309 &define_params.internal_format);
10310 // Set up the async state if needed, and make the texture
10311 // immutable so the async state stays valid.
[email protected]896425e2013-06-12 17:27:1810312 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
[email protected]85a4ac22013-05-31 01:58:4710313 texture_ref, define_params);
[email protected]5b3a8e02013-03-13 05:36:4410314 texture->SetImmutable(true);
10315 }
10316
[email protected]896425e2013-06-12 17:27:1810317 delegate->AsyncTexSubImage2D(tex_params, mem_params);
[email protected]32145a92012-12-17 09:01:5910318 return error::kNoError;
[email protected]69023942012-11-30 19:57:1610319}
10320
[email protected]a00c1f742013-03-05 17:02:1610321error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10322 uint32 immediate_data_size, const cmds::WaitAsyncTexImage2DCHROMIUM& c) {
10323 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10324 GLenum target = static_cast<GLenum>(c.target);
10325
10326 if (GL_TEXTURE_2D != target) {
[email protected]ab09b612013-03-11 22:11:5110327 LOCAL_SET_GL_ERROR(
10328 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
[email protected]a00c1f742013-03-05 17:02:1610329 return error::kNoError;
10330 }
[email protected]c986af502013-08-14 01:04:4410331 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10332 &state_, target);
[email protected]370eaf12013-05-18 09:19:4910333 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:5110334 LOCAL_SET_GL_ERROR(
10335 GL_INVALID_OPERATION,
10336 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
[email protected]a00c1f742013-03-05 17:02:1610337 return error::kNoError;
10338 }
[email protected]896425e2013-06-12 17:27:1810339 AsyncPixelTransferDelegate* delegate =
10340 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10341 if (!delegate) {
[email protected]370eaf12013-05-18 09:19:4910342 LOCAL_SET_GL_ERROR(
10343 GL_INVALID_OPERATION,
10344 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10345 return error::kNoError;
10346 }
[email protected]896425e2013-06-12 17:27:1810347 delegate->WaitForTransferCompletion();
[email protected]69a8701e2013-03-07 21:31:0910348 ProcessFinishedAsyncTransfers();
[email protected]a00c1f742013-03-05 17:02:1610349 return error::kNoError;
10350}
10351
[email protected]96449d2c2009-11-25 00:01:3210352// Include the auto-generated part of this file. We split this because it means
10353// we can easily edit the non-auto generated parts right here in this file
10354// instead of having to edit some template or the code generator.
10355#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
10356
10357} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:2510358} // namespace gpu