blob: 8914a8470e29ea43395bfb57375cde79a2212aeb [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]0f8afe82012-05-14 23:43:0125#include "base/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
28#include "gpu/command_buffer/common/gles2_cmd_format.h"
29#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]d2a0e1a2012-08-12 02:25:0130#include "gpu/command_buffer/common/debug_marker_manager.h"
[email protected]066849e32010-05-03 19:14:1031#include "gpu/command_buffer/common/id_allocator.h"
[email protected]3916c97e2010-02-25 03:20:5032#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3233#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5034#include "gpu/command_buffer/service/context_group.h"
[email protected]e259eb412012-10-13 05:47:2435#include "gpu/command_buffer/service/context_state.h"
[email protected]915a59a12010-09-30 21:29:1136#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5837#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3238#include "gpu/command_buffer/service/gl_utils.h"
[email protected]43410e92012-04-20 17:06:2839#include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
[email protected]ba3176a2009-12-16 18:19:4640#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]e844ae22012-01-14 03:36:2641#include "gpu/command_buffer/service/gpu_switches.h"
[email protected]94307712012-11-16 23:26:1142#include "gpu/command_buffer/service/gpu_trace.h"
[email protected]09d50362012-10-18 20:54:3743#include "gpu/command_buffer/service/image_manager.h"
[email protected]78b514b2012-05-01 21:50:5944#include "gpu/command_buffer/service/mailbox_manager.h"
[email protected]ff6493f2012-07-31 19:52:2545#include "gpu/command_buffer/service/memory_tracking.h"
[email protected]a93bb842010-02-16 23:03:4746#include "gpu/command_buffer/service/program_manager.h"
[email protected]882ba1e22012-03-08 19:02:5347#include "gpu/command_buffer/service/query_manager.h"
[email protected]a25fa872010-03-25 02:57:5848#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4749#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4550#include "gpu/command_buffer/service/shader_translator.h"
[email protected]87fb6ab2012-06-13 22:28:0451#include "gpu/command_buffer/service/shader_translator_cache.h"
[email protected]b0af4f52011-09-28 22:04:4252#include "gpu/command_buffer/service/stream_texture.h"
53#include "gpu/command_buffer/service/stream_texture_manager.h"
[email protected]78b514b2012-05-01 21:50:5954#include "gpu/command_buffer/service/texture_definition.h"
[email protected]a93bb842010-02-16 23:03:4755#include "gpu/command_buffer/service/texture_manager.h"
[email protected]d8ea9772011-07-11 18:11:4356#include "gpu/command_buffer/service/vertex_attrib_manager.h"
[email protected]944b62f32012-09-27 02:20:4657#include "gpu/command_buffer/service/vertex_array_manager.h"
[email protected]09d50362012-10-18 20:54:3758#include "ui/gl/gl_image.h"
[email protected]c9e2cbbb2012-05-12 21:17:2759#include "ui/gl/gl_implementation.h"
60#include "ui/gl/gl_surface.h"
[email protected]e51bdf32011-11-23 22:21:4661#if defined(OS_MACOSX)
[email protected]d353541f2012-05-03 22:45:4162#include "ui/surface/io_surface_support_mac.h"
[email protected]e51bdf32011-11-23 22:21:4663#endif
[email protected]de17df392010-04-23 21:09:4164
[email protected]6217d392010-03-25 22:08:3565#if !defined(GL_DEPTH24_STENCIL8)
66#define GL_DEPTH24_STENCIL8 0x88F0
67#endif
68
[email protected]693ca512012-11-13 18:09:1369// TODO(zmo): we can't include "City.h" due to type def conflicts.
70extern uint64 CityHash64(const char*, size_t);
71
[email protected]a7a27ace2009-12-12 00:11:2572namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3273namespace gles2 {
74
[email protected]f0d74742011-10-03 16:31:0475namespace {
[email protected]693ca512012-11-13 18:09:1376
[email protected]f0d74742011-10-03 16:31:0477static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
[email protected]693ca512012-11-13 18:09:1378
79khronos_uint64_t CityHashForAngle(const char* name, unsigned int len) {
80 return static_cast<khronos_uint64_t>(
81 CityHash64(name, static_cast<size_t>(len)));
82}
83
[email protected]f0d74742011-10-03 16:31:0484}
85
[email protected]6217d392010-03-25 22:08:3586class GLES2DecoderImpl;
87
[email protected]07f54fcc2009-12-22 02:46:3088// Check that certain assumptions the code makes are true. There are places in
89// the code where shared memory is passed direclty to GL. Example, glUniformiv,
90// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
91// a few others) are 32bits. If they are not 32bits the code will have to change
92// to call those GL functions with service side memory and then copy the results
93// to shared memory, converting the sizes.
94COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
95 GLint_not_same_size_as_uint32);
96COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
97 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3798COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
99 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:30100
[email protected]43f28f832010-02-03 02:28:48101// TODO(kbr): the use of this anonymous namespace core dumps the
102// linker on Mac OS X 10.6 when the symbol ordering file is used
103// namespace {
[email protected]96449d2c2009-11-25 00:01:32104
105// Returns the address of the first byte after a struct.
106template <typename T>
107const void* AddressAfterStruct(const T& pod) {
108 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
109}
110
[email protected]07f54fcc2009-12-22 02:46:30111// Returns the address of the frst byte after the struct or NULL if size >
112// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:32113template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:30114RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
115 uint32 size,
116 uint32 immediate_data_size) {
117 return (size <= immediate_data_size) ?
118 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
119 NULL;
[email protected]96449d2c2009-11-25 00:01:32120}
121
[email protected]07f54fcc2009-12-22 02:46:30122// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:18123bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:32124 GLuint count,
125 size_t size,
[email protected]a76b0052010-03-05 00:33:18126 unsigned int elements_per_unit,
127 uint32* dst) {
128 uint32 value;
129 if (!SafeMultiplyUint32(count, size, &value)) {
130 return false;
131 }
132 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
133 return false;
134 }
135 *dst = value;
136 return true;
[email protected]96449d2c2009-11-25 00:01:32137}
138
139// A struct to hold info about each command.
140struct CommandInfo {
141 int arg_flags; // How to handle the arguments for this command
142 int arg_count; // How many arguments are expected for this command.
143};
144
145// A table of CommandInfo for all the commands.
146const CommandInfo g_command_info[] = {
147 #define GLES2_CMD_OP(name) { \
148 name::kArgFlags, \
149 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
150
151 GLES2_COMMAND_LIST(GLES2_CMD_OP)
152
153 #undef GLES2_CMD_OP
154};
155
[email protected]258a3313f2011-10-18 20:13:57156// Return true if a character belongs to the ASCII subset as defined in
157// GLSL ES 1.0 spec section 3.1.
158static bool CharacterIsValidForGLES(unsigned char c) {
159 // Printing characters are valid except " $ ` @ \ ' DEL.
160 if (c >= 32 && c <= 126 &&
161 c != '"' &&
162 c != '$' &&
163 c != '`' &&
164 c != '@' &&
165 c != '\\' &&
166 c != '\'') {
167 return true;
168 }
169 // Horizontal tab, line feed, vertical tab, form feed, carriage return
170 // are also valid.
171 if (c >= 9 && c <= 13) {
172 return true;
173 }
174
175 return false;
176}
177
178static bool StringIsValidForGLES(const char* str) {
179 for (; *str; ++str) {
180 if (!CharacterIsValidForGLES(*str)) {
181 return false;
182 }
183 }
184 return true;
185}
186
[email protected]f0e6a34f2012-01-04 20:53:40187static inline GLenum GetTexInternalFormat(GLenum internal_format) {
188 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
189 if (internal_format == GL_BGRA_EXT || internal_format == GL_BGRA8_EXT)
190 return GL_RGBA8;
191 }
192 return internal_format;
193}
194
[email protected]297ca1c2011-06-20 23:08:46195static void WrappedTexImage2D(
[email protected]473c01ccb2011-06-07 01:33:30196 GLenum target,
197 GLint level,
198 GLenum internal_format,
199 GLsizei width,
200 GLsizei height,
201 GLint border,
202 GLenum format,
203 GLenum type,
204 const void* pixels) {
[email protected]f0e6a34f2012-01-04 20:53:40205 GLenum gl_internal_format = GetTexInternalFormat(internal_format);
[email protected]473c01ccb2011-06-07 01:33:30206 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]f0e6a34f2012-01-04 20:53:40207 if (type == GL_FLOAT) {
[email protected]58b75f92012-03-20 21:15:43208 switch (format) {
209 case GL_RGBA:
210 gl_internal_format = GL_RGBA32F_ARB;
211 break;
212 case GL_RGB:
213 gl_internal_format = GL_RGB32F_ARB;
214 break;
215 case GL_LUMINANCE_ALPHA:
216 gl_internal_format = GL_LUMINANCE_ALPHA32F_ARB;
217 break;
218 case GL_LUMINANCE:
219 gl_internal_format = GL_LUMINANCE32F_ARB;
220 break;
221 case GL_ALPHA:
222 gl_internal_format = GL_ALPHA32F_ARB;
223 break;
224 default:
225 NOTREACHED();
226 break;
[email protected]473c01ccb2011-06-07 01:33:30227 }
228 } else if (type == GL_HALF_FLOAT_OES) {
[email protected]58b75f92012-03-20 21:15:43229 switch (format) {
230 case GL_RGBA:
231 gl_internal_format = GL_RGBA16F_ARB;
232 break;
233 case GL_RGB:
234 gl_internal_format = GL_RGB16F_ARB;
235 break;
236 case GL_LUMINANCE_ALPHA:
237 gl_internal_format = GL_LUMINANCE_ALPHA16F_ARB;
238 break;
239 case GL_LUMINANCE:
240 gl_internal_format = GL_LUMINANCE16F_ARB;
241 break;
242 case GL_ALPHA:
243 gl_internal_format = GL_ALPHA16F_ARB;
244 break;
245 default:
246 NOTREACHED();
247 break;
[email protected]473c01ccb2011-06-07 01:33:30248 }
249 }
250 }
251 glTexImage2D(
252 target, level, gl_internal_format, width, height, border, format, type,
253 pixels);
254}
255
[email protected]297ca1c2011-06-20 23:08:46256// Wrapper for glEnable/glDisable that doesn't suck.
257static void EnableDisable(GLenum pname, bool enable) {
258 if (enable) {
259 glEnable(pname);
260 } else {
261 glDisable(pname);
262 }
263}
264
[email protected]6217d392010-03-25 22:08:35265// This class prevents any GL errors that occur when it is in scope from
266// being reported to the client.
267class ScopedGLErrorSuppressor {
268 public:
269 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
270 ~ScopedGLErrorSuppressor();
271 private:
272 GLES2DecoderImpl* decoder_;
273 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
274};
275
276// Temporarily changes a decoder's bound 2D texture and restore it when this
277// object goes out of scope. Also temporarily switches to using active texture
278// unit zero in case the client has changed that to something invalid.
279class ScopedTexture2DBinder {
280 public:
281 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
282 ~ScopedTexture2DBinder();
283
284 private:
285 GLES2DecoderImpl* decoder_;
286 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
287};
288
289// Temporarily changes a decoder's bound render buffer and restore it when this
290// object goes out of scope.
291class ScopedRenderBufferBinder {
292 public:
293 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
294 ~ScopedRenderBufferBinder();
295
296 private:
297 GLES2DecoderImpl* decoder_;
298 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
299};
300
301// Temporarily changes a decoder's bound frame buffer and restore it when this
302// object goes out of scope.
303class ScopedFrameBufferBinder {
304 public:
305 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
306 ~ScopedFrameBufferBinder();
307
308 private:
309 GLES2DecoderImpl* decoder_;
310 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
311};
312
[email protected]34ff8b0c2010-10-01 20:06:02313// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52314// the multisampled offscreen render buffer if that buffer is multisampled, and,
[email protected]de26b3c2011-08-03 21:54:27315// if it is bound or enforce_internal_framebuffer is true. If internal is
316// true, the resolved framebuffer is not visible to the parent.
[email protected]34ff8b0c2010-10-01 20:06:02317class ScopedResolvedFrameBufferBinder {
318 public:
[email protected]e7e38032011-07-26 17:25:25319 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
[email protected]de26b3c2011-08-03 21:54:27320 bool enforce_internal_framebuffer,
321 bool internal);
[email protected]34ff8b0c2010-10-01 20:06:02322 ~ScopedResolvedFrameBufferBinder();
323
324 private:
325 GLES2DecoderImpl* decoder_;
326 bool resolve_and_bind_;
327 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
328};
329
[email protected]63b465922012-09-06 02:04:52330// This class records texture upload time when in scope.
331class ScopedTextureUploadTimer {
332 public:
333 explicit ScopedTextureUploadTimer(GLES2DecoderImpl* decoder);
334 ~ScopedTextureUploadTimer();
335
336 private:
337 GLES2DecoderImpl* decoder_;
338 base::TimeTicks begin_time_;
339 DISALLOW_COPY_AND_ASSIGN(ScopedTextureUploadTimer);
340};
341
[email protected]6217d392010-03-25 22:08:35342// Encapsulates an OpenGL texture.
343class Texture {
344 public:
345 explicit Texture(GLES2DecoderImpl* decoder);
346 ~Texture();
347
348 // Create a new render texture.
349 void Create();
350
351 // Set the initial size and format of a render texture or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02352 bool AllocateStorage(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35353
354 // Copy the contents of the currently bound frame buffer.
[email protected]3a4d0c52011-06-29 23:11:58355 void Copy(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35356
357 // Destroy the render texture. This must be explicitly called before
358 // destroying this object.
359 void Destroy();
360
[email protected]97872062010-11-03 19:07:05361 // Invalidate the texture. This can be used when a context is lost and it is
362 // not possible to make it current in order to free the resource.
363 void Invalidate();
364
[email protected]6217d392010-03-25 22:08:35365 GLuint id() const {
366 return id_;
367 }
368
[email protected]d37231fa2010-04-09 21:16:02369 gfx::Size size() const {
370 return size_;
371 }
372
[email protected]1078f912011-12-23 13:12:14373 size_t estimated_size() const {
[email protected]ff6493f2012-07-31 19:52:25374 return memory_tracker_.GetMemRepresented();
[email protected]1078f912011-12-23 13:12:14375 }
376
[email protected]6217d392010-03-25 22:08:35377 private:
378 GLES2DecoderImpl* decoder_;
[email protected]ff6493f2012-07-31 19:52:25379 MemoryTypeTracker memory_tracker_;
[email protected]6217d392010-03-25 22:08:35380 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02381 gfx::Size size_;
[email protected]6217d392010-03-25 22:08:35382 DISALLOW_COPY_AND_ASSIGN(Texture);
383};
384
385// Encapsulates an OpenGL render buffer of any format.
386class RenderBuffer {
387 public:
388 explicit RenderBuffer(GLES2DecoderImpl* decoder);
389 ~RenderBuffer();
390
391 // Create a new render buffer.
392 void Create();
393
394 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02395 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35396
397 // Destroy the render buffer. This must be explicitly called before destroying
398 // this object.
399 void Destroy();
400
[email protected]97872062010-11-03 19:07:05401 // Invalidate the render buffer. This can be used when a context is lost and
402 // it is not possible to make it current in order to free the resource.
403 void Invalidate();
404
[email protected]6217d392010-03-25 22:08:35405 GLuint id() const {
406 return id_;
407 }
408
[email protected]1078f912011-12-23 13:12:14409 size_t estimated_size() const {
[email protected]ff6493f2012-07-31 19:52:25410 return memory_tracker_.GetMemRepresented();
[email protected]1078f912011-12-23 13:12:14411 }
412
[email protected]6217d392010-03-25 22:08:35413 private:
414 GLES2DecoderImpl* decoder_;
[email protected]ff6493f2012-07-31 19:52:25415 MemoryTypeTracker memory_tracker_;
[email protected]6217d392010-03-25 22:08:35416 GLuint id_;
417 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
418};
419
420// Encapsulates an OpenGL frame buffer.
421class FrameBuffer {
422 public:
423 explicit FrameBuffer(GLES2DecoderImpl* decoder);
424 ~FrameBuffer();
425
426 // Create a new frame buffer.
427 void Create();
428
429 // Attach a color render buffer to a frame buffer.
430 void AttachRenderTexture(Texture* texture);
431
[email protected]b9363b22010-06-09 22:06:15432 // Attach a render buffer to a frame buffer. Note that this unbinds any
433 // currently bound frame buffer.
434 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35435
[email protected]6217d392010-03-25 22:08:35436 // Destroy the frame buffer. This must be explicitly called before destroying
437 // this object.
438 void Destroy();
439
[email protected]97872062010-11-03 19:07:05440 // Invalidate the frame buffer. This can be used when a context is lost and it
441 // is not possible to make it current in order to free the resource.
442 void Invalidate();
443
[email protected]6217d392010-03-25 22:08:35444 // See glCheckFramebufferStatusEXT.
445 GLenum CheckStatus();
446
447 GLuint id() const {
448 return id_;
449 }
450
451 private:
452 GLES2DecoderImpl* decoder_;
453 GLuint id_;
454 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
455};
[email protected]34ff8b0c2010-10-01 20:06:02456
[email protected]43f28f832010-02-03 02:28:48457// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32458
[email protected]ddb1e5a2010-12-13 20:10:45459bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
460 uint32* service_texture_id) {
461 return false;
462}
463
[email protected]a3ded6d2010-10-19 06:44:39464GLES2Decoder::GLES2Decoder()
[email protected]e844ae22012-01-14 03:36:26465 : debug_(false),
[email protected]b5d647c2012-02-10 01:41:32466 log_commands_(false),
467 log_synthesized_gl_errors_(true) {
[email protected]96449d2c2009-11-25 00:01:32468}
469
[email protected]3916c97e2010-02-25 03:20:50470GLES2Decoder::~GLES2Decoder() {
471}
472
[email protected]57edfdad2012-02-07 04:57:15473bool GLES2Decoder::testing_force_is_angle_;
474
475void GLES2Decoder::set_testing_force_is_angle(bool force) {
476 testing_force_is_angle_ = force;
477}
478
479bool GLES2Decoder::IsAngle() {
480#if defined(OS_WIN)
481 return testing_force_is_angle_ ||
482 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
483#else
484 return testing_force_is_angle_;
485#endif
486}
487
[email protected]f39f4b3f2010-05-12 17:04:08488// This class implements GLES2Decoder so we don't have to expose all the GLES2
489// cmd stuff to outside this class.
[email protected]ee1e6aa2012-11-29 09:24:10490class GLES2DecoderImpl : public GLES2Decoder {
[email protected]f39f4b3f2010-05-12 17:04:08491 public:
[email protected]0f8afe82012-05-14 23:43:01492 static const int kMaxLogMessages = 256;
[email protected]fa20ec82012-05-04 04:02:48493
[email protected]aa7666122011-09-02 19:45:52494 explicit GLES2DecoderImpl(ContextGroup* group);
[email protected]b8e97b62012-09-30 15:09:00495 virtual ~GLES2DecoderImpl();
[email protected]f39f4b3f2010-05-12 17:04:08496
[email protected]96449d2c2009-11-25 00:01:32497 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14498 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50499 unsigned int arg_count,
[email protected]b8e97b62012-09-30 15:09:00500 const void* args) OVERRIDE;
[email protected]96449d2c2009-11-25 00:01:32501
502 // Overridden from AsyncAPIInterface.
[email protected]b8e97b62012-09-30 15:09:00503 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
[email protected]96449d2c2009-11-25 00:01:32504
505 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38506 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
507 const scoped_refptr<gfx::GLContext>& context,
[email protected]069944672012-04-25 20:52:23508 bool offscreen,
[email protected]6217d392010-03-25 22:08:35509 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:29510 const DisallowedFeatures& disallowed_features,
[email protected]a3ded6d2010-10-19 06:44:39511 const char* allowed_extensions,
[email protected]b8e97b62012-09-30 15:09:00512 const std::vector<int32>& attribs) OVERRIDE;
513 virtual void Destroy(bool have_context) OVERRIDE;
[email protected]63c9b052012-05-17 18:27:38514 virtual void SetSurface(
515 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
[email protected]3c644d82011-06-20 19:58:24516 virtual bool SetParent(GLES2Decoder* parent_decoder,
[email protected]b8e97b62012-09-30 15:09:00517 uint32 parent_texture_id) OVERRIDE;
518 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
[email protected]9a5afa432011-07-22 18:16:39519 void UpdateParentTextureInfo();
[email protected]b8e97b62012-09-30 15:09:00520 virtual bool MakeCurrent() OVERRIDE;
521 virtual void ReleaseCurrent() OVERRIDE;
522 virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
523 virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
524 virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
[email protected]1868a342012-11-07 15:56:02525 virtual void RestoreState() const OVERRIDE;
[email protected]b8e97b62012-09-30 15:09:00526 virtual QueryManager* GetQueryManager() OVERRIDE {
527 return query_manager_.get();
528 }
529 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
[email protected]944b62f32012-09-27 02:20:46530 return vertex_array_manager_.get();
531 }
[email protected]b8e97b62012-09-30 15:09:00532 virtual bool ProcessPendingQueries() OVERRIDE;
[email protected]43f28f832010-02-03 02:28:48533
[email protected]b8e97b62012-09-30 15:09:00534 virtual void SetGLError(GLenum error,
535 const char* function_name,
536 const char* msg);
537 virtual void SetGLErrorInvalidEnum(const char* function_name,
538 GLenum value,
539 const char* label);
[email protected]9d37f062011-11-22 01:24:52540 virtual void SetResizeCallback(
[email protected]b8e97b62012-09-30 15:09:00541 const base::Callback<void(gfx::Size)>& callback) OVERRIDE;
[email protected]22f320a2011-08-30 01:17:00542
[email protected]b8e97b62012-09-30 15:09:00543 virtual void SetMsgCallback(const MsgCallback& callback) OVERRIDE;
[email protected]22f320a2011-08-30 01:17:00544
[email protected]b8e97b62012-09-30 15:09:00545 virtual void SetStreamTextureManager(StreamTextureManager* manager) OVERRIDE;
[email protected]1318e922010-09-17 22:03:16546 virtual bool GetServiceTextureId(uint32 client_texture_id,
[email protected]b8e97b62012-09-30 15:09:00547 uint32* service_texture_id) OVERRIDE;
[email protected]43f28f832010-02-03 02:28:48548
[email protected]efcdd2362012-07-09 21:07:00549 virtual uint32 GetGLError() OVERRIDE;
550
[email protected]63b465922012-09-06 02:04:52551 virtual uint32 GetTextureUploadCount() OVERRIDE;
552 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
553 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
[email protected]dc25dda2012-09-27 21:36:30554 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE;
[email protected]63b465922012-09-06 02:04:52555
[email protected]8e3e0662010-08-23 18:46:30556 // Restores the current state to the user's settings.
557 void RestoreCurrentFramebufferBindings();
558 void RestoreCurrentRenderbufferBindings();
559 void RestoreCurrentTexture2DBindings();
560
[email protected]297ca1c2011-06-20 23:08:46561 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
562 void ApplyDirtyState();
563
[email protected]78b514b2012-05-01 21:50:59564 // Reapply the texture parameters to the given texture.
565 void BindAndApplyTextureParameters(TextureManager::TextureInfo* info);
566
[email protected]297ca1c2011-06-20 23:08:46567 // These check the state of the currently bound framebuffer or the
568 // backbuffer if no framebuffer is bound.
569 bool BoundFramebufferHasColorAttachmentWithAlpha();
570 bool BoundFramebufferHasDepthAttachment();
571 bool BoundFramebufferHasStencilAttachment();
572
[email protected]b8e97b62012-09-30 15:09:00573 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
[email protected]38d139d2011-07-14 00:38:43574
[email protected]96449d2c2009-11-25 00:01:32575 private:
[email protected]6217d392010-03-25 22:08:35576 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02577 friend class ScopedResolvedFrameBufferBinder;
[email protected]63b465922012-09-06 02:04:52578 friend class ScopedTextureUploadTimer;
[email protected]1078f912011-12-23 13:12:14579 friend class Texture;
[email protected]6217d392010-03-25 22:08:35580 friend class RenderBuffer;
581 friend class FrameBuffer;
582
[email protected]c2f8c8402010-12-06 18:07:24583 // Initialize or re-initialize the shader translator.
584 bool InitializeShaderTranslator();
585
[email protected]302ce6d2011-07-07 23:28:11586 void UpdateCapabilities();
587
[email protected]ae51d192010-04-27 00:48:03588 // Helpers for the glGen and glDelete functions.
589 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
590 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
591 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
592 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
593 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
594 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
595 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
596 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]882ba1e22012-03-08 19:02:53597 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
598 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
[email protected]944b62f32012-09-27 02:20:46599 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
600 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47601
[email protected]3916c97e2010-02-25 03:20:50602 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50603 BufferManager* buffer_manager() {
604 return group_->buffer_manager();
605 }
606
[email protected]a25fa872010-03-25 02:57:58607 RenderbufferManager* renderbuffer_manager() {
608 return group_->renderbuffer_manager();
609 }
610
611 FramebufferManager* framebuffer_manager() {
612 return group_->framebuffer_manager();
613 }
614
[email protected]3916c97e2010-02-25 03:20:50615 ProgramManager* program_manager() {
616 return group_->program_manager();
617 }
618
619 ShaderManager* shader_manager() {
620 return group_->shader_manager();
621 }
622
623 TextureManager* texture_manager() {
624 return group_->texture_manager();
625 }
626
[email protected]78b514b2012-05-01 21:50:59627 MailboxManager* mailbox_manager() {
628 return group_->mailbox_manager();
629 }
630
[email protected]09d50362012-10-18 20:54:37631 ImageManager* image_manager() {
632 return group_->image_manager();
633 }
634
[email protected]944b62f32012-09-27 02:20:46635 VertexArrayManager* vertex_array_manager() {
636 return vertex_array_manager_.get();
637 }
638
[email protected]34ff8b0c2010-10-01 20:06:02639 bool IsOffscreenBufferMultisampled() const {
640 return offscreen_target_samples_ > 1;
641 }
642
[email protected]a93bb842010-02-16 23:03:47643 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03644 TextureManager::TextureInfo* CreateTextureInfo(
645 GLuint client_id, GLuint service_id) {
[email protected]80eb6b52012-01-19 00:14:41646 return texture_manager()->CreateTextureInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47647 }
648
649 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03650 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50651 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03652 texture_manager()->GetTextureInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10653 return info;
[email protected]a93bb842010-02-16 23:03:47654 }
655
656 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03657 void RemoveTextureInfo(GLuint client_id) {
[email protected]80eb6b52012-01-19 00:14:41658 texture_manager()->RemoveTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50659 }
[email protected]a93bb842010-02-16 23:03:47660
[email protected]d37231fa2010-04-09 21:16:02661 // Get the size (in pixels) of the currently bound frame buffer (either FBO
662 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30663 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02664
[email protected]9edc6b22010-12-23 02:00:26665 // Get the format of the currently bound frame buffer (either FBO or regular
666 // back buffer)
667 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46668 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26669
[email protected]a93bb842010-02-16 23:03:47670 // Wrapper for CompressedTexImage2D commands.
671 error::Error DoCompressedTexImage2D(
[email protected]09d50362012-10-18 20:54:37672 GLenum target,
673 GLint level,
674 GLenum internal_format,
675 GLsizei width,
676 GLsizei height,
677 GLint border,
678 GLsizei image_size,
679 const void* data);
[email protected]a93bb842010-02-16 23:03:47680
[email protected]cadde4a2010-07-31 17:10:43681 // Wrapper for CompressedTexSubImage2D.
682 void DoCompressedTexSubImage2D(
[email protected]09d50362012-10-18 20:54:37683 GLenum target,
684 GLint level,
685 GLint xoffset,
686 GLint yoffset,
687 GLsizei width,
688 GLsizei height,
689 GLenum format,
690 GLsizei imageSize,
691 const void * data);
[email protected]cadde4a2010-07-31 17:10:43692
693 // Wrapper for CopyTexImage2D.
694 void DoCopyTexImage2D(
[email protected]09d50362012-10-18 20:54:37695 GLenum target,
696 GLint level,
697 GLenum internal_format,
698 GLint x,
699 GLint y,
700 GLsizei width,
701 GLsizei height,
702 GLint border);
[email protected]cadde4a2010-07-31 17:10:43703
704 // Wrapper for CopyTexSubImage2D.
705 void DoCopyTexSubImage2D(
[email protected]09d50362012-10-18 20:54:37706 GLenum target,
707 GLint level,
708 GLint xoffset,
709 GLint yoffset,
710 GLint x,
711 GLint y,
712 GLsizei width,
713 GLsizei height);
[email protected]cadde4a2010-07-31 17:10:43714
[email protected]a93bb842010-02-16 23:03:47715 // Wrapper for TexImage2D commands.
716 error::Error DoTexImage2D(
[email protected]09d50362012-10-18 20:54:37717 GLenum target,
718 GLint level,
719 GLenum internal_format,
720 GLsizei width,
721 GLsizei height,
722 GLint border,
723 GLenum format,
724 GLenum type,
725 const void* pixels,
726 uint32 pixels_size);
[email protected]a93bb842010-02-16 23:03:47727
[email protected]cadde4a2010-07-31 17:10:43728 // Wrapper for TexSubImage2D.
729 void DoTexSubImage2D(
[email protected]09d50362012-10-18 20:54:37730 GLenum target,
731 GLint level,
732 GLint xoffset,
733 GLint yoffset,
734 GLsizei width,
735 GLsizei height,
736 GLenum format,
737 GLenum type,
738 const void * data);
[email protected]cadde4a2010-07-31 17:10:43739
[email protected]e51bdf32011-11-23 22:21:46740 // Wrapper for TexImageIOSurface2DCHROMIUM.
741 void DoTexImageIOSurface2DCHROMIUM(
[email protected]09d50362012-10-18 20:54:37742 GLenum target,
743 GLsizei width,
744 GLsizei height,
745 GLuint io_surface_id,
746 GLuint plane);
[email protected]e51bdf32011-11-23 22:21:46747
[email protected]43410e92012-04-20 17:06:28748 void DoCopyTextureCHROMIUM(
[email protected]09d50362012-10-18 20:54:37749 GLenum target,
750 GLuint source_id,
751 GLuint target_id,
752 GLint level,
753 GLenum internal_format);
[email protected]43410e92012-04-20 17:06:28754
[email protected]97dc7cbe2011-12-06 17:26:17755 // Wrapper for TexStorage2DEXT.
756 void DoTexStorage2DEXT(
[email protected]09d50362012-10-18 20:54:37757 GLenum target,
758 GLint levels,
759 GLenum internal_format,
760 GLsizei width,
761 GLsizei height);
[email protected]97dc7cbe2011-12-06 17:26:17762
[email protected]78b514b2012-05-01 21:50:59763 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
764 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
765
[email protected]09d50362012-10-18 20:54:37766 void DoBindTexImage2DCHROMIUM(
767 GLenum target,
768 GLint image_id);
769 void DoReleaseTexImage2DCHROMIUM(
770 GLenum target,
771 GLint image_id);
772
[email protected]94307712012-11-16 23:26:11773 void DoTraceEndCHROMIUM(void);
774
[email protected]a93bb842010-02-16 23:03:47775 // Creates a ProgramInfo for the given program.
[email protected]d685a682011-04-29 16:19:57776 ProgramManager::ProgramInfo* CreateProgramInfo(
777 GLuint client_id, GLuint service_id) {
778 return program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47779 }
780
[email protected]07f54fcc2009-12-22 02:46:30781 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03782 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14783 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46784 }
[email protected]07f54fcc2009-12-22 02:46:30785
[email protected]6b8cf1a2010-05-06 16:13:58786 // Gets the program info for the given program. If it's not a program
787 // generates a GL error. Returns NULL if not program.
788 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
789 GLuint client_id, const char* function_name) {
790 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
791 if (!info) {
792 if (GetShaderInfo(client_id)) {
[email protected]ad84a3a2012-06-08 21:42:43793 SetGLError(
794 GL_INVALID_OPERATION, function_name, "shader passed for program");
[email protected]6b8cf1a2010-05-06 16:13:58795 } else {
[email protected]ad84a3a2012-06-08 21:42:43796 SetGLError(GL_INVALID_VALUE, function_name, "unknown program");
[email protected]6b8cf1a2010-05-06 16:13:58797 }
798 }
799 return info;
800 }
801
802
[email protected]45bf5152010-02-12 00:11:31803 // Creates a ShaderInfo for the given shader.
[email protected]d685a682011-04-29 16:19:57804 ShaderManager::ShaderInfo* CreateShaderInfo(
805 GLuint client_id,
806 GLuint service_id,
807 GLenum shader_type) {
808 return shader_manager()->CreateShaderInfo(
809 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31810 }
811
812 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03813 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14814 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31815 }
816
[email protected]6b8cf1a2010-05-06 16:13:58817 // Gets the shader info for the given shader. If it's not a shader generates a
818 // GL error. Returns NULL if not shader.
819 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
820 GLuint client_id, const char* function_name) {
821 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
822 if (!info) {
823 if (GetProgramInfo(client_id)) {
824 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:43825 GL_INVALID_OPERATION, function_name, "program passed for shader");
[email protected]6b8cf1a2010-05-06 16:13:58826 } else {
[email protected]ad84a3a2012-06-08 21:42:43827 SetGLError(
828 GL_INVALID_VALUE, function_name, "unknown shader");
[email protected]6b8cf1a2010-05-06 16:13:58829 }
830 }
831 return info;
832 }
833
[email protected]a93bb842010-02-16 23:03:47834 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03835 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
836 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47837 }
838
[email protected]07f54fcc2009-12-22 02:46:30839 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03840 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
841 BufferManager::BufferInfo* info =
842 buffer_manager()->GetBufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10843 return info;
[email protected]1d32bc82010-01-13 22:06:46844 }
[email protected]07f54fcc2009-12-22 02:46:30845
[email protected]a93bb842010-02-16 23:03:47846 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
847 // on glDeleteBuffers so we can make sure the user does not try to render
848 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03849 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47850
[email protected]a25fa872010-03-25 02:57:58851 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03852 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
853 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58854 }
855
856 // Gets the framebuffer info for the given framebuffer.
857 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03858 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58859 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03860 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10861 return info;
[email protected]a25fa872010-03-25 02:57:58862 }
863
864 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03865 void RemoveFramebufferInfo(GLuint client_id) {
866 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58867 }
868
869 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03870 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
871 return renderbuffer_manager()->CreateRenderbufferInfo(
872 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58873 }
874
875 // Gets the renderbuffer info for the given renderbuffer.
876 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03877 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58878 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03879 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10880 return info;
[email protected]a25fa872010-03-25 02:57:58881 }
882
883 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03884 void RemoveRenderbufferInfo(GLuint client_id) {
885 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58886 }
887
[email protected]944b62f32012-09-27 02:20:46888 // Gets the vertex attrib manager for the given vertex array.
889 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
890 VertexAttribManager* info =
891 vertex_array_manager()->GetVertexAttribManager(client_id);
892 return info;
893 }
894
895 // Removes the vertex attrib manager for the given vertex array.
896 void RemoveVertexAttribManager(GLuint client_id) {
897 vertex_array_manager()->RemoveVertexAttribManager(client_id);
898 }
899
900 // Creates a vertex attrib manager for the given vertex array.
901 void CreateVertexAttribManager(GLuint client_id, GLuint service_id) {
902 return vertex_array_manager()->CreateVertexAttribManager(
903 client_id, service_id, group_->max_vertex_attribs());
904 }
905
[email protected]258a3313f2011-10-18 20:13:57906 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
[email protected]2be6abf32012-06-26 00:28:33907 void DoBindUniformLocationCHROMIUM(
908 GLuint client_id, GLint location, const char* name);
[email protected]258a3313f2011-10-18 20:13:57909
[email protected]558847a2010-03-24 07:02:54910 error::Error GetAttribLocationHelper(
911 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
912 const std::string& name_str);
913
914 error::Error GetUniformLocationHelper(
915 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
916 const std::string& name_str);
917
[email protected]3916c97e2010-02-25 03:20:50918 // Helper for glShaderSource.
919 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03920 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30921
[email protected]0d6bfdc2011-11-02 01:32:20922 // Clear any textures used by the current program.
923 bool ClearUnclearedTextures();
924
925 // Clear any uncleared level in texture.
926 // Returns false if there was a generated GL error.
927 bool ClearTexture(TextureManager::TextureInfo* info);
928
929 // Clears any uncleared attachments attached to the given frame buffer.
930 // Returns false if there was a generated GL error.
931 void ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:30932 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28933
[email protected]0d6bfdc2011-11-02 01:32:20934 // overridden from GLES2Decoder
[email protected]b8e97b62012-09-30 15:09:00935 virtual bool ClearLevel(unsigned service_id,
936 unsigned bind_target,
937 unsigned target,
938 int level,
939 unsigned format,
940 unsigned type,
941 int width,
942 int height,
943 bool is_texture_immutable) OVERRIDE;
[email protected]0d6bfdc2011-11-02 01:32:20944
[email protected]c007aa02010-09-02 22:22:40945 // Restore all GL state that affects clearing.
946 void RestoreClearState();
947
[email protected]3a2e7c7b2010-08-06 01:12:28948 // Remembers the state of some capabilities.
[email protected]297ca1c2011-06-20 23:08:46949 // Returns: true if glEnable/glDisable should actually be called.
950 bool SetCapabilityState(GLenum cap, bool enabled);
[email protected]3a2e7c7b2010-08-06 01:12:28951
[email protected]0d6bfdc2011-11-02 01:32:20952 // Check that the currently bound framebuffers are valid.
953 // Generates GL error if not.
954 bool CheckBoundFramebuffersValid(const char* func_name);
955
956 // Check if a framebuffer meets our requirements.
957 bool CheckFramebufferValid(
958 FramebufferManager::FramebufferInfo* framebuffer,
959 GLenum target,
960 const char* func_name);
[email protected]3a03a8f2011-03-19 00:51:27961
[email protected]939e7362010-05-13 20:49:10962 // Checks if the current program exists and is valid. If not generates the
963 // appropriate GL error. Returns true if the current program is in a usable
964 // state.
965 bool CheckCurrentProgram(const char* function_name);
966
967 // Checks if the current program exists and is valid and that location is not
968 // -1. If the current program is not valid generates the appropriate GL
969 // error. Returns true if the current program is in a usable state and
970 // location is not -1.
971 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
972
973 // Gets the type of a uniform for a location in the current program. Sets GL
974 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:36975 // program is valid and the location exists. Adjusts count so it
976 // does not overflow the uniform.
977 bool PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:12978 GLint fake_location, const char* function_name,
979 GLint* real_location, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:10980
[email protected]b177ae22011-11-01 03:29:11981 // Gets the service id for any simulated backbuffer fbo.
[email protected]1868a342012-11-07 15:56:02982 GLuint GetBackbufferServiceId() const;
[email protected]b177ae22011-11-01 03:29:11983
[email protected]b273e432010-04-12 17:23:58984 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
985 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
986
[email protected]96449d2c2009-11-25 00:01:32987 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03988 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32989
990 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03991 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32992
[email protected]3916c97e2010-02-25 03:20:50993 // Wrapper for glActiveTexture
994 void DoActiveTexture(GLenum texture_unit);
995
[email protected]ae51d192010-04-27 00:48:03996 // Wrapper for glAttachShader
997 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
998
[email protected]96449d2c2009-11-25 00:01:32999 // Wrapper for glBindBuffer since we need to track the current targets.
1000 void DoBindBuffer(GLenum target, GLuint buffer);
1001
[email protected]86093972010-03-11 00:13:561002 // Wrapper for glBindFramebuffer since we need to track the current targets.
1003 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1004
1005 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1006 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1007
[email protected]a93bb842010-02-16 23:03:471008 // Wrapper for glBindTexture since we need to track the current targets.
1009 void DoBindTexture(GLenum target, GLuint texture);
1010
[email protected]944b62f32012-09-27 02:20:461011 // Wrapper for glBindVertexArrayOES
1012 void DoBindVertexArrayOES(GLuint array);
[email protected]ab4fd7282012-10-12 16:25:571013 void EmulateVertexArrayState();
[email protected]944b62f32012-09-27 02:20:461014
[email protected]8e3e0662010-08-23 18:46:301015 // Wrapper for glBlitFramebufferEXT.
1016 void DoBlitFramebufferEXT(
1017 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1018 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1019 GLbitfield mask, GLenum filter);
1020
[email protected]36cef8ce2010-03-16 07:34:451021 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:111022 void DoBufferData(
1023 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
1024
[email protected]36cef8ce2010-03-16 07:34:451025 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:111026 void DoBufferSubData(
1027 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1028
[email protected]36cef8ce2010-03-16 07:34:451029 // Wrapper for glCheckFramebufferStatus
1030 GLenum DoCheckFramebufferStatus(GLenum target);
1031
[email protected]3a03a8f2011-03-19 00:51:271032 // Wrapper for glClear
[email protected]a7266a92012-06-28 02:11:081033 error::Error DoClear(GLbitfield mask);
[email protected]3a03a8f2011-03-19 00:51:271034
[email protected]88a61bf2012-10-27 13:00:421035 // Wrappers for various state.
[email protected]88a61bf2012-10-27 13:00:421036 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1037 void DoHint(GLenum target, GLenum mode);
1038 void DoSampleCoverage (GLclampf value, GLboolean invert);
[email protected]3a2e7c7b2010-08-06 01:12:281039
[email protected]45bf5152010-02-12 00:11:311040 // Wrapper for glCompileShader.
1041 void DoCompileShader(GLuint shader);
1042
[email protected]269200b12010-11-18 22:53:061043 // Helper for DeleteSharedIdsCHROMIUM commands.
1044 void DoDeleteSharedIdsCHROMIUM(
1045 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101046
[email protected]ae51d192010-04-27 00:48:031047 // Wrapper for glDetachShader
1048 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1049
[email protected]3a2e7c7b2010-08-06 01:12:281050 // Wrapper for glDisable
1051 void DoDisable(GLenum cap);
1052
[email protected]07f54fcc2009-12-22 02:46:301053 // Wrapper for glDisableVertexAttribArray.
1054 void DoDisableVertexAttribArray(GLuint index);
1055
[email protected]3a2e7c7b2010-08-06 01:12:281056 // Wrapper for glEnable
1057 void DoEnable(GLenum cap);
1058
[email protected]07f54fcc2009-12-22 02:46:301059 // Wrapper for glEnableVertexAttribArray.
1060 void DoEnableVertexAttribArray(GLuint index);
1061
[email protected]882ba1e22012-03-08 19:02:531062 // Wrapper for glFinish.
1063 void DoFinish();
1064
1065 // Wrapper for glFlush.
1066 void DoFlush();
1067
[email protected]36cef8ce2010-03-16 07:34:451068 // Wrapper for glFramebufferRenderbufffer.
1069 void DoFramebufferRenderbuffer(
1070 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1071 GLuint renderbuffer);
1072
1073 // Wrapper for glFramebufferTexture2D.
1074 void DoFramebufferTexture2D(
1075 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1076 GLint level);
1077
[email protected]a93bb842010-02-16 23:03:471078 // Wrapper for glGenerateMipmap
1079 void DoGenerateMipmap(GLenum target);
1080
[email protected]269200b12010-11-18 22:53:061081 // Helper for GenSharedIdsCHROMIUM commands.
1082 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:101083 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1084
[email protected]b273e432010-04-12 17:23:581085 // Wrapper for DoGetBooleanv.
1086 void DoGetBooleanv(GLenum pname, GLboolean* params);
1087
1088 // Wrapper for DoGetFloatv.
1089 void DoGetFloatv(GLenum pname, GLfloat* params);
1090
[email protected]36cef8ce2010-03-16 07:34:451091 // Wrapper for glGetFramebufferAttachmentParameteriv.
1092 void DoGetFramebufferAttachmentParameteriv(
1093 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1094
[email protected]a0c3e972010-04-21 00:49:131095 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581096 void DoGetIntegerv(GLenum pname, GLint* params);
1097
[email protected]29a9eb52010-04-13 09:04:231098 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:061099 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:231100 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1101
[email protected]a0c3e972010-04-21 00:49:131102 // Wrapper for glGetProgramiv.
1103 void DoGetProgramiv(
1104 GLuint program_id, GLenum pname, GLint* params);
1105
[email protected]36cef8ce2010-03-16 07:34:451106 // Wrapper for glRenderbufferParameteriv.
1107 void DoGetRenderbufferParameteriv(
1108 GLenum target, GLenum pname, GLint* params);
1109
[email protected]ddd968b82010-03-02 00:44:291110 // Wrapper for glGetShaderiv
1111 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1112
[email protected]b1122982010-05-17 23:04:241113 // Wrappers for glGetVertexAttrib.
1114 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1115 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1116
[email protected]1958e0e2010-04-22 05:17:151117 // Wrappers for glIsXXX functions.
[email protected]3dc69c42012-05-12 02:29:241118 bool DoIsEnabled(GLenum cap);
[email protected]1958e0e2010-04-22 05:17:151119 bool DoIsBuffer(GLuint client_id);
1120 bool DoIsFramebuffer(GLuint client_id);
1121 bool DoIsProgram(GLuint client_id);
1122 bool DoIsRenderbuffer(GLuint client_id);
1123 bool DoIsShader(GLuint client_id);
1124 bool DoIsTexture(GLuint client_id);
[email protected]944b62f32012-09-27 02:20:461125 bool DoIsVertexArrayOES(GLuint client_id);
[email protected]1958e0e2010-04-22 05:17:151126
[email protected]07f54fcc2009-12-22 02:46:301127 // Wrapper for glLinkProgram
1128 void DoLinkProgram(GLuint program);
1129
[email protected]269200b12010-11-18 22:53:061130 // Helper for RegisterSharedIdsCHROMIUM.
1131 void DoRegisterSharedIdsCHROMIUM(
1132 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101133
[email protected]36cef8ce2010-03-16 07:34:451134 // Wrapper for glRenderbufferStorage.
1135 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031136 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451137
[email protected]8e3e0662010-08-23 18:46:301138 // Wrapper for glRenderbufferStorageMultisampleEXT.
1139 void DoRenderbufferStorageMultisample(
1140 GLenum target, GLsizei samples, GLenum internalformat,
1141 GLsizei width, GLsizei height);
1142
[email protected]b273e432010-04-12 17:23:581143 // Wrapper for glReleaseShaderCompiler.
1144 void DoReleaseShaderCompiler() { }
1145
[email protected]3916c97e2010-02-25 03:20:501146 // Wrappers for glTexParameter functions.
1147 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1148 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1149 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1150 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1151
1152 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1153 // spec only these 2 functions can be used to set sampler uniforms.
[email protected]1b0a6752012-02-22 03:44:121154 void DoUniform1i(GLint fake_location, GLint v0);
1155 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1156 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1157 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1158 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101159
1160 // Wrappers for glUniformfv because some drivers don't correctly accept
1161 // bool uniforms.
[email protected]1b0a6752012-02-22 03:44:121162 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1163 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1164 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1165 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501166
[email protected]43c2f1f2011-03-25 18:35:361167 void DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:121168 GLint fake_location, GLsizei count, GLboolean transpose,
1169 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361170 void DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:121171 GLint fake_location, GLsizei count, GLboolean transpose,
1172 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361173 void DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:121174 GLint fake_location, GLsizei count, GLboolean transpose,
1175 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361176
[email protected]af6380962012-11-29 23:24:131177 bool SetVertexAttribValue(
1178 const char* function_name, GLuint index, const GLfloat* value);
1179
[email protected]b1122982010-05-17 23:04:241180 // Wrappers for glVertexAttrib??
1181 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1182 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1183 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1184 void DoVertexAttrib4f(
1185 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1186 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1187 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1188 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1189 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1190
[email protected]43410e92012-04-20 17:06:281191 // Wrapper for glViewport
1192 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1193
[email protected]07f54fcc2009-12-22 02:46:301194 // Wrapper for glUseProgram
1195 void DoUseProgram(GLuint program);
1196
[email protected]ae51d192010-04-27 00:48:031197 // Wrapper for glValidateProgram.
1198 void DoValidateProgram(GLuint program_client_id);
1199
[email protected]d2a0e1a2012-08-12 02:25:011200 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1201 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1202 void DoPopGroupMarkerEXT(void);
1203
[email protected]4e8a5b122010-05-08 22:00:101204 // Gets the number of values that will be returned by glGetXXX. Returns
1205 // false if pname is unknown.
1206 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1207
[email protected]1002c2d2011-06-28 22:39:041208 // Gets the GLError and stores it in our wrapper. Effectively
1209 // this lets us peek at the error without losing it.
1210 GLenum PeekGLError();
1211
[email protected]07f54fcc2009-12-22 02:46:301212 // Copies the real GL errors to the wrapper. This is so we can
1213 // make sure there are no native GL errors before calling some GL function
1214 // so that on return we know any error generated was for that specific
1215 // command.
1216 void CopyRealGLErrorsToWrapper();
1217
[email protected]6217d392010-03-25 22:08:351218 // Clear all real GL errors. This is to prevent the client from seeing any
1219 // errors caused by GL calls that it was not responsible for issuing.
1220 void ClearRealGLErrors();
1221
[email protected]07f54fcc2009-12-22 02:46:301222 // Checks if the current program and vertex attributes are valid for drawing.
[email protected]ad84a3a2012-06-08 21:42:431223 bool IsDrawValid(
1224 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount);
[email protected]07f54fcc2009-12-22 02:46:301225
[email protected]c13e1da62011-09-09 21:48:301226 // Returns true if successful, simulated will be true if attrib0 was
1227 // simulated.
[email protected]c6aef902012-02-14 03:31:421228 bool SimulateAttrib0(
[email protected]ad84a3a2012-06-08 21:42:431229 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
[email protected]43410e92012-04-20 17:06:281230 void RestoreStateForAttrib(GLuint attrib);
[email protected]b1122982010-05-17 23:04:241231
[email protected]ef526492010-06-02 23:12:251232 // Returns true if textures were set.
1233 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501234 void RestoreStateForNonRenderableTextures();
1235
[email protected]8fbedc02010-11-18 18:43:401236 // Returns true if GL_FIXED attribs were simulated.
[email protected]c6aef902012-02-14 03:31:421237 bool SimulateFixedAttribs(
[email protected]ad84a3a2012-06-08 21:42:431238 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421239 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
[email protected]8fbedc02010-11-18 18:43:401240 void RestoreStateForSimulatedFixedAttribs();
1241
[email protected]c6aef902012-02-14 03:31:421242 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1243 // cases (primcount is 0 for non-instanced).
1244 error::Error DoDrawArrays(
[email protected]ad84a3a2012-06-08 21:42:431245 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421246 bool instanced, GLenum mode, GLint first, GLsizei count,
1247 GLsizei primcount);
1248 error::Error DoDrawElements(
[email protected]ad84a3a2012-06-08 21:42:431249 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421250 bool instanced, GLenum mode, GLsizei count, GLenum type,
1251 int32 offset, GLsizei primcount);
1252
[email protected]07f54fcc2009-12-22 02:46:301253 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501254 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301255 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]944b62f32012-09-27 02:20:461256 if (target == GL_ARRAY_BUFFER) {
[email protected]e259eb412012-10-13 05:47:241257 return state_.bound_array_buffer;
[email protected]944b62f32012-09-27 02:20:461258 } else {
[email protected]e259eb412012-10-13 05:47:241259 return state_.vertex_attrib_manager->element_array_buffer();
[email protected]944b62f32012-09-27 02:20:461260 }
[email protected]07f54fcc2009-12-22 02:46:301261 }
1262
[email protected]a93bb842010-02-16 23:03:471263 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501264 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
[email protected]e259eb412012-10-13 05:47:241265 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]3916c97e2010-02-25 03:20:501266 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471267 switch (target) {
1268 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501269 info = unit.bound_texture_2d;
1270 break;
[email protected]a93bb842010-02-16 23:03:471271 case GL_TEXTURE_CUBE_MAP:
1272 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1273 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1274 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1275 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1276 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1277 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501278 info = unit.bound_texture_cube_map;
1279 break;
[email protected]61eeb33f2011-07-26 15:30:311280 case GL_TEXTURE_EXTERNAL_OES:
1281 info = unit.bound_texture_external_oes;
1282 break;
[email protected]e51bdf32011-11-23 22:21:461283 case GL_TEXTURE_RECTANGLE_ARB:
1284 info = unit.bound_texture_rectangle_arb;
1285 break;
[email protected]a93bb842010-02-16 23:03:471286 default:
1287 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501288 return NULL;
[email protected]a93bb842010-02-16 23:03:471289 }
[email protected]a0b78dc2011-11-11 10:43:101290 return info;
[email protected]a93bb842010-02-16 23:03:471291 }
1292
[email protected]09d50362012-10-18 20:54:371293 TextureManager::TextureInfo* GetTextureInfoForTargetUnlessDefault(
1294 GLenum target) {
1295 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
1296 if (!info)
1297 return NULL;
1298 if (info == texture_manager()->GetDefaultTextureInfo(target))
1299 return NULL;
1300 return info;
1301 }
1302
[email protected]61eeb33f2011-07-26 15:30:311303 GLenum GetBindTargetForSamplerType(GLenum type) {
1304 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:461305 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1306 switch (type) {
1307 case GL_SAMPLER_2D:
1308 return GL_TEXTURE_2D;
1309 case GL_SAMPLER_CUBE:
1310 return GL_TEXTURE_CUBE_MAP;
1311 case GL_SAMPLER_EXTERNAL_OES:
1312 return GL_TEXTURE_EXTERNAL_OES;
1313 case GL_SAMPLER_2D_RECT_ARB:
1314 return GL_TEXTURE_RECTANGLE_ARB;
1315 }
1316
1317 NOTREACHED();
1318 return 0;
[email protected]61eeb33f2011-07-26 15:30:311319 }
1320
[email protected]8e3e0662010-08-23 18:46:301321 // Gets the framebuffer info for a particular target.
1322 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1323 GLenum target) {
1324 FramebufferManager::FramebufferInfo* info = NULL;
1325 switch (target) {
1326 case GL_FRAMEBUFFER:
[email protected]ebfb73c2012-08-15 02:37:451327 case GL_DRAW_FRAMEBUFFER_EXT:
[email protected]e259eb412012-10-13 05:47:241328 info = state_.bound_draw_framebuffer;
[email protected]8e3e0662010-08-23 18:46:301329 break;
[email protected]ebfb73c2012-08-15 02:37:451330 case GL_READ_FRAMEBUFFER_EXT:
[email protected]e259eb412012-10-13 05:47:241331 info = state_.bound_read_framebuffer;
[email protected]8e3e0662010-08-23 18:46:301332 break;
1333 default:
1334 NOTREACHED();
1335 break;
1336 }
[email protected]a0b78dc2011-11-11 10:43:101337 return info;
[email protected]8e3e0662010-08-23 18:46:301338 }
1339
[email protected]0d6bfdc2011-11-02 01:32:201340 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfoForTarget(
1341 GLenum target) {
1342 RenderbufferManager::RenderbufferInfo* info = NULL;
1343 switch (target) {
1344 case GL_RENDERBUFFER:
[email protected]e259eb412012-10-13 05:47:241345 info = state_.bound_renderbuffer;
[email protected]0d6bfdc2011-11-02 01:32:201346 break;
1347 default:
1348 NOTREACHED();
1349 break;
1350 }
[email protected]a0b78dc2011-11-11 10:43:101351 return info;
[email protected]0d6bfdc2011-11-02 01:32:201352 }
1353
[email protected]f7b85372010-02-03 01:11:371354 // Validates the program and location for a glGetUniform call and returns
1355 // a SizeResult setup to receive the result. Returns true if glGetUniform
1356 // should be called.
1357 bool GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:121358 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:371359 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:121360 error::Error* error, GLint* real_location, GLuint* service_id,
1361 void** result, GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371362
[email protected]1078f912011-12-23 13:12:141363 // Computes the estimated memory used for the backbuffer and passes it to
1364 // the tracing system.
[email protected]260ddc4e2012-06-28 00:01:531365 size_t GetBackbufferMemoryTotal();
[email protected]1078f912011-12-23 13:12:141366
[email protected]38d139d2011-07-14 00:38:431367 // Returns true if the context was just lost due to e.g. GL_ARB_robustness.
[email protected]a10b4a02012-11-26 23:09:501368 virtual bool WasContextLost() OVERRIDE;
[email protected]38d139d2011-07-14 00:38:431369
[email protected]e51bdf32011-11-23 22:21:461370#if defined(OS_MACOSX)
1371 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1372#endif
1373
[email protected]81375742012-06-08 00:04:001374 // Validates the combination of texture parameters. For example validates that
1375 // for a given format the specific type, level and targets are valid.
1376 // Synthesizes the correct GL error if invalid. Returns true if valid.
1377 bool ValidateTextureParameters(
1378 const char* function_name,
1379 GLenum target, GLenum format, GLenum type, GLint level);
1380
[email protected]ad84a3a2012-06-08 21:42:431381 bool ValidateCompressedTexDimensions(
1382 const char* function_name,
1383 GLint level, GLsizei width, GLsizei height, GLenum format);
1384 bool ValidateCompressedTexFuncData(
1385 const char* function_name,
1386 GLsizei width, GLsizei height, GLenum format, size_t size);
1387 bool ValidateCompressedTexSubDimensions(
1388 const char* function_name,
1389 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1390 GLsizei width, GLsizei height, GLenum format,
1391 TextureManager::TextureInfo* texture);
1392
[email protected]0f8afe82012-05-14 23:43:011393 void LogMessage(const std::string& msg);
1394 void RenderWarning(const std::string& msg);
1395 void PerformanceWarning(const std::string& msg);
[email protected]d2a0e1a2012-08-12 02:25:011396 const std::string& GetLogPrefix() const;
[email protected]0f8afe82012-05-14 23:43:011397
[email protected]62e155e2012-10-23 22:43:151398 const FeatureInfo::FeatureFlags& features() const {
1399 return feature_info_->feature_flags();
1400 }
1401
1402 const FeatureInfo::Workarounds& workarounds() const {
1403 return feature_info_->workarounds();
1404 }
1405
[email protected]a7266a92012-06-28 02:11:081406 bool ShouldDeferDraws() {
1407 return !offscreen_target_frame_buffer_.get() &&
[email protected]e259eb412012-10-13 05:47:241408 state_.bound_draw_framebuffer == NULL &&
[email protected]a7266a92012-06-28 02:11:081409 surface_->DeferDraws();
1410 }
1411
[email protected]09e17272012-11-30 10:30:441412 bool ShouldDeferReads() {
1413 return !offscreen_target_frame_buffer_.get() &&
1414 state_.bound_read_framebuffer == NULL &&
1415 surface_->DeferDraws();
1416 }
1417
[email protected]c447acd2012-07-23 23:48:411418 void ForceCompileShaderIfPending(ShaderManager::ShaderInfo* info);
1419
[email protected]96449d2c2009-11-25 00:01:321420 // Generate a member function prototype for each command in an automated and
1421 // typesafe way.
1422 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141423 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191424 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321425 const gles2::name& args); \
1426
1427 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1428
1429 #undef GLES2_CMD_OP
1430
[email protected]2f2d7042010-04-14 21:45:581431 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381432 scoped_refptr<gfx::GLSurface> surface_;
1433 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021434
[email protected]a3ded6d2010-10-19 06:44:391435 // The ContextGroup for this decoder uses to track resources.
1436 ContextGroup::Ref group_;
1437
[email protected]e259eb412012-10-13 05:47:241438 // All the state for this context.
1439 ContextState state_;
1440
[email protected]6217d392010-03-25 22:08:351441 // A parent decoder can access this decoders saved offscreen frame buffer.
1442 // The parent pointer is reset if the parent is destroyed.
1443 base::WeakPtr<GLES2DecoderImpl> parent_;
1444
[email protected]34ff8b0c2010-10-01 20:06:021445 // Current width and height of the offscreen frame buffer.
1446 gfx::Size offscreen_size_;
1447
[email protected]96449d2c2009-11-25 00:01:321448 // Current GL error bits.
1449 uint32 error_bits_;
1450
[email protected]96449d2c2009-11-25 00:01:321451 // Util to help with GL.
1452 GLES2Util util_;
1453
[email protected]43410e92012-04-20 17:06:281454 // unpack flip y as last set by glPixelStorei
1455 bool unpack_flip_y_;
1456
[email protected]6c75c712012-06-19 15:43:171457 // unpack (un)premultiply alpha as last set by glPixelStorei
[email protected]43410e92012-04-20 17:06:281458 bool unpack_premultiply_alpha_;
[email protected]6c75c712012-06-19 15:43:171459 bool unpack_unpremultiply_alpha_;
[email protected]43410e92012-04-20 17:06:281460
[email protected]944b62f32012-09-27 02:20:461461 // Default vertex attribs manager, used when no VAOs are bound.
1462 VertexAttribManager::Ref default_vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301463
[email protected]b1122982010-05-17 23:04:241464 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1465 GLuint attrib_0_buffer_id_;
1466
1467 // The value currently in attrib_0.
[email protected]af6380962012-11-29 23:24:131468 Vec4 attrib_0_value_;
[email protected]b1122982010-05-17 23:04:241469
[email protected]fc753442011-02-04 19:49:491470 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1471 bool attrib_0_buffer_matches_value_;
1472
[email protected]b1122982010-05-17 23:04:241473 // The size of attrib 0.
1474 GLsizei attrib_0_size_;
1475
[email protected]8fbedc02010-11-18 18:43:401476 // The buffer used to simulate GL_FIXED attribs.
1477 GLuint fixed_attrib_buffer_id_;
1478
1479 // The size of fiixed attrib buffer.
1480 GLsizei fixed_attrib_buffer_size_;
1481
[email protected]3a2e7c7b2010-08-06 01:12:281482 // state saved for clearing so we can clear render buffers and then
1483 // restore to these values.
[email protected]88a61bf2012-10-27 13:00:421484 bool clear_state_dirty_;
[email protected]3a2e7c7b2010-08-06 01:12:281485
[email protected]b9363b22010-06-09 22:06:151486 // The offscreen frame buffer that the client renders to. With EGL, the
1487 // depth and stencil buffers are separate. With regular GL there is a single
1488 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1489 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351490 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1491 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021492 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151493 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1494 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021495 GLenum offscreen_target_color_format_;
1496 GLenum offscreen_target_depth_format_;
1497 GLenum offscreen_target_stencil_format_;
1498 GLsizei offscreen_target_samples_;
[email protected]8a61d872012-01-20 12:43:561499 GLboolean offscreen_target_buffer_preserved_;
[email protected]6217d392010-03-25 22:08:351500
[email protected]de26b3c2011-08-03 21:54:271501 // The copy that is saved when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021502 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351503 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]8a61d872012-01-20 12:43:561504 TextureManager::TextureInfo::Ref offscreen_saved_color_texture_info_;
[email protected]de26b3c2011-08-03 21:54:271505
1506 // The copy that is used as the destination for multi-sample resolves.
1507 scoped_ptr<FrameBuffer> offscreen_resolved_frame_buffer_;
1508 scoped_ptr<Texture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051509 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351510
[email protected]882ba1e22012-03-08 19:02:531511 scoped_ptr<QueryManager> query_manager_;
[email protected]882ba1e22012-03-08 19:02:531512
[email protected]944b62f32012-09-27 02:20:461513 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1514
[email protected]9d37f062011-11-22 01:24:521515 base::Callback<void(gfx::Size)> resize_callback_;
[email protected]22f320a2011-08-30 01:17:001516
[email protected]6b6e7ee2011-12-13 08:04:521517 MsgCallback msg_callback_;
[email protected]43f28f832010-02-03 02:28:481518
[email protected]b0af4f52011-09-28 22:04:421519 StreamTextureManager* stream_texture_manager_;
1520
[email protected]32fe9aa2011-01-21 23:47:131521 // The format of the back buffer_
1522 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461523 bool back_buffer_has_depth_;
1524 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131525
[email protected]473c01ccb2011-06-07 01:33:301526 bool teximage2d_faster_than_texsubimage2d_;
[email protected]473c01ccb2011-06-07 01:33:301527
[email protected]8eee29c2010-04-29 03:38:291528 // The last error message set.
1529 std::string last_error_;
1530
[email protected]0f8afe82012-05-14 23:43:011531 int log_message_count_;
[email protected]fa20ec82012-05-04 04:02:481532
[email protected]a3a93e7b2010-08-28 00:48:561533 // The current decoder error.
1534 error::Error current_decoder_error_;
1535
[email protected]d2a0e1a2012-08-12 02:25:011536 DebugMarkerManager debug_marker_manager_;
1537 std::string this_in_hex_;
1538
[email protected]b1d2dcb2010-05-17 19:24:181539 bool use_shader_translator_;
[email protected]87fb6ab2012-06-13 22:28:041540 scoped_refptr<ShaderTranslator> vertex_translator_;
1541 scoped_refptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181542
[email protected]e82fb792011-09-22 00:33:291543 DisallowedFeatures disallowed_features_;
[email protected]c410da802011-03-14 19:17:411544
[email protected]915a59a12010-09-30 21:29:111545 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051546 const Validators* validators_;
[email protected]80eb6b52012-01-19 00:14:411547 FeatureInfo::Ref feature_info_;
[email protected]9438b012010-06-15 22:55:051548
[email protected]b493ee622011-04-13 23:52:001549 // This indicates all the following texSubImage2D calls that are part of the
1550 // failed texImage2D call should be ignored.
1551 bool tex_image_2d_failed_;
1552
[email protected]65225772011-05-12 21:10:241553 int frame_number_;
1554
[email protected]706b69f2012-07-27 04:59:301555 bool has_robustness_extension_;
[email protected]38d139d2011-07-14 00:38:431556 GLenum reset_status_;
1557
[email protected]f0d74742011-10-03 16:31:041558 // These flags are used to override the state of the shared feature_info_
1559 // member. Because the same FeatureInfo instance may be shared among many
1560 // contexts, the assumptions on the availablity of extensions in WebGL
1561 // contexts may be broken. These flags override the shared state to preserve
1562 // WebGL semantics.
1563 bool force_webgl_glsl_validation_;
1564 bool derivatives_explicitly_enabled_;
1565
[email protected]062c38b2012-01-18 03:25:101566 bool compile_shader_always_succeeds_;
1567
[email protected]e51bdf32011-11-23 22:21:461568#if defined(OS_MACOSX)
1569 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1570 TextureToIOSurfaceMap texture_to_io_surface_map_;
1571#endif
1572
[email protected]c826d732012-02-09 04:40:261573 typedef std::vector<GLES2DecoderImpl*> ChildList;
1574 ChildList children_;
1575
[email protected]43410e92012-04-20 17:06:281576 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1577
[email protected]1868a342012-11-07 15:56:021578 // Cached values of the currently assigned viewport dimensions.
1579 GLsizei viewport_max_width_;
1580 GLsizei viewport_max_height_;
1581
[email protected]63b465922012-09-06 02:04:521582 // Command buffer stats.
1583 int texture_upload_count_;
1584 base::TimeDelta total_texture_upload_time_;
1585 base::TimeDelta total_processing_commands_time_;
1586
[email protected]94307712012-11-16 23:26:111587 std::stack<linked_ptr<GPUTrace> > gpu_trace_stack_;
1588
[email protected]96449d2c2009-11-25 00:01:321589 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1590};
1591
[email protected]6217d392010-03-25 22:08:351592ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1593 : decoder_(decoder) {
1594 decoder_->CopyRealGLErrorsToWrapper();
1595}
1596
1597ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1598 decoder_->ClearRealGLErrors();
1599}
1600
1601ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1602 GLuint id)
1603 : decoder_(decoder) {
1604 ScopedGLErrorSuppressor suppressor(decoder_);
1605
1606 // TODO(apatrick): Check if there are any other states that need to be reset
1607 // before binding a new texture.
1608 glActiveTexture(GL_TEXTURE0);
1609 glBindTexture(GL_TEXTURE_2D, id);
1610}
1611
1612ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1613 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301614 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351615}
1616
1617ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1618 GLuint id)
1619 : decoder_(decoder) {
1620 ScopedGLErrorSuppressor suppressor(decoder_);
1621 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1622}
1623
1624ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1625 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301626 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351627}
1628
1629ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1630 GLuint id)
1631 : decoder_(decoder) {
1632 ScopedGLErrorSuppressor suppressor(decoder_);
1633 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1634}
1635
1636ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1637 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301638 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351639}
1640
[email protected]34ff8b0c2010-10-01 20:06:021641ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271642 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521643 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021644 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1645 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]e259eb412012-10-13 05:47:241646 (!decoder_->state_.bound_read_framebuffer.get() ||
[email protected]c0701082011-04-20 00:34:521647 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021648 if (!resolve_and_bind_)
1649 return;
1650
1651 ScopedGLErrorSuppressor suppressor(decoder_);
1652 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1653 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271654 GLuint targetid;
1655 if (internal) {
1656 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1657 decoder_->offscreen_resolved_frame_buffer_.reset(
1658 new FrameBuffer(decoder_));
1659 decoder_->offscreen_resolved_frame_buffer_->Create();
1660 decoder_->offscreen_resolved_color_texture_.reset(new Texture(decoder_));
1661 decoder_->offscreen_resolved_color_texture_->Create();
1662
1663 DCHECK(decoder_->offscreen_saved_color_format_);
1664 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1665 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_);
[email protected]de26b3c2011-08-03 21:54:271666 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1667 decoder_->offscreen_resolved_color_texture_.get());
1668 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1669 GL_FRAMEBUFFER_COMPLETE) {
1670 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1671 << "because offscreen resolved FBO was incomplete.";
1672 return;
1673 }
1674 }
1675 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1676 } else {
1677 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1678 }
1679 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021680 const int width = decoder_->offscreen_size_.width();
1681 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181682 glDisable(GL_SCISSOR_TEST);
[email protected]57edfdad2012-02-07 04:57:151683 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021684 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1685 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1686 } else {
1687 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1688 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1689 }
[email protected]de26b3c2011-08-03 21:54:271690 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021691}
1692
1693ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1694 if (!resolve_and_bind_)
1695 return;
1696
1697 ScopedGLErrorSuppressor suppressor(decoder_);
1698 decoder_->RestoreCurrentFramebufferBindings();
[email protected]f731b9462012-10-30 00:35:221699 if (decoder_->state_.enable_flags.scissor_test) {
[email protected]8c3e68782010-10-27 16:41:181700 glEnable(GL_SCISSOR_TEST);
1701 }
[email protected]34ff8b0c2010-10-01 20:06:021702}
1703
[email protected]63b465922012-09-06 02:04:521704ScopedTextureUploadTimer::ScopedTextureUploadTimer(GLES2DecoderImpl* decoder)
1705 : decoder_(decoder),
1706 begin_time_(base::TimeTicks::HighResNow()) {
1707}
1708
1709ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
1710 decoder_->texture_upload_count_++;
1711 decoder_->total_texture_upload_time_ +=
1712 base::TimeTicks::HighResNow() - begin_time_;
1713}
1714
[email protected]6217d392010-03-25 22:08:351715Texture::Texture(GLES2DecoderImpl* decoder)
1716 : decoder_(decoder),
[email protected]3e7951c2012-09-17 03:16:281717 memory_tracker_(decoder->GetContextGroup()->memory_tracker()),
[email protected]ff6493f2012-07-31 19:52:251718 id_(0) {
[email protected]6217d392010-03-25 22:08:351719}
1720
1721Texture::~Texture() {
1722 // This does not destroy the render texture because that would require that
1723 // the associated GL context was current. Just check that it was explicitly
1724 // destroyed.
1725 DCHECK_EQ(id_, 0u);
1726}
1727
1728void Texture::Create() {
1729 ScopedGLErrorSuppressor suppressor(decoder_);
1730 Destroy();
1731 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581732 ScopedTexture2DBinder binder(decoder_, id_);
1733 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1734 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1735 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1736 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]62788802011-10-03 17:57:161737
1738 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1739 // never called on an offscreen context, no data will ever be uploaded to the
1740 // saved offscreen color texture (it is deferred until to when SwapBuffers
1741 // is called). My idea is that some nvidia drivers might have a bug where
1742 // deleting a texture that has never been populated might cause a
1743 // crash.
1744 glTexImage2D(
1745 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
[email protected]ff6493f2012-07-31 19:52:251746 memory_tracker_.UpdateMemRepresented(16u * 16u * 4u);
[email protected]6217d392010-03-25 22:08:351747}
1748
[email protected]34ff8b0c2010-10-01 20:06:021749bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351750 DCHECK_NE(id_, 0u);
1751 ScopedGLErrorSuppressor suppressor(decoder_);
1752 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]6217d392010-03-25 22:08:351753
[email protected]f0e6a34f2012-01-04 20:53:401754 WrappedTexImage2D(GL_TEXTURE_2D,
1755 0, // mip level
1756 format,
1757 size.width(),
1758 size.height(),
1759 0, // border
1760 format,
1761 GL_UNSIGNED_BYTE,
1762 NULL);
[email protected]6217d392010-03-25 22:08:351763
[email protected]d37231fa2010-04-09 21:16:021764 size_ = size;
1765
[email protected]1078f912011-12-23 13:12:141766 bool success = glGetError() == GL_NO_ERROR;
1767 if (success) {
1768 uint32 image_size = 0;
[email protected]3458a64a2012-04-10 17:39:341769 GLES2Util::ComputeImageDataSizes(
1770 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 4, &image_size,
1771 NULL, NULL);
[email protected]ff6493f2012-07-31 19:52:251772 memory_tracker_.UpdateMemRepresented(image_size);
[email protected]1078f912011-12-23 13:12:141773 }
1774 return success;
[email protected]6217d392010-03-25 22:08:351775}
1776
[email protected]3a4d0c52011-06-29 23:11:581777void Texture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351778 DCHECK_NE(id_, 0u);
1779 ScopedGLErrorSuppressor suppressor(decoder_);
1780 ScopedTexture2DBinder binder(decoder_, id_);
1781 glCopyTexImage2D(GL_TEXTURE_2D,
1782 0, // level
[email protected]3a4d0c52011-06-29 23:11:581783 format,
[email protected]6217d392010-03-25 22:08:351784 0, 0,
1785 size.width(),
1786 size.height(),
1787 0); // border
1788}
1789
1790void Texture::Destroy() {
1791 if (id_ != 0) {
1792 ScopedGLErrorSuppressor suppressor(decoder_);
1793 glDeleteTextures(1, &id_);
1794 id_ = 0;
[email protected]ff6493f2012-07-31 19:52:251795 memory_tracker_.UpdateMemRepresented(0);
[email protected]6217d392010-03-25 22:08:351796 }
1797}
1798
[email protected]97872062010-11-03 19:07:051799void Texture::Invalidate() {
1800 id_ = 0;
1801}
1802
[email protected]6217d392010-03-25 22:08:351803RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1804 : decoder_(decoder),
[email protected]3e7951c2012-09-17 03:16:281805 memory_tracker_(decoder->GetContextGroup()->memory_tracker()),
[email protected]ff6493f2012-07-31 19:52:251806 id_(0) {
[email protected]6217d392010-03-25 22:08:351807}
1808
1809RenderBuffer::~RenderBuffer() {
1810 // This does not destroy the render buffer because that would require that
1811 // the associated GL context was current. Just check that it was explicitly
1812 // destroyed.
1813 DCHECK_EQ(id_, 0u);
1814}
1815
1816void RenderBuffer::Create() {
1817 ScopedGLErrorSuppressor suppressor(decoder_);
1818 Destroy();
1819 glGenRenderbuffersEXT(1, &id_);
1820}
1821
[email protected]34ff8b0c2010-10-01 20:06:021822bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1823 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351824 ScopedGLErrorSuppressor suppressor(decoder_);
1825 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021826 if (samples <= 1) {
1827 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1828 format,
1829 size.width(),
1830 size.height());
1831 } else {
[email protected]57edfdad2012-02-07 04:57:151832 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021833 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1834 samples,
1835 format,
1836 size.width(),
1837 size.height());
1838 } else {
1839 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1840 samples,
1841 format,
1842 size.width(),
1843 size.height());
1844 }
1845 }
[email protected]1078f912011-12-23 13:12:141846 bool success = glGetError() == GL_NO_ERROR;
1847 if (success) {
[email protected]ff6493f2012-07-31 19:52:251848 memory_tracker_.UpdateMemRepresented(
1849 size.width() * size.height() * samples *
1850 GLES2Util::RenderbufferBytesPerPixel(format));
[email protected]1078f912011-12-23 13:12:141851 }
1852 return success;
[email protected]6217d392010-03-25 22:08:351853}
1854
1855void RenderBuffer::Destroy() {
1856 if (id_ != 0) {
1857 ScopedGLErrorSuppressor suppressor(decoder_);
1858 glDeleteRenderbuffersEXT(1, &id_);
1859 id_ = 0;
[email protected]ff6493f2012-07-31 19:52:251860 memory_tracker_.UpdateMemRepresented(0);
[email protected]6217d392010-03-25 22:08:351861 }
1862}
1863
[email protected]97872062010-11-03 19:07:051864void RenderBuffer::Invalidate() {
1865 id_ = 0;
1866}
1867
[email protected]6217d392010-03-25 22:08:351868FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1869 : decoder_(decoder),
1870 id_(0) {
1871}
1872
1873FrameBuffer::~FrameBuffer() {
1874 // This does not destroy the frame buffer because that would require that
1875 // the associated GL context was current. Just check that it was explicitly
1876 // destroyed.
1877 DCHECK_EQ(id_, 0u);
1878}
1879
1880void FrameBuffer::Create() {
1881 ScopedGLErrorSuppressor suppressor(decoder_);
1882 Destroy();
1883 glGenFramebuffersEXT(1, &id_);
1884}
1885
1886void FrameBuffer::AttachRenderTexture(Texture* texture) {
1887 DCHECK_NE(id_, 0u);
1888 ScopedGLErrorSuppressor suppressor(decoder_);
1889 ScopedFrameBufferBinder binder(decoder_, id_);
1890 GLuint attach_id = texture ? texture->id() : 0;
1891 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1892 GL_COLOR_ATTACHMENT0,
1893 GL_TEXTURE_2D,
1894 attach_id,
1895 0);
1896}
1897
[email protected]b9363b22010-06-09 22:06:151898void FrameBuffer::AttachRenderBuffer(GLenum target,
1899 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351900 DCHECK_NE(id_, 0u);
1901 ScopedGLErrorSuppressor suppressor(decoder_);
1902 ScopedFrameBufferBinder binder(decoder_, id_);
1903 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1904 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151905 target,
[email protected]6217d392010-03-25 22:08:351906 GL_RENDERBUFFER,
1907 attach_id);
1908}
1909
[email protected]6217d392010-03-25 22:08:351910void FrameBuffer::Destroy() {
1911 if (id_ != 0) {
1912 ScopedGLErrorSuppressor suppressor(decoder_);
1913 glDeleteFramebuffersEXT(1, &id_);
1914 id_ = 0;
1915 }
1916}
1917
[email protected]97872062010-11-03 19:07:051918void FrameBuffer::Invalidate() {
1919 id_ = 0;
1920}
1921
[email protected]6217d392010-03-25 22:08:351922GLenum FrameBuffer::CheckStatus() {
1923 DCHECK_NE(id_, 0u);
1924 ScopedGLErrorSuppressor suppressor(decoder_);
1925 ScopedFrameBufferBinder binder(decoder_, id_);
1926 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1927}
1928
[email protected]aa7666122011-09-02 19:45:521929GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1930 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321931}
1932
[email protected]aa7666122011-09-02 19:45:521933GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391934 : GLES2Decoder(),
[email protected]3b1ecc262011-08-03 22:49:571935 group_(group),
[email protected]96449d2c2009-11-25 00:01:321936 error_bits_(0),
[email protected]43410e92012-04-20 17:06:281937 unpack_flip_y_(false),
1938 unpack_premultiply_alpha_(false),
[email protected]6c75c712012-06-19 15:43:171939 unpack_unpremultiply_alpha_(false),
[email protected]b1122982010-05-17 23:04:241940 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491941 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241942 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401943 fixed_attrib_buffer_id_(0),
1944 fixed_attrib_buffer_size_(0),
[email protected]88a61bf2012-10-27 13:00:421945 clear_state_dirty_(true),
[email protected]34ff8b0c2010-10-01 20:06:021946 offscreen_target_color_format_(0),
1947 offscreen_target_depth_format_(0),
1948 offscreen_target_stencil_format_(0),
1949 offscreen_target_samples_(0),
[email protected]8a61d872012-01-20 12:43:561950 offscreen_target_buffer_preserved_(true),
[email protected]97872062010-11-03 19:07:051951 offscreen_saved_color_format_(0),
[email protected]b0af4f52011-09-28 22:04:421952 stream_texture_manager_(NULL),
[email protected]32fe9aa2011-01-21 23:47:131953 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:461954 back_buffer_has_depth_(false),
1955 back_buffer_has_stencil_(false),
[email protected]473c01ccb2011-06-07 01:33:301956 teximage2d_faster_than_texsubimage2d_(true),
[email protected]0f8afe82012-05-14 23:43:011957 log_message_count_(0),
[email protected]a3a93e7b2010-08-28 00:48:561958 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051959 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111960 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001961 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241962 tex_image_2d_failed_(false),
[email protected]38d139d2011-07-14 00:38:431963 frame_number_(0),
[email protected]706b69f2012-07-27 04:59:301964 has_robustness_extension_(false),
[email protected]75c023c2011-08-22 23:54:511965 reset_status_(GL_NO_ERROR),
[email protected]f0d74742011-10-03 16:31:041966 force_webgl_glsl_validation_(false),
[email protected]062c38b2012-01-18 03:25:101967 derivatives_explicitly_enabled_(false),
[email protected]43410e92012-04-20 17:06:281968 compile_shader_always_succeeds_(false),
[email protected]1868a342012-11-07 15:56:021969 viewport_max_width_(0),
1970 viewport_max_height_(0),
[email protected]63b465922012-09-06 02:04:521971 texture_upload_count_(0) {
[email protected]3b1ecc262011-08-03 22:49:571972 DCHECK(group);
1973
[email protected]d2a0e1a2012-08-12 02:25:011974 GLES2DecoderImpl* this_temp = this;
1975 this_in_hex_ = HexEncode(&this_temp, sizeof(this_temp));
1976
[email protected]b1122982010-05-17 23:04:241977 attrib_0_value_.v[0] = 0.0f;
1978 attrib_0_value_.v[1] = 0.0f;
1979 attrib_0_value_.v[2] = 0.0f;
1980 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151981
[email protected]c2f8c8402010-12-06 18:07:241982 // The shader translator is used for WebGL even when running on EGL
1983 // because additional restrictions are needed (like only enabling
1984 // GL_OES_standard_derivatives on demand). It is used for the unit
1985 // tests because
1986 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1987 // empty string to CompileShader and this is not a valid shader.
1988 // TODO(apatrick): fix this test.
1989 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]62e155e2012-10-23 22:43:151990 !features().chromium_webglsl && !force_webgl_glsl_validation_) ||
[email protected]39ba4f02012-03-26 01:16:001991 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
1992 CommandLine::ForCurrentProcess()->HasSwitch(
1993 switches::kDisableGLSLTranslator)) {
[email protected]b9363b22010-06-09 22:06:151994 use_shader_translator_ = false;
1995 }
[email protected]473c01ccb2011-06-07 01:33:301996
[email protected]a39370652012-09-25 21:52:131997 // TODO(gman): Consider setting this based on GPU and/or driver.
[email protected]473c01ccb2011-06-07 01:33:301998 if (IsAngle()) {
1999 teximage2d_faster_than_texsubimage2d_ = false;
[email protected]473c01ccb2011-06-07 01:33:302000 }
[email protected]96449d2c2009-11-25 00:01:322001}
2002
[email protected]80eb6b52012-01-19 00:14:412003GLES2DecoderImpl::~GLES2DecoderImpl() {
2004}
2005
[email protected]c410da802011-03-14 19:17:412006bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:382007 const scoped_refptr<gfx::GLSurface>& surface,
2008 const scoped_refptr<gfx::GLContext>& context,
[email protected]069944672012-04-25 20:52:232009 bool offscreen,
[email protected]c410da802011-03-14 19:17:412010 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:292011 const DisallowedFeatures& disallowed_features,
[email protected]c410da802011-03-14 19:17:412012 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:242013 const std::vector<int32>& attribs) {
[email protected]3551cb202012-05-24 10:55:322014 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
[email protected]63c9b052012-05-17 18:27:382015 DCHECK(context->IsCurrent(surface.get()));
[email protected]66791e382010-07-14 20:48:302016 DCHECK(!context_.get());
2017
[email protected]e844ae22012-01-14 03:36:262018 if (CommandLine::ForCurrentProcess()->HasSwitch(
2019 switches::kEnableGPUDebugging)) {
2020 set_debug(true);
2021 }
2022
[email protected]39ba4f02012-03-26 01:16:002023 if (CommandLine::ForCurrentProcess()->HasSwitch(
2024 switches::kEnableGPUCommandLogging)) {
2025 set_log_commands(true);
2026 }
2027
[email protected]062c38b2012-01-18 03:25:102028 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2029 switches::kCompileShaderAlwaysSucceeds);
2030
[email protected]f62a5ab2011-05-23 20:34:152031
[email protected]63c9b052012-05-17 18:27:382032 // Take ownership of the context and surface. The surface can be replaced with
2033 // SetSurface.
[email protected]fbe20372011-06-01 01:46:382034 context_ = context;
[email protected]63c9b052012-05-17 18:27:382035 surface_ = surface;
[email protected]eb54a562010-01-20 21:55:182036
[email protected]e82fb792011-09-22 00:33:292037 if (!group_->Initialize(disallowed_features, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:222038 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:392039 << "failed to initialize.";
[email protected]1871a092011-10-10 21:46:422040 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]63c9b052012-05-17 18:27:382041 Destroy(true);
[email protected]ae1741092010-11-17 19:16:032042 return false;
[email protected]a3ded6d2010-10-19 06:44:392043 }
[email protected]b64c24952012-04-19 03:20:272044 CHECK_GL_ERROR();
[email protected]43410e92012-04-20 17:06:282045
[email protected]e82fb792011-09-22 00:33:292046 disallowed_features_ = disallowed_features;
[email protected]246a70452010-03-05 21:53:502047
[email protected]af6380962012-11-29 23:24:132048 state_.attrib_values.resize(group_->max_vertex_attribs());
[email protected]944b62f32012-09-27 02:20:462049 default_vertex_attrib_manager_ = new VertexAttribManager();
2050 default_vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
2051
[email protected]ab4fd7282012-10-12 16:25:572052 // vertex_attrib_manager is set to default_vertex_attrib_manager_ by this call
2053 DoBindVertexArrayOES(0);
[email protected]876f6fee2010-08-02 23:10:322054
[email protected]d6ca4792012-05-14 19:24:132055 query_manager_.reset(new QueryManager(this, feature_info_));
[email protected]944b62f32012-09-27 02:20:462056 vertex_array_manager_.reset(new VertexArrayManager());
[email protected]882ba1e22012-03-08 19:02:532057
[email protected]302ce6d2011-07-07 23:28:112058 util_.set_num_compressed_texture_formats(
2059 validators_->compressed_texture_format.GetValues().size());
2060
[email protected]1071e572011-02-09 20:00:122061 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2062 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2063 // OpenGL ES 2.0 does not have this issue.
2064 glEnableVertexAttribArray(0);
2065 }
[email protected]b1122982010-05-17 23:04:242066 glGenBuffersARB(1, &attrib_0_buffer_id_);
2067 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2068 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2069 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:402070 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:082071
[email protected]1868a342012-11-07 15:56:022072 state_.texture_units.resize(group_->max_texture_units());
2073 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
[email protected]00f893d2010-08-24 18:55:492074 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:312075 // We want the last bind to be 2D.
2076 TextureManager::TextureInfo* info;
[email protected]62e155e2012-10-23 22:43:152077 if (features().oes_egl_image_external) {
[email protected]61eeb33f2011-07-26 15:30:312078 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_EXTERNAL_OES);
[email protected]e259eb412012-10-13 05:47:242079 state_.texture_units[tt].bound_texture_external_oes = info;
[email protected]61eeb33f2011-07-26 15:30:312080 glBindTexture(GL_TEXTURE_EXTERNAL_OES, info->service_id());
2081 }
[email protected]62e155e2012-10-23 22:43:152082 if (features().arb_texture_rectangle) {
[email protected]e51bdf32011-11-23 22:21:462083 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_RECTANGLE_ARB);
[email protected]e259eb412012-10-13 05:47:242084 state_.texture_units[tt].bound_texture_rectangle_arb = info;
[email protected]e51bdf32011-11-23 22:21:462085 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, info->service_id());
2086 }
[email protected]61eeb33f2011-07-26 15:30:312087 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]e259eb412012-10-13 05:47:242088 state_.texture_units[tt].bound_texture_cube_map = info;
[email protected]00f893d2010-08-24 18:55:492089 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
2090 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
[email protected]e259eb412012-10-13 05:47:242091 state_.texture_units[tt].bound_texture_2d = info;
[email protected]00f893d2010-08-24 18:55:492092 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:152093 }
[email protected]00f893d2010-08-24 18:55:492094 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:502095 CHECK_GL_ERROR();
2096
[email protected]297ca1c2011-06-20 23:08:462097 ContextCreationAttribParser attrib_parser;
2098 if (!attrib_parser.Parse(attribs))
2099 return false;
[email protected]41c56362011-06-14 16:47:432100
[email protected]297ca1c2011-06-20 23:08:462101 // These are NOT if the back buffer has these proprorties. They are
2102 // if we want the command buffer to enforce them regardless of what
2103 // the real backbuffer is assuming the real back buffer gives us more than
2104 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2105 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2106 // can't do anything about that.
2107
2108 GLint v = 0;
2109 glGetIntegerv(GL_ALPHA_BITS, &v);
2110 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2111 // user requested RGB then RGB. If the user did not specify a preference than
2112 // use whatever we were given. Same for DEPTH and STENCIL.
2113 back_buffer_color_format_ =
2114 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2115 glGetIntegerv(GL_DEPTH_BITS, &v);
2116 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2117 glGetIntegerv(GL_STENCIL_BITS, &v);
2118 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2119
[email protected]069944672012-04-25 20:52:232120 if (offscreen) {
[email protected]34ff8b0c2010-10-01 20:06:022121 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:542122 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:022123 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
2124 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:432125 // max_sample_count must be initialized to a sane value. If
2126 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2127 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:022128 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2129 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2130 max_sample_count);
2131 } else {
2132 offscreen_target_samples_ = 1;
2133 }
[email protected]8a61d872012-01-20 12:43:562134 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
[email protected]34ff8b0c2010-10-01 20:06:022135
2136 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2137 const bool rgb8_supported =
2138 context_->HasExtension("GL_OES_rgb8_rgba8");
2139 // The only available default render buffer formats in GLES2 have very
2140 // little precision. Don't enable multisampling unless 8-bit render
2141 // buffer formats are available--instead fall back to 8-bit textures.
2142 if (rgb8_supported && offscreen_target_samples_ > 1) {
2143 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2144 GL_RGBA8 : GL_RGB8;
2145 } else {
2146 offscreen_target_samples_ = 1;
2147 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2148 GL_RGBA : GL_RGB;
2149 }
2150
2151 // ANGLE only supports packed depth/stencil formats, so use it if it is
2152 // available.
2153 const bool depth24_stencil8_supported =
2154 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272155 VLOG(1) << "GL_OES_packed_depth_stencil "
2156 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:002157 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2158 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022159 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2160 offscreen_target_stencil_format_ = 0;
2161 } else {
2162 // It may be the case that this depth/stencil combination is not
2163 // supported, but this will be checked later by CheckFramebufferStatus.
2164 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2165 GL_DEPTH_COMPONENT16 : 0;
2166 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2167 GL_STENCIL_INDEX8 : 0;
2168 }
2169 } else {
2170 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2171 GL_RGBA : GL_RGB;
2172
2173 // If depth is requested at all, use the packed depth stencil format if
2174 // it's available, as some desktop GL drivers don't support any non-packed
2175 // formats for depth attachments.
2176 const bool depth24_stencil8_supported =
2177 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272178 VLOG(1) << "GL_EXT_packed_depth_stencil "
2179 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:022180
[email protected]71ee3642010-10-14 18:08:002181 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2182 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022183 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2184 offscreen_target_stencil_format_ = 0;
2185 } else {
2186 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2187 GL_DEPTH_COMPONENT : 0;
2188 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2189 GL_STENCIL_INDEX : 0;
2190 }
2191 }
2192
[email protected]97872062010-11-03 19:07:052193 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2194 GL_RGBA : GL_RGB;
2195
[email protected]6217d392010-03-25 22:08:352196 // Create the target frame buffer. This is the one that the client renders
2197 // directly to.
2198 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
2199 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022200 // Due to GLES2 format limitations, either the color texture (for
2201 // non-multisampling) or the color render buffer (for multisampling) will be
2202 // attached to the offscreen frame buffer. The render buffer has more
2203 // limited formats available to it, but the texture can't do multisampling.
2204 if (IsOffscreenBufferMultisampled()) {
2205 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
2206 offscreen_target_color_render_buffer_->Create();
2207 } else {
2208 offscreen_target_color_texture_.reset(new Texture(this));
2209 offscreen_target_color_texture_->Create();
2210 }
2211 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152212 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022213 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152214 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:352215
2216 // Create the saved offscreen texture. The target frame buffer is copied
2217 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:022218 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
2219 offscreen_saved_frame_buffer_->Create();
2220 //
[email protected]6217d392010-03-25 22:08:352221 offscreen_saved_color_texture_.reset(new Texture(this));
2222 offscreen_saved_color_texture_->Create();
2223
[email protected]6217d392010-03-25 22:08:352224 // Allocate the render buffers at their initial size and check the status
2225 // of the frame buffers is okay.
[email protected]799b4b22011-08-22 17:09:592226 if (!ResizeOffscreenFrameBuffer(size)) {
[email protected]d0498742010-09-20 20:27:012227 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]63c9b052012-05-17 18:27:382228 Destroy(true);
[email protected]6217d392010-03-25 22:08:352229 return false;
2230 }
2231
2232 // Bind to the new default frame buffer (the offscreen target frame buffer).
2233 // This should now be associated with ID zero.
2234 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2235 }
2236
[email protected]295faf4b2012-01-25 23:31:412237 // Clear the backbuffer.
2238 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2239
[email protected]76a0ee102010-04-07 21:03:042240 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2241 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2242 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372243 // mailing list archives. It also implicitly enables the desktop GL
2244 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2245 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152246 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2247 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372248 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152249 }
[email protected]de17df392010-04-23 21:09:412250
[email protected]706b69f2012-07-27 04:59:302251 has_robustness_extension_ =
2252 context->HasExtension("GL_ARB_robustness") ||
2253 context->HasExtension("GL_EXT_robustness");
[email protected]38d139d2011-07-14 00:38:432254
[email protected]c2f8c8402010-12-06 18:07:242255 if (!InitializeShaderTranslator()) {
2256 return false;
[email protected]de17df392010-04-23 21:09:412257 }
[email protected]76a0ee102010-04-07 21:03:042258
[email protected]e259eb412012-10-13 05:47:242259 state_.viewport_width = size.width();
2260 state_.viewport_height = size.height();
[email protected]43410e92012-04-20 17:06:282261
[email protected]5904806b2012-05-08 18:10:222262 GLint viewport_params[4] = { 0 };
[email protected]43410e92012-04-20 17:06:282263 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
[email protected]1868a342012-11-07 15:56:022264 viewport_max_width_ = viewport_params[0];
2265 viewport_max_height_ = viewport_params[1];
[email protected]43410e92012-04-20 17:06:282266
[email protected]88a61bf2012-10-27 13:00:422267 state_.scissor_width = state_.viewport_width;
2268 state_.scissor_height = state_.viewport_height;
2269
[email protected]11f3e702012-06-19 19:00:012270 // Set all the default state because some GL drivers get it wrong.
[email protected]f731b9462012-10-30 00:35:222271 state_.InitCapabilities();
2272 state_.InitState();
[email protected]e259eb412012-10-13 05:47:242273 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
[email protected]88a61bf2012-10-27 13:00:422274 glHint(GL_GENERATE_MIPMAP_HINT, state_.hint_generate_mipmap);
[email protected]e259eb412012-10-13 05:47:242275 glPixelStorei(GL_PACK_ALIGNMENT, state_.pack_alignment);
[email protected]e259eb412012-10-13 05:47:242276 glPixelStorei(GL_UNPACK_ALIGNMENT, state_.unpack_alignment);
[email protected]11f3e702012-06-19 19:00:012277
2278 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2279 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2280 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2281 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2282
[email protected]6d9374e2012-07-17 03:31:242283 // AMD and Intel drivers on Mac OS apparently get gl_PointCoord
2284 // backward from the spec and this setting makes them work
2285 // correctly. rdar://problem/11883495
[email protected]62e155e2012-10-23 22:43:152286 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
[email protected]dd289a5d62012-06-30 22:05:462287 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2288 }
[email protected]dd289a5d62012-06-30 22:05:462289
[email protected]246a70452010-03-05 21:53:502290 return true;
[email protected]96449d2c2009-11-25 00:01:322291}
2292
[email protected]302ce6d2011-07-07 23:28:112293void GLES2DecoderImpl::UpdateCapabilities() {
2294 util_.set_num_compressed_texture_formats(
2295 validators_->compressed_texture_format.GetValues().size());
2296 util_.set_num_shader_binary_formats(
2297 validators_->shader_binary_format.GetValues().size());
2298}
2299
[email protected]c2f8c8402010-12-06 18:07:242300bool GLES2DecoderImpl::InitializeShaderTranslator() {
[email protected]a5d3dad2012-05-26 04:34:442301 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2302
[email protected]c2f8c8402010-12-06 18:07:242303 // Re-check the state of use_shader_translator_ each time this is called.
2304 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]62e155e2012-10-23 22:43:152305 (features().chromium_webglsl || force_webgl_glsl_validation_) &&
[email protected]c2f8c8402010-12-06 18:07:242306 !use_shader_translator_) {
2307 use_shader_translator_ = true;
2308 }
2309 if (!use_shader_translator_) {
2310 return true;
2311 }
2312 ShBuiltInResources resources;
2313 ShInitBuiltInResources(&resources);
2314 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2315 resources.MaxVertexUniformVectors =
2316 group_->max_vertex_uniform_vectors();
2317 resources.MaxVaryingVectors = group_->max_varying_vectors();
2318 resources.MaxVertexTextureImageUnits =
2319 group_->max_vertex_texture_image_units();
2320 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2321 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2322 resources.MaxFragmentUniformVectors =
2323 group_->max_fragment_uniform_vectors();
2324 resources.MaxDrawBuffers = 1;
[email protected]f0d74742011-10-03 16:31:042325
2326 if (force_webgl_glsl_validation_) {
2327 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2328 } else {
2329 resources.OES_standard_derivatives =
[email protected]62e155e2012-10-23 22:43:152330 features().oes_standard_derivatives ? 1 : 0;
[email protected]e51bdf32011-11-23 22:21:462331 resources.ARB_texture_rectangle =
[email protected]62e155e2012-10-23 22:43:152332 features().arb_texture_rectangle ? 1 : 0;
[email protected]70e7bb12012-09-29 14:01:062333 resources.OES_EGL_image_external =
[email protected]62e155e2012-10-23 22:43:152334 features().oes_egl_image_external ? 1 : 0;
[email protected]f0d74742011-10-03 16:31:042335 }
2336
[email protected]693ca512012-11-13 18:09:132337 if (features().enable_shader_name_hashing)
2338 resources.HashFunction = &CityHashForAngle;
2339
[email protected]f0d74742011-10-03 16:31:042340 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ||
[email protected]62e155e2012-10-23 22:43:152341 features().chromium_webglsl ? SH_WEBGL_SPEC : SH_GLES2_SPEC;
[email protected]a2a0fe762011-09-20 00:59:122342 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2343 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2344 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2345 ShaderTranslatorInterface::GlslBuiltInFunctionBehavior function_behavior =
[email protected]62e155e2012-10-23 22:43:152346 workarounds().needs_glsl_built_in_function_emulation ?
[email protected]a2a0fe762011-09-20 00:59:122347 ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated :
2348 ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal;
[email protected]87fb6ab2012-06-13 22:28:042349
2350 ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
2351 vertex_translator_ = cache->GetTranslator(
2352 SH_VERTEX_SHADER, shader_spec, &resources,
2353 implementation_type, function_behavior);
2354 if (!vertex_translator_.get()) {
[email protected]c2f8c8402010-12-06 18:07:242355 LOG(ERROR) << "Could not initialize vertex shader translator.";
[email protected]63c9b052012-05-17 18:27:382356 Destroy(true);
[email protected]c2f8c8402010-12-06 18:07:242357 return false;
2358 }
[email protected]87fb6ab2012-06-13 22:28:042359
2360 fragment_translator_ = cache->GetTranslator(
2361 SH_FRAGMENT_SHADER, shader_spec, &resources,
2362 implementation_type, function_behavior);
2363 if (!fragment_translator_.get()) {
[email protected]c2f8c8402010-12-06 18:07:242364 LOG(ERROR) << "Could not initialize fragment shader translator.";
[email protected]63c9b052012-05-17 18:27:382365 Destroy(true);
[email protected]c2f8c8402010-12-06 18:07:242366 return false;
2367 }
2368 return true;
2369}
2370
[email protected]ae51d192010-04-27 00:48:032371bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472372 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032373 if (GetBufferInfo(client_ids[ii])) {
2374 return false;
2375 }
2376 }
2377 scoped_array<GLuint> service_ids(new GLuint[n]);
2378 glGenBuffersARB(n, service_ids.get());
2379 for (GLsizei ii = 0; ii < n; ++ii) {
2380 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2381 }
2382 return true;
2383}
2384
2385bool GLES2DecoderImpl::GenFramebuffersHelper(
2386 GLsizei n, const GLuint* client_ids) {
2387 for (GLsizei ii = 0; ii < n; ++ii) {
2388 if (GetFramebufferInfo(client_ids[ii])) {
2389 return false;
2390 }
2391 }
2392 scoped_array<GLuint> service_ids(new GLuint[n]);
2393 glGenFramebuffersEXT(n, service_ids.get());
2394 for (GLsizei ii = 0; ii < n; ++ii) {
2395 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2396 }
2397 return true;
2398}
2399
2400bool GLES2DecoderImpl::GenRenderbuffersHelper(
2401 GLsizei n, const GLuint* client_ids) {
2402 for (GLsizei ii = 0; ii < n; ++ii) {
2403 if (GetRenderbufferInfo(client_ids[ii])) {
2404 return false;
2405 }
2406 }
2407 scoped_array<GLuint> service_ids(new GLuint[n]);
2408 glGenRenderbuffersEXT(n, service_ids.get());
2409 for (GLsizei ii = 0; ii < n; ++ii) {
2410 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2411 }
2412 return true;
2413}
2414
2415bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2416 for (GLsizei ii = 0; ii < n; ++ii) {
2417 if (GetTextureInfo(client_ids[ii])) {
2418 return false;
2419 }
2420 }
2421 scoped_array<GLuint> service_ids(new GLuint[n]);
2422 glGenTextures(n, service_ids.get());
2423 for (GLsizei ii = 0; ii < n; ++ii) {
2424 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2425 }
2426 return true;
2427}
2428
2429void GLES2DecoderImpl::DeleteBuffersHelper(
2430 GLsizei n, const GLuint* client_ids) {
2431 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102432 BufferManager::BufferInfo* buffer = GetBufferInfo(client_ids[ii]);
2433 if (buffer && !buffer->IsDeleted()) {
[email protected]e259eb412012-10-13 05:47:242434 state_.vertex_attrib_manager->Unbind(buffer);
2435 if (state_.bound_array_buffer == buffer) {
2436 state_.bound_array_buffer = NULL;
[email protected]a0b78dc2011-11-11 10:43:102437 }
[email protected]ae51d192010-04-27 00:48:032438 RemoveBufferInfo(client_ids[ii]);
2439 }
[email protected]a93bb842010-02-16 23:03:472440 }
[email protected]07f54fcc2009-12-22 02:46:302441}
2442
[email protected]ae51d192010-04-27 00:48:032443void GLES2DecoderImpl::DeleteFramebuffersHelper(
2444 GLsizei n, const GLuint* client_ids) {
[email protected]ebfb73c2012-08-15 02:37:452445 bool supports_separate_framebuffer_binds =
[email protected]62e155e2012-10-23 22:43:152446 features().chromium_framebuffer_multisample;
[email protected]b177ae22011-11-01 03:29:112447
[email protected]a25fa872010-03-25 02:57:582448 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102449 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ae51d192010-04-27 00:48:032450 GetFramebufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102451 if (framebuffer && !framebuffer->IsDeleted()) {
[email protected]e259eb412012-10-13 05:47:242452 if (framebuffer == state_.bound_draw_framebuffer) {
2453 state_.bound_draw_framebuffer = NULL;
[email protected]88a61bf2012-10-27 13:00:422454 clear_state_dirty_ = true;
[email protected]ebfb73c2012-08-15 02:37:452455 GLenum target = supports_separate_framebuffer_binds ?
2456 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
[email protected]b177ae22011-11-01 03:29:112457 glBindFramebufferEXT(target, GetBackbufferServiceId());
2458 }
[email protected]e259eb412012-10-13 05:47:242459 if (framebuffer == state_.bound_read_framebuffer) {
2460 state_.bound_read_framebuffer = NULL;
[email protected]ebfb73c2012-08-15 02:37:452461 GLenum target = supports_separate_framebuffer_binds ?
2462 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
[email protected]b177ae22011-11-01 03:29:112463 glBindFramebufferEXT(target, GetBackbufferServiceId());
[email protected]297ca1c2011-06-20 23:08:462464 }
[email protected]ae51d192010-04-27 00:48:032465 RemoveFramebufferInfo(client_ids[ii]);
2466 }
[email protected]a25fa872010-03-25 02:57:582467 }
[email protected]07f54fcc2009-12-22 02:46:302468}
2469
[email protected]ae51d192010-04-27 00:48:032470void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2471 GLsizei n, const GLuint* client_ids) {
[email protected]ebfb73c2012-08-15 02:37:452472 bool supports_separate_framebuffer_binds =
[email protected]62e155e2012-10-23 22:43:152473 features().chromium_framebuffer_multisample;
[email protected]a25fa872010-03-25 02:57:582474 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102475 RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]ae51d192010-04-27 00:48:032476 GetRenderbufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102477 if (renderbuffer && !renderbuffer->IsDeleted()) {
[email protected]e259eb412012-10-13 05:47:242478 if (state_.bound_renderbuffer == renderbuffer) {
2479 state_.bound_renderbuffer = NULL;
[email protected]a0b78dc2011-11-11 10:43:102480 }
2481 // Unbind from current framebuffers.
[email protected]ebfb73c2012-08-15 02:37:452482 if (supports_separate_framebuffer_binds) {
[email protected]e259eb412012-10-13 05:47:242483 if (state_.bound_read_framebuffer) {
2484 state_.bound_read_framebuffer->UnbindRenderbuffer(
[email protected]ebfb73c2012-08-15 02:37:452485 GL_READ_FRAMEBUFFER_EXT, renderbuffer);
[email protected]a0b78dc2011-11-11 10:43:102486 }
[email protected]e259eb412012-10-13 05:47:242487 if (state_.bound_draw_framebuffer) {
2488 state_.bound_draw_framebuffer->UnbindRenderbuffer(
[email protected]ebfb73c2012-08-15 02:37:452489 GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
[email protected]a0b78dc2011-11-11 10:43:102490 }
2491 } else {
[email protected]e259eb412012-10-13 05:47:242492 if (state_.bound_draw_framebuffer) {
2493 state_.bound_draw_framebuffer->UnbindRenderbuffer(
[email protected]a0b78dc2011-11-11 10:43:102494 GL_FRAMEBUFFER, renderbuffer);
2495 }
2496 }
[email protected]88a61bf2012-10-27 13:00:422497 clear_state_dirty_ = true;
[email protected]ae51d192010-04-27 00:48:032498 RemoveRenderbufferInfo(client_ids[ii]);
2499 }
[email protected]a25fa872010-03-25 02:57:582500 }
[email protected]07f54fcc2009-12-22 02:46:302501}
2502
[email protected]ae51d192010-04-27 00:48:032503void GLES2DecoderImpl::DeleteTexturesHelper(
2504 GLsizei n, const GLuint* client_ids) {
[email protected]ebfb73c2012-08-15 02:37:452505 bool supports_separate_framebuffer_binds =
[email protected]62e155e2012-10-23 22:43:152506 features().chromium_framebuffer_multisample;
[email protected]a93bb842010-02-16 23:03:472507 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102508 TextureManager::TextureInfo* texture = GetTextureInfo(client_ids[ii]);
2509 if (texture && !texture->IsDeleted()) {
2510 if (texture->IsAttachedToFramebuffer()) {
[email protected]88a61bf2012-10-27 13:00:422511 clear_state_dirty_ = true;
[email protected]297ca1c2011-06-20 23:08:462512 }
[email protected]a0b78dc2011-11-11 10:43:102513 // Unbind texture from texture units.
[email protected]1868a342012-11-07 15:56:022514 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
[email protected]e259eb412012-10-13 05:47:242515 state_.texture_units[jj].Unbind(texture);
[email protected]a0b78dc2011-11-11 10:43:102516 }
2517 // Unbind from current framebuffers.
[email protected]ebfb73c2012-08-15 02:37:452518 if (supports_separate_framebuffer_binds) {
[email protected]e259eb412012-10-13 05:47:242519 if (state_.bound_read_framebuffer) {
2520 state_.bound_read_framebuffer->UnbindTexture(
[email protected]ebfb73c2012-08-15 02:37:452521 GL_READ_FRAMEBUFFER_EXT, texture);
[email protected]a0b78dc2011-11-11 10:43:102522 }
[email protected]e259eb412012-10-13 05:47:242523 if (state_.bound_draw_framebuffer) {
2524 state_.bound_draw_framebuffer->UnbindTexture(
[email protected]ebfb73c2012-08-15 02:37:452525 GL_DRAW_FRAMEBUFFER_EXT, texture);
[email protected]a0b78dc2011-11-11 10:43:102526 }
2527 } else {
[email protected]e259eb412012-10-13 05:47:242528 if (state_.bound_draw_framebuffer) {
2529 state_.bound_draw_framebuffer->UnbindTexture(GL_FRAMEBUFFER, texture);
[email protected]a0b78dc2011-11-11 10:43:102530 }
2531 }
2532 GLuint service_id = texture->service_id();
2533 if (texture->IsStreamTexture() && stream_texture_manager_) {
[email protected]b0af4f52011-09-28 22:04:422534 stream_texture_manager_->DestroyStreamTexture(service_id);
2535 }
[email protected]e51bdf32011-11-23 22:21:462536#if defined(OS_MACOSX)
2537 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2538 ReleaseIOSurfaceForTexture(service_id);
2539 }
2540#endif
[email protected]ae51d192010-04-27 00:48:032541 RemoveTextureInfo(client_ids[ii]);
2542 }
[email protected]a93bb842010-02-16 23:03:472543 }
[email protected]07f54fcc2009-12-22 02:46:302544}
2545
[email protected]43f28f832010-02-03 02:28:482546// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322547
[email protected]eb54a562010-01-20 21:55:182548bool GLES2DecoderImpl::MakeCurrent() {
[email protected]63c9b052012-05-17 18:27:382549 if (!context_.get() || !context_->MakeCurrent(surface_.get()))
2550 return false;
2551
2552 if (WasContextLost()) {
[email protected]38d139d2011-07-14 00:38:432553 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
[email protected]63c9b052012-05-17 18:27:382554 return false;
[email protected]38d139d2011-07-14 00:38:432555 }
2556
[email protected]63c9b052012-05-17 18:27:382557 return true;
[email protected]eb54a562010-01-20 21:55:182558}
2559
[email protected]a96a6022011-11-04 00:58:122560void GLES2DecoderImpl::ReleaseCurrent() {
2561 if (context_.get())
2562 context_->ReleaseCurrent(surface_.get());
2563}
2564
[email protected]8e3e0662010-08-23 18:46:302565void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
[email protected]0d6bfdc2011-11-02 01:32:202566 RenderbufferManager::RenderbufferInfo* renderbuffer =
2567 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
[email protected]8e3e0662010-08-23 18:46:302568 glBindRenderbufferEXT(
[email protected]0d6bfdc2011-11-02 01:32:202569 GL_RENDERBUFFER, renderbuffer ? renderbuffer->service_id() : 0);
[email protected]8e3e0662010-08-23 18:46:302570}
2571
2572static void RebindCurrentFramebuffer(
2573 GLenum target,
2574 FramebufferManager::FramebufferInfo* info,
[email protected]a3783712012-01-20 22:18:242575 GLuint back_buffer_service_id) {
[email protected]8e3e0662010-08-23 18:46:302576 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462577
[email protected]a3783712012-01-20 22:18:242578 if (framebuffer_id == 0) {
2579 framebuffer_id = back_buffer_service_id;
[email protected]8e3e0662010-08-23 18:46:302580 }
[email protected]297ca1c2011-06-20 23:08:462581
[email protected]8e3e0662010-08-23 18:46:302582 glBindFramebufferEXT(target, framebuffer_id);
2583}
2584
2585void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]88a61bf2012-10-27 13:00:422586 clear_state_dirty_ = true;
[email protected]297ca1c2011-06-20 23:08:462587
[email protected]62e155e2012-10-23 22:43:152588 if (!features().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302589 RebindCurrentFramebuffer(
2590 GL_FRAMEBUFFER,
[email protected]e259eb412012-10-13 05:47:242591 state_.bound_draw_framebuffer.get(),
[email protected]a3783712012-01-20 22:18:242592 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302593 } else {
2594 RebindCurrentFramebuffer(
2595 GL_READ_FRAMEBUFFER_EXT,
[email protected]e259eb412012-10-13 05:47:242596 state_.bound_read_framebuffer.get(),
[email protected]a3783712012-01-20 22:18:242597 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302598 RebindCurrentFramebuffer(
2599 GL_DRAW_FRAMEBUFFER_EXT,
[email protected]e259eb412012-10-13 05:47:242600 state_.bound_draw_framebuffer.get(),
[email protected]a3783712012-01-20 22:18:242601 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302602 }
2603}
2604
2605void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
[email protected]e259eb412012-10-13 05:47:242606 TextureUnit& info = state_.texture_units[0];
[email protected]8e3e0662010-08-23 18:46:302607 GLuint last_id;
2608 if (info.bound_texture_2d) {
2609 last_id = info.bound_texture_2d->service_id();
2610 } else {
2611 last_id = 0;
2612 }
2613
2614 glBindTexture(GL_TEXTURE_2D, last_id);
[email protected]e259eb412012-10-13 05:47:242615 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
[email protected]8e3e0662010-08-23 18:46:302616}
2617
[email protected]0d6bfdc2011-11-02 01:32:202618bool GLES2DecoderImpl::CheckFramebufferValid(
2619 FramebufferManager::FramebufferInfo* framebuffer,
2620 GLenum target, const char* func_name) {
[email protected]a0b78dc2011-11-11 10:43:102621 if (!framebuffer) {
[email protected]0d6bfdc2011-11-02 01:32:202622 return true;
2623 }
2624
[email protected]968351b2011-12-20 08:26:512625 if (framebuffer_manager()->IsComplete(framebuffer)) {
2626 return true;
2627 }
2628
[email protected]0d6bfdc2011-11-02 01:32:202629 GLenum completeness = framebuffer->IsPossiblyComplete();
2630 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
2631 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:432632 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
[email protected]3a03a8f2011-03-19 00:51:272633 return false;
2634 }
[email protected]0d6bfdc2011-11-02 01:32:202635
2636 // Are all the attachments cleared?
2637 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2638 texture_manager()->HaveUnclearedMips()) {
2639 if (!framebuffer->IsCleared()) {
2640 // Can we clear them?
[email protected]73276522012-11-09 05:50:202641 if (framebuffer->GetStatus(texture_manager(), target) !=
2642 GL_FRAMEBUFFER_COMPLETE) {
[email protected]0d6bfdc2011-11-02 01:32:202643 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:432644 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2645 "framebuffer incomplete (clear)");
[email protected]0d6bfdc2011-11-02 01:32:202646 return false;
2647 }
2648 ClearUnclearedAttachments(target, framebuffer);
2649 }
2650 }
2651
[email protected]968351b2011-12-20 08:26:512652 if (!framebuffer_manager()->IsComplete(framebuffer)) {
[email protected]73276522012-11-09 05:50:202653 if (framebuffer->GetStatus(texture_manager(), target) !=
2654 GL_FRAMEBUFFER_COMPLETE) {
[email protected]968351b2011-12-20 08:26:512655 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:432656 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2657 "framebuffer incomplete (check)");
[email protected]968351b2011-12-20 08:26:512658 return false;
2659 }
2660 framebuffer_manager()->MarkAsComplete(framebuffer);
2661 }
2662
[email protected]0d6bfdc2011-11-02 01:32:202663 // NOTE: At this point we don't know if the framebuffer is complete but
2664 // we DO know that everything that needs to be cleared has been cleared.
[email protected]3a03a8f2011-03-19 00:51:272665 return true;
2666}
2667
[email protected]0d6bfdc2011-11-02 01:32:202668bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
[email protected]62e155e2012-10-23 22:43:152669 if (!features().chromium_framebuffer_multisample) {
[email protected]0d6bfdc2011-11-02 01:32:202670 return CheckFramebufferValid(
[email protected]e259eb412012-10-13 05:47:242671 state_.bound_draw_framebuffer, GL_FRAMEBUFFER_EXT, func_name);
[email protected]0d6bfdc2011-11-02 01:32:202672 }
2673 return CheckFramebufferValid(
[email protected]e259eb412012-10-13 05:47:242674 state_.bound_draw_framebuffer,
2675 GL_DRAW_FRAMEBUFFER_EXT, func_name) &&
[email protected]0d6bfdc2011-11-02 01:32:202676 CheckFramebufferValid(
[email protected]e259eb412012-10-13 05:47:242677 state_.bound_read_framebuffer,
2678 GL_READ_FRAMEBUFFER_EXT, func_name);
[email protected]0d6bfdc2011-11-02 01:32:202679}
2680
[email protected]8e3e0662010-08-23 18:46:302681gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
[email protected]0d6bfdc2011-11-02 01:32:202682 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:452683 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:202684 if (framebuffer != NULL) {
[email protected]9edc6b22010-12-23 02:00:262685 const FramebufferManager::FramebufferInfo::Attachment* attachment =
[email protected]0d6bfdc2011-11-02 01:32:202686 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
[email protected]9edc6b22010-12-23 02:00:262687 if (attachment) {
2688 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502689 }
[email protected]9edc6b22010-12-23 02:00:262690 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022691 } else if (offscreen_target_frame_buffer_.get()) {
2692 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352693 } else {
[email protected]f62a5ab2011-05-23 20:34:152694 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022695 }
[email protected]246a70452010-03-05 21:53:502696}
2697
[email protected]9edc6b22010-12-23 02:00:262698GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202699 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:452700 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:202701 if (framebuffer != NULL) {
2702 return framebuffer->GetColorAttachmentFormat();
[email protected]297ca1c2011-06-20 23:08:462703 } else if (offscreen_target_frame_buffer_.get()) {
2704 return offscreen_target_color_format_;
2705 } else {
2706 return back_buffer_color_format_;
2707 }
2708}
2709
2710GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202711 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:452712 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:202713 if (framebuffer != NULL) {
2714 return framebuffer->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262715 } else if (offscreen_target_frame_buffer_.get()) {
2716 return offscreen_target_color_format_;
2717 } else {
[email protected]32fe9aa2011-01-21 23:47:132718 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262719 }
2720}
2721
[email protected]9a5afa432011-07-22 18:16:392722void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]34ff8b0c2010-10-01 20:06:022723 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582724 // Update the info about the offscreen saved color texture in the parent.
2725 // The reference to the parent is a weak pointer and will become null if the
2726 // parent is later destroyed.
[email protected]262d7aa2010-12-03 22:07:292727 TextureManager* parent_texture_manager = parent_->texture_manager();
[email protected]262d7aa2010-12-03 22:07:292728 parent_texture_manager->SetLevelInfo(
[email protected]8a61d872012-01-20 12:43:562729 offscreen_saved_color_texture_info_,
[email protected]ef526492010-06-02 23:12:252730 GL_TEXTURE_2D,
2731 0, // level
2732 GL_RGBA,
[email protected]799b4b22011-08-22 17:09:592733 offscreen_size_.width(),
2734 offscreen_size_.height(),
[email protected]ef526492010-06-02 23:12:252735 1, // depth
2736 0, // border
2737 GL_RGBA,
[email protected]0d6bfdc2011-11-02 01:32:202738 GL_UNSIGNED_BYTE,
2739 true);
[email protected]262d7aa2010-12-03 22:07:292740 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562741 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042742 GL_TEXTURE_MAG_FILTER,
2743 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292744 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562745 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042746 GL_TEXTURE_MIN_FILTER,
2747 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292748 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562749 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042750 GL_TEXTURE_WRAP_S,
2751 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292752 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562753 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042754 GL_TEXTURE_WRAP_T,
2755 GL_CLAMP_TO_EDGE);
[email protected]8a61d872012-01-20 12:43:562756 } else {
2757 offscreen_saved_color_texture_info_ = NULL;
[email protected]0c8c9d22010-06-25 17:36:392758 }
[email protected]6217d392010-03-25 22:08:352759}
2760
[email protected]799b4b22011-08-22 17:09:592761void GLES2DecoderImpl::SetResizeCallback(
[email protected]9d37f062011-11-22 01:24:522762 const base::Callback<void(gfx::Size)>& callback) {
2763 resize_callback_ = callback;
[email protected]7ff86b92010-11-25 17:50:002764}
2765
[email protected]6b6e7ee2011-12-13 08:04:522766void GLES2DecoderImpl::SetMsgCallback(const MsgCallback& callback) {
2767 msg_callback_ = callback;
2768}
2769
[email protected]b0af4f52011-09-28 22:04:422770void GLES2DecoderImpl::SetStreamTextureManager(StreamTextureManager* manager) {
2771 stream_texture_manager_ = manager;
2772}
2773
[email protected]1318e922010-09-17 22:03:162774bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2775 uint32* service_texture_id) {
2776 TextureManager::TextureInfo* texture =
2777 texture_manager()->GetTextureInfo(client_texture_id);
2778 if (texture) {
2779 *service_texture_id = texture->service_id();
2780 return true;
2781 }
2782 return false;
2783}
2784
[email protected]63b465922012-09-06 02:04:522785uint32 GLES2DecoderImpl::GetTextureUploadCount() {
2786 return texture_upload_count_;
2787}
2788
2789base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
2790 return total_texture_upload_time_;
2791}
2792
2793base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
2794 return total_processing_commands_time_;
2795}
2796
[email protected]dc25dda2012-09-27 21:36:302797void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
2798 total_processing_commands_time_ += time;
2799}
2800
[email protected]63c9b052012-05-17 18:27:382801void GLES2DecoderImpl::Destroy(bool have_context) {
2802 DCHECK(!have_context || context_->IsCurrent(NULL));
[email protected]97872062010-11-03 19:07:052803
[email protected]c826d732012-02-09 04:40:262804 ChildList children = children_;
2805 for (ChildList::iterator it = children.begin(); it != children.end(); ++it)
2806 (*it)->SetParent(NULL, 0);
2807 DCHECK(children_.empty());
[email protected]3c644d82011-06-20 19:58:242808 SetParent(NULL, 0);
2809
[email protected]80eb6b52012-01-19 00:14:412810 // Unbind everything.
[email protected]e259eb412012-10-13 05:47:242811 state_.vertex_attrib_manager = NULL;
[email protected]944b62f32012-09-27 02:20:462812 default_vertex_attrib_manager_ = NULL;
[email protected]1868a342012-11-07 15:56:022813 state_.texture_units.clear();
[email protected]e259eb412012-10-13 05:47:242814 state_.bound_array_buffer = NULL;
2815 state_.current_query = NULL;
2816 state_.current_program = NULL;
2817 state_.bound_read_framebuffer = NULL;
2818 state_.bound_draw_framebuffer = NULL;
2819 state_.bound_renderbuffer = NULL;
[email protected]80eb6b52012-01-19 00:14:412820
[email protected]eadc96792010-10-27 19:39:392821 if (have_context) {
[email protected]c322e882012-05-23 18:06:182822 if (copy_texture_CHROMIUM_.get()) {
2823 copy_texture_CHROMIUM_->Destroy();
2824 copy_texture_CHROMIUM_.reset();
2825 }
[email protected]43410e92012-04-20 17:06:282826
[email protected]e259eb412012-10-13 05:47:242827 if (state_.current_program) {
2828 program_manager()->UnuseProgram(shader_manager(), state_.current_program);
2829 state_.current_program = NULL;
[email protected]ca488e12010-12-13 20:06:142830 }
2831
[email protected]b1122982010-05-17 23:04:242832 if (attrib_0_buffer_id_) {
2833 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2834 }
[email protected]8fbedc02010-11-18 18:43:402835 if (fixed_attrib_buffer_id_) {
2836 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2837 }
[email protected]b1122982010-05-17 23:04:242838
[email protected]97872062010-11-03 19:07:052839 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542840 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052841 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542842 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052843 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022844 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052845 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152846 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052847 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152848 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052849 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022850 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052851 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542852 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:272853 if (offscreen_resolved_frame_buffer_.get())
2854 offscreen_resolved_frame_buffer_->Destroy();
2855 if (offscreen_resolved_color_texture_.get())
2856 offscreen_resolved_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052857 } else {
2858 if (offscreen_target_frame_buffer_.get())
2859 offscreen_target_frame_buffer_->Invalidate();
2860 if (offscreen_target_color_texture_.get())
2861 offscreen_target_color_texture_->Invalidate();
2862 if (offscreen_target_color_render_buffer_.get())
2863 offscreen_target_color_render_buffer_->Invalidate();
2864 if (offscreen_target_depth_render_buffer_.get())
2865 offscreen_target_depth_render_buffer_->Invalidate();
2866 if (offscreen_target_stencil_render_buffer_.get())
2867 offscreen_target_stencil_render_buffer_->Invalidate();
2868 if (offscreen_saved_frame_buffer_.get())
2869 offscreen_saved_frame_buffer_->Invalidate();
2870 if (offscreen_saved_color_texture_.get())
2871 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:272872 if (offscreen_resolved_frame_buffer_.get())
2873 offscreen_resolved_frame_buffer_->Invalidate();
2874 if (offscreen_resolved_color_texture_.get())
2875 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022876 }
[email protected]43410e92012-04-20 17:06:282877 copy_texture_CHROMIUM_.reset();
[email protected]97872062010-11-03 19:07:052878
[email protected]882ba1e22012-03-08 19:02:532879 if (query_manager_.get()) {
2880 query_manager_->Destroy(have_context);
2881 query_manager_.reset();
2882 }
2883
[email protected]944b62f32012-09-27 02:20:462884 if (vertex_array_manager_ .get()) {
2885 vertex_array_manager_->Destroy(have_context);
2886 vertex_array_manager_.reset();
2887 }
2888
[email protected]1871a092011-10-10 21:46:422889 if (group_) {
2890 group_->Destroy(have_context);
2891 group_ = NULL;
2892 }
[email protected]3ae019382011-10-05 19:42:412893
[email protected]fe871662011-06-16 20:43:052894 if (context_.get()) {
2895 context_->ReleaseCurrent(NULL);
[email protected]79311e82011-09-20 00:40:502896 context_ = NULL;
[email protected]fe871662011-06-16 20:43:052897 }
[email protected]0fc35742011-04-13 17:57:542898
[email protected]97872062010-11-03 19:07:052899 offscreen_target_frame_buffer_.reset();
2900 offscreen_target_color_texture_.reset();
2901 offscreen_target_color_render_buffer_.reset();
2902 offscreen_target_depth_render_buffer_.reset();
2903 offscreen_target_stencil_render_buffer_.reset();
2904 offscreen_saved_frame_buffer_.reset();
2905 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:272906 offscreen_resolved_frame_buffer_.reset();
2907 offscreen_resolved_color_texture_.reset();
[email protected]e51bdf32011-11-23 22:21:462908
2909#if defined(OS_MACOSX)
2910 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
2911 it != texture_to_io_surface_map_.end(); ++it) {
2912 CFRelease(it->second);
2913 }
2914 texture_to_io_surface_map_.clear();
2915#endif
[email protected]96449d2c2009-11-25 00:01:322916}
2917
[email protected]63c9b052012-05-17 18:27:382918void GLES2DecoderImpl::SetSurface(
2919 const scoped_refptr<gfx::GLSurface>& surface) {
2920 DCHECK(context_->IsCurrent(NULL));
2921 DCHECK(surface_.get());
2922 surface_ = surface;
2923 RestoreCurrentFramebufferBindings();
2924}
2925
[email protected]3c644d82011-06-20 19:58:242926bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
2927 uint32 new_parent_texture_id) {
[email protected]9a5afa432011-07-22 18:16:392928 if (!offscreen_saved_color_texture_.get())
2929 return false;
2930
[email protected]3c644d82011-06-20 19:58:242931 // Remove the saved frame buffer mapping from the parent decoder. The
2932 // parent pointer is a weak pointer so it will be null if the parent has
2933 // already been destroyed.
2934 if (parent_) {
[email protected]c826d732012-02-09 04:40:262935 ChildList::iterator it = std::find(
2936 parent_->children_.begin(),
2937 parent_->children_.end(),
2938 this);
2939 DCHECK(it != parent_->children_.end());
2940 parent_->children_.erase(it);
[email protected]3c644d82011-06-20 19:58:242941 // First check the texture has been mapped into the parent. This might not
2942 // be the case if initialization failed midway through.
2943 GLuint service_id = offscreen_saved_color_texture_->id();
2944 GLuint client_id = 0;
2945 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
[email protected]80eb6b52012-01-19 00:14:412946 parent_->texture_manager()->RemoveTextureInfo(client_id);
[email protected]3c644d82011-06-20 19:58:242947 }
2948 }
2949
2950 GLES2DecoderImpl* new_parent_impl = static_cast<GLES2DecoderImpl*>(
2951 new_parent);
2952 if (new_parent_impl) {
[email protected]c826d732012-02-09 04:40:262953#ifndef NDEBUG
2954 ChildList::iterator it = std::find(
2955 new_parent_impl->children_.begin(),
2956 new_parent_impl->children_.end(),
2957 this);
2958 DCHECK(it == new_parent_impl->children_.end());
2959#endif
2960 new_parent_impl->children_.push_back(this);
[email protected]3c644d82011-06-20 19:58:242961 // Map the ID of the saved offscreen texture into the parent so that
2962 // it can reference it.
2963 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]98687862011-07-11 23:31:302964
2965 // Replace texture info when ID is already in use by parent.
2966 if (new_parent_impl->texture_manager()->GetTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412967 new_parent_texture_id))
[email protected]98687862011-07-11 23:31:302968 new_parent_impl->texture_manager()->RemoveTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412969 new_parent_texture_id);
[email protected]98687862011-07-11 23:31:302970
[email protected]8a61d872012-01-20 12:43:562971 offscreen_saved_color_texture_info_ =
[email protected]5f4f2a732011-07-30 00:47:552972 new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id);
[email protected]8a61d872012-01-20 12:43:562973 offscreen_saved_color_texture_info_->SetNotOwned();
2974 new_parent_impl->texture_manager()->
2975 SetInfoTarget(offscreen_saved_color_texture_info_, GL_TEXTURE_2D);
[email protected]3c644d82011-06-20 19:58:242976
[email protected]ee1e6aa2012-11-29 09:24:102977 parent_ = base::AsWeakPtr<GLES2DecoderImpl>(new_parent_impl);
[email protected]9a5afa432011-07-22 18:16:392978
2979 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:242980 } else {
2981 parent_.reset();
[email protected]8a61d872012-01-20 12:43:562982 offscreen_saved_color_texture_info_ = NULL;
[email protected]3c644d82011-06-20 19:58:242983 }
2984
2985 return true;
2986}
2987
[email protected]260ddc4e2012-06-28 00:01:532988size_t GLES2DecoderImpl::GetBackbufferMemoryTotal() {
[email protected]1078f912011-12-23 13:12:142989 size_t total = 0;
2990 if (offscreen_target_frame_buffer_.get()) {
2991 if (offscreen_target_color_texture_.get()) {
2992 total += offscreen_target_color_texture_->estimated_size();
2993 }
2994 if (offscreen_target_color_render_buffer_.get()) {
2995 total += offscreen_target_color_render_buffer_->estimated_size();
2996 }
2997 if (offscreen_target_depth_render_buffer_.get()) {
2998 total += offscreen_target_depth_render_buffer_->estimated_size();
2999 }
3000 if (offscreen_target_stencil_render_buffer_.get()) {
3001 total += offscreen_target_stencil_render_buffer_->estimated_size();
3002 }
3003 if (offscreen_saved_color_texture_.get()) {
3004 total += offscreen_saved_color_texture_->estimated_size();
3005 }
3006 if (offscreen_resolved_color_texture_.get()) {
3007 total += offscreen_resolved_color_texture_->estimated_size();
3008 }
3009 } else {
3010 gfx::Size size = surface_->GetSize();
3011 total += size.width() * size.height() *
3012 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_);
3013 }
[email protected]260ddc4e2012-06-28 00:01:533014 return total;
[email protected]1078f912011-12-23 13:12:143015}
3016
[email protected]799b4b22011-08-22 17:09:593017bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3018 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3019 if (!is_offscreen) {
3020 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3021 << " with an onscreen framebuffer.";
3022 return false;
3023 }
3024
3025 if (offscreen_size_ == size)
3026 return true;
3027
3028 offscreen_size_ = size;
3029 int w = offscreen_size_.width();
3030 int h = offscreen_size_.height();
3031 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3032 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3033 << "to allocate storage due to excessive dimensions.";
3034 return false;
3035 }
3036
3037 // Reallocate the offscreen target buffers.
3038 DCHECK(offscreen_target_color_format_);
3039 if (IsOffscreenBufferMultisampled()) {
3040 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3041 offscreen_size_, offscreen_target_color_format_,
3042 offscreen_target_samples_)) {
3043 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3044 << "to allocate storage for offscreen target color buffer.";
3045 return false;
3046 }
3047 } else {
3048 if (!offscreen_target_color_texture_->AllocateStorage(
3049 offscreen_size_, offscreen_target_color_format_)) {
3050 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3051 << "to allocate storage for offscreen target color texture.";
3052 return false;
3053 }
3054 }
3055 if (offscreen_target_depth_format_ &&
3056 !offscreen_target_depth_render_buffer_->AllocateStorage(
3057 offscreen_size_, offscreen_target_depth_format_,
3058 offscreen_target_samples_)) {
3059 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3060 << "to allocate storage for offscreen target depth buffer.";
3061 return false;
3062 }
3063 if (offscreen_target_stencil_format_ &&
3064 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3065 offscreen_size_, offscreen_target_stencil_format_,
3066 offscreen_target_samples_)) {
3067 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3068 << "to allocate storage for offscreen target stencil buffer.";
3069 return false;
3070 }
3071
3072 // Attach the offscreen target buffers to the target frame buffer.
3073 if (IsOffscreenBufferMultisampled()) {
3074 offscreen_target_frame_buffer_->AttachRenderBuffer(
3075 GL_COLOR_ATTACHMENT0,
3076 offscreen_target_color_render_buffer_.get());
3077 } else {
3078 offscreen_target_frame_buffer_->AttachRenderTexture(
3079 offscreen_target_color_texture_.get());
3080 }
3081 if (offscreen_target_depth_format_) {
3082 offscreen_target_frame_buffer_->AttachRenderBuffer(
3083 GL_DEPTH_ATTACHMENT,
3084 offscreen_target_depth_render_buffer_.get());
3085 }
3086 const bool packed_depth_stencil =
3087 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3088 if (packed_depth_stencil) {
3089 offscreen_target_frame_buffer_->AttachRenderBuffer(
3090 GL_STENCIL_ATTACHMENT,
3091 offscreen_target_depth_render_buffer_.get());
3092 } else if (offscreen_target_stencil_format_) {
3093 offscreen_target_frame_buffer_->AttachRenderBuffer(
3094 GL_STENCIL_ATTACHMENT,
3095 offscreen_target_stencil_render_buffer_.get());
3096 }
3097
3098 if (offscreen_target_frame_buffer_->CheckStatus() !=
3099 GL_FRAMEBUFFER_COMPLETE) {
3100 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3101 << "because offscreen FBO was incomplete.";
3102 return false;
3103 }
3104
3105 // Clear the target frame buffer.
3106 {
3107 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3108 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3109 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3110 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3111 glClearStencil(0);
3112 glStencilMaskSeparate(GL_FRONT, -1);
3113 glStencilMaskSeparate(GL_BACK, -1);
3114 glClearDepth(0);
3115 glDepthMask(GL_TRUE);
3116 glDisable(GL_SCISSOR_TEST);
3117 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3118 RestoreClearState();
3119 }
[email protected]d85ef76d2011-09-08 22:21:433120
3121 // Destroy the offscreen resolved framebuffers.
3122 if (offscreen_resolved_frame_buffer_.get())
3123 offscreen_resolved_frame_buffer_->Destroy();
3124 if (offscreen_resolved_color_texture_.get())
3125 offscreen_resolved_color_texture_->Destroy();
3126 offscreen_resolved_color_texture_.reset();
3127 offscreen_resolved_frame_buffer_.reset();
3128
[email protected]799b4b22011-08-22 17:09:593129 return true;
[email protected]6217d392010-03-25 22:08:353130}
3131
[email protected]799b4b22011-08-22 17:09:593132error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3133 uint32 immediate_data_size, const gles2::ResizeCHROMIUM& c) {
[email protected]09e17272012-11-30 10:30:443134 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
[email protected]452120872012-09-27 15:21:023135 return error::kDeferCommandUntilLater;
3136
[email protected]799b4b22011-08-22 17:09:593137 GLuint width = static_cast<GLuint>(c.width);
3138 GLuint height = static_cast<GLuint>(c.height);
3139 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
[email protected]a0d989162011-11-22 13:15:073140#if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3141 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
[email protected]7ff86b92010-11-25 17:50:003142 // Make sure that we are done drawing to the back buffer before resizing.
3143 glFinish();
3144#endif
[email protected]799b4b22011-08-22 17:09:593145 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3146 if (is_offscreen) {
[email protected]7794d512012-04-17 20:36:493147 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3148 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3149 << "ResizeOffscreenFrameBuffer failed.";
[email protected]799b4b22011-08-22 17:09:593150 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:493151 }
[email protected]7ff86b92010-11-25 17:50:003152 }
[email protected]799b4b22011-08-22 17:09:593153
[email protected]9d37f062011-11-22 01:24:523154 if (!resize_callback_.is_null()) {
3155 resize_callback_.Run(gfx::Size(width, height));
[email protected]c777de52011-09-09 23:08:563156 DCHECK(context_->IsCurrent(surface_.get()));
[email protected]7794d512012-04-17 20:36:493157 if (!context_->IsCurrent(surface_.get())) {
3158 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3159 << "current after resize callback.";
[email protected]658f7562011-09-09 05:24:053160 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:493161 }
[email protected]658f7562011-09-09 05:24:053162 }
[email protected]799b4b22011-08-22 17:09:593163
3164 return error::kNoError;
[email protected]43ecf372010-11-16 19:19:393165}
3166
[email protected]96449d2c2009-11-25 00:01:323167const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3168 if (command_id > kStartPoint && command_id < kNumCommands) {
3169 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3170 }
3171 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3172}
3173
3174// Decode command with its arguments, and call the corresponding GL function.
3175// Note: args is a pointer to the command buffer. As such, it could be changed
3176// by a (malicious) client at any time, so if validation has to happen, it
3177// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:143178error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:323179 unsigned int command,
3180 unsigned int arg_count,
3181 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:143182 error::Error result = error::kNoError;
[email protected]e844ae22012-01-14 03:36:263183 if (log_commands()) {
[email protected]39ba4f02012-03-26 01:16:003184 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3185 // LOG(INFO), tried VLOG(1), no luck.
[email protected]d2a0e1a2012-08-12 02:25:013186 LOG(ERROR) << "[" << GetLogPrefix() << "]" << "cmd: "
3187 << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193188 }
[email protected]96449d2c2009-11-25 00:01:323189 unsigned int command_index = command - kStartPoint - 1;
3190 if (command_index < arraysize(g_command_info)) {
3191 const CommandInfo& info = g_command_info[command_index];
3192 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3193 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3194 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:193195 uint32 immediate_data_size =
3196 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:323197 switch (command) {
3198 #define GLES2_CMD_OP(name) \
3199 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:193200 result = Handle ## name( \
3201 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:323202 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:193203 break; \
[email protected]96449d2c2009-11-25 00:01:323204
3205 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:323206 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:383207 }
3208 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:303209 GLenum error;
3210 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]d2a0e1a2012-08-12 02:25:013211 LOG(ERROR) << "[" << GetLogPrefix() << "] "
[email protected]39ba4f02012-03-26 01:16:003212 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3213 << GetCommandName(command);
[email protected]ad84a3a2012-06-08 21:42:433214 SetGLError(error, "DoCommand", "GL error from driver");
[email protected]b9849abf2009-11-25 19:13:193215 }
[email protected]96449d2c2009-11-25 00:01:323216 }
3217 } else {
[email protected]f7a64ee2010-02-01 22:24:143218 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:323219 }
[email protected]b9849abf2009-11-25 19:13:193220 } else {
3221 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:323222 }
[email protected]a3a93e7b2010-08-28 00:48:563223 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3224 result = current_decoder_error_;
3225 current_decoder_error_ = error::kNoError;
3226 }
[email protected]b9849abf2009-11-25 19:13:193227 return result;
[email protected]96449d2c2009-11-25 00:01:323228}
3229
[email protected]ae51d192010-04-27 00:48:033230void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
3231 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:503232}
3233
[email protected]ae51d192010-04-27 00:48:033234bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3235 if (GetProgramInfo(client_id)) {
3236 return false;
3237 }
[email protected]96449d2c2009-11-25 00:01:323238 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:033239 if (service_id != 0) {
3240 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:323241 }
[email protected]ae51d192010-04-27 00:48:033242 return true;
[email protected]96449d2c2009-11-25 00:01:323243}
3244
[email protected]ae51d192010-04-27 00:48:033245bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3246 if (GetShaderInfo(client_id)) {
3247 return false;
[email protected]96449d2c2009-11-25 00:01:323248 }
[email protected]ae51d192010-04-27 00:48:033249 GLuint service_id = glCreateShader(type);
3250 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:383251 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:033252 }
3253 return true;
[email protected]96449d2c2009-11-25 00:01:323254}
3255
[email protected]882ba1e22012-03-08 19:02:533256void GLES2DecoderImpl::DoFinish() {
3257 glFinish();
[email protected]22e3f552012-03-13 01:54:193258 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533259}
3260
3261void GLES2DecoderImpl::DoFlush() {
3262 glFlush();
[email protected]22e3f552012-03-13 01:54:193263 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533264}
3265
[email protected]3916c97e2010-02-25 03:20:503266void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:453267 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]1868a342012-11-07 15:56:023268 if (texture_index >= state_.texture_units.size()) {
[email protected]f80e6e12012-08-31 00:43:533269 SetGLErrorInvalidEnum(
3270 "glActiveTexture", texture_unit, "texture_unit");
[email protected]3916c97e2010-02-25 03:20:503271 return;
3272 }
[email protected]e259eb412012-10-13 05:47:243273 state_.active_texture_unit = texture_index;
[email protected]36cef8ce2010-03-16 07:34:453274 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:503275}
3276
[email protected]051b1372010-04-12 02:42:083277void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:503278 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083279 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033280 if (client_id != 0) {
3281 info = GetBufferInfo(client_id);
3282 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353283 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153284 LOG(ERROR) << "glBindBuffer: id not generated by glGenBuffers";
3285 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353286 return;
3287 }
3288
[email protected]ae51d192010-04-27 00:48:033289 // It's a new id so make a buffer info for it.
3290 glGenBuffersARB(1, &service_id);
3291 CreateBufferInfo(client_id, service_id);
3292 info = GetBufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573293 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103294 group_->GetIdAllocator(id_namespaces::kBuffers);
3295 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033296 }
[email protected]051b1372010-04-12 02:42:083297 }
[email protected]ae51d192010-04-27 00:48:033298 if (info) {
[email protected]4e8a5b122010-05-08 22:00:103299 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:293300 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:433301 "glBindBuffer", "buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:473302 return;
3303 }
[email protected]ae51d192010-04-27 00:48:033304 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:473305 }
[email protected]96449d2c2009-11-25 00:01:323306 switch (target) {
3307 case GL_ARRAY_BUFFER:
[email protected]e259eb412012-10-13 05:47:243308 state_.bound_array_buffer = info;
[email protected]96449d2c2009-11-25 00:01:323309 break;
3310 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]e259eb412012-10-13 05:47:243311 state_.vertex_attrib_manager->SetElementArrayBuffer(info);
[email protected]96449d2c2009-11-25 00:01:323312 break;
3313 default:
[email protected]a93bb842010-02-16 23:03:473314 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:323315 break;
3316 }
[email protected]051b1372010-04-12 02:42:083317 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:323318}
3319
[email protected]297ca1c2011-06-20 23:08:463320bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
3321 return (GLES2Util::GetChannelsForFormat(
3322 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3323}
3324
3325bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203326 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:453327 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:203328 if (framebuffer) {
3329 return framebuffer->HasDepthAttachment();
[email protected]297ca1c2011-06-20 23:08:463330 }
3331 if (offscreen_target_frame_buffer_.get()) {
3332 return offscreen_target_depth_format_ != 0;
3333 }
3334 return back_buffer_has_depth_;
3335}
3336
3337bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203338 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:453339 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:203340 if (framebuffer) {
3341 return framebuffer->HasStencilAttachment();
[email protected]297ca1c2011-06-20 23:08:463342 }
3343 if (offscreen_target_frame_buffer_.get()) {
3344 return offscreen_target_stencil_format_ != 0 ||
3345 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3346 }
3347 return back_buffer_has_stencil_;
3348}
3349
3350void GLES2DecoderImpl::ApplyDirtyState() {
[email protected]88a61bf2012-10-27 13:00:423351 if (clear_state_dirty_) {
[email protected]297ca1c2011-06-20 23:08:463352 glColorMask(
[email protected]e259eb412012-10-13 05:47:243353 state_.color_mask_red, state_.color_mask_green, state_.color_mask_blue,
3354 state_.color_mask_alpha &&
3355 BoundFramebufferHasColorAttachmentWithAlpha());
[email protected]297ca1c2011-06-20 23:08:463356 bool have_depth = BoundFramebufferHasDepthAttachment();
[email protected]e259eb412012-10-13 05:47:243357 glDepthMask(state_.depth_mask && have_depth);
[email protected]f731b9462012-10-30 00:35:223358 EnableDisable(GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
[email protected]297ca1c2011-06-20 23:08:463359 bool have_stencil = BoundFramebufferHasStencilAttachment();
[email protected]e259eb412012-10-13 05:47:243360 glStencilMaskSeparate(
[email protected]88a61bf2012-10-27 13:00:423361 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
[email protected]e259eb412012-10-13 05:47:243362 glStencilMaskSeparate(
[email protected]88a61bf2012-10-27 13:00:423363 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
[email protected]f731b9462012-10-30 00:35:223364 EnableDisable(
3365 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
3366 EnableDisable(GL_CULL_FACE, state_.enable_flags.cull_face);
3367 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
3368 EnableDisable(GL_BLEND, state_.enable_flags.blend);
[email protected]88a61bf2012-10-27 13:00:423369 clear_state_dirty_ = false;
[email protected]297ca1c2011-06-20 23:08:463370 }
3371}
3372
[email protected]78b514b2012-05-01 21:50:593373void GLES2DecoderImpl::BindAndApplyTextureParameters(
3374 TextureManager::TextureInfo* info) {
3375 glBindTexture(info->target(), info->service_id());
3376 glTexParameteri(info->target(), GL_TEXTURE_MIN_FILTER, info->min_filter());
3377 glTexParameteri(info->target(), GL_TEXTURE_MAG_FILTER, info->mag_filter());
3378 glTexParameteri(info->target(), GL_TEXTURE_WRAP_S, info->wrap_s());
3379 glTexParameteri(info->target(), GL_TEXTURE_WRAP_T, info->wrap_t());
3380}
3381
[email protected]1868a342012-11-07 15:56:023382GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
[email protected]b177ae22011-11-01 03:29:113383 return (offscreen_target_frame_buffer_.get()) ?
3384 offscreen_target_frame_buffer_->id() :
[email protected]1868a342012-11-07 15:56:023385 (surface_ ? surface_->GetBackingFrameBufferObject() : 0);
3386}
3387
3388void GLES2DecoderImpl::RestoreState() const {
3389 state_.RestoreState();
3390
3391 // TODO: Restore multisample bindings
3392 GLuint service_id = state_.bound_draw_framebuffer ?
3393 state_.bound_draw_framebuffer->service_id() :
3394 GetBackbufferServiceId();
3395 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
[email protected]b177ae22011-11-01 03:29:113396}
3397
[email protected]051b1372010-04-12 02:42:083398void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3399 FramebufferManager::FramebufferInfo* info = NULL;
3400 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033401 if (client_id != 0) {
3402 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083403 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353404 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153405 LOG(ERROR)
3406 << "glBindFramebuffer: id not generated by glGenFramebuffers";
3407 current_decoder_error_ = error::kGenericError;
3408 return;
[email protected]bf5a8d132011-08-16 08:39:353409 }
3410
[email protected]ae51d192010-04-27 00:48:033411 // It's a new id so make a framebuffer info for it.
3412 glGenFramebuffersEXT(1, &service_id);
3413 CreateFramebufferInfo(client_id, service_id);
3414 info = GetFramebufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573415 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103416 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3417 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033418 } else {
3419 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083420 }
[email protected]06c8b082011-01-05 18:00:363421 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083422 }
[email protected]8e3e0662010-08-23 18:46:303423
3424 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
[email protected]e259eb412012-10-13 05:47:243425 state_.bound_draw_framebuffer = info;
[email protected]8e3e0662010-08-23 18:46:303426 }
3427 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]e259eb412012-10-13 05:47:243428 state_.bound_read_framebuffer = info;
[email protected]8e3e0662010-08-23 18:46:303429 }
[email protected]6217d392010-03-25 22:08:353430
[email protected]88a61bf2012-10-27 13:00:423431 clear_state_dirty_ = true;
[email protected]297ca1c2011-06-20 23:08:463432
[email protected]b177ae22011-11-01 03:29:113433 // If we are rendering to the backbuffer get the FBO id for any simulated
3434 // backbuffer.
3435 if (info == NULL) {
3436 service_id = GetBackbufferServiceId();
[email protected]297ca1c2011-06-20 23:08:463437 }
[email protected]6217d392010-03-25 22:08:353438
[email protected]051b1372010-04-12 02:42:083439 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563440}
3441
[email protected]051b1372010-04-12 02:42:083442void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
3443 RenderbufferManager::RenderbufferInfo* info = NULL;
3444 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033445 if (client_id != 0) {
3446 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083447 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353448 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153449 LOG(ERROR)
3450 << "glBindRenderbuffer: id not generated by glGenRenderbuffers";
3451 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353452 return;
3453 }
3454
[email protected]ae51d192010-04-27 00:48:033455 // It's a new id so make a renderbuffer info for it.
3456 glGenRenderbuffersEXT(1, &service_id);
3457 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:103458 info = GetRenderbufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573459 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103460 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3461 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033462 } else {
3463 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083464 }
[email protected]06c8b082011-01-05 18:00:363465 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083466 }
[email protected]e259eb412012-10-13 05:47:243467 state_.bound_renderbuffer = info;
[email protected]051b1372010-04-12 02:42:083468 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563469}
3470
[email protected]051b1372010-04-12 02:42:083471void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033472 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083473 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033474 if (client_id != 0) {
3475 info = GetTextureInfo(client_id);
3476 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353477 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153478 LOG(ERROR) << "glBindTexture: id not generated by glGenTextures";
3479 current_decoder_error_ = error::kGenericError;
3480 return;
[email protected]bf5a8d132011-08-16 08:39:353481 }
3482
[email protected]ae51d192010-04-27 00:48:033483 // It's a new id so make a texture info for it.
3484 glGenTextures(1, &service_id);
[email protected]80eb6b52012-01-19 00:14:413485 DCHECK_NE(0u, service_id);
[email protected]ae51d192010-04-27 00:48:033486 CreateTextureInfo(client_id, service_id);
3487 info = GetTextureInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573488 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103489 group_->GetIdAllocator(id_namespaces::kTextures);
3490 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033491 }
3492 } else {
3493 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:083494 }
[email protected]ae51d192010-04-27 00:48:033495
[email protected]1958e0e2010-04-22 05:17:153496 // Check the texture exists
3497 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:033498 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:293499 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:433500 "glBindTexture", "texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:153501 return;
3502 }
[email protected]b0af4f52011-09-28 22:04:423503 if (info->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
3504 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:433505 "glBindTexture", "illegal target for stream texture.");
[email protected]b0af4f52011-09-28 22:04:423506 return;
3507 }
[email protected]1958e0e2010-04-22 05:17:153508 if (info->target() == 0) {
[email protected]80eb6b52012-01-19 00:14:413509 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:473510 }
[email protected]ae51d192010-04-27 00:48:033511 glBindTexture(target, info->service_id());
[email protected]e259eb412012-10-13 05:47:243512 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]3916c97e2010-02-25 03:20:503513 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:473514 switch (target) {
3515 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:503516 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:473517 break;
3518 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:503519 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:473520 break;
[email protected]61eeb33f2011-07-26 15:30:313521 case GL_TEXTURE_EXTERNAL_OES:
3522 unit.bound_texture_external_oes = info;
[email protected]b0af4f52011-09-28 22:04:423523 if (info->IsStreamTexture()) {
3524 DCHECK(stream_texture_manager_);
3525 StreamTexture* stream_tex =
3526 stream_texture_manager_->LookupStreamTexture(info->service_id());
3527 if (stream_tex)
3528 stream_tex->Update();
3529 }
[email protected]61eeb33f2011-07-26 15:30:313530 break;
[email protected]e51bdf32011-11-23 22:21:463531 case GL_TEXTURE_RECTANGLE_ARB:
3532 unit.bound_texture_rectangle_arb = info;
3533 break;
[email protected]a93bb842010-02-16 23:03:473534 default:
3535 NOTREACHED(); // Validation should prevent us getting here.
3536 break;
3537 }
3538}
3539
[email protected]07f54fcc2009-12-22 02:46:303540void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]e259eb412012-10-13 05:47:243541 if (state_.vertex_attrib_manager->Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:123542 if (index != 0 ||
3543 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:243544 glDisableVertexAttribArray(index);
3545 }
[email protected]07f54fcc2009-12-22 02:46:303546 } else {
[email protected]8eee29c2010-04-29 03:38:293547 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:433548 "glDisableVertexAttribArray", "index out of range");
[email protected]07f54fcc2009-12-22 02:46:303549 }
3550}
3551
3552void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]e259eb412012-10-13 05:47:243553 if (state_.vertex_attrib_manager->Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:303554 glEnableVertexAttribArray(index);
3555 } else {
[email protected]8eee29c2010-04-29 03:38:293556 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:433557 "glEnableVertexAttribArray", "index out of range");
[email protected]07f54fcc2009-12-22 02:46:303558 }
3559}
3560
[email protected]a93bb842010-02-16 23:03:473561void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:503562 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]97dc7cbe2011-12-06 17:26:173563 if (!info ||
[email protected]38c0a972012-05-12 00:48:023564 !texture_manager()->CanGenerateMipmaps(info)) {
[email protected]8eee29c2010-04-29 03:38:293565 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:433566 "glGenerateMipmaps", "Can not generate mips");
[email protected]a93bb842010-02-16 23:03:473567 return;
3568 }
[email protected]38c0a972012-05-12 00:48:023569
[email protected]7687479c2012-05-14 23:54:043570 if (!texture_manager()->ClearTextureLevel(this, info, target, 0)) {
[email protected]ad84a3a2012-06-08 21:42:433571 SetGLError(GL_OUT_OF_MEMORY, "glGenerateMipmaps", "dimensions too big");
[email protected]7687479c2012-05-14 23:54:043572 return;
3573 }
3574
[email protected]38c0a972012-05-12 00:48:023575 CopyRealGLErrorsToWrapper();
[email protected]59f3ca02011-03-26 22:24:193576 // Workaround for Mac driver bug. In the large scheme of things setting
3577 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
[email protected]a8bad262011-10-21 18:28:563578 // hit so there's probably no need to make this conditional. The bug appears
3579 // to be that if the filtering mode is set to something that doesn't require
3580 // mipmaps for rendering, or is never set to something other than the default,
3581 // then glGenerateMipmap misbehaves.
[email protected]62e155e2012-10-23 22:43:153582 if (workarounds().set_texture_filter_before_generating_mipmap) {
[email protected]c892a4e12012-05-08 18:20:193583 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3584 }
[email protected]a93bb842010-02-16 23:03:473585 glGenerateMipmapEXT(target);
[email protected]62e155e2012-10-23 22:43:153586 if (workarounds().set_texture_filter_before_generating_mipmap) {
[email protected]c892a4e12012-05-08 18:20:193587 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
3588 }
[email protected]38c0a972012-05-12 00:48:023589 GLenum error = PeekGLError();
3590 if (error == GL_NO_ERROR) {
3591 texture_manager()->MarkMipmapsGenerated(info);
3592 }
[email protected]a93bb842010-02-16 23:03:473593}
3594
[email protected]b273e432010-04-12 17:23:583595bool GLES2DecoderImpl::GetHelper(
3596 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:583597 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:153598 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
3599 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:433600 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
3601 *num_written = 1;
3602 if (params) {
3603 *params = GL_RGBA; // We don't support other formats.
3604 }
3605 return true;
3606 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3607 *num_written = 1;
3608 if (params) {
3609 *params = GL_UNSIGNED_BYTE; // We don't support other types.
3610 }
3611 return true;
3612 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
3613 *num_written = 1;
3614 if (params) {
3615 *params = group_->max_fragment_uniform_vectors();
3616 }
3617 return true;
3618 case GL_MAX_VARYING_VECTORS:
3619 *num_written = 1;
3620 if (params) {
3621 *params = group_->max_varying_vectors();
3622 }
3623 return true;
3624 case GL_MAX_VERTEX_UNIFORM_VECTORS:
3625 *num_written = 1;
3626 if (params) {
3627 *params = group_->max_vertex_uniform_vectors();
3628 }
3629 return true;
[email protected]4e8a5b122010-05-08 22:00:103630 }
[email protected]5cb735d2011-10-13 01:37:233631 }
3632 switch (pname) {
[email protected]5094b0f2010-11-09 19:45:243633 case GL_MAX_VIEWPORT_DIMS:
3634 if (offscreen_target_frame_buffer_.get()) {
3635 *num_written = 2;
3636 if (params) {
3637 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3638 params[1] = renderbuffer_manager()->max_renderbuffer_size();
3639 }
3640 return true;
3641 }
[email protected]5cb735d2011-10-13 01:37:233642 return false;
[email protected]84afefa2011-10-19 21:45:533643 case GL_MAX_SAMPLES:
3644 *num_written = 1;
3645 if (params) {
3646 params[0] = renderbuffer_manager()->max_samples();
3647 }
3648 return true;
3649 case GL_MAX_RENDERBUFFER_SIZE:
3650 *num_written = 1;
3651 if (params) {
3652 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3653 }
3654 return true;
[email protected]5cb735d2011-10-13 01:37:233655 case GL_MAX_TEXTURE_SIZE:
3656 *num_written = 1;
3657 if (params) {
3658 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
3659 }
3660 return true;
3661 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
3662 *num_written = 1;
3663 if (params) {
3664 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
3665 }
3666 return true;
[email protected]297ca1c2011-06-20 23:08:463667 case GL_ALPHA_BITS:
3668 *num_written = 1;
3669 if (params) {
3670 GLint v = 0;
3671 glGetIntegerv(GL_ALPHA_BITS, &v);
3672 params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0;
3673 }
3674 return true;
3675 case GL_DEPTH_BITS:
3676 *num_written = 1;
3677 if (params) {
3678 GLint v = 0;
3679 glGetIntegerv(GL_DEPTH_BITS, &v);
3680 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
3681 }
3682 return true;
3683 case GL_STENCIL_BITS:
3684 *num_written = 1;
3685 if (params) {
3686 GLint v = 0;
3687 glGetIntegerv(GL_STENCIL_BITS, &v);
3688 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
3689 }
3690 return true;
[email protected]656dcaad2010-05-07 17:18:373691 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113692 *num_written = validators_->compressed_texture_format.GetValues().size();
3693 if (params) {
3694 for (GLint ii = 0; ii < *num_written; ++ii) {
3695 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
3696 }
3697 }
[email protected]656dcaad2010-05-07 17:18:373698 return true;
[email protected]b273e432010-04-12 17:23:583699 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
3700 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103701 if (params) {
[email protected]302ce6d2011-07-07 23:28:113702 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103703 }
[email protected]b273e432010-04-12 17:23:583704 return true;
3705 case GL_NUM_SHADER_BINARY_FORMATS:
3706 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103707 if (params) {
[email protected]302ce6d2011-07-07 23:28:113708 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103709 }
[email protected]b273e432010-04-12 17:23:583710 return true;
3711 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113712 *num_written = validators_->shader_binary_format.GetValues().size();
3713 if (params) {
3714 for (GLint ii = 0; ii < *num_written; ++ii) {
3715 params[ii] = validators_->shader_binary_format.GetValues()[ii];
3716 }
3717 }
3718 return true;
[email protected]b273e432010-04-12 17:23:583719 case GL_SHADER_COMPILER:
3720 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103721 if (params) {
3722 *params = GL_TRUE;
3723 }
[email protected]b273e432010-04-12 17:23:583724 return true;
[email protected]6b8cf1a2010-05-06 16:13:583725 case GL_ARRAY_BUFFER_BINDING:
3726 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103727 if (params) {
[email protected]e259eb412012-10-13 05:47:243728 if (state_.bound_array_buffer) {
[email protected]4e8a5b122010-05-08 22:00:103729 GLuint client_id = 0;
[email protected]e259eb412012-10-13 05:47:243730 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
[email protected]4e8a5b122010-05-08 22:00:103731 &client_id);
3732 *params = client_id;
3733 } else {
3734 *params = 0;
3735 }
[email protected]6b8cf1a2010-05-06 16:13:583736 }
3737 return true;
3738 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3739 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103740 if (params) {
[email protected]e259eb412012-10-13 05:47:243741 if (state_.vertex_attrib_manager->element_array_buffer()) {
[email protected]4e8a5b122010-05-08 22:00:103742 GLuint client_id = 0;
3743 buffer_manager()->GetClientId(
[email protected]e259eb412012-10-13 05:47:243744 state_.vertex_attrib_manager->element_array_buffer(
3745 )->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103746 *params = client_id;
3747 } else {
3748 *params = 0;
3749 }
[email protected]6b8cf1a2010-05-06 16:13:583750 }
3751 return true;
3752 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:303753 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:583754 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103755 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203756 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:453757 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
[email protected]0d6bfdc2011-11-02 01:32:203758 if (framebuffer) {
[email protected]4e8a5b122010-05-08 22:00:103759 GLuint client_id = 0;
3760 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203761 framebuffer->service_id(), &client_id);
[email protected]8e3e0662010-08-23 18:46:303762 *params = client_id;
3763 } else {
3764 *params = 0;
3765 }
3766 }
3767 return true;
[email protected]ebfb73c2012-08-15 02:37:453768 case GL_READ_FRAMEBUFFER_BINDING_EXT:
[email protected]8e3e0662010-08-23 18:46:303769 *num_written = 1;
3770 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203771 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:453772 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:203773 if (framebuffer) {
[email protected]8e3e0662010-08-23 18:46:303774 GLuint client_id = 0;
3775 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203776 framebuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103777 *params = client_id;
3778 } else {
3779 *params = 0;
3780 }
[email protected]6b8cf1a2010-05-06 16:13:583781 }
3782 return true;
3783 case GL_RENDERBUFFER_BINDING:
3784 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103785 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203786 RenderbufferManager::RenderbufferInfo* renderbuffer =
3787 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
3788 if (renderbuffer) {
[email protected]4e8a5b122010-05-08 22:00:103789 GLuint client_id = 0;
3790 renderbuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203791 renderbuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103792 *params = client_id;
3793 } else {
3794 *params = 0;
3795 }
[email protected]6b8cf1a2010-05-06 16:13:583796 }
3797 return true;
3798 case GL_CURRENT_PROGRAM:
3799 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103800 if (params) {
[email protected]e259eb412012-10-13 05:47:243801 if (state_.current_program) {
[email protected]4e8a5b122010-05-08 22:00:103802 GLuint client_id = 0;
3803 program_manager()->GetClientId(
[email protected]e259eb412012-10-13 05:47:243804 state_.current_program->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103805 *params = client_id;
3806 } else {
3807 *params = 0;
3808 }
[email protected]6b8cf1a2010-05-06 16:13:583809 }
3810 return true;
[email protected]bf835842012-11-19 15:21:513811 case GL_VERTEX_ARRAY_BINDING_OES:
3812 *num_written = 1;
3813 if (params) {
3814 if (state_.vertex_attrib_manager != default_vertex_attrib_manager_) {
3815 GLuint client_id = 0;
3816 vertex_array_manager_->GetClientId(
3817 state_.vertex_attrib_manager->service_id(), &client_id);
3818 *params = client_id;
3819 } else {
3820 *params = 0;
3821 }
3822 }
3823 return true;
[email protected]4e8a5b122010-05-08 22:00:103824 case GL_TEXTURE_BINDING_2D:
3825 *num_written = 1;
3826 if (params) {
[email protected]e259eb412012-10-13 05:47:243827 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]6b8cf1a2010-05-06 16:13:583828 if (unit.bound_texture_2d) {
3829 GLuint client_id = 0;
3830 texture_manager()->GetClientId(
3831 unit.bound_texture_2d->service_id(), &client_id);
3832 *params = client_id;
3833 } else {
3834 *params = 0;
3835 }
[email protected]6b8cf1a2010-05-06 16:13:583836 }
[email protected]4e8a5b122010-05-08 22:00:103837 return true;
3838 case GL_TEXTURE_BINDING_CUBE_MAP:
3839 *num_written = 1;
3840 if (params) {
[email protected]e259eb412012-10-13 05:47:243841 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]6b8cf1a2010-05-06 16:13:583842 if (unit.bound_texture_cube_map) {
3843 GLuint client_id = 0;
3844 texture_manager()->GetClientId(
3845 unit.bound_texture_cube_map->service_id(), &client_id);
3846 *params = client_id;
3847 } else {
3848 *params = 0;
3849 }
[email protected]6b8cf1a2010-05-06 16:13:583850 }
[email protected]4e8a5b122010-05-08 22:00:103851 return true;
[email protected]61eeb33f2011-07-26 15:30:313852 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3853 *num_written = 1;
3854 if (params) {
[email protected]e259eb412012-10-13 05:47:243855 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]61eeb33f2011-07-26 15:30:313856 if (unit.bound_texture_external_oes) {
3857 GLuint client_id = 0;
3858 texture_manager()->GetClientId(
3859 unit.bound_texture_external_oes->service_id(), &client_id);
3860 *params = client_id;
3861 } else {
3862 *params = 0;
3863 }
3864 }
3865 return true;
[email protected]e51bdf32011-11-23 22:21:463866 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
3867 *num_written = 1;
3868 if (params) {
[email protected]e259eb412012-10-13 05:47:243869 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]e51bdf32011-11-23 22:21:463870 if (unit.bound_texture_rectangle_arb) {
3871 GLuint client_id = 0;
3872 texture_manager()->GetClientId(
3873 unit.bound_texture_rectangle_arb->service_id(), &client_id);
3874 *params = client_id;
3875 } else {
3876 *params = 0;
3877 }
3878 }
3879 return true;
[email protected]6c75c712012-06-19 15:43:173880 case GL_UNPACK_FLIP_Y_CHROMIUM:
3881 *num_written = 1;
3882 if (params) {
3883 params[0] = unpack_flip_y_;
3884 }
3885 return true;
3886 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
3887 *num_written = 1;
3888 if (params) {
3889 params[0] = unpack_premultiply_alpha_;
3890 }
3891 return true;
3892 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
3893 *num_written = 1;
3894 if (params) {
3895 params[0] = unpack_unpremultiply_alpha_;
3896 }
3897 return true;
[email protected]b273e432010-04-12 17:23:583898 default:
[email protected]4e8a5b122010-05-08 22:00:103899 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533900 return false;
[email protected]b273e432010-04-12 17:23:583901 }
3902}
3903
[email protected]4e8a5b122010-05-08 22:00:103904bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3905 GLenum pname, GLsizei* num_values) {
[email protected]d058bca2012-11-26 10:27:263906 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
[email protected]f63b1232012-10-31 07:03:533907 return true;
3908 }
[email protected]4e8a5b122010-05-08 22:00:103909 return GetHelper(pname, NULL, num_values);
3910}
3911
[email protected]b273e432010-04-12 17:23:583912void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3913 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103914 GLsizei num_written = 0;
[email protected]f63b1232012-10-31 07:03:533915 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
[email protected]4e8a5b122010-05-08 22:00:103916 scoped_array<GLint> values(new GLint[num_written]);
[email protected]d058bca2012-11-26 10:27:263917 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
[email protected]f63b1232012-10-31 07:03:533918 GetHelper(pname, values.get(), &num_written);
3919 }
[email protected]b273e432010-04-12 17:23:583920 for (GLsizei ii = 0; ii < num_written; ++ii) {
3921 params[ii] = static_cast<GLboolean>(values[ii]);
3922 }
3923 } else {
3924 glGetBooleanv(pname, params);
3925 }
3926}
3927
3928void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3929 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103930 GLsizei num_written = 0;
[email protected]d058bca2012-11-26 10:27:263931 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
[email protected]f63b1232012-10-31 07:03:533932 if (GetHelper(pname, NULL, &num_written)) {
3933 scoped_array<GLint> values(new GLint[num_written]);
3934 GetHelper(pname, values.get(), &num_written);
3935 for (GLsizei ii = 0; ii < num_written; ++ii) {
3936 params[ii] = static_cast<GLfloat>(values[ii]);
3937 }
3938 } else {
3939 glGetFloatv(pname, params);
[email protected]b273e432010-04-12 17:23:583940 }
[email protected]b273e432010-04-12 17:23:583941 }
3942}
3943
3944void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3945 DCHECK(params);
3946 GLsizei num_written;
[email protected]d058bca2012-11-26 10:27:263947 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
[email protected]f63b1232012-10-31 07:03:533948 !GetHelper(pname, params, &num_written)) {
[email protected]b273e432010-04-12 17:23:583949 glGetIntegerv(pname, params);
3950 }
3951}
3952
[email protected]a0c3e972010-04-21 00:49:133953void GLES2DecoderImpl::DoGetProgramiv(
3954 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583955 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3956 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133957 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133958 return;
3959 }
3960 info->GetProgramiv(pname, params);
3961}
3962
[email protected]258a3313f2011-10-18 20:13:573963void GLES2DecoderImpl::DoBindAttribLocation(
3964 GLuint program, GLuint index, const char* name) {
3965 if (!StringIsValidForGLES(name)) {
[email protected]ad84a3a2012-06-08 21:42:433966 SetGLError(GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:573967 return;
3968 }
[email protected]68dcb1f2012-04-07 00:14:563969 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
[email protected]ad84a3a2012-06-08 21:42:433970 SetGLError(GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
[email protected]68dcb1f2012-04-07 00:14:563971 return;
3972 }
3973 if (index >= group_->max_vertex_attribs()) {
[email protected]ad84a3a2012-06-08 21:42:433974 SetGLError(GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
[email protected]68dcb1f2012-04-07 00:14:563975 return;
3976 }
[email protected]6b8cf1a2010-05-06 16:13:583977 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3978 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033979 if (!info) {
[email protected]258a3313f2011-10-18 20:13:573980 return;
[email protected]558847a2010-03-24 07:02:543981 }
[email protected]c3e4c4e2012-03-02 19:23:243982 info->SetAttribLocationBinding(name, static_cast<GLint>(index));
[email protected]258a3313f2011-10-18 20:13:573983 glBindAttribLocation(info->service_id(), index, name);
3984}
3985
3986error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3987 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
3988 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543989 GLuint index = static_cast<GLuint>(c.index);
3990 uint32 name_size = c.data_size;
3991 const char* name = GetSharedMemoryAs<const char*>(
3992 c.name_shm_id, c.name_shm_offset, name_size);
3993 if (name == NULL) {
3994 return error::kOutOfBounds;
3995 }
3996 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573997 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543998 return error::kNoError;
3999}
4000
4001error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
4002 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:584003 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:544004 GLuint index = static_cast<GLuint>(c.index);
4005 uint32 name_size = c.data_size;
4006 const char* name = GetImmediateDataAs<const char*>(
4007 c, name_size, immediate_data_size);
4008 if (name == NULL) {
4009 return error::kOutOfBounds;
4010 }
4011 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:574012 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:544013 return error::kNoError;
4014}
4015
4016error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
4017 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:584018 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:544019 GLuint index = static_cast<GLuint>(c.index);
4020 Bucket* bucket = GetBucket(c.name_bucket_id);
4021 if (!bucket || bucket->size() == 0) {
4022 return error::kInvalidArguments;
4023 }
4024 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:184025 if (!bucket->GetAsString(&name_str)) {
4026 return error::kInvalidArguments;
4027 }
[email protected]258a3313f2011-10-18 20:13:574028 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:544029 return error::kNoError;
4030}
4031
[email protected]2be6abf32012-06-26 00:28:334032void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4033 GLuint program, GLint location, const char* name) {
4034 if (!StringIsValidForGLES(name)) {
4035 SetGLError(GL_INVALID_VALUE,
4036 "glBindUniformLocationCHROMIUM", "Invalid character");
4037 return;
4038 }
4039 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4040 SetGLError(GL_INVALID_OPERATION,
4041 "glBindUniformLocationCHROMIUM", "reserved prefix");
4042 return;
4043 }
4044 if (location < 0 || static_cast<uint32>(location) >=
4045 (group_->max_fragment_uniform_vectors() +
4046 group_->max_vertex_uniform_vectors()) * 4) {
4047 SetGLError(GL_INVALID_VALUE,
4048 "glBindUniformLocationCHROMIUM", "location out of range");
4049 return;
4050 }
4051 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4052 program, "glBindUniformLocationCHROMIUM");
4053 if (!info) {
4054 return;
4055 }
4056 if (!info->SetUniformLocationBinding(name, location)) {
4057 SetGLError(GL_INVALID_VALUE,
4058 "glBindUniformLocationCHROMIUM", "location out of range");
4059 }
4060}
4061
4062error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUM(
4063 uint32 immediate_data_size, const gles2::BindUniformLocationCHROMIUM& c) {
4064 GLuint program = static_cast<GLuint>(c.program);
4065 GLint location = static_cast<GLint>(c.location);
4066 uint32 name_size = c.data_size;
4067 const char* name = GetSharedMemoryAs<const char*>(
4068 c.name_shm_id, c.name_shm_offset, name_size);
4069 if (name == NULL) {
4070 return error::kOutOfBounds;
4071 }
4072 String name_str(name, name_size);
4073 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4074 return error::kNoError;
4075}
4076
4077error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMImmediate(
4078 uint32 immediate_data_size,
4079 const gles2::BindUniformLocationCHROMIUMImmediate& c) {
4080 GLuint program = static_cast<GLuint>(c.program);
4081 GLint location = static_cast<GLint>(c.location);
4082 uint32 name_size = c.data_size;
4083 const char* name = GetImmediateDataAs<const char*>(
4084 c, name_size, immediate_data_size);
4085 if (name == NULL) {
4086 return error::kOutOfBounds;
4087 }
4088 String name_str(name, name_size);
4089 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4090 return error::kNoError;
4091}
4092
4093error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4094 uint32 immediate_data_size,
4095 const gles2::BindUniformLocationCHROMIUMBucket& c) {
4096 GLuint program = static_cast<GLuint>(c.program);
4097 GLint location = static_cast<GLint>(c.location);
4098 Bucket* bucket = GetBucket(c.name_bucket_id);
4099 if (!bucket || bucket->size() == 0) {
4100 return error::kInvalidArguments;
4101 }
4102 std::string name_str;
4103 if (!bucket->GetAsString(&name_str)) {
4104 return error::kInvalidArguments;
4105 }
4106 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4107 return error::kNoError;
4108}
4109
[email protected]f7a64ee2010-02-01 22:24:144110error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:464111 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:034112 GLuint client_id = c.shader;
4113 if (client_id) {
4114 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
4115 if (info) {
[email protected]ca488e12010-12-13 20:06:144116 if (!info->IsDeleted()) {
4117 glDeleteShader(info->service_id());
4118 shader_manager()->MarkAsDeleted(info);
4119 }
[email protected]ae51d192010-04-27 00:48:034120 } else {
[email protected]ad84a3a2012-06-08 21:42:434121 SetGLError(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
[email protected]ae51d192010-04-27 00:48:034122 }
[email protected]96449d2c2009-11-25 00:01:324123 }
[email protected]f7a64ee2010-02-01 22:24:144124 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324125}
4126
[email protected]f7a64ee2010-02-01 22:24:144127error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:464128 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:034129 GLuint client_id = c.program;
4130 if (client_id) {
4131 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
4132 if (info) {
[email protected]ca488e12010-12-13 20:06:144133 if (!info->IsDeleted()) {
[email protected]ca488e12010-12-13 20:06:144134 program_manager()->MarkAsDeleted(shader_manager(), info);
4135 }
[email protected]ae51d192010-04-27 00:48:034136 } else {
[email protected]ad84a3a2012-06-08 21:42:434137 SetGLError(GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
[email protected]ae51d192010-04-27 00:48:034138 }
[email protected]96449d2c2009-11-25 00:01:324139 }
[email protected]f7a64ee2010-02-01 22:24:144140 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324141}
4142
[email protected]269200b12010-11-18 22:53:064143void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104144 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574145 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104146 for (GLsizei ii = 0; ii < n; ++ii) {
4147 id_allocator->FreeID(ids[ii]);
4148 }
4149}
4150
[email protected]269200b12010-11-18 22:53:064151error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
4152 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104153 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4154 GLsizei n = static_cast<GLsizei>(c.n);
4155 uint32 data_size;
4156 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4157 return error::kOutOfBounds;
4158 }
4159 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4160 c.ids_shm_id, c.ids_shm_offset, data_size);
4161 if (n < 0) {
[email protected]ad84a3a2012-06-08 21:42:434162 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104163 return error::kNoError;
4164 }
4165 if (ids == NULL) {
4166 return error::kOutOfBounds;
4167 }
[email protected]269200b12010-11-18 22:53:064168 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:104169 return error::kNoError;
4170}
4171
[email protected]269200b12010-11-18 22:53:064172void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104173 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574174 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104175 if (id_offset == 0) {
4176 for (GLsizei ii = 0; ii < n; ++ii) {
4177 ids[ii] = id_allocator->AllocateID();
4178 }
4179 } else {
4180 for (GLsizei ii = 0; ii < n; ++ii) {
4181 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4182 id_offset = ids[ii] + 1;
4183 }
4184 }
4185}
4186
[email protected]269200b12010-11-18 22:53:064187error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4188 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104189 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4190 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4191 GLsizei n = static_cast<GLsizei>(c.n);
4192 uint32 data_size;
4193 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4194 return error::kOutOfBounds;
4195 }
4196 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4197 c.ids_shm_id, c.ids_shm_offset, data_size);
4198 if (n < 0) {
[email protected]ad84a3a2012-06-08 21:42:434199 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104200 return error::kNoError;
4201 }
4202 if (ids == NULL) {
4203 return error::kOutOfBounds;
4204 }
[email protected]269200b12010-11-18 22:53:064205 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:104206 return error::kNoError;
4207}
4208
[email protected]269200b12010-11-18 22:53:064209void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104210 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574211 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104212 for (GLsizei ii = 0; ii < n; ++ii) {
4213 if (!id_allocator->MarkAsUsed(ids[ii])) {
4214 for (GLsizei jj = 0; jj < ii; ++jj) {
4215 id_allocator->FreeID(ids[jj]);
4216 }
4217 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:434218 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4219 "attempt to register id that already exists");
[email protected]066849e32010-05-03 19:14:104220 return;
4221 }
4222 }
4223}
4224
[email protected]269200b12010-11-18 22:53:064225error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4226 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104227 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4228 GLsizei n = static_cast<GLsizei>(c.n);
4229 uint32 data_size;
4230 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4231 return error::kOutOfBounds;
4232 }
4233 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4234 c.ids_shm_id, c.ids_shm_offset, data_size);
4235 if (n < 0) {
[email protected]ad84a3a2012-06-08 21:42:434236 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104237 return error::kNoError;
4238 }
4239 if (ids == NULL) {
4240 return error::kOutOfBounds;
4241 }
[email protected]269200b12010-11-18 22:53:064242 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:104243 return error::kNoError;
4244}
4245
[email protected]a7266a92012-06-28 02:11:084246error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
[email protected]09e17272012-11-30 10:30:444247 DCHECK(!ShouldDeferDraws());
[email protected]0d6bfdc2011-11-02 01:32:204248 if (CheckBoundFramebuffersValid("glClear")) {
[email protected]e259eb412012-10-13 05:47:244249 UNSHIPPED_TRACE_EVENT_INSTANT2(
4250 "test_gpu", "DoClear",
4251 "red", state_.color_clear_red,
4252 "green", state_.color_clear_green);
[email protected]297ca1c2011-06-20 23:08:464253 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:274254 glClear(mask);
4255 }
[email protected]a7266a92012-06-28 02:11:084256 return error::kNoError;
4257}
4258
[email protected]36cef8ce2010-03-16 07:34:454259void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4260 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:034261 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:304262 FramebufferManager::FramebufferInfo* framebuffer_info =
4263 GetFramebufferInfoForTarget(target);
4264 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294265 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434266 "glFramebufferRenderbuffer", "no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454267 return;
4268 }
[email protected]ae51d192010-04-27 00:48:034269 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:284270 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:034271 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:284272 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:034273 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294274 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434275 "glFramebufferRenderbuffer", "unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:034276 return;
4277 }
4278 service_id = info->service_id();
4279 }
[email protected]9edc6b22010-12-23 02:00:264280 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034281 glFramebufferRenderbufferEXT(
4282 target, attachment, renderbuffertarget, service_id);
[email protected]1002c2d2011-06-28 22:39:044283 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264284 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:304285 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]3a2e7c7b2010-08-06 01:12:284286 }
[email protected]e259eb412012-10-13 05:47:244287 if (framebuffer_info == state_.bound_draw_framebuffer) {
[email protected]88a61bf2012-10-27 13:00:424288 clear_state_dirty_ = true;
[email protected]297ca1c2011-06-20 23:08:464289 }
[email protected]3a2e7c7b2010-08-06 01:12:284290}
4291
[email protected]3a2e7c7b2010-08-06 01:12:284292void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464293 if (SetCapabilityState(cap, false)) {
4294 glDisable(cap);
4295 }
[email protected]3a2e7c7b2010-08-06 01:12:284296}
4297
4298void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464299 if (SetCapabilityState(cap, true)) {
4300 glEnable(cap);
4301 }
[email protected]3a2e7c7b2010-08-06 01:12:284302}
4303
[email protected]88a61bf2012-10-27 13:00:424304void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
4305 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
4306 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
4307 glDepthRange(znear, zfar);
[email protected]3a2e7c7b2010-08-06 01:12:284308}
4309
[email protected]88a61bf2012-10-27 13:00:424310void GLES2DecoderImpl::DoHint(GLenum target, GLenum mode) {
4311 switch (target) {
4312 case GL_GENERATE_MIPMAP_HINT:
4313 state_.hint_generate_mipmap = mode;
4314 break;
4315 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4316 state_.hint_fragment_shader_derivative = mode;
4317 break;
4318 default:
4319 NOTREACHED();
4320 }
4321 glHint(target, mode);
4322}
4323
4324void GLES2DecoderImpl::DoSampleCoverage (GLclampf value, GLboolean invert) {
4325 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
4326 state_.sample_coverage_invert = (invert != 0);
4327 glSampleCoverage(state_.sample_coverage_value, invert);
[email protected]3a2e7c7b2010-08-06 01:12:284328}
4329
[email protected]0d6bfdc2011-11-02 01:32:204330// Assumes framebuffer is complete.
4331void GLES2DecoderImpl::ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:304332 GLenum target, FramebufferManager::FramebufferInfo* info) {
4333 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204334 // bind this to the DRAW point, clear then bind back to READ
4335 // TODO(gman): I don't think there is any guarantee that an FBO that
4336 // is complete on the READ attachment will be complete as a DRAW
4337 // attachment.
4338 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
4339 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, info->service_id());
[email protected]8e3e0662010-08-23 18:46:304340 }
[email protected]3a2e7c7b2010-08-06 01:12:284341 GLbitfield clear_bits = 0;
4342 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:464343 glClearColor(
[email protected]0d6bfdc2011-11-02 01:32:204344 0.0f, 0.0f, 0.0f,
[email protected]297ca1c2011-06-20 23:08:464345 (GLES2Util::GetChannelsForFormat(
[email protected]0d6bfdc2011-11-02 01:32:204346 info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f : 1.0f);
[email protected]3a2e7c7b2010-08-06 01:12:284347 glColorMask(true, true, true, true);
4348 clear_bits |= GL_COLOR_BUFFER_BIT;
4349 }
4350
4351 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4352 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4353 glClearStencil(0);
4354 glStencilMask(-1);
4355 clear_bits |= GL_STENCIL_BUFFER_BIT;
4356 }
4357
4358 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4359 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4360 glClearDepth(1.0f);
4361 glDepthMask(true);
4362 clear_bits |= GL_DEPTH_BUFFER_BIT;
4363 }
4364
4365 glDisable(GL_SCISSOR_TEST);
4366 glClear(clear_bits);
4367
[email protected]968351b2011-12-20 08:26:514368 framebuffer_manager()->MarkAttachmentsAsCleared(
4369 info, renderbuffer_manager(), texture_manager());
[email protected]3a2e7c7b2010-08-06 01:12:284370
[email protected]c007aa02010-09-02 22:22:404371 RestoreClearState();
4372
4373 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204374 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, info->service_id());
[email protected]87d1a3fe2011-12-01 04:25:484375 FramebufferManager::FramebufferInfo* framebuffer =
4376 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4377 GLuint service_id =
4378 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
4379 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
[email protected]c007aa02010-09-02 22:22:404380 }
4381}
4382
4383void GLES2DecoderImpl::RestoreClearState() {
[email protected]88a61bf2012-10-27 13:00:424384 clear_state_dirty_ = true;
[email protected]e259eb412012-10-13 05:47:244385 glClearColor(
4386 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
4387 state_.color_clear_alpha);
4388 glClearStencil(state_.stencil_clear);
4389 glClearDepth(state_.depth_clear);
[email protected]f731b9462012-10-30 00:35:224390 if (state_.enable_flags.scissor_test) {
[email protected]3a2e7c7b2010-08-06 01:12:284391 glEnable(GL_SCISSOR_TEST);
4392 }
[email protected]36cef8ce2010-03-16 07:34:454393}
4394
4395GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]0d6bfdc2011-11-02 01:32:204396 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]8e3e0662010-08-23 18:46:304397 GetFramebufferInfoForTarget(target);
[email protected]0d6bfdc2011-11-02 01:32:204398 if (!framebuffer) {
[email protected]36cef8ce2010-03-16 07:34:454399 return GL_FRAMEBUFFER_COMPLETE;
4400 }
[email protected]0d6bfdc2011-11-02 01:32:204401 GLenum completeness = framebuffer->IsPossiblyComplete();
4402 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4403 return completeness;
4404 }
[email protected]73276522012-11-09 05:50:204405 return framebuffer->GetStatus(texture_manager(), target);
[email protected]36cef8ce2010-03-16 07:34:454406}
4407
4408void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:034409 GLenum target, GLenum attachment, GLenum textarget,
4410 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:304411 FramebufferManager::FramebufferInfo* framebuffer_info =
4412 GetFramebufferInfoForTarget(target);
4413 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294414 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434415 "glFramebufferTexture2D", "no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:454416 return;
4417 }
[email protected]ae51d192010-04-27 00:48:034418 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:284419 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:034420 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:284421 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:034422 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294423 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434424 "glFramebufferTexture2D", "unknown texture");
[email protected]ae51d192010-04-27 00:48:034425 return;
4426 }
4427 service_id = info->service_id();
4428 }
[email protected]0d6bfdc2011-11-02 01:32:204429
[email protected]80eb6b52012-01-19 00:14:414430 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
[email protected]0d6bfdc2011-11-02 01:32:204431 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:434432 "glFramebufferTexture2D", "level out of range");
[email protected]0d6bfdc2011-11-02 01:32:204433 return;
4434 }
4435
[email protected]9edc6b22010-12-23 02:00:264436 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034437 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]1002c2d2011-06-28 22:39:044438 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264439 if (error == GL_NO_ERROR) {
4440 framebuffer_info->AttachTexture(attachment, info, textarget, level);
[email protected]3a2e7c7b2010-08-06 01:12:284441 }
[email protected]e259eb412012-10-13 05:47:244442 if (framebuffer_info == state_.bound_draw_framebuffer) {
[email protected]88a61bf2012-10-27 13:00:424443 clear_state_dirty_ = true;
[email protected]297ca1c2011-06-20 23:08:464444 }
[email protected]36cef8ce2010-03-16 07:34:454445}
4446
4447void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4448 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:304449 FramebufferManager::FramebufferInfo* framebuffer_info =
4450 GetFramebufferInfoForTarget(target);
4451 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294452 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434453 "glFramebufferAttachmentParameteriv", "no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454454 return;
4455 }
4456 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:574457 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4458 GLint type = 0;
4459 GLuint client_id = 0;
4460 glGetFramebufferAttachmentParameterivEXT(
4461 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
4462 switch (type) {
4463 case GL_RENDERBUFFER: {
4464 renderbuffer_manager()->GetClientId(*params, &client_id);
4465 break;
4466 }
4467 case GL_TEXTURE: {
4468 texture_manager()->GetClientId(*params, &client_id);
4469 break;
4470 }
4471 default:
4472 break;
4473 }
4474 *params = client_id;
4475 }
[email protected]36cef8ce2010-03-16 07:34:454476}
4477
4478void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4479 GLenum target, GLenum pname, GLint* params) {
[email protected]0d6bfdc2011-11-02 01:32:204480 RenderbufferManager::RenderbufferInfo* renderbuffer =
4481 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4482 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294483 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434484 "glGetRenderbufferParameteriv", "no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454485 return;
4486 }
[email protected]3a03a8f2011-03-19 00:51:274487 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:434488 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4489 *params = renderbuffer->internal_format();
4490 break;
4491 case GL_RENDERBUFFER_WIDTH:
4492 *params = renderbuffer->width();
4493 break;
4494 case GL_RENDERBUFFER_HEIGHT:
4495 *params = renderbuffer->height();
4496 break;
4497 default:
4498 glGetRenderbufferParameterivEXT(target, pname, params);
4499 break;
[email protected]b71f52c2010-06-18 22:20:204500 }
[email protected]36cef8ce2010-03-16 07:34:454501}
4502
[email protected]8e3e0662010-08-23 18:46:304503void GLES2DecoderImpl::DoBlitFramebufferEXT(
4504 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
4505 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
4506 GLbitfield mask, GLenum filter) {
[email protected]09e17272012-11-30 10:30:444507 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
[email protected]62e155e2012-10-23 22:43:154508 if (!features().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304509 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434510 "glBlitFramebufferEXT", "function not available");
[email protected]8e3e0662010-08-23 18:46:304511 }
[email protected]d058bca2012-11-26 10:27:264512 glDisable(GL_SCISSOR_TEST);
[email protected]5094b0f2010-11-09 19:45:244513 if (IsAngle()) {
4514 glBlitFramebufferANGLE(
4515 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4516 } else {
4517 glBlitFramebufferEXT(
4518 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4519 }
[email protected]d058bca2012-11-26 10:27:264520 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
[email protected]529c6672012-01-04 02:18:264521 UNSHIPPED_TRACE_EVENT_INSTANT1("test_gpu", "DoBlit", "width", srcX1 - srcX0);
[email protected]8e3e0662010-08-23 18:46:304522}
4523
4524void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
4525 GLenum target, GLsizei samples, GLenum internalformat,
4526 GLsizei width, GLsizei height) {
[email protected]62e155e2012-10-23 22:43:154527 if (!features().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304528 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434529 "glRenderbufferStorageMultisampleEXT", "function not available");
[email protected]8e3e0662010-08-23 18:46:304530 return;
4531 }
[email protected]8e3e0662010-08-23 18:46:304532
[email protected]0d6bfdc2011-11-02 01:32:204533 RenderbufferManager::RenderbufferInfo* renderbuffer =
4534 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4535 if (!renderbuffer) {
4536 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434537 "glGetRenderbufferStorageMultisample", "no renderbuffer bound");
[email protected]0d6bfdc2011-11-02 01:32:204538 return;
4539 }
4540
[email protected]84afefa2011-10-19 21:45:534541 if (samples > renderbuffer_manager()->max_samples()) {
4542 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:434543 "glGetRenderbufferStorageMultisample", "samples too large");
[email protected]84afefa2011-10-19 21:45:534544 return;
4545 }
4546
4547 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4548 height > renderbuffer_manager()->max_renderbuffer_size()) {
4549 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:434550 "glGetRenderbufferStorageMultisample", "size too large");
[email protected]84afefa2011-10-19 21:45:534551 return;
4552 }
4553
[email protected]9edc6b22010-12-23 02:00:264554 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:304555 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264556 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:304557 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264558 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:304559 break;
4560 case GL_RGBA4:
4561 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264562 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:304563 break;
4564 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264565 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:304566 break;
4567 }
4568 }
4569
[email protected]9edc6b22010-12-23 02:00:264570 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:084571 if (IsAngle()) {
4572 glRenderbufferStorageMultisampleANGLE(
4573 target, samples, impl_format, width, height);
4574 } else {
4575 glRenderbufferStorageMultisampleEXT(
4576 target, samples, impl_format, width, height);
4577 }
[email protected]1002c2d2011-06-28 22:39:044578 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264579 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514580 // TODO(gman): If renderbuffers tracked which framebuffers they were
4581 // attached to we could just mark those framebuffers as not complete.
4582 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204583 renderbuffer_manager()->SetInfo(
4584 renderbuffer, samples, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264585 }
[email protected]8e3e0662010-08-23 18:46:304586}
4587
[email protected]36cef8ce2010-03-16 07:34:454588void GLES2DecoderImpl::DoRenderbufferStorage(
4589 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]0d6bfdc2011-11-02 01:32:204590 RenderbufferManager::RenderbufferInfo* renderbuffer =
4591 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4592 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294593 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434594 "glGetRenderbufferStorage", "no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454595 return;
4596 }
[email protected]876f6fee2010-08-02 23:10:324597
[email protected]84afefa2011-10-19 21:45:534598 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4599 height > renderbuffer_manager()->max_renderbuffer_size()) {
4600 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:434601 "glGetRenderbufferStorage", "size too large");
[email protected]84afefa2011-10-19 21:45:534602 return;
4603 }
4604
[email protected]9edc6b22010-12-23 02:00:264605 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:324606 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264607 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:324608 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264609 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:324610 break;
4611 case GL_RGBA4:
4612 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264613 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:324614 break;
4615 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264616 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:324617 break;
4618 }
[email protected]b71f52c2010-06-18 22:20:204619 }
[email protected]876f6fee2010-08-02 23:10:324620
[email protected]9edc6b22010-12-23 02:00:264621 CopyRealGLErrorsToWrapper();
4622 glRenderbufferStorageEXT(target, impl_format, width, height);
[email protected]1002c2d2011-06-28 22:39:044623 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264624 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514625 // TODO(gman): If tetxures tracked which framebuffers they were attached to
4626 // we could just mark those framebuffers as not complete.
4627 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204628 renderbuffer_manager()->SetInfo(
4629 renderbuffer, 0, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264630 }
[email protected]36cef8ce2010-03-16 07:34:454631}
4632
[email protected]07f54fcc2009-12-22 02:46:304633void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]43ed3a72012-05-30 22:55:384634 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]6b8cf1a2010-05-06 16:13:584635 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4636 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:474637 if (!info) {
[email protected]a93bb842010-02-16 23:03:474638 return;
4639 }
[email protected]05afda12011-01-20 00:17:344640
[email protected]65dfc602012-07-23 20:39:394641 ShaderTranslator* vertex_translator = NULL;
4642 ShaderTranslator* fragment_translator = NULL;
4643 if (use_shader_translator_) {
4644 vertex_translator = vertex_translator_;
4645 fragment_translator = fragment_translator_;
4646 }
4647 if (info->Link(shader_manager(),
4648 vertex_translator,
4649 fragment_translator,
4650 feature_info_)) {
[email protected]e259eb412012-10-13 05:47:244651 if (info == state_.current_program.get()) {
[email protected]62e155e2012-10-23 22:43:154652 if (workarounds().use_current_program_after_successful_link) {
4653 glUseProgram(info->service_id());
[email protected]c2a3caf12012-10-23 19:32:004654 }
[email protected]62e155e2012-10-23 22:43:154655 program_manager()->ClearUniforms(info);
[email protected]2df73892012-04-28 01:09:544656 }
4657 }
[email protected]07f54fcc2009-12-22 02:46:304658};
4659
[email protected]3916c97e2010-02-25 03:20:504660void GLES2DecoderImpl::DoTexParameterf(
4661 GLenum target, GLenum pname, GLfloat param) {
4662 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:304663 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:434664 SetGLError(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:244665 return;
[email protected]07f54fcc2009-12-22 02:46:304666 }
[email protected]cbb22e42011-05-12 23:36:244667
4668 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414669 info, pname, static_cast<GLint>(param))) {
[email protected]f80e6e12012-08-31 00:43:534670 SetGLErrorInvalidEnum("glTexParameterf", pname, "pname");
[email protected]cbb22e42011-05-12 23:36:244671 return;
4672 }
4673 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:304674}
4675
[email protected]3916c97e2010-02-25 03:20:504676void GLES2DecoderImpl::DoTexParameteri(
4677 GLenum target, GLenum pname, GLint param) {
4678 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4679 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:434680 SetGLError(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:244681 return;
[email protected]3916c97e2010-02-25 03:20:504682 }
[email protected]cbb22e42011-05-12 23:36:244683
[email protected]80eb6b52012-01-19 00:14:414684 if (!texture_manager()->SetParameter(info, pname, param)) {
[email protected]f80e6e12012-08-31 00:43:534685 SetGLErrorInvalidEnum("glTexParameteri", pname, "pname");
[email protected]cbb22e42011-05-12 23:36:244686 return;
4687 }
4688 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:504689}
4690
4691void GLES2DecoderImpl::DoTexParameterfv(
4692 GLenum target, GLenum pname, const GLfloat* params) {
4693 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4694 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:434695 SetGLError(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:244696 return;
[email protected]3916c97e2010-02-25 03:20:504697 }
[email protected]cbb22e42011-05-12 23:36:244698
4699 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414700 info, pname, static_cast<GLint>(params[0]))) {
[email protected]f80e6e12012-08-31 00:43:534701 SetGLErrorInvalidEnum("glTexParameterfv", pname, "pname");
[email protected]cbb22e42011-05-12 23:36:244702 return;
4703 }
4704 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504705}
4706
4707void GLES2DecoderImpl::DoTexParameteriv(
4708 GLenum target, GLenum pname, const GLint* params) {
4709 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4710 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:434711 SetGLError(GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:244712 return;
[email protected]3916c97e2010-02-25 03:20:504713 }
[email protected]cbb22e42011-05-12 23:36:244714
[email protected]80eb6b52012-01-19 00:14:414715 if (!texture_manager()->SetParameter(info, pname, *params)) {
[email protected]f80e6e12012-08-31 00:43:534716 SetGLErrorInvalidEnum("glTexParameteriv", pname, "pname");
[email protected]cbb22e42011-05-12 23:36:244717 return;
4718 }
4719 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504720}
4721
[email protected]939e7362010-05-13 20:49:104722bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]e259eb412012-10-13 05:47:244723 if (!state_.current_program) {
[email protected]ad84a3a2012-06-08 21:42:434724 // The program does not exist.
4725 SetGLError(GL_INVALID_OPERATION, function_name, "no program in use");
4726 return false;
[email protected]939e7362010-05-13 20:49:104727 }
[email protected]e259eb412012-10-13 05:47:244728 if (!state_.current_program->InUse()) {
[email protected]ad84a3a2012-06-08 21:42:434729 SetGLError(GL_INVALID_OPERATION, function_name, "program not linked");
[email protected]939e7362010-05-13 20:49:104730 return false;
4731 }
4732 return true;
4733}
4734
4735bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
4736 GLint location, const char* function_name) {
4737 if (!CheckCurrentProgram(function_name)) {
4738 return false;
4739 }
4740 return location != -1;
4741}
4742
[email protected]43c2f1f2011-03-25 18:35:364743bool GLES2DecoderImpl::PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124744 GLint fake_location, const char* function_name,
4745 GLint* real_location, GLenum* type, GLsizei* count) {
[email protected]43c2f1f2011-03-25 18:35:364746 DCHECK(type);
4747 DCHECK(count);
[email protected]1b0a6752012-02-22 03:44:124748 DCHECK(real_location);
4749 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
[email protected]939e7362010-05-13 20:49:104750 return false;
4751 }
[email protected]43c2f1f2011-03-25 18:35:364752 GLint array_index = -1;
4753 const ProgramManager::ProgramInfo::UniformInfo* info =
[email protected]e259eb412012-10-13 05:47:244754 state_.current_program->GetUniformInfoByFakeLocation(
[email protected]1b0a6752012-02-22 03:44:124755 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:364756 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:434757 SetGLError(GL_INVALID_OPERATION, function_name, "unknown location");
[email protected]939e7362010-05-13 20:49:104758 return false;
4759 }
[email protected]43c2f1f2011-03-25 18:35:364760 if (*count > 1 && !info->is_array) {
4761 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:434762 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
[email protected]43c2f1f2011-03-25 18:35:364763 return false;
4764 }
4765 *count = std::min(info->size - array_index, *count);
4766 if (*count <= 0) {
4767 return false;
4768 }
4769 *type = info->type;
[email protected]939e7362010-05-13 20:49:104770 return true;
4771}
4772
[email protected]1b0a6752012-02-22 03:44:124773void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
4774 GLenum type = 0;
4775 GLsizei count = 1;
4776 GLint real_location = -1;
4777 if (!PrepForSetUniformByLocation(
4778 fake_location, "glUniform1iv", &real_location, &type, &count)) {
[email protected]3916c97e2010-02-25 03:20:504779 return;
4780 }
[email protected]e259eb412012-10-13 05:47:244781 if (!state_.current_program->SetSamplers(
[email protected]1868a342012-11-07 15:56:024782 state_.texture_units.size(), fake_location, 1, &v0)) {
[email protected]ad84a3a2012-06-08 21:42:434783 SetGLError(GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
[email protected]d20a6512012-05-02 20:17:464784 return;
4785 }
[email protected]1b0a6752012-02-22 03:44:124786 glUniform1i(real_location, v0);
[email protected]3916c97e2010-02-25 03:20:504787}
4788
4789void GLES2DecoderImpl::DoUniform1iv(
[email protected]1b0a6752012-02-22 03:44:124790 GLint fake_location, GLsizei count, const GLint *value) {
[email protected]43c2f1f2011-03-25 18:35:364791 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124792 GLint real_location = -1;
4793 if (!PrepForSetUniformByLocation(
4794 fake_location, "glUniform1iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364795 return;
4796 }
[email protected]74727112012-06-13 21:18:084797 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
4798 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]e259eb412012-10-13 05:47:244799 if (!state_.current_program->SetSamplers(
[email protected]1868a342012-11-07 15:56:024800 state_.texture_units.size(), fake_location, count, value)) {
[email protected]ad84a3a2012-06-08 21:42:434801 SetGLError(GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
[email protected]d20a6512012-05-02 20:17:464802 return;
4803 }
[email protected]43c2f1f2011-03-25 18:35:364804 }
[email protected]1b0a6752012-02-22 03:44:124805 glUniform1iv(real_location, count, value);
[email protected]3916c97e2010-02-25 03:20:504806}
4807
[email protected]939e7362010-05-13 20:49:104808void GLES2DecoderImpl::DoUniform1fv(
[email protected]1b0a6752012-02-22 03:44:124809 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364810 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124811 GLint real_location = -1;
4812 if (!PrepForSetUniformByLocation(
4813 fake_location, "glUniform1fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104814 return;
4815 }
4816 if (type == GL_BOOL) {
4817 scoped_array<GLint> temp(new GLint[count]);
4818 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:534819 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104820 }
[email protected]1b0a6752012-02-22 03:44:124821 DoUniform1iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104822 } else {
[email protected]1b0a6752012-02-22 03:44:124823 glUniform1fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104824 }
4825}
4826
4827void GLES2DecoderImpl::DoUniform2fv(
[email protected]1b0a6752012-02-22 03:44:124828 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364829 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124830 GLint real_location = -1;
4831 if (!PrepForSetUniformByLocation(
4832 fake_location, "glUniform2fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104833 return;
4834 }
4835 if (type == GL_BOOL_VEC2) {
4836 GLsizei num_values = count * 2;
4837 scoped_array<GLint> temp(new GLint[num_values]);
4838 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534839 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104840 }
[email protected]1b0a6752012-02-22 03:44:124841 glUniform2iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104842 } else {
[email protected]1b0a6752012-02-22 03:44:124843 glUniform2fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104844 }
4845}
4846
4847void GLES2DecoderImpl::DoUniform3fv(
[email protected]1b0a6752012-02-22 03:44:124848 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364849 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124850 GLint real_location = -1;
4851 if (!PrepForSetUniformByLocation(
4852 fake_location, "glUniform3fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104853 return;
4854 }
4855 if (type == GL_BOOL_VEC3) {
4856 GLsizei num_values = count * 3;
4857 scoped_array<GLint> temp(new GLint[num_values]);
4858 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534859 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104860 }
[email protected]1b0a6752012-02-22 03:44:124861 glUniform3iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104862 } else {
[email protected]1b0a6752012-02-22 03:44:124863 glUniform3fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104864 }
4865}
4866
4867void GLES2DecoderImpl::DoUniform4fv(
[email protected]1b0a6752012-02-22 03:44:124868 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364869 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124870 GLint real_location = -1;
4871 if (!PrepForSetUniformByLocation(
4872 fake_location, "glUniform4fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104873 return;
4874 }
4875 if (type == GL_BOOL_VEC4) {
4876 GLsizei num_values = count * 4;
4877 scoped_array<GLint> temp(new GLint[num_values]);
4878 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534879 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104880 }
[email protected]1b0a6752012-02-22 03:44:124881 glUniform4iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104882 } else {
[email protected]1b0a6752012-02-22 03:44:124883 glUniform4fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104884 }
4885}
4886
[email protected]43c2f1f2011-03-25 18:35:364887void GLES2DecoderImpl::DoUniform2iv(
[email protected]1b0a6752012-02-22 03:44:124888 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364889 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124890 GLint real_location = -1;
4891 if (!PrepForSetUniformByLocation(
4892 fake_location, "glUniform2iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364893 return;
4894 }
[email protected]1b0a6752012-02-22 03:44:124895 glUniform2iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364896}
4897
4898void GLES2DecoderImpl::DoUniform3iv(
[email protected]1b0a6752012-02-22 03:44:124899 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364900 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124901 GLint real_location = -1;
4902 if (!PrepForSetUniformByLocation(
4903 fake_location, "glUniform3iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364904 return;
4905 }
[email protected]1b0a6752012-02-22 03:44:124906 glUniform3iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364907}
4908
4909void GLES2DecoderImpl::DoUniform4iv(
[email protected]1b0a6752012-02-22 03:44:124910 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364911 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124912 GLint real_location = -1;
4913 if (!PrepForSetUniformByLocation(
4914 fake_location, "glUniform4iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364915 return;
4916 }
[email protected]1b0a6752012-02-22 03:44:124917 glUniform4iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364918}
4919
4920void GLES2DecoderImpl::DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:124921 GLint fake_location, GLsizei count, GLboolean transpose,
4922 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364923 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124924 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364925 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124926 fake_location, "glUniformMatrix2fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364927 return;
4928 }
[email protected]1b0a6752012-02-22 03:44:124929 glUniformMatrix2fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364930}
4931
4932void GLES2DecoderImpl::DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:124933 GLint fake_location, GLsizei count, GLboolean transpose,
4934 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364935 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124936 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364937 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124938 fake_location, "glUniformMatrix3fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364939 return;
4940 }
[email protected]1b0a6752012-02-22 03:44:124941 glUniformMatrix3fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364942}
4943
4944void GLES2DecoderImpl::DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:124945 GLint fake_location, GLsizei count, GLboolean transpose,
4946 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364947 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124948 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364949 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124950 fake_location, "glUniformMatrix4fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364951 return;
4952 }
[email protected]1b0a6752012-02-22 03:44:124953 glUniformMatrix4fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364954}
4955
[email protected]3916c97e2010-02-25 03:20:504956void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:034957 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:504958 ProgramManager::ProgramInfo* info = NULL;
4959 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:584960 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:504961 if (!info) {
[email protected]ae51d192010-04-27 00:48:034962 return;
4963 }
4964 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:504965 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]ad84a3a2012-06-08 21:42:434966 SetGLError(GL_INVALID_OPERATION, "glUseProgram", "program not linked");
[email protected]3916c97e2010-02-25 03:20:504967 return;
4968 }
[email protected]ae51d192010-04-27 00:48:034969 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:504970 }
[email protected]e259eb412012-10-13 05:47:244971 if (state_.current_program) {
4972 program_manager()->UnuseProgram(shader_manager(), state_.current_program);
[email protected]ca488e12010-12-13 20:06:144973 }
[email protected]e259eb412012-10-13 05:47:244974 state_.current_program = info;
[email protected]2df73892012-04-28 01:09:544975 glUseProgram(service_id);
[email protected]e259eb412012-10-13 05:47:244976 if (state_.current_program) {
4977 program_manager()->UseProgram(state_.current_program);
[email protected]ca488e12010-12-13 20:06:144978 }
[email protected]3916c97e2010-02-25 03:20:504979}
4980
[email protected]efcdd2362012-07-09 21:07:004981uint32 GLES2DecoderImpl::GetGLError() {
[email protected]96449d2c2009-11-25 00:01:324982 // Check the GL error first, then our wrapped error.
4983 GLenum error = glGetError();
4984 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:374985 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:324986 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:294987 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:324988 break;
4989 }
4990 }
4991 }
4992
4993 if (error != GL_NO_ERROR) {
4994 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:294995 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324996 }
4997 return error;
4998}
4999
[email protected]1002c2d2011-06-28 22:39:045000GLenum GLES2DecoderImpl::PeekGLError() {
5001 GLenum error = glGetError();
5002 if (error != GL_NO_ERROR) {
[email protected]ad84a3a2012-06-08 21:42:435003 SetGLError(error, "", "");
[email protected]1002c2d2011-06-28 22:39:045004 }
5005 return error;
5006}
5007
[email protected]ad84a3a2012-06-08 21:42:435008void GLES2DecoderImpl::SetGLError(
5009 GLenum error, const char* function_name, const char* msg) {
[email protected]8eee29c2010-04-29 03:38:295010 if (msg) {
5011 last_error_ = msg;
[email protected]d2a0e1a2012-08-12 02:25:015012 LogMessage(GetLogPrefix() + ": " + std::string("GL ERROR :") +
[email protected]ad84a3a2012-06-08 21:42:435013 GLES2Util::GetStringEnum(error) + " : " +
5014 function_name + ": " + msg);
[email protected]8eee29c2010-04-29 03:38:295015 }
[email protected]ddd968b82010-03-02 00:44:295016 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:325017}
5018
[email protected]f80e6e12012-08-31 00:43:535019void GLES2DecoderImpl::SetGLErrorInvalidEnum(
5020 const char* function_name, GLenum value, const char* label) {
5021 SetGLError(GL_INVALID_ENUM, function_name,
5022 (std::string(label) + " was " +
5023 GLES2Util::GetStringEnum(value)).c_str());
5024}
5025
[email protected]d2a0e1a2012-08-12 02:25:015026const std::string& GLES2DecoderImpl::GetLogPrefix() const {
5027 const std::string& prefix(debug_marker_manager_.GetMarker());
5028 return prefix.empty() ? this_in_hex_ : prefix;
5029}
5030
[email protected]0f8afe82012-05-14 23:43:015031void GLES2DecoderImpl::LogMessage(const std::string& msg) {
5032 if (log_message_count_ < kMaxLogMessages ||
5033 CommandLine::ForCurrentProcess()->HasSwitch(
5034 switches::kDisableGLErrorLimit)) {
5035 ++log_message_count_;
5036 // LOG this unless logging is turned off as any chromium code that
5037 // generates these errors probably has a bug.
5038 if (log_synthesized_gl_errors()) {
[email protected]3f00df92012-06-19 00:44:585039 LOG(ERROR) << msg;
[email protected]0f8afe82012-05-14 23:43:015040 }
5041 if (!msg_callback_.is_null()) {
5042 msg_callback_.Run(0, msg);
5043 }
5044 } else {
5045 if (log_message_count_ == kMaxLogMessages) {
5046 ++log_message_count_;
5047 LOG(ERROR)
5048 << "Too many GL errors, not reporting any more for this context."
5049 << " use --disable-gl-error-limit to see all errors.";
5050 }
5051 }
5052}
5053
5054void GLES2DecoderImpl::RenderWarning(const std::string& msg) {
5055 LogMessage(std::string("RENDER WARNING: ") + msg);
5056}
5057
5058void GLES2DecoderImpl::PerformanceWarning(const std::string& msg) {
5059 LogMessage(std::string("PERFORMANCE WARNING: ") + msg);
5060}
5061
[email protected]c447acd2012-07-23 23:48:415062void GLES2DecoderImpl::ForceCompileShaderIfPending(
5063 ShaderManager::ShaderInfo* info) {
5064 if (info->compilation_status() ==
5065 ShaderManager::ShaderInfo::PENDING_DEFERRED_COMPILE) {
[email protected]c447acd2012-07-23 23:48:415066 ShaderTranslator* translator = NULL;
5067 if (use_shader_translator_) {
5068 translator = info->shader_type() == GL_VERTEX_SHADER ?
5069 vertex_translator_.get() : fragment_translator_.get();
5070 }
5071 // We know there will be no errors, because we only defer compilation on
5072 // shaders that were previously compiled successfully.
5073 program_manager()->ForceCompileShader(info->deferred_compilation_source(),
5074 info,
5075 translator,
5076 feature_info_);
5077 }
5078}
5079
[email protected]07f54fcc2009-12-22 02:46:305080void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
5081 GLenum error;
5082 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]ad84a3a2012-06-08 21:42:435083 SetGLError(error, "", NULL);
[email protected]07f54fcc2009-12-22 02:46:305084 }
5085}
5086
[email protected]6217d392010-03-25 22:08:355087void GLES2DecoderImpl::ClearRealGLErrors() {
5088 GLenum error;
5089 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]3ed14d112011-12-13 22:05:515090 if (error != GL_OUT_OF_MEMORY) {
5091 // GL_OUT_OF_MEMORY can legally happen on lost device.
5092 NOTREACHED() << "GL error " << error << " was unhandled.";
5093 }
[email protected]6217d392010-03-25 22:08:355094 }
5095}
5096
[email protected]ef526492010-06-02 23:12:255097bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]e259eb412012-10-13 05:47:245098 DCHECK(state_.current_program);
[email protected]ef526492010-06-02 23:12:255099 // Only check if there are some unrenderable textures.
5100 if (!texture_manager()->HaveUnrenderableTextures()) {
5101 return false;
5102 }
5103 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:505104 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
[email protected]e259eb412012-10-13 05:47:245105 state_.current_program->sampler_indices();
[email protected]3916c97e2010-02-25 03:20:505106 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5107 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
[email protected]e259eb412012-10-13 05:47:245108 state_.current_program->GetUniformInfo(sampler_indices[ii]);
[email protected]3916c97e2010-02-25 03:20:505109 DCHECK(uniform_info);
5110 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5111 GLuint texture_unit_index = uniform_info->texture_units[jj];
[email protected]1868a342012-11-07 15:56:025112 if (texture_unit_index < state_.texture_units.size()) {
[email protected]e259eb412012-10-13 05:47:245113 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
[email protected]3916c97e2010-02-25 03:20:505114 TextureManager::TextureInfo* texture_info =
[email protected]61eeb33f2011-07-26 15:30:315115 texture_unit.GetInfoForSamplerType(uniform_info->type);
[email protected]80eb6b52012-01-19 00:14:415116 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]ef526492010-06-02 23:12:255117 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:505118 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5119 glBindTexture(
[email protected]61eeb33f2011-07-26 15:30:315120 GetBindTargetForSamplerType(uniform_info->type),
[email protected]00f893d2010-08-24 18:55:495121 texture_manager()->black_texture_id(uniform_info->type));
[email protected]0f8afe82012-05-14 23:43:015122 RenderWarning(
5123 std::string("texture bound to texture unit ") +
5124 base::IntToString(texture_unit_index) +
5125 " is not renderable. It maybe non-power-of-2 and have "
5126 " incompatible texture filtering or is not "
5127 "'texture complete'");
[email protected]3916c97e2010-02-25 03:20:505128 }
5129 }
5130 // else: should this be an error?
5131 }
5132 }
[email protected]ef526492010-06-02 23:12:255133 return textures_set;
[email protected]3916c97e2010-02-25 03:20:505134}
5135
5136void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
[email protected]e259eb412012-10-13 05:47:245137 DCHECK(state_.current_program);
[email protected]3916c97e2010-02-25 03:20:505138 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
[email protected]e259eb412012-10-13 05:47:245139 state_.current_program->sampler_indices();
[email protected]3916c97e2010-02-25 03:20:505140 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5141 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
[email protected]e259eb412012-10-13 05:47:245142 state_.current_program->GetUniformInfo(sampler_indices[ii]);
[email protected]3916c97e2010-02-25 03:20:505143 DCHECK(uniform_info);
5144 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5145 GLuint texture_unit_index = uniform_info->texture_units[jj];
[email protected]1868a342012-11-07 15:56:025146 if (texture_unit_index < state_.texture_units.size()) {
[email protected]e259eb412012-10-13 05:47:245147 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
[email protected]3916c97e2010-02-25 03:20:505148 TextureManager::TextureInfo* texture_info =
5149 uniform_info->type == GL_SAMPLER_2D ?
5150 texture_unit.bound_texture_2d :
5151 texture_unit.bound_texture_cube_map;
[email protected]80eb6b52012-01-19 00:14:415152 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]3916c97e2010-02-25 03:20:505153 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5154 // Get the texture info that was previously bound here.
5155 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
5156 texture_unit.bound_texture_2d :
5157 texture_unit.bound_texture_cube_map;
5158 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:035159 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:505160 }
5161 }
5162 }
5163 }
5164 // Set the active texture back to whatever the user had it as.
[email protected]e259eb412012-10-13 05:47:245165 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
[email protected]07f54fcc2009-12-22 02:46:305166}
5167
[email protected]0d6bfdc2011-11-02 01:32:205168bool GLES2DecoderImpl::ClearUnclearedTextures() {
5169 // Only check if there are some uncleared textures.
5170 if (!texture_manager()->HaveUnsafeTextures()) {
5171 return true;
5172 }
5173
5174 // 1: Check all textures we are about to render with.
[email protected]e259eb412012-10-13 05:47:245175 if (state_.current_program) {
[email protected]0d6bfdc2011-11-02 01:32:205176 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
[email protected]e259eb412012-10-13 05:47:245177 state_.current_program->sampler_indices();
[email protected]0d6bfdc2011-11-02 01:32:205178 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5179 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
[email protected]e259eb412012-10-13 05:47:245180 state_.current_program->GetUniformInfo(sampler_indices[ii]);
[email protected]0d6bfdc2011-11-02 01:32:205181 DCHECK(uniform_info);
5182 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5183 GLuint texture_unit_index = uniform_info->texture_units[jj];
[email protected]1868a342012-11-07 15:56:025184 if (texture_unit_index < state_.texture_units.size()) {
[email protected]e259eb412012-10-13 05:47:245185 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
[email protected]0d6bfdc2011-11-02 01:32:205186 TextureManager::TextureInfo* texture_info =
5187 texture_unit.GetInfoForSamplerType(uniform_info->type);
5188 if (texture_info && !texture_info->SafeToRenderFrom()) {
5189 if (!texture_manager()->ClearRenderableLevels(this, texture_info)) {
5190 return false;
5191 }
5192 }
5193 }
5194 }
5195 }
5196 }
5197 return true;
5198}
5199
[email protected]c6aef902012-02-14 03:31:425200bool GLES2DecoderImpl::IsDrawValid(
[email protected]ad84a3a2012-06-08 21:42:435201 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount) {
[email protected]689fa1c52010-06-09 18:35:035202 // NOTE: We specifically do not check current_program->IsValid() because
5203 // it could never be invalid since glUseProgram would have failed. While
5204 // glLinkProgram could later mark the program as invalid the previous
5205 // valid program will still function if it is still the current program.
[email protected]e259eb412012-10-13 05:47:245206 if (!state_.current_program) {
[email protected]3916c97e2010-02-25 03:20:505207 // The program does not exist.
5208 // But GL says no ERROR.
[email protected]0f8afe82012-05-14 23:43:015209 RenderWarning("Drawing with no current shader program.");
[email protected]3916c97e2010-02-25 03:20:505210 return false;
5211 }
[email protected]c6aef902012-02-14 03:31:425212
5213 // true if any enabled, used divisor is zero
5214 bool divisor0 = false;
[email protected]f39f4b3f2010-05-12 17:04:085215 // Validate all attribs currently enabled. If they are used by the current
5216 // program then check that they have enough elements to handle the draw call.
5217 // If they are not used by the current program check that they have a buffer
5218 // assigned.
5219 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]e259eb412012-10-13 05:47:245220 state_.vertex_attrib_manager->GetEnabledVertexAttribInfos();
[email protected]f39f4b3f2010-05-12 17:04:085221 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:405222 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:085223 const VertexAttribManager::VertexAttribInfo* info = *it;
5224 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
[email protected]e259eb412012-10-13 05:47:245225 state_.current_program->GetAttribInfoByLocation(info->index());
[email protected]f39f4b3f2010-05-12 17:04:085226 if (attrib_info) {
[email protected]c6aef902012-02-14 03:31:425227 divisor0 |= (info->divisor() == 0);
5228 GLuint count = info->MaxVertexAccessed(primcount, max_vertex_accessed);
[email protected]f39f4b3f2010-05-12 17:04:085229 // This attrib is used in the current program.
[email protected]c6aef902012-02-14 03:31:425230 if (!info->CanAccess(count)) {
[email protected]0f8afe82012-05-14 23:43:015231 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:435232 GL_INVALID_OPERATION, function_name,
[email protected]0f8afe82012-05-14 23:43:015233 (std::string(
[email protected]ad84a3a2012-06-08 21:42:435234 "attempt to access out of range vertices in attribute ") +
5235 base::IntToString(info->index())).c_str());
[email protected]f39f4b3f2010-05-12 17:04:085236 return false;
5237 }
5238 } else {
5239 // This attrib is not used in the current program.
[email protected]a0b78dc2011-11-11 10:43:105240 if (!info->buffer()) {
[email protected]f39f4b3f2010-05-12 17:04:085241 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:435242 GL_INVALID_OPERATION, function_name,
[email protected]0f8afe82012-05-14 23:43:015243 (std::string(
[email protected]ad84a3a2012-06-08 21:42:435244 "attempt to render with no buffer attached to "
[email protected]0f8afe82012-05-14 23:43:015245 "enabled attribute ") +
5246 base::IntToString(info->index())).c_str());
[email protected]f39f4b3f2010-05-12 17:04:085247 return false;
5248 }
[email protected]1d32bc82010-01-13 22:06:465249 }
[email protected]07f54fcc2009-12-22 02:46:305250 }
[email protected]c6aef902012-02-14 03:31:425251
5252 if (primcount && !divisor0) {
5253 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:435254 GL_INVALID_OPERATION, function_name,
5255 "attempt instanced render with all attributes having "
[email protected]c6aef902012-02-14 03:31:425256 "non-zero divisors");
5257 return false;
5258 }
5259
[email protected]3916c97e2010-02-25 03:20:505260 return true;
[email protected]b1122982010-05-17 23:04:245261}
5262
[email protected]c13e1da62011-09-09 21:48:305263bool GLES2DecoderImpl::SimulateAttrib0(
[email protected]ad84a3a2012-06-08 21:42:435264 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
[email protected]c13e1da62011-09-09 21:48:305265 DCHECK(simulated);
5266 *simulated = false;
5267
[email protected]876f6fee2010-08-02 23:10:325268 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
[email protected]c13e1da62011-09-09 21:48:305269 return true;
[email protected]876f6fee2010-08-02 23:10:325270
[email protected]b1122982010-05-17 23:04:245271 const VertexAttribManager::VertexAttribInfo* info =
[email protected]e259eb412012-10-13 05:47:245272 state_.vertex_attrib_manager->GetVertexAttribInfo(0);
[email protected]b1122982010-05-17 23:04:245273 // If it's enabled or it's not used then we don't need to do anything.
[email protected]e259eb412012-10-13 05:47:245274 bool attrib_0_used =
5275 state_.current_program->GetAttribInfoByLocation(0) != NULL;
[email protected]fc753442011-02-04 19:49:495276 if (info->enabled() && attrib_0_used) {
[email protected]c13e1da62011-09-09 21:48:305277 return true;
[email protected]b1122982010-05-17 23:04:245278 }
5279
[email protected]b1122982010-05-17 23:04:245280 // Make a buffer with a single repeated vec4 value enough to
5281 // simulate the constant value that is supposed to be here.
5282 // This is required to emulate GLES2 on GL.
[email protected]c13e1da62011-09-09 21:48:305283 GLuint num_vertices = max_vertex_accessed + 1;
[email protected]3aad1a32012-09-07 20:54:475284 uint32 size_needed = 0;
[email protected]c13e1da62011-09-09 21:48:305285
5286 if (num_vertices == 0 ||
[email protected]3aad1a32012-09-07 20:54:475287 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
[email protected]c13e1da62011-09-09 21:48:305288 size_needed > 0x7FFFFFFFU) {
[email protected]ad84a3a2012-06-08 21:42:435289 SetGLError(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c13e1da62011-09-09 21:48:305290 return false;
5291 }
5292
[email protected]0f8afe82012-05-14 23:43:015293 PerformanceWarning(
5294 "Attribute 0 is disabled. This has signficant performance penalty");
5295
[email protected]c13e1da62011-09-09 21:48:305296 CopyRealGLErrorsToWrapper();
5297 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
5298
[email protected]8f0b86c2f2012-04-10 05:48:285299 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
5300 if (new_buffer) {
[email protected]fc753442011-02-04 19:49:495301 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305302 GLenum error = glGetError();
5303 if (error != GL_NO_ERROR) {
[email protected]ad84a3a2012-06-08 21:42:435304 SetGLError(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c13e1da62011-09-09 21:48:305305 return false;
5306 }
[email protected]fc753442011-02-04 19:49:495307 }
[email protected]af6380962012-11-29 23:24:135308
5309 const Vec4& value = state_.attrib_values[0];
[email protected]8f0b86c2f2012-04-10 05:48:285310 if (new_buffer ||
5311 (attrib_0_used &&
5312 (!attrib_0_buffer_matches_value_ ||
[email protected]af6380962012-11-29 23:24:135313 (value.v[0] != attrib_0_value_.v[0] ||
5314 value.v[1] != attrib_0_value_.v[1] ||
5315 value.v[2] != attrib_0_value_.v[2] ||
5316 value.v[3] != attrib_0_value_.v[3])))) {
5317 std::vector<Vec4> temp(num_vertices, value);
[email protected]fc753442011-02-04 19:49:495318 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
5319 attrib_0_buffer_matches_value_ = true;
[email protected]af6380962012-11-29 23:24:135320 attrib_0_value_ = value;
[email protected]b1122982010-05-17 23:04:245321 attrib_0_size_ = size_needed;
5322 }
5323
5324 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5325
[email protected]c6aef902012-02-14 03:31:425326 if (info->divisor())
5327 glVertexAttribDivisorANGLE(0, 0);
5328
[email protected]c13e1da62011-09-09 21:48:305329 *simulated = true;
[email protected]b1122982010-05-17 23:04:245330 return true;
[email protected]b1122982010-05-17 23:04:245331}
5332
[email protected]43410e92012-04-20 17:06:285333void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib) {
[email protected]b1122982010-05-17 23:04:245334 const VertexAttribManager::VertexAttribInfo* info =
[email protected]e259eb412012-10-13 05:47:245335 state_.vertex_attrib_manager->GetVertexAttribInfo(attrib);
[email protected]b1122982010-05-17 23:04:245336 const void* ptr = reinterpret_cast<const void*>(info->offset());
5337 BufferManager::BufferInfo* buffer_info = info->buffer();
5338 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
5339 glVertexAttribPointer(
[email protected]43410e92012-04-20 17:06:285340 attrib, info->size(), info->type(), info->normalized(), info->gl_stride(),
[email protected]b1122982010-05-17 23:04:245341 ptr);
[email protected]c6aef902012-02-14 03:31:425342 if (info->divisor())
[email protected]43410e92012-04-20 17:06:285343 glVertexAttribDivisorANGLE(attrib, info->divisor());
[email protected]e259eb412012-10-13 05:47:245344 glBindBuffer(
5345 GL_ARRAY_BUFFER,
5346 state_.bound_array_buffer ? state_.bound_array_buffer->service_id() : 0);
[email protected]43410e92012-04-20 17:06:285347
[email protected]265f8992012-07-20 01:03:145348 // Never touch vertex attribute 0's state (in particular, never
5349 // disable it) when running on desktop GL because it will never be
5350 // re-enabled.
5351 if (attrib != 0 ||
5352 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
5353 if (info->enabled()) {
5354 glEnableVertexAttribArray(attrib);
5355 } else {
5356 glDisableVertexAttribArray(attrib);
5357 }
[email protected]43410e92012-04-20 17:06:285358 }
[email protected]b1122982010-05-17 23:04:245359}
[email protected]07f54fcc2009-12-22 02:46:305360
[email protected]8fbedc02010-11-18 18:43:405361bool GLES2DecoderImpl::SimulateFixedAttribs(
[email protected]ad84a3a2012-06-08 21:42:435362 const char* function_name,
[email protected]c6aef902012-02-14 03:31:425363 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
[email protected]8fbedc02010-11-18 18:43:405364 DCHECK(simulated);
5365 *simulated = false;
5366 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
5367 return true;
5368
[email protected]e259eb412012-10-13 05:47:245369 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
[email protected]8fbedc02010-11-18 18:43:405370 return true;
5371 }
5372
[email protected]0f8afe82012-05-14 23:43:015373 PerformanceWarning(
5374 "GL_FIXED attributes have a signficant performance penalty");
5375
[email protected]8fbedc02010-11-18 18:43:405376 // NOTE: we could be smart and try to check if a buffer is used
5377 // twice in 2 different attribs, find the overlapping parts and therefore
5378 // duplicate the minimum amount of data but this whole code path is not meant
5379 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
5380 // tests so we just add to the buffer attrib used.
5381
[email protected]c13e1da62011-09-09 21:48:305382 GLuint elements_needed = 0;
[email protected]8fbedc02010-11-18 18:43:405383 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]e259eb412012-10-13 05:47:245384 state_.vertex_attrib_manager->GetEnabledVertexAttribInfos();
[email protected]8fbedc02010-11-18 18:43:405385 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5386 infos.begin(); it != infos.end(); ++it) {
5387 const VertexAttribManager::VertexAttribInfo* info = *it;
5388 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
[email protected]e259eb412012-10-13 05:47:245389 state_.current_program->GetAttribInfoByLocation(info->index());
[email protected]c6aef902012-02-14 03:31:425390 GLuint max_accessed = info->MaxVertexAccessed(primcount,
5391 max_vertex_accessed);
5392 GLuint num_vertices = max_accessed + 1;
5393 if (num_vertices == 0) {
[email protected]ad84a3a2012-06-08 21:42:435394 SetGLError(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c6aef902012-02-14 03:31:425395 return false;
5396 }
[email protected]8fbedc02010-11-18 18:43:405397 if (attrib_info &&
[email protected]c6aef902012-02-14 03:31:425398 info->CanAccess(max_accessed) &&
[email protected]8fbedc02010-11-18 18:43:405399 info->type() == GL_FIXED) {
[email protected]3aad1a32012-09-07 20:54:475400 uint32 elements_used = 0;
5401 if (!SafeMultiplyUint32(num_vertices, info->size(), &elements_used) ||
5402 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
[email protected]ad84a3a2012-06-08 21:42:435403 SetGLError(
5404 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]8fbedc02010-11-18 18:43:405405 return false;
5406 }
5407 }
5408 }
5409
[email protected]3aad1a32012-09-07 20:54:475410 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
5411 uint32 size_needed = 0;
5412 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
[email protected]c13e1da62011-09-09 21:48:305413 size_needed > 0x7FFFFFFFU) {
[email protected]ad84a3a2012-06-08 21:42:435414 SetGLError(GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]8fbedc02010-11-18 18:43:405415 return false;
5416 }
5417
[email protected]c13e1da62011-09-09 21:48:305418 CopyRealGLErrorsToWrapper();
[email protected]8fbedc02010-11-18 18:43:405419
5420 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
[email protected]c13e1da62011-09-09 21:48:305421 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
[email protected]8fbedc02010-11-18 18:43:405422 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305423 GLenum error = glGetError();
5424 if (error != GL_NO_ERROR) {
[email protected]ad84a3a2012-06-08 21:42:435425 SetGLError(
5426 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]c13e1da62011-09-09 21:48:305427 return false;
5428 }
[email protected]8fbedc02010-11-18 18:43:405429 }
5430
5431 // Copy the elements and convert to float
5432 GLintptr offset = 0;
5433 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5434 infos.begin(); it != infos.end(); ++it) {
5435 const VertexAttribManager::VertexAttribInfo* info = *it;
5436 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
[email protected]e259eb412012-10-13 05:47:245437 state_.current_program->GetAttribInfoByLocation(info->index());
[email protected]c6aef902012-02-14 03:31:425438 GLuint max_accessed = info->MaxVertexAccessed(primcount,
5439 max_vertex_accessed);
5440 GLuint num_vertices = max_accessed + 1;
5441 if (num_vertices == 0) {
[email protected]ad84a3a2012-06-08 21:42:435442 SetGLError(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c6aef902012-02-14 03:31:425443 return false;
5444 }
[email protected]8fbedc02010-11-18 18:43:405445 if (attrib_info &&
[email protected]c6aef902012-02-14 03:31:425446 info->CanAccess(max_accessed) &&
[email protected]8fbedc02010-11-18 18:43:405447 info->type() == GL_FIXED) {
5448 int num_elements = info->size() * kSizeOfFloat;
5449 int size = num_elements * num_vertices;
5450 scoped_array<float> data(new float[size]);
5451 const int32* src = reinterpret_cast<const int32 *>(
5452 info->buffer()->GetRange(info->offset(), size));
5453 const int32* end = src + num_elements;
5454 float* dst = data.get();
5455 while (src != end) {
5456 *dst++ = static_cast<float>(*src++) / 65536.0f;
5457 }
5458 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
5459 glVertexAttribPointer(
5460 info->index(), info->size(), GL_FLOAT, false, 0,
5461 reinterpret_cast<GLvoid*>(offset));
5462 offset += size;
5463 }
5464 }
5465 *simulated = true;
5466 return true;
5467}
5468
5469void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
5470 // There's no need to call glVertexAttribPointer because we shadow all the
5471 // settings and passing GL_FIXED to it will not work.
[email protected]e259eb412012-10-13 05:47:245472 glBindBuffer(
5473 GL_ARRAY_BUFFER,
5474 state_.bound_array_buffer ? state_.bound_array_buffer->service_id() : 0);
[email protected]8fbedc02010-11-18 18:43:405475}
5476
[email protected]ad84a3a2012-06-08 21:42:435477error::Error GLES2DecoderImpl::DoDrawArrays(
5478 const char* function_name,
5479 bool instanced,
5480 GLenum mode,
5481 GLint first,
5482 GLsizei count,
5483 GLsizei primcount) {
[email protected]a7266a92012-06-28 02:11:085484 if (ShouldDeferDraws())
5485 return error::kDeferCommandUntilLater;
[email protected]38d139d2011-07-14 00:38:435486 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]f80e6e12012-08-31 00:43:535487 SetGLErrorInvalidEnum(function_name, mode, "mode");
[email protected]38d139d2011-07-14 00:38:435488 return error::kNoError;
5489 }
5490 if (count < 0) {
[email protected]ad84a3a2012-06-08 21:42:435491 SetGLError(GL_INVALID_VALUE, function_name, "count < 0");
[email protected]38d139d2011-07-14 00:38:435492 return error::kNoError;
5493 }
[email protected]c6aef902012-02-14 03:31:425494 if (primcount < 0) {
[email protected]ad84a3a2012-06-08 21:42:435495 SetGLError(GL_INVALID_VALUE, function_name, "primcount < 0");
[email protected]c6aef902012-02-14 03:31:425496 return error::kNoError;
5497 }
[email protected]ad84a3a2012-06-08 21:42:435498 if (!CheckBoundFramebuffersValid(function_name)) {
[email protected]38d139d2011-07-14 00:38:435499 return error::kNoError;
5500 }
5501 // We have to check this here because the prototype for glDrawArrays
5502 // is GLint not GLsizei.
5503 if (first < 0) {
[email protected]ad84a3a2012-06-08 21:42:435504 SetGLError(GL_INVALID_VALUE, function_name, "first < 0");
[email protected]38d139d2011-07-14 00:38:435505 return error::kNoError;
5506 }
5507
[email protected]c6aef902012-02-14 03:31:425508 if (count == 0 || (instanced && primcount == 0)) {
[email protected]0f8afe82012-05-14 23:43:015509 RenderWarning("Render count or primcount is 0.");
[email protected]38d139d2011-07-14 00:38:435510 return error::kNoError;
5511 }
5512
5513 GLuint max_vertex_accessed = first + count - 1;
[email protected]ad84a3a2012-06-08 21:42:435514 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:205515 if (!ClearUnclearedTextures()) {
[email protected]ad84a3a2012-06-08 21:42:435516 SetGLError(GL_INVALID_VALUE, function_name, "out of memory");
[email protected]0d6bfdc2011-11-02 01:32:205517 return error::kNoError;
5518 }
[email protected]c13e1da62011-09-09 21:48:305519 bool simulated_attrib_0 = false;
[email protected]ad84a3a2012-06-08 21:42:435520 if (!SimulateAttrib0(
5521 function_name, max_vertex_accessed, &simulated_attrib_0)) {
[email protected]c13e1da62011-09-09 21:48:305522 return error::kNoError;
5523 }
[email protected]38d139d2011-07-14 00:38:435524 bool simulated_fixed_attribs = false;
[email protected]ad84a3a2012-06-08 21:42:435525 if (SimulateFixedAttribs(
5526 function_name, max_vertex_accessed, &simulated_fixed_attribs,
5527 primcount)) {
[email protected]38d139d2011-07-14 00:38:435528 bool textures_set = SetBlackTextureForNonRenderableTextures();
5529 ApplyDirtyState();
[email protected]c6aef902012-02-14 03:31:425530 if (!instanced) {
5531 glDrawArrays(mode, first, count);
5532 } else {
5533 glDrawArraysInstancedANGLE(mode, first, count, primcount);
5534 }
[email protected]22e3f552012-03-13 01:54:195535 ProcessPendingQueries();
[email protected]38d139d2011-07-14 00:38:435536 if (textures_set) {
5537 RestoreStateForNonRenderableTextures();
5538 }
5539 if (simulated_fixed_attribs) {
5540 RestoreStateForSimulatedFixedAttribs();
5541 }
5542 }
5543 if (simulated_attrib_0) {
[email protected]43410e92012-04-20 17:06:285544 RestoreStateForAttrib(0);
[email protected]38d139d2011-07-14 00:38:435545 }
[email protected]38d139d2011-07-14 00:38:435546 }
5547 return error::kNoError;
5548}
5549
[email protected]c6aef902012-02-14 03:31:425550error::Error GLES2DecoderImpl::HandleDrawArrays(
5551 uint32 immediate_data_size, const gles2::DrawArrays& c) {
[email protected]ad84a3a2012-06-08 21:42:435552 return DoDrawArrays("glDrawArrays",
5553 false,
[email protected]c6aef902012-02-14 03:31:425554 static_cast<GLenum>(c.mode),
5555 static_cast<GLint>(c.first),
5556 static_cast<GLsizei>(c.count),
5557 0);
5558}
5559
5560error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
5561 uint32 immediate_data_size, const gles2::DrawArraysInstancedANGLE& c) {
[email protected]62e155e2012-10-23 22:43:155562 if (!features().angle_instanced_arrays) {
[email protected]c6aef902012-02-14 03:31:425563 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435564 "glDrawArraysInstancedANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:425565 return error::kNoError;
5566 }
[email protected]ad84a3a2012-06-08 21:42:435567 return DoDrawArrays("glDrawArraysIntancedANGLE",
5568 true,
[email protected]c6aef902012-02-14 03:31:425569 static_cast<GLenum>(c.mode),
5570 static_cast<GLint>(c.first),
5571 static_cast<GLsizei>(c.count),
5572 static_cast<GLsizei>(c.primcount));
5573}
5574
[email protected]ad84a3a2012-06-08 21:42:435575error::Error GLES2DecoderImpl::DoDrawElements(
5576 const char* function_name,
5577 bool instanced,
5578 GLenum mode,
5579 GLsizei count,
5580 GLenum type,
5581 int32 offset,
5582 GLsizei primcount) {
[email protected]a7266a92012-06-28 02:11:085583 if (ShouldDeferDraws())
5584 return error::kDeferCommandUntilLater;
[email protected]e259eb412012-10-13 05:47:245585 if (!state_.vertex_attrib_manager->element_array_buffer()) {
[email protected]8eee29c2010-04-29 03:38:295586 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435587 function_name, "No element array buffer bound");
[email protected]8eee29c2010-04-29 03:38:295588 return error::kNoError;
5589 }
5590
[email protected]8eee29c2010-04-29 03:38:295591 if (count < 0) {
[email protected]ad84a3a2012-06-08 21:42:435592 SetGLError(GL_INVALID_VALUE, function_name, "count < 0");
[email protected]8eee29c2010-04-29 03:38:295593 return error::kNoError;
5594 }
5595 if (offset < 0) {
[email protected]ad84a3a2012-06-08 21:42:435596 SetGLError(GL_INVALID_VALUE, function_name, "offset < 0");
[email protected]8eee29c2010-04-29 03:38:295597 return error::kNoError;
5598 }
[email protected]9438b012010-06-15 22:55:055599 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]f80e6e12012-08-31 00:43:535600 SetGLErrorInvalidEnum(function_name, mode, "mode");
[email protected]8eee29c2010-04-29 03:38:295601 return error::kNoError;
5602 }
[email protected]9438b012010-06-15 22:55:055603 if (!validators_->index_type.IsValid(type)) {
[email protected]f80e6e12012-08-31 00:43:535604 SetGLErrorInvalidEnum(function_name, type, "type");
[email protected]8eee29c2010-04-29 03:38:295605 return error::kNoError;
5606 }
[email protected]c6aef902012-02-14 03:31:425607 if (primcount < 0) {
[email protected]ad84a3a2012-06-08 21:42:435608 SetGLError(GL_INVALID_VALUE, function_name, "primcount < 0");
[email protected]c6aef902012-02-14 03:31:425609 return error::kNoError;
5610 }
[email protected]8eee29c2010-04-29 03:38:295611
[email protected]ad84a3a2012-06-08 21:42:435612 if (!CheckBoundFramebuffersValid(function_name)) {
[email protected]3a03a8f2011-03-19 00:51:275613 return error::kNoError;
5614 }
5615
[email protected]c6aef902012-02-14 03:31:425616 if (count == 0 || (instanced && primcount == 0)) {
[email protected]6c788fb72010-08-26 02:16:315617 return error::kNoError;
5618 }
5619
[email protected]8eee29c2010-04-29 03:38:295620 GLuint max_vertex_accessed;
[email protected]e259eb412012-10-13 05:47:245621 if (!state_.vertex_attrib_manager->element_array_buffer(
5622 )->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]8eee29c2010-04-29 03:38:295623 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435624 function_name, "range out of bounds for buffer");
[email protected]8eee29c2010-04-29 03:38:295625 return error::kNoError;
5626 }
5627
[email protected]ad84a3a2012-06-08 21:42:435628 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:205629 if (!ClearUnclearedTextures()) {
[email protected]ad84a3a2012-06-08 21:42:435630 SetGLError(GL_INVALID_VALUE, function_name, "out of memory");
[email protected]0d6bfdc2011-11-02 01:32:205631 return error::kNoError;
5632 }
[email protected]c13e1da62011-09-09 21:48:305633 bool simulated_attrib_0 = false;
[email protected]ad84a3a2012-06-08 21:42:435634 if (!SimulateAttrib0(
5635 function_name, max_vertex_accessed, &simulated_attrib_0)) {
[email protected]c13e1da62011-09-09 21:48:305636 return error::kNoError;
5637 }
[email protected]8fbedc02010-11-18 18:43:405638 bool simulated_fixed_attribs = false;
[email protected]ad84a3a2012-06-08 21:42:435639 if (SimulateFixedAttribs(
5640 function_name, max_vertex_accessed, &simulated_fixed_attribs,
5641 primcount)) {
[email protected]8fbedc02010-11-18 18:43:405642 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:465643 ApplyDirtyState();
[email protected]8fbedc02010-11-18 18:43:405644 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
[email protected]c6aef902012-02-14 03:31:425645 if (!instanced) {
5646 glDrawElements(mode, count, type, indices);
5647 } else {
5648 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
5649 }
[email protected]22e3f552012-03-13 01:54:195650 ProcessPendingQueries();
[email protected]8fbedc02010-11-18 18:43:405651 if (textures_set) {
5652 RestoreStateForNonRenderableTextures();
5653 }
5654 if (simulated_fixed_attribs) {
5655 RestoreStateForSimulatedFixedAttribs();
5656 }
[email protected]ba3176a2009-12-16 18:19:465657 }
[email protected]b1122982010-05-17 23:04:245658 if (simulated_attrib_0) {
[email protected]43410e92012-04-20 17:06:285659 RestoreStateForAttrib(0);
[email protected]b1122982010-05-17 23:04:245660 }
[email protected]96449d2c2009-11-25 00:01:325661 }
[email protected]f7a64ee2010-02-01 22:24:145662 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325663}
5664
[email protected]c6aef902012-02-14 03:31:425665error::Error GLES2DecoderImpl::HandleDrawElements(
5666 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]ad84a3a2012-06-08 21:42:435667 return DoDrawElements("glDrawElements",
5668 false,
[email protected]c6aef902012-02-14 03:31:425669 static_cast<GLenum>(c.mode),
5670 static_cast<GLsizei>(c.count),
5671 static_cast<GLenum>(c.type),
5672 static_cast<int32>(c.index_offset),
5673 0);
5674}
5675
5676error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
5677 uint32 immediate_data_size, const gles2::DrawElementsInstancedANGLE& c) {
[email protected]62e155e2012-10-23 22:43:155678 if (!features().angle_instanced_arrays) {
[email protected]c6aef902012-02-14 03:31:425679 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435680 "glDrawElementsInstancedANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:425681 return error::kNoError;
5682 }
[email protected]ad84a3a2012-06-08 21:42:435683 return DoDrawElements("glDrawElementsInstancedANGLE",
5684 true,
[email protected]c6aef902012-02-14 03:31:425685 static_cast<GLenum>(c.mode),
5686 static_cast<GLsizei>(c.count),
5687 static_cast<GLenum>(c.type),
5688 static_cast<int32>(c.index_offset),
5689 static_cast<GLsizei>(c.primcount));
5690}
5691
[email protected]269200b12010-11-18 22:53:065692GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:235693 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
5694 GLuint max_vertex_accessed = 0;
5695 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:295696 if (!info) {
[email protected]ae51d192010-04-27 00:48:035697 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:295698 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:435699 "GetMaxValueInBufferCHROMIUM", "unknown buffer");
[email protected]29a9eb52010-04-13 09:04:235700 } else {
5701 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:035702 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:065703 SetGLError(
5704 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435705 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:235706 }
5707 }
5708 return max_vertex_accessed;
5709}
5710
[email protected]96449d2c2009-11-25 00:01:325711// Calls glShaderSource for the various versions of the ShaderSource command.
5712// Assumes that data / data_size points to a piece of memory that is in range
5713// of whatever context it came from (shared memory, immediate memory, bucket
5714// memory.)
[email protected]45bf5152010-02-12 00:11:315715error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035716 GLuint client_id, const char* data, uint32 data_size) {
[email protected]258a3313f2011-10-18 20:13:575717 std::string str(data, data + data_size);
[email protected]6b8cf1a2010-05-06 16:13:585718 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5719 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:315720 if (!info) {
[email protected]45bf5152010-02-12 00:11:315721 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325722 }
[email protected]45bf5152010-02-12 00:11:315723 // Note: We don't actually call glShaderSource here. We wait until
5724 // the call to glCompileShader.
[email protected]258a3313f2011-10-18 20:13:575725 info->UpdateSource(str.c_str());
[email protected]f7a64ee2010-02-01 22:24:145726 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325727}
5728
[email protected]f7a64ee2010-02-01 22:24:145729error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:195730 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:325731 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315732 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:325733 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:465734 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145735 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325736 }
[email protected]ae51d192010-04-27 00:48:035737 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:325738}
5739
[email protected]f7a64ee2010-02-01 22:24:145740error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:195741 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:325742 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315743 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:305744 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465745 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145746 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325747 }
[email protected]ae51d192010-04-27 00:48:035748 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:315749}
5750
[email protected]558847a2010-03-24 07:02:545751error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
5752 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:545753 Bucket* bucket = GetBucket(c.data_bucket_id);
5754 if (!bucket || bucket->size() == 0) {
5755 return error::kInvalidArguments;
5756 }
5757 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035758 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:545759 bucket->size() - 1);
5760}
5761
[email protected]ae51d192010-04-27 00:48:035762void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]43ed3a72012-05-30 22:55:385763 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]6b8cf1a2010-05-06 16:13:585764 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5765 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:315766 if (!info) {
[email protected]45bf5152010-02-12 00:11:315767 return;
5768 }
[email protected]f57bb282010-11-12 00:51:345769 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:185770 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:345771 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:455772 vertex_translator_.get() : fragment_translator_.get();
[email protected]de17df392010-04-23 21:09:415773 }
[email protected]de17df392010-04-23 21:09:415774
[email protected]65dfc602012-07-23 20:39:395775 program_manager()->DoCompileShader(info, translator, feature_info_);
[email protected]45bf5152010-02-12 00:11:315776};
5777
[email protected]ddd968b82010-03-02 00:44:295778void GLES2DecoderImpl::DoGetShaderiv(
5779 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:585780 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5781 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:295782 if (!info) {
[email protected]ddd968b82010-03-02 00:44:295783 return;
5784 }
[email protected]8f1ccdac2010-05-19 21:01:485785 switch (pname) {
5786 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525787 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:485788 return;
5789 case GL_COMPILE_STATUS:
[email protected]062c38b2012-01-18 03:25:105790 *params = compile_shader_always_succeeds_ ? true : info->IsValid();
[email protected]e5186162010-06-14 18:54:415791 return;
[email protected]8f1ccdac2010-05-19 21:01:485792 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525793 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:415794 return;
[email protected]d6a53e42011-10-05 00:09:365795 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
[email protected]c447acd2012-07-23 23:48:415796 ForceCompileShaderIfPending(info);
[email protected]d6a53e42011-10-05 00:09:365797 *params = info->translated_source() ?
5798 info->translated_source()->size() + 1 : 0;
5799 return;
[email protected]8f1ccdac2010-05-19 21:01:485800 default:
5801 break;
[email protected]ddd968b82010-03-02 00:44:295802 }
[email protected]8f1ccdac2010-05-19 21:01:485803 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:295804}
5805
[email protected]ae51d192010-04-27 00:48:035806error::Error GLES2DecoderImpl::HandleGetShaderSource(
5807 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
5808 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:035809 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5810 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:585811 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5812 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:525813 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:295814 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:295815 return error::kNoError;
5816 }
[email protected]df6cf1ad2011-01-29 01:20:525817 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:035818 return error::kNoError;
5819}
5820
[email protected]d6a53e42011-10-05 00:09:365821error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
5822 uint32 immediate_data_size,
5823 const gles2::GetTranslatedShaderSourceANGLE& c) {
5824 GLuint shader = c.shader;
5825
5826 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5827 Bucket* bucket = CreateBucket(bucket_id);
5828 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5829 shader, "glTranslatedGetShaderSourceANGLE");
5830 if (!info) {
5831 bucket->SetSize(0);
5832 return error::kNoError;
5833 }
[email protected]c447acd2012-07-23 23:48:415834 ForceCompileShaderIfPending(info);
[email protected]d6a53e42011-10-05 00:09:365835
5836 bucket->SetFromString(info->translated_source() ?
5837 info->translated_source()->c_str() : NULL);
5838 return error::kNoError;
5839}
5840
[email protected]ae51d192010-04-27 00:48:035841error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
5842 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
5843 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:585844 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5845 Bucket* bucket = CreateBucket(bucket_id);
5846 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5847 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525848 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465849 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035850 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:315851 }
[email protected]df6cf1ad2011-01-29 01:20:525852 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035853 return error::kNoError;
5854}
5855
5856error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
5857 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
5858 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:585859 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5860 Bucket* bucket = CreateBucket(bucket_id);
5861 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5862 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525863 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465864 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035865 return error::kNoError;
5866 }
[email protected]df6cf1ad2011-01-29 01:20:525867 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035868 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325869}
5870
[email protected]d058bca2012-11-26 10:27:265871bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
5872 return state_.GetEnabled(cap);
5873}
5874
[email protected]1958e0e2010-04-22 05:17:155875bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105876 const BufferManager::BufferInfo* buffer = GetBufferInfo(client_id);
5877 return buffer && buffer->IsValid() && !buffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155878}
5879
5880bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105881 const FramebufferManager::FramebufferInfo* framebuffer =
[email protected]06c8b082011-01-05 18:00:365882 GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105883 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155884}
5885
5886bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365887 // IsProgram is true for programs as soon as they are created, until they are
5888 // deleted and no longer in use.
[email protected]a0b78dc2011-11-11 10:43:105889 const ProgramManager::ProgramInfo* program = GetProgramInfo(client_id);
5890 return program != NULL && !program->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155891}
5892
5893bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105894 const RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]06c8b082011-01-05 18:00:365895 GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105896 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155897}
5898
5899bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365900 // IsShader is true for shaders as soon as they are created, until they
5901 // are deleted and not attached to any programs.
[email protected]a0b78dc2011-11-11 10:43:105902 const ShaderManager::ShaderInfo* shader = GetShaderInfo(client_id);
5903 return shader != NULL && !shader->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155904}
5905
5906bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105907 const TextureManager::TextureInfo* texture = GetTextureInfo(client_id);
5908 return texture && texture->IsValid() && !texture->IsDeleted();
[email protected]ae51d192010-04-27 00:48:035909}
5910
5911void GLES2DecoderImpl::DoAttachShader(
5912 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585913 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5914 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035915 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035916 return;
[email protected]1958e0e2010-04-22 05:17:155917 }
[email protected]6b8cf1a2010-05-06 16:13:585918 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5919 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035920 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035921 return;
5922 }
[email protected]ca488e12010-12-13 20:06:145923 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:315924 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435925 "glAttachShader", "can not attach more than"
[email protected]fb96c8e2010-08-12 04:10:315926 " one shader of the same type.");
5927 return;
5928 }
[email protected]ae51d192010-04-27 00:48:035929 glAttachShader(program_info->service_id(), shader_info->service_id());
5930}
5931
5932void GLES2DecoderImpl::DoDetachShader(
5933 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585934 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5935 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035936 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035937 return;
5938 }
[email protected]6b8cf1a2010-05-06 16:13:585939 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5940 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035941 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035942 return;
5943 }
[email protected]9a0ccd42011-03-16 23:58:225944 if (!program_info->DetachShader(shader_manager(), shader_info)) {
5945 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435946 "glDetachShader", "shader not attached to program");
[email protected]9a0ccd42011-03-16 23:58:225947 return;
5948 }
[email protected]ae51d192010-04-27 00:48:035949 glDetachShader(program_info->service_id(), shader_info->service_id());
5950}
5951
5952void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585953 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5954 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:035955 if (!info) {
[email protected]ae51d192010-04-27 00:48:035956 return;
5957 }
[email protected]d685a682011-04-29 16:19:575958 info->Validate();
[email protected]1958e0e2010-04-22 05:17:155959}
5960
[email protected]b1122982010-05-17 23:04:245961void GLES2DecoderImpl::DoGetVertexAttribfv(
5962 GLuint index, GLenum pname, GLfloat* params) {
5963 VertexAttribManager::VertexAttribInfo* info =
[email protected]e259eb412012-10-13 05:47:245964 state_.vertex_attrib_manager->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245965 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:435966 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
[email protected]b1122982010-05-17 23:04:245967 return;
5968 }
5969 switch (pname) {
5970 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5971 BufferManager::BufferInfo* buffer = info->buffer();
5972 if (buffer && !buffer->IsDeleted()) {
5973 GLuint client_id;
5974 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5975 *params = static_cast<GLfloat>(client_id);
5976 }
5977 break;
5978 }
5979 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5980 *params = static_cast<GLfloat>(info->enabled());
5981 break;
5982 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5983 *params = static_cast<GLfloat>(info->size());
5984 break;
5985 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5986 *params = static_cast<GLfloat>(info->gl_stride());
5987 break;
5988 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5989 *params = static_cast<GLfloat>(info->type());
5990 break;
5991 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5992 *params = static_cast<GLfloat>(info->normalized());
5993 break;
[email protected]af6380962012-11-29 23:24:135994 case GL_CURRENT_VERTEX_ATTRIB: {
5995 const Vec4& value = state_.attrib_values[index];
5996 params[0] = value.v[0];
5997 params[1] = value.v[1];
5998 params[2] = value.v[2];
5999 params[3] = value.v[3];
[email protected]b1122982010-05-17 23:04:246000 break;
[email protected]af6380962012-11-29 23:24:136001 }
[email protected]c6aef902012-02-14 03:31:426002 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
6003 *params = static_cast<GLfloat>(info->divisor());
6004 break;
[email protected]b1122982010-05-17 23:04:246005 default:
6006 NOTREACHED();
6007 break;
6008 }
6009}
6010
6011void GLES2DecoderImpl::DoGetVertexAttribiv(
6012 GLuint index, GLenum pname, GLint* params) {
6013 VertexAttribManager::VertexAttribInfo* info =
[email protected]e259eb412012-10-13 05:47:246014 state_.vertex_attrib_manager->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246015 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436016 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
[email protected]b1122982010-05-17 23:04:246017 return;
6018 }
6019 switch (pname) {
6020 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
6021 BufferManager::BufferInfo* buffer = info->buffer();
6022 if (buffer && !buffer->IsDeleted()) {
6023 GLuint client_id;
6024 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
6025 *params = client_id;
6026 }
6027 break;
6028 }
6029 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
6030 *params = info->enabled();
6031 break;
6032 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
6033 *params = info->size();
6034 break;
6035 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
6036 *params = info->gl_stride();
6037 break;
6038 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
6039 *params = info->type();
6040 break;
6041 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
6042 *params = static_cast<GLint>(info->normalized());
6043 break;
[email protected]c6aef902012-02-14 03:31:426044 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
6045 *params = info->divisor();
6046 break;
[email protected]af6380962012-11-29 23:24:136047 case GL_CURRENT_VERTEX_ATTRIB: {
6048 const Vec4& value = state_.attrib_values[index];
6049 params[0] = static_cast<GLint>(value.v[0]);
6050 params[1] = static_cast<GLint>(value.v[1]);
6051 params[2] = static_cast<GLint>(value.v[2]);
6052 params[3] = static_cast<GLint>(value.v[3]);
[email protected]b1122982010-05-17 23:04:246053 break;
[email protected]af6380962012-11-29 23:24:136054 }
[email protected]b1122982010-05-17 23:04:246055 default:
6056 NOTREACHED();
6057 break;
6058 }
6059}
6060
[email protected]af6380962012-11-29 23:24:136061bool GLES2DecoderImpl::SetVertexAttribValue(
6062 const char* function_name, GLuint index, const GLfloat* value) {
6063 if (index >= state_.attrib_values.size()) {
6064 SetGLError(GL_INVALID_VALUE, function_name, "index out of range");
6065 return false;
[email protected]b1122982010-05-17 23:04:246066 }
[email protected]af6380962012-11-29 23:24:136067 Vec4& v = state_.attrib_values[index];
6068 v.v[0] = value[0];
6069 v.v[1] = value[1];
6070 v.v[2] = value[2];
6071 v.v[3] = value[3];
6072 return true;
6073}
6074
6075void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
6076 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
6077 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
6078 glVertexAttrib1f(index, v0);
6079 }
[email protected]b1122982010-05-17 23:04:246080}
6081
6082void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
[email protected]af6380962012-11-29 23:24:136083 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
6084 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
6085 glVertexAttrib2f(index, v0, v1);
[email protected]b1122982010-05-17 23:04:246086 }
[email protected]b1122982010-05-17 23:04:246087}
6088
6089void GLES2DecoderImpl::DoVertexAttrib3f(
6090 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
[email protected]af6380962012-11-29 23:24:136091 GLfloat v[4] = { v0, v1, v2, 1.0f, };
6092 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
6093 glVertexAttrib3f(index, v0, v1, v2);
[email protected]b1122982010-05-17 23:04:246094 }
[email protected]b1122982010-05-17 23:04:246095}
6096
6097void GLES2DecoderImpl::DoVertexAttrib4f(
6098 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
[email protected]af6380962012-11-29 23:24:136099 GLfloat v[4] = { v0, v1, v2, v3, };
6100 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
6101 glVertexAttrib4f(index, v0, v1, v2, v3);
[email protected]b1122982010-05-17 23:04:246102 }
[email protected]b1122982010-05-17 23:04:246103}
6104
6105void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136106 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
6107 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
6108 glVertexAttrib1fv(index, v);
[email protected]b1122982010-05-17 23:04:246109 }
[email protected]b1122982010-05-17 23:04:246110}
6111
6112void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136113 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
6114 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
6115 glVertexAttrib2fv(index, v);
[email protected]b1122982010-05-17 23:04:246116 }
[email protected]b1122982010-05-17 23:04:246117}
6118
6119void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136120 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
6121 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
6122 glVertexAttrib3fv(index, v);
[email protected]b1122982010-05-17 23:04:246123 }
[email protected]b1122982010-05-17 23:04:246124}
6125
6126void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136127 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
6128 glVertexAttrib4fv(index, v);
[email protected]b1122982010-05-17 23:04:246129 }
[email protected]b1122982010-05-17 23:04:246130}
6131
[email protected]f7a64ee2010-02-01 22:24:146132error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:196133 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]944b62f32012-09-27 02:20:466134
[email protected]e259eb412012-10-13 05:47:246135 if (!state_.bound_array_buffer || state_.bound_array_buffer->IsDeleted()) {
6136 if (state_.vertex_attrib_manager == default_vertex_attrib_manager_) {
[email protected]944b62f32012-09-27 02:20:466137 SetGLError(GL_INVALID_VALUE,
6138 "glVertexAttribPointer", "no array buffer bound");
6139 return error::kNoError;
6140 } else if (c.offset != 0) {
6141 SetGLError(GL_INVALID_VALUE,
6142 "glVertexAttribPointer", "client side arrays are not allowed");
6143 return error::kNoError;
6144 }
[email protected]96449d2c2009-11-25 00:01:326145 }
[email protected]8eee29c2010-04-29 03:38:296146
6147 GLuint indx = c.indx;
6148 GLint size = c.size;
6149 GLenum type = c.type;
6150 GLboolean normalized = c.normalized;
6151 GLsizei stride = c.stride;
6152 GLsizei offset = c.offset;
6153 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:056154 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]f80e6e12012-08-31 00:43:536155 SetGLErrorInvalidEnum("glVertexAttribPointer", type, "type");
[email protected]8eee29c2010-04-29 03:38:296156 return error::kNoError;
6157 }
[email protected]9438b012010-06-15 22:55:056158 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:316159 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436160 "glVertexAttribPointer", "size GL_INVALID_VALUE");
[email protected]8eee29c2010-04-29 03:38:296161 return error::kNoError;
6162 }
6163 if (indx >= group_->max_vertex_attribs()) {
[email protected]ad84a3a2012-06-08 21:42:436164 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
[email protected]8eee29c2010-04-29 03:38:296165 return error::kNoError;
6166 }
6167 if (stride < 0) {
6168 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436169 "glVertexAttribPointer", "stride < 0");
[email protected]8eee29c2010-04-29 03:38:296170 return error::kNoError;
6171 }
6172 if (stride > 255) {
6173 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436174 "glVertexAttribPointer", "stride > 255");
[email protected]8eee29c2010-04-29 03:38:296175 return error::kNoError;
6176 }
6177 if (offset < 0) {
6178 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436179 "glVertexAttribPointer", "offset < 0");
[email protected]8eee29c2010-04-29 03:38:296180 return error::kNoError;
6181 }
6182 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:316183 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:296184 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:316185 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436186 "glVertexAttribPointer", "offset not valid for type");
[email protected]ff81c192011-01-07 23:04:316187 return error::kNoError;
6188 }
6189 if (stride % component_size > 0) {
6190 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436191 "glVertexAttribPointer", "stride not valid for type");
[email protected]8eee29c2010-04-29 03:38:296192 return error::kNoError;
6193 }
[email protected]e259eb412012-10-13 05:47:246194 state_.vertex_attrib_manager->SetAttribInfo(
[email protected]8fbedc02010-11-18 18:43:406195 indx,
[email protected]e259eb412012-10-13 05:47:246196 state_.bound_array_buffer,
[email protected]8eee29c2010-04-29 03:38:296197 size,
6198 type,
[email protected]b1122982010-05-17 23:04:246199 normalized,
6200 stride,
6201 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:296202 offset);
[email protected]8fbedc02010-11-18 18:43:406203 if (type != GL_FIXED) {
6204 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
6205 }
[email protected]f7a64ee2010-02-01 22:24:146206 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326207}
6208
[email protected]43410e92012-04-20 17:06:286209void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
6210 GLsizei height) {
[email protected]e259eb412012-10-13 05:47:246211 state_.viewport_x = x;
6212 state_.viewport_y = y;
[email protected]1868a342012-11-07 15:56:026213 state_.viewport_width = std::min(width, viewport_max_width_);
6214 state_.viewport_height = std::min(height, viewport_max_height_);
[email protected]43410e92012-04-20 17:06:286215 glViewport(x, y, width, height);
6216}
6217
[email protected]c6aef902012-02-14 03:31:426218error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
6219 uint32 immediate_data_size, const gles2::VertexAttribDivisorANGLE& c) {
[email protected]62e155e2012-10-23 22:43:156220 if (!features().angle_instanced_arrays) {
[email protected]c6aef902012-02-14 03:31:426221 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436222 "glVertexAttribDivisorANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:426223 }
6224 GLuint index = c.index;
6225 GLuint divisor = c.divisor;
6226 if (index >= group_->max_vertex_attribs()) {
6227 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436228 "glVertexAttribDivisorANGLE", "index out of range");
[email protected]c6aef902012-02-14 03:31:426229 return error::kNoError;
6230 }
6231
[email protected]e259eb412012-10-13 05:47:246232 state_.vertex_attrib_manager->SetDivisor(
[email protected]c6aef902012-02-14 03:31:426233 index,
6234 divisor);
6235 glVertexAttribDivisorANGLE(index, divisor);
6236 return error::kNoError;
6237}
6238
[email protected]f7a64ee2010-02-01 22:24:146239error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:196240 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]09e17272012-11-30 10:30:446241 if (ShouldDeferReads())
6242 return error::kDeferCommandUntilLater;
[email protected]612d2f82009-12-08 20:49:316243 GLint x = c.x;
6244 GLint y = c.y;
6245 GLsizei width = c.width;
6246 GLsizei height = c.height;
6247 GLenum format = c.format;
6248 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:566249 if (width < 0 || height < 0) {
[email protected]ad84a3a2012-06-08 21:42:436250 SetGLError(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
[email protected]57f223832010-03-19 01:57:566251 return error::kNoError;
6252 }
[email protected]a51788e2010-02-24 21:54:256253 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:186254 uint32 pixels_size;
[email protected]3458a64a2012-04-10 17:39:346255 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:246256 width, height, format, type, state_.pack_alignment, &pixels_size,
6257 NULL, NULL)) {
[email protected]a76b0052010-03-05 00:33:186258 return error::kOutOfBounds;
6259 }
[email protected]612d2f82009-12-08 20:49:316260 void* pixels = GetSharedMemoryAs<void*>(
6261 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:256262 Result* result = GetSharedMemoryAs<Result*>(
6263 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6264 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:146265 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466266 }
[email protected]a51788e2010-02-24 21:54:256267
[email protected]9438b012010-06-15 22:55:056268 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]f80e6e12012-08-31 00:43:536269 SetGLErrorInvalidEnum("glReadPixels", format, "format");
[email protected]8eee29c2010-04-29 03:38:296270 return error::kNoError;
6271 }
[email protected]9438b012010-06-15 22:55:056272 if (!validators_->pixel_type.IsValid(type)) {
[email protected]f80e6e12012-08-31 00:43:536273 SetGLErrorInvalidEnum("glReadPixels", type, "type");
[email protected]d2cf0a2d2010-02-25 21:36:126274 return error::kNoError;
6275 }
[email protected]57f223832010-03-19 01:57:566276 if (width == 0 || height == 0) {
6277 return error::kNoError;
6278 }
6279
[email protected]57f223832010-03-19 01:57:566280 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:306281 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:566282
[email protected]3aad1a32012-09-07 20:54:476283 int32 max_x;
6284 int32 max_y;
6285 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
[email protected]ad84a3a2012-06-08 21:42:436286 SetGLError(GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:146287 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:316288 }
[email protected]57f223832010-03-19 01:57:566289
[email protected]0d6bfdc2011-11-02 01:32:206290 if (!CheckBoundFramebuffersValid("glReadPixels")) {
6291 return error::kNoError;
6292 }
6293
[email protected]a0b78dc2011-11-11 10:43:106294 CopyRealGLErrorsToWrapper();
6295
6296 ScopedResolvedFrameBufferBinder binder(this, false, true);
6297
[email protected]d37231fa2010-04-09 21:16:026298 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:566299 // The user requested an out of range area. Get the results 1 line
6300 // at a time.
6301 uint32 temp_size;
[email protected]3458a64a2012-04-10 17:39:346302 uint32 unpadded_row_size;
6303 uint32 padded_row_size;
6304 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:246305 width, 2, format, type, state_.pack_alignment, &temp_size,
[email protected]3458a64a2012-04-10 17:39:346306 &unpadded_row_size, &padded_row_size)) {
[email protected]ad84a3a2012-06-08 21:42:436307 SetGLError(GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]57f223832010-03-19 01:57:566308 return error::kNoError;
6309 }
6310
6311 GLint dest_x_offset = std::max(-x, 0);
6312 uint32 dest_row_offset;
[email protected]3458a64a2012-04-10 17:39:346313 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:246314 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
6315 NULL, NULL)) {
[email protected]ad84a3a2012-06-08 21:42:436316 SetGLError(GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]57f223832010-03-19 01:57:566317 return error::kNoError;
6318 }
6319
6320 // Copy each row into the larger dest rect.
6321 int8* dst = static_cast<int8*>(pixels);
6322 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:026323 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:566324 GLint read_width = read_end_x - read_x;
6325 for (GLint yy = 0; yy < height; ++yy) {
6326 GLint ry = y + yy;
6327
6328 // Clear the row.
6329 memset(dst, 0, unpadded_row_size);
6330
6331 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:026332 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:566333 glReadPixels(
6334 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
6335 }
6336 dst += padded_row_size;
6337 }
6338 } else {
6339 glReadPixels(x, y, width, height, format, type, pixels);
6340 }
[email protected]1002c2d2011-06-28 22:39:046341 GLenum error = PeekGLError();
[email protected]a51788e2010-02-24 21:54:256342 if (error == GL_NO_ERROR) {
6343 *result = true;
[email protected]4848b9f82011-03-10 18:37:566344
6345 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6346 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
[email protected]84eb4252012-06-29 22:56:446347 if ((channels_exist & 0x0008) == 0 &&
[email protected]62e155e2012-10-23 22:43:156348 workarounds().clear_alpha_in_readpixels) {
[email protected]4848b9f82011-03-10 18:37:566349 // Set the alpha to 255 because some drivers are buggy in this regard.
6350 uint32 temp_size;
[email protected]3458a64a2012-04-10 17:39:346351
6352 uint32 unpadded_row_size;
6353 uint32 padded_row_size;
6354 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:246355 width, 2, format, type, state_.pack_alignment, &temp_size,
[email protected]3458a64a2012-04-10 17:39:346356 &unpadded_row_size, &padded_row_size)) {
[email protected]ad84a3a2012-06-08 21:42:436357 SetGLError(GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]4848b9f82011-03-10 18:37:566358 return error::kNoError;
6359 }
6360 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
6361 // of this implementation.
6362 if (type != GL_UNSIGNED_BYTE) {
[email protected]ad84a3a2012-06-08 21:42:436363 SetGLError(
6364 GL_INVALID_OPERATION, "glReadPixels",
6365 "unsupported readPixel format");
[email protected]4848b9f82011-03-10 18:37:566366 return error::kNoError;
6367 }
6368 switch (format) {
6369 case GL_RGBA:
[email protected]297ca1c2011-06-20 23:08:466370 case GL_BGRA_EXT:
[email protected]4848b9f82011-03-10 18:37:566371 case GL_ALPHA: {
6372 int offset = (format == GL_ALPHA) ? 0 : 3;
6373 int step = (format == GL_ALPHA) ? 1 : 4;
6374 uint8* dst = static_cast<uint8*>(pixels) + offset;
6375 for (GLint yy = 0; yy < height; ++yy) {
6376 uint8* end = dst + unpadded_row_size;
6377 for (uint8* d = dst; d < end; d += step) {
6378 *d = 255;
6379 }
6380 dst += padded_row_size;
6381 }
6382 break;
6383 }
6384 default:
6385 break;
6386 }
6387 }
[email protected]a51788e2010-02-24 21:54:256388 }
[email protected]4848b9f82011-03-10 18:37:566389
[email protected]f7a64ee2010-02-01 22:24:146390 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326391}
6392
[email protected]f7a64ee2010-02-01 22:24:146393error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:196394 uint32 immediate_data_size, const gles2::PixelStorei& c) {
6395 GLenum pname = c.pname;
6396 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:056397 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]f80e6e12012-08-31 00:43:536398 SetGLErrorInvalidEnum("glPixelStorei", pname, "pname");
[email protected]d2cf0a2d2010-02-25 21:36:126399 return error::kNoError;
6400 }
[email protected]222471d2011-11-30 18:06:396401 switch (pname) {
6402 case GL_PACK_ALIGNMENT:
6403 case GL_UNPACK_ALIGNMENT:
6404 if (!validators_->pixel_store_alignment.IsValid(param)) {
6405 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436406 "glPixelStore", "param GL_INVALID_VALUE");
[email protected]222471d2011-11-30 18:06:396407 return error::kNoError;
6408 }
[email protected]164d6d52012-05-05 00:55:036409 break;
[email protected]0a1e9ad2012-05-04 21:13:036410 case GL_UNPACK_FLIP_Y_CHROMIUM:
6411 unpack_flip_y_ = (param != 0);
6412 return error::kNoError;
6413 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
6414 unpack_premultiply_alpha_ = (param != 0);
6415 return error::kNoError;
[email protected]6c75c712012-06-19 15:43:176416 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
6417 unpack_unpremultiply_alpha_ = (param != 0);
6418 return error::kNoError;
[email protected]222471d2011-11-30 18:06:396419 default:
6420 break;
[email protected]b9849abf2009-11-25 19:13:196421 }
6422 glPixelStorei(pname, param);
6423 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:436424 case GL_PACK_ALIGNMENT:
[email protected]e259eb412012-10-13 05:47:246425 state_.pack_alignment = param;
[email protected]ad84a3a2012-06-08 21:42:436426 break;
6427 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
[email protected]88a61bf2012-10-27 13:00:426428 state_.pack_reverse_row_order = (param != 0);
[email protected]ad84a3a2012-06-08 21:42:436429 break;
6430 case GL_UNPACK_ALIGNMENT:
[email protected]e259eb412012-10-13 05:47:246431 state_.unpack_alignment = param;
[email protected]ad84a3a2012-06-08 21:42:436432 break;
6433 default:
6434 // Validation should have prevented us from getting here.
6435 NOTREACHED();
6436 break;
[email protected]b9849abf2009-11-25 19:13:196437 }
[email protected]f7a64ee2010-02-01 22:24:146438 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196439}
6440
[email protected]1c75a3702011-11-11 14:15:286441error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
6442 uint32 immediate_data_size, const gles2::PostSubBufferCHROMIUM& c) {
[email protected]43ed3a72012-05-30 22:55:386443 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
[email protected]6f5fac9d12012-06-26 21:02:456444 if (!surface_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
[email protected]1c75a3702011-11-11 14:15:286445 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436446 "glPostSubBufferCHROMIUM", "command not supported by surface");
[email protected]1c75a3702011-11-11 14:15:286447 return error::kNoError;
6448 }
[email protected]7794d512012-04-17 20:36:496449 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
[email protected]1c75a3702011-11-11 14:15:286450 return error::kNoError;
[email protected]7794d512012-04-17 20:36:496451 } else {
6452 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
[email protected]1c75a3702011-11-11 14:15:286453 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:496454 }
[email protected]1c75a3702011-11-11 14:15:286455}
6456
[email protected]558847a2010-03-24 07:02:546457error::Error GLES2DecoderImpl::GetAttribLocationHelper(
6458 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6459 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576460 if (!StringIsValidForGLES(name_str.c_str())) {
[email protected]ad84a3a2012-06-08 21:42:436461 SetGLError(GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:576462 return error::kNoError;
6463 }
[email protected]6b8cf1a2010-05-06 16:13:586464 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6465 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:036466 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146467 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196468 }
[email protected]ae51d192010-04-27 00:48:036469 if (!info->IsValid()) {
[email protected]ad84a3a2012-06-08 21:42:436470 SetGLError(
6471 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
[email protected]0bfd9882010-02-05 23:02:256472 return error::kNoError;
6473 }
[email protected]b9849abf2009-11-25 19:13:196474 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546475 location_shm_id, location_shm_offset, sizeof(GLint));
6476 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146477 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196478 }
[email protected]558847a2010-03-24 07:02:546479 // Require the client to init this incase the context is lost and we are no
6480 // longer executing commands.
6481 if (*location != -1) {
6482 return error::kGenericError;
6483 }
[email protected]0bfd9882010-02-05 23:02:256484 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:146485 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196486}
6487
[email protected]558847a2010-03-24 07:02:546488error::Error GLES2DecoderImpl::HandleGetAttribLocation(
6489 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
6490 uint32 name_size = c.data_size;
6491 const char* name = GetSharedMemoryAs<const char*>(
6492 c.name_shm_id, c.name_shm_offset, name_size);
6493 if (!name) {
6494 return error::kOutOfBounds;
6495 }
6496 String name_str(name, name_size);
6497 return GetAttribLocationHelper(
6498 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6499}
6500
[email protected]f7a64ee2010-02-01 22:24:146501error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196502 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:546503 uint32 name_size = c.data_size;
6504 const char* name = GetImmediateDataAs<const char*>(
6505 c, name_size, immediate_data_size);
6506 if (!name) {
6507 return error::kOutOfBounds;
6508 }
6509 String name_str(name, name_size);
6510 return GetAttribLocationHelper(
6511 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6512}
6513
6514error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
6515 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
6516 Bucket* bucket = GetBucket(c.name_bucket_id);
6517 if (!bucket) {
6518 return error::kInvalidArguments;
6519 }
6520 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186521 if (!bucket->GetAsString(&name_str)) {
6522 return error::kInvalidArguments;
6523 }
[email protected]558847a2010-03-24 07:02:546524 return GetAttribLocationHelper(
6525 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6526}
6527
6528error::Error GLES2DecoderImpl::GetUniformLocationHelper(
6529 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6530 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576531 if (!StringIsValidForGLES(name_str.c_str())) {
[email protected]ad84a3a2012-06-08 21:42:436532 SetGLError(GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:576533 return error::kNoError;
6534 }
[email protected]6b8cf1a2010-05-06 16:13:586535 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6536 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:036537 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146538 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196539 }
[email protected]ae51d192010-04-27 00:48:036540 if (!info->IsValid()) {
[email protected]ad84a3a2012-06-08 21:42:436541 SetGLError(
6542 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
[email protected]0bfd9882010-02-05 23:02:256543 return error::kNoError;
6544 }
[email protected]b9849abf2009-11-25 19:13:196545 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546546 location_shm_id, location_shm_offset, sizeof(GLint));
6547 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146548 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196549 }
[email protected]558847a2010-03-24 07:02:546550 // Require the client to init this incase the context is lost an we are no
6551 // longer executing commands.
6552 if (*location != -1) {
6553 return error::kGenericError;
6554 }
[email protected]2be6abf32012-06-26 00:28:336555 *location = info->GetUniformFakeLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:146556 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196557}
6558
[email protected]f7a64ee2010-02-01 22:24:146559error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:196560 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:196561 uint32 name_size = c.data_size;
6562 const char* name = GetSharedMemoryAs<const char*>(
6563 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:546564 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146565 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196566 }
6567 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546568 return GetUniformLocationHelper(
6569 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196570}
6571
[email protected]f7a64ee2010-02-01 22:24:146572error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196573 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:196574 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:306575 const char* name = GetImmediateDataAs<const char*>(
6576 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:546577 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146578 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196579 }
6580 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546581 return GetUniformLocationHelper(
6582 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6583}
6584
6585error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
6586 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
6587 Bucket* bucket = GetBucket(c.name_bucket_id);
6588 if (!bucket) {
6589 return error::kInvalidArguments;
6590 }
6591 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186592 if (!bucket->GetAsString(&name_str)) {
6593 return error::kInvalidArguments;
6594 }
[email protected]558847a2010-03-24 07:02:546595 return GetUniformLocationHelper(
6596 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196597}
6598
[email protected]ddd968b82010-03-02 00:44:296599error::Error GLES2DecoderImpl::HandleGetString(
6600 uint32 immediate_data_size, const gles2::GetString& c) {
6601 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:056602 if (!validators_->string_type.IsValid(name)) {
[email protected]f80e6e12012-08-31 00:43:536603 SetGLErrorInvalidEnum("glGetString", name, "name");
[email protected]ddd968b82010-03-02 00:44:296604 return error::kNoError;
6605 }
[email protected]1958e0e2010-04-22 05:17:156606 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
6607 const char* str = NULL;
[email protected]f0d74742011-10-03 16:31:046608 std::string extensions;
[email protected]1958e0e2010-04-22 05:17:156609 switch (name) {
6610 case GL_VERSION:
6611 str = "OpenGL ES 2.0 Chromium";
6612 break;
6613 case GL_SHADING_LANGUAGE_VERSION:
6614 str = "OpenGL ES GLSL ES 1.0 Chromium";
6615 break;
[email protected]32939602012-05-09 06:25:166616 case GL_RENDERER:
6617 str = "Chromium";
6618 break;
6619 case GL_VENDOR:
6620 str = "Chromium";
6621 break;
[email protected]1958e0e2010-04-22 05:17:156622 case GL_EXTENSIONS:
[email protected]f0d74742011-10-03 16:31:046623 {
6624 // For WebGL contexts, strip out the OES derivatives extension if it has
6625 // not been enabled.
6626 if (force_webgl_glsl_validation_ &&
6627 !derivatives_explicitly_enabled_) {
6628 extensions = feature_info_->extensions();
6629 size_t offset = extensions.find(kOESDerivativeExtension);
6630 if (std::string::npos != offset) {
6631 extensions.replace(offset,
6632 offset + arraysize(kOESDerivativeExtension),
6633 std::string());
6634 }
[email protected]f0d74742011-10-03 16:31:046635 } else {
[email protected]6f5fac9d12012-06-26 21:02:456636 extensions = feature_info_->extensions().c_str();
[email protected]f0d74742011-10-03 16:31:046637 }
[email protected]6f5fac9d12012-06-26 21:02:456638 std::string surface_extensions = surface_->GetExtensions();
6639 if (!surface_extensions.empty())
6640 extensions += " " + surface_extensions;
6641 str = extensions.c_str();
[email protected]f0d74742011-10-03 16:31:046642 }
[email protected]1958e0e2010-04-22 05:17:156643 break;
6644 default:
6645 str = gl_str;
6646 break;
6647 }
[email protected]ddd968b82010-03-02 00:44:296648 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:156649 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:296650 return error::kNoError;
6651}
6652
[email protected]0c86dbf2010-03-05 08:14:116653void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:156654 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:056655 if (!validators_->buffer_target.IsValid(target)) {
[email protected]f80e6e12012-08-31 00:43:536656 SetGLErrorInvalidEnum("glBufferData", target, "target");
[email protected]8eee29c2010-04-29 03:38:296657 return;
6658 }
[email protected]9438b012010-06-15 22:55:056659 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]f80e6e12012-08-31 00:43:536660 SetGLErrorInvalidEnum("glBufferData", usage, "usage");
[email protected]0c86dbf2010-03-05 08:14:116661 return;
[email protected]3b6ec202010-03-05 05:16:236662 }
6663 if (size < 0) {
[email protected]ad84a3a2012-06-08 21:42:436664 SetGLError(GL_INVALID_VALUE, "glBufferData", "size < 0");
[email protected]037896bd2010-04-21 19:07:286665 return;
[email protected]3b6ec202010-03-05 05:16:236666 }
6667 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
6668 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436669 SetGLError(GL_INVALID_VALUE, "glBufferData", "unknown buffer");
[email protected]037896bd2010-04-21 19:07:286670 return;
[email protected]3b6ec202010-03-05 05:16:236671 }
6672 // Clear the buffer to 0 if no initial data was passed in.
6673 scoped_array<int8> zero;
6674 if (!data) {
6675 zero.reset(new int8[size]);
6676 memset(zero.get(), 0, size);
6677 data = zero.get();
6678 }
[email protected]473c01ccb2011-06-07 01:33:306679
[email protected]3b6ec202010-03-05 05:16:236680 CopyRealGLErrorsToWrapper();
6681 glBufferData(target, size, data, usage);
[email protected]1002c2d2011-06-28 22:39:046682 GLenum error = PeekGLError();
6683 if (error == GL_NO_ERROR) {
[email protected]473c01ccb2011-06-07 01:33:306684 buffer_manager()->SetInfo(info, size, usage);
[email protected]0c86dbf2010-03-05 08:14:116685 info->SetRange(0, size, data);
[email protected]a39370652012-09-25 21:52:136686 } else {
6687 buffer_manager()->SetInfo(info, 0, usage);
[email protected]3b6ec202010-03-05 05:16:236688 }
[email protected]0c86dbf2010-03-05 08:14:116689}
6690
6691error::Error GLES2DecoderImpl::HandleBufferData(
6692 uint32 immediate_data_size, const gles2::BufferData& c) {
6693 GLenum target = static_cast<GLenum>(c.target);
6694 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
6695 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6696 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6697 GLenum usage = static_cast<GLenum>(c.usage);
6698 const void* data = NULL;
6699 if (data_shm_id != 0 || data_shm_offset != 0) {
6700 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
6701 if (!data) {
6702 return error::kOutOfBounds;
6703 }
6704 }
6705 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:146706 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196707}
6708
[email protected]f7a64ee2010-02-01 22:24:146709error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:196710 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
6711 GLenum target = static_cast<GLenum>(c.target);
6712 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:306713 const void* data = GetImmediateDataAs<const void*>(
6714 c, size, immediate_data_size);
6715 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146716 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:306717 }
[email protected]b9849abf2009-11-25 19:13:196718 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:116719 DoBufferData(target, size, data, usage);
6720 return error::kNoError;
6721}
6722
6723void GLES2DecoderImpl::DoBufferSubData(
6724 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:506725 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476726 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436727 SetGLError(GL_INVALID_VALUE, "glBufferSubData", "unknown buffer");
[email protected]037896bd2010-04-21 19:07:286728 return;
[email protected]a93bb842010-02-16 23:03:476729 }
[email protected]0c86dbf2010-03-05 08:14:116730 if (!info->SetRange(offset, size, data)) {
[email protected]ad84a3a2012-06-08 21:42:436731 SetGLError(GL_INVALID_VALUE, "glBufferSubData", "out of range");
[email protected]473c01ccb2011-06-07 01:33:306732 return;
[email protected]07f54fcc2009-12-22 02:46:306733 }
[email protected]473c01ccb2011-06-07 01:33:306734 glBufferSubData(target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:196735}
6736
[email protected]0d6bfdc2011-11-02 01:32:206737bool GLES2DecoderImpl::ClearLevel(
6738 unsigned service_id,
6739 unsigned bind_target,
6740 unsigned target,
6741 int level,
6742 unsigned format,
6743 unsigned type,
6744 int width,
[email protected]4502e6492011-12-14 19:39:156745 int height,
6746 bool is_texture_immutable) {
[email protected]81375742012-06-08 00:04:006747 uint32 channels = GLES2Util::GetChannelsForFormat(format);
6748 if (IsAngle() && (channels & GLES2Util::kDepth) != 0) {
6749 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
6750 // on depth formats.
6751 GLuint fb = 0;
6752 glGenFramebuffersEXT(1, &fb);
6753 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
6754
6755 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
6756 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
6757 GL_DEPTH_ATTACHMENT;
6758
6759 glFramebufferTexture2DEXT(
6760 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
6761 // ANGLE promises a depth only attachment ok.
6762 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
6763 GL_FRAMEBUFFER_COMPLETE) {
6764 return false;
6765 }
6766 glClearStencil(0);
6767 glStencilMask(-1);
6768 glClearDepth(1.0f);
6769 glDepthMask(true);
6770 glDisable(GL_SCISSOR_TEST);
6771 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
6772
6773 RestoreClearState();
6774
6775 glDeleteFramebuffersEXT(1, &fb);
6776 FramebufferManager::FramebufferInfo* framebuffer =
6777 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
6778 GLuint fb_service_id =
6779 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
6780 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
6781 return true;
6782 }
6783
[email protected]45d15a62012-04-18 14:33:176784 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
6785
6786 uint32 size;
6787 uint32 padded_row_size;
[email protected]3458a64a2012-04-10 17:39:346788 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:246789 width, height, format, type, state_.unpack_alignment, &size,
[email protected]45d15a62012-04-18 14:33:176790 NULL, &padded_row_size)) {
[email protected]0d6bfdc2011-11-02 01:32:206791 return false;
6792 }
[email protected]45d15a62012-04-18 14:33:176793
[email protected]a5d3dad2012-05-26 04:34:446794 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
6795
[email protected]45d15a62012-04-18 14:33:176796 int tile_height;
6797
6798 if (size > kMaxZeroSize) {
6799 if (kMaxZeroSize < padded_row_size) {
6800 // That'd be an awfully large texture.
6801 return false;
6802 }
6803 // We should never have a large total size with a zero row size.
6804 DCHECK_GT(padded_row_size, 0U);
6805 tile_height = kMaxZeroSize / padded_row_size;
6806 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:246807 width, tile_height, format, type, state_.unpack_alignment, &size,
6808 NULL, NULL)) {
[email protected]45d15a62012-04-18 14:33:176809 return false;
6810 }
[email protected]4502e6492011-12-14 19:39:156811 } else {
[email protected]45d15a62012-04-18 14:33:176812 tile_height = height;
6813 }
6814
6815 // Assumes the size has already been checked.
6816 scoped_array<char> zero(new char[size]);
6817 memset(zero.get(), 0, size);
6818 glBindTexture(bind_target, service_id);
6819
6820 GLint y = 0;
6821 while (y < height) {
6822 GLint h = y + tile_height > height ? height - y : tile_height;
6823 if (is_texture_immutable || h != height) {
6824 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
6825 } else {
6826 WrappedTexImage2D(
6827 target, level, format, width, h, 0, format, type, zero.get());
6828 }
6829 y += tile_height;
[email protected]4502e6492011-12-14 19:39:156830 }
[email protected]0d6bfdc2011-11-02 01:32:206831 TextureManager::TextureInfo* info = GetTextureInfoForTarget(bind_target);
6832 glBindTexture(bind_target, info ? info->service_id() : 0);
6833 return true;
6834}
6835
[email protected]ad84a3a2012-06-08 21:42:436836namespace {
6837
6838const int kS3TCBlockWidth = 4;
6839const int kS3TCBlockHeight = 4;
6840const int kS3TCDXT1BlockSize = 8;
6841const int kS3TCDXT3AndDXT5BlockSize = 16;
[email protected]2d3765b2012-10-03 00:31:076842const int kETC1BlockWidth = 4;
6843const int kETC1BlockHeight = 4;
6844const int kETC1BlockSize = 8;
[email protected]ad84a3a2012-06-08 21:42:436845
6846bool IsValidDXTSize(GLint level, GLsizei size) {
[email protected]10b56de2012-07-14 02:09:516847 return (size == 1) ||
6848 (size == 2) || !(size % kS3TCBlockWidth);
[email protected]ad84a3a2012-06-08 21:42:436849}
6850
6851} // anonymous namespace.
6852
6853bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
6854 const char* function_name,
6855 GLsizei width, GLsizei height, GLenum format, size_t size) {
6856 unsigned int bytes_required = 0;
6857
6858 switch (format) {
6859 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
6860 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: {
6861 int num_blocks_across =
6862 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
6863 int num_blocks_down =
6864 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
6865 int num_blocks = num_blocks_across * num_blocks_down;
6866 bytes_required = num_blocks * kS3TCDXT1BlockSize;
6867 break;
6868 }
6869 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
6870 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
6871 int num_blocks_across =
6872 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
6873 int num_blocks_down =
6874 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
6875 int num_blocks = num_blocks_across * num_blocks_down;
6876 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
6877 break;
6878 }
[email protected]2d3765b2012-10-03 00:31:076879 case GL_ETC1_RGB8_OES: {
6880 int num_blocks_across =
6881 (width + kETC1BlockWidth - 1) / kETC1BlockWidth;
6882 int num_blocks_down =
6883 (height + kETC1BlockHeight - 1) / kETC1BlockHeight;
6884 int num_blocks = num_blocks_across * num_blocks_down;
6885 bytes_required = num_blocks * kETC1BlockSize;
6886 break;
6887 }
[email protected]ad84a3a2012-06-08 21:42:436888 default:
[email protected]f80e6e12012-08-31 00:43:536889 SetGLErrorInvalidEnum(function_name, format, "format");
[email protected]ad84a3a2012-06-08 21:42:436890 return false;
6891 }
6892
6893 if (size != bytes_required) {
6894 SetGLError(
6895 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
6896 return false;
6897 }
6898
6899 return true;
6900}
6901
6902bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
6903 const char* function_name,
6904 GLint level, GLsizei width, GLsizei height, GLenum format) {
6905 switch (format) {
6906 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
6907 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
6908 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
6909 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
6910 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
6911 SetGLError(
6912 GL_INVALID_OPERATION, function_name,
6913 "width or height invalid for level");
6914 return false;
6915 }
6916 return true;
6917 }
[email protected]2d3765b2012-10-03 00:31:076918 case GL_ETC1_RGB8_OES:
6919 if (width <= 0 || height <= 0) {
6920 SetGLError(
6921 GL_INVALID_OPERATION, function_name,
6922 "width or height invalid for level");
6923 return false;
6924 }
6925 return true;
[email protected]ad84a3a2012-06-08 21:42:436926 default:
6927 return false;
6928 }
6929}
6930
6931bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
6932 const char* function_name,
6933 GLenum target, GLint level, GLint xoffset, GLint yoffset,
6934 GLsizei width, GLsizei height, GLenum format,
6935 TextureManager::TextureInfo* texture) {
6936 if (xoffset < 0 || yoffset < 0) {
6937 SetGLError(
6938 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
6939 return false;
6940 }
6941
6942 switch (format) {
6943 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
6944 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
6945 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
6946 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
6947 const int kBlockWidth = 4;
6948 const int kBlockHeight = 4;
6949 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
6950 SetGLError(
6951 GL_INVALID_OPERATION, function_name,
6952 "xoffset or yoffset not multiple of 4");
6953 return false;
6954 }
6955 GLsizei tex_width = 0;
6956 GLsizei tex_height = 0;
6957 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
6958 width - xoffset > tex_width ||
6959 height - yoffset > tex_height) {
6960 SetGLError(
6961 GL_INVALID_OPERATION, function_name, "dimensions out of range");
6962 return false;
6963 }
6964 return ValidateCompressedTexDimensions(
6965 function_name, level, width, height, format);
6966 }
[email protected]2d3765b2012-10-03 00:31:076967 case GL_ETC1_RGB8_OES: {
6968 SetGLError(
6969 GL_INVALID_OPERATION, function_name,
6970 "TexsubImage2d not supported for ECT1_RGB8_OES textures");
6971 return false;
6972 }
[email protected]ad84a3a2012-06-08 21:42:436973 default:
6974 return false;
6975 }
6976}
6977
[email protected]a93bb842010-02-16 23:03:476978error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
6979 GLenum target,
6980 GLint level,
6981 GLenum internal_format,
6982 GLsizei width,
6983 GLsizei height,
6984 GLint border,
6985 GLsizei image_size,
6986 const void* data) {
[email protected]a93bb842010-02-16 23:03:476987 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:056988 if (!validators_->texture_target.IsValid(target)) {
[email protected]f80e6e12012-08-31 00:43:536989 SetGLErrorInvalidEnum("glCompressedTexImage2D", target, "target");
[email protected]8eee29c2010-04-29 03:38:296990 return error::kNoError;
6991 }
[email protected]9438b012010-06-15 22:55:056992 if (!validators_->compressed_texture_format.IsValid(
6993 internal_format)) {
[email protected]f80e6e12012-08-31 00:43:536994 SetGLErrorInvalidEnum(
6995 "glCompressedTexImage2D", internal_format, "internal_format");
[email protected]a93bb842010-02-16 23:03:476996 return error::kNoError;
6997 }
[email protected]80eb6b52012-01-19 00:14:416998 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476999 border != 0) {
[email protected]8eee29c2010-04-29 03:38:297000 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:437001 "glCompressedTexImage2D", "dimensions out of range");
[email protected]a93bb842010-02-16 23:03:477002 return error::kNoError;
7003 }
[email protected]3916c97e2010-02-25 03:20:507004 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:477005 if (!info) {
[email protected]8eee29c2010-04-29 03:38:297006 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:437007 "glCompressedTexImage2D", "unknown texture target");
[email protected]a93bb842010-02-16 23:03:477008 return error::kNoError;
7009 }
[email protected]97dc7cbe2011-12-06 17:26:177010 if (info->IsImmutable()) {
7011 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437012 "glCompressedTexImage2D", "texture is immutable");
7013 return error::kNoError;
7014 }
7015
7016 if (!ValidateCompressedTexDimensions(
7017 "glCompressedTexImage2D", level, width, height, internal_format) ||
7018 !ValidateCompressedTexFuncData(
7019 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
[email protected]97dc7cbe2011-12-06 17:26:177020 return error::kNoError;
7021 }
[email protected]968351b2011-12-20 08:26:517022
7023 if (info->IsAttachedToFramebuffer()) {
[email protected]88a61bf2012-10-27 13:00:427024 clear_state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:517025 // TODO(gman): If textures tracked which framebuffers they were attached to
7026 // we could just mark those framebuffers as not complete.
7027 framebuffer_manager()->IncFramebufferStateChangeCount();
7028 }
7029
[email protected]a93bb842010-02-16 23:03:477030 scoped_array<int8> zero;
7031 if (!data) {
7032 zero.reset(new int8[image_size]);
7033 memset(zero.get(), 0, image_size);
7034 data = zero.get();
7035 }
[email protected]cadde4a2010-07-31 17:10:437036 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:477037 glCompressedTexImage2D(
7038 target, level, internal_format, width, height, border, image_size, data);
[email protected]1002c2d2011-06-28 22:39:047039 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:437040 if (error == GL_NO_ERROR) {
7041 texture_manager()->SetLevelInfo(
[email protected]0d6bfdc2011-11-02 01:32:207042 info, target, level, internal_format, width, height, 1, border, 0, 0,
7043 true);
[email protected]cadde4a2010-07-31 17:10:437044 }
[email protected]a93bb842010-02-16 23:03:477045 return error::kNoError;
7046}
7047
[email protected]f7a64ee2010-02-01 22:24:147048error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:197049 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
7050 GLenum target = static_cast<GLenum>(c.target);
7051 GLint level = static_cast<GLint>(c.level);
7052 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7053 GLsizei width = static_cast<GLsizei>(c.width);
7054 GLsizei height = static_cast<GLsizei>(c.height);
7055 GLint border = static_cast<GLint>(c.border);
7056 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
7057 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7058 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7059 const void* data = NULL;
7060 if (data_shm_id != 0 || data_shm_offset != 0) {
7061 data = GetSharedMemoryAs<const void*>(
7062 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:467063 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:147064 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197065 }
7066 }
[email protected]a93bb842010-02-16 23:03:477067 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:197068 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:197069}
7070
[email protected]f7a64ee2010-02-01 22:24:147071error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:197072 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
7073 GLenum target = static_cast<GLenum>(c.target);
7074 GLint level = static_cast<GLint>(c.level);
7075 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7076 GLsizei width = static_cast<GLsizei>(c.width);
7077 GLsizei height = static_cast<GLsizei>(c.height);
7078 GLint border = static_cast<GLint>(c.border);
7079 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:307080 const void* data = GetImmediateDataAs<const void*>(
7081 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:467082 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:147083 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:467084 }
[email protected]a93bb842010-02-16 23:03:477085 return DoCompressedTexImage2D(
7086 target, level, internal_format, width, height, border, image_size, data);
7087}
7088
[email protected]b6140d02010-05-17 14:47:167089error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
7090 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
7091 GLenum target = static_cast<GLenum>(c.target);
7092 GLint level = static_cast<GLint>(c.level);
7093 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7094 GLsizei width = static_cast<GLsizei>(c.width);
7095 GLsizei height = static_cast<GLsizei>(c.height);
7096 GLint border = static_cast<GLint>(c.border);
7097 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287098 if (!bucket) {
7099 return error::kInvalidArguments;
7100 }
7101 uint32 data_size = bucket->size();
7102 GLsizei imageSize = data_size;
7103 const void* data = bucket->GetData(0, data_size);
7104 if (!data) {
7105 return error::kInvalidArguments;
7106 }
[email protected]b6140d02010-05-17 14:47:167107 return DoCompressedTexImage2D(
7108 target, level, internal_format, width, height, border,
[email protected]12f93d82011-10-17 21:16:287109 imageSize, data);
[email protected]b6140d02010-05-17 14:47:167110}
7111
7112error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
7113 uint32 immediate_data_size,
7114 const gles2::CompressedTexSubImage2DBucket& c) {
7115 GLenum target = static_cast<GLenum>(c.target);
7116 GLint level = static_cast<GLint>(c.level);
7117 GLint xoffset = static_cast<GLint>(c.xoffset);
7118 GLint yoffset = static_cast<GLint>(c.yoffset);
7119 GLsizei width = static_cast<GLsizei>(c.width);
7120 GLsizei height = static_cast<GLsizei>(c.height);
7121 GLenum format = static_cast<GLenum>(c.format);
7122 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287123 if (!bucket) {
7124 return error::kInvalidArguments;
7125 }
[email protected]b6140d02010-05-17 14:47:167126 uint32 data_size = bucket->size();
7127 GLsizei imageSize = data_size;
7128 const void* data = bucket->GetData(0, data_size);
[email protected]12f93d82011-10-17 21:16:287129 if (!data) {
7130 return error::kInvalidArguments;
7131 }
[email protected]9438b012010-06-15 22:55:057132 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:167133 SetGLError(
[email protected]f80e6e12012-08-31 00:43:537134 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
[email protected]b6140d02010-05-17 14:47:167135 return error::kNoError;
7136 }
[email protected]9438b012010-06-15 22:55:057137 if (!validators_->compressed_texture_format.IsValid(format)) {
[email protected]f80e6e12012-08-31 00:43:537138 SetGLErrorInvalidEnum("glCompressedTexSubImage2D", format, "format");
[email protected]9438b012010-06-15 22:55:057139 return error::kNoError;
7140 }
[email protected]b6140d02010-05-17 14:47:167141 if (width < 0) {
[email protected]ad84a3a2012-06-08 21:42:437142 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
[email protected]b6140d02010-05-17 14:47:167143 return error::kNoError;
7144 }
7145 if (height < 0) {
[email protected]ad84a3a2012-06-08 21:42:437146 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
[email protected]b6140d02010-05-17 14:47:167147 return error::kNoError;
7148 }
7149 if (imageSize < 0) {
[email protected]ad84a3a2012-06-08 21:42:437150 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
[email protected]b6140d02010-05-17 14:47:167151 return error::kNoError;
7152 }
[email protected]cadde4a2010-07-31 17:10:437153 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:167154 target, level, xoffset, yoffset, width, height, format, imageSize, data);
7155 return error::kNoError;
7156}
7157
[email protected]81375742012-06-08 00:04:007158bool GLES2DecoderImpl::ValidateTextureParameters(
7159 const char* function_name,
7160 GLenum target, GLenum format, GLenum type, GLint level) {
7161 if (!feature_info_->GetTextureFormatValidator(format).IsValid(type)) {
[email protected]ad84a3a2012-06-08 21:42:437162 SetGLError(GL_INVALID_OPERATION, function_name,
7163 (std::string("invalid type ") +
[email protected]81375742012-06-08 00:04:007164 GLES2Util::GetStringEnum(type) + " for format " +
7165 GLES2Util::GetStringEnum(format)).c_str());
7166 return false;
7167 }
7168
7169 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7170 if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) {
[email protected]ad84a3a2012-06-08 21:42:437171 SetGLError(GL_INVALID_OPERATION, function_name,
7172 (std::string("invalid type ") +
[email protected]81375742012-06-08 00:04:007173 GLES2Util::GetStringEnum(type) + " for format " +
7174 GLES2Util::GetStringEnum(format)).c_str());
7175 return false;
7176 }
7177 return true;
7178}
7179
[email protected]a93bb842010-02-16 23:03:477180error::Error GLES2DecoderImpl::DoTexImage2D(
7181 GLenum target,
7182 GLint level,
7183 GLenum internal_format,
7184 GLsizei width,
7185 GLsizei height,
7186 GLint border,
7187 GLenum format,
7188 GLenum type,
7189 const void* pixels,
7190 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:057191 if (!validators_->texture_target.IsValid(target)) {
[email protected]f80e6e12012-08-31 00:43:537192 SetGLErrorInvalidEnum("glTexImage2D", target, "target");
[email protected]8eee29c2010-04-29 03:38:297193 return error::kNoError;
7194 }
[email protected]9438b012010-06-15 22:55:057195 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]f80e6e12012-08-31 00:43:537196 SetGLErrorInvalidEnum("glTexImage2D", internal_format, "internal_format");
[email protected]8eee29c2010-04-29 03:38:297197 return error::kNoError;
7198 }
[email protected]9438b012010-06-15 22:55:057199 if (!validators_->texture_format.IsValid(format)) {
[email protected]f80e6e12012-08-31 00:43:537200 SetGLErrorInvalidEnum("glTexImage2D", format, "format");
[email protected]8eee29c2010-04-29 03:38:297201 return error::kNoError;
7202 }
[email protected]9438b012010-06-15 22:55:057203 if (!validators_->pixel_type.IsValid(type)) {
[email protected]f80e6e12012-08-31 00:43:537204 SetGLErrorInvalidEnum("glTexImage2D", type, "type");
[email protected]f7a64ee2010-02-01 22:24:147205 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197206 }
[email protected]7b92c412010-07-20 17:48:257207 if (format != internal_format) {
[email protected]ad84a3a2012-06-08 21:42:437208 SetGLError(GL_INVALID_OPERATION,
7209 "glTexImage2D", "format != internalFormat");
[email protected]7b92c412010-07-20 17:48:257210 return error::kNoError;
7211 }
[email protected]81375742012-06-08 00:04:007212 if (!ValidateTextureParameters("glTexImage2D", target, format, type, level)) {
7213 return error::kNoError;
7214 }
[email protected]80eb6b52012-01-19 00:14:417215 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:477216 border != 0) {
[email protected]ad84a3a2012-06-08 21:42:437217 SetGLError(GL_INVALID_VALUE, "glTexImage2D", "dimensions out of range");
[email protected]a93bb842010-02-16 23:03:477218 return error::kNoError;
7219 }
[email protected]81375742012-06-08 00:04:007220 if ((GLES2Util::GetChannelsForFormat(format) &
7221 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && pixels) {
7222 SetGLError(
7223 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437224 "glTexImage2D", "can not supply data for depth or stencil textures");
[email protected]81375742012-06-08 00:04:007225 return error::kNoError;
7226 }
[email protected]3916c97e2010-02-25 03:20:507227 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:477228 if (!info) {
[email protected]8eee29c2010-04-29 03:38:297229 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437230 "glTexImage2D", "unknown texture for target");
[email protected]a93bb842010-02-16 23:03:477231 return error::kNoError;
7232 }
[email protected]0226c112011-07-22 03:25:077233
[email protected]97dc7cbe2011-12-06 17:26:177234 if (info->IsImmutable()) {
7235 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437236 "glTexImage2D", "texture is immutable");
[email protected]97dc7cbe2011-12-06 17:26:177237 return error::kNoError;
7238 }
7239
[email protected]0226c112011-07-22 03:25:077240 GLsizei tex_width = 0;
7241 GLsizei tex_height = 0;
7242 GLenum tex_type = 0;
7243 GLenum tex_format = 0;
7244 bool level_is_same =
7245 info->GetLevelSize(target, level, &tex_width, &tex_height) &&
7246 info->GetLevelType(target, level, &tex_type, &tex_format) &&
7247 width == tex_width && height == tex_height &&
7248 type == tex_type && format == tex_format;
7249
7250 if (level_is_same && !pixels) {
[email protected]1bed6222011-12-21 11:21:397251 // Just set the level info but mark the texture as uncleared.
7252 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:417253 info,
[email protected]1bed6222011-12-21 11:21:397254 target, level, internal_format, width, height, 1, border, format, type,
7255 false);
[email protected]ea72ed222011-08-17 18:58:437256 tex_image_2d_failed_ = false;
[email protected]0226c112011-07-22 03:25:077257 return error::kNoError;
7258 }
7259
[email protected]297ca1c2011-06-20 23:08:467260 if (info->IsAttachedToFramebuffer()) {
[email protected]88a61bf2012-10-27 13:00:427261 clear_state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:517262 // TODO(gman): If textures tracked which framebuffers they were attached to
7263 // we could just mark those framebuffers as not complete.
7264 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:467265 }
7266
[email protected]1bed6222011-12-21 11:21:397267 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same && pixels) {
[email protected]0226c112011-07-22 03:25:077268 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
[email protected]57edfdad2012-02-07 04:57:157269 texture_manager()->SetLevelCleared(info, target, level);
[email protected]0226c112011-07-22 03:25:077270 tex_image_2d_failed_ = false;
7271 return error::kNoError;
[email protected]7488d962010-07-16 02:41:587272 }
[email protected]876f6fee2010-08-02 23:10:327273
[email protected]cadde4a2010-07-31 17:10:437274 CopyRealGLErrorsToWrapper();
[email protected]473c01ccb2011-06-07 01:33:307275 WrappedTexImage2D(
7276 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:477277 pixels);
[email protected]1002c2d2011-06-28 22:39:047278 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:437279 if (error == GL_NO_ERROR) {
[email protected]0d6bfdc2011-11-02 01:32:207280 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:417281 info,
[email protected]0d6bfdc2011-11-02 01:32:207282 target, level, internal_format, width, height, 1, border, format, type,
7283 pixels != NULL);
[email protected]b493ee622011-04-13 23:52:007284 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:437285 }
[email protected]f7a64ee2010-02-01 22:24:147286 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197287}
7288
[email protected]f7a64ee2010-02-01 22:24:147289error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:197290 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]43ed3a72012-05-30 22:55:387291 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:007292 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:197293 GLenum target = static_cast<GLenum>(c.target);
7294 GLint level = static_cast<GLint>(c.level);
7295 GLint internal_format = static_cast<GLint>(c.internalformat);
7296 GLsizei width = static_cast<GLsizei>(c.width);
7297 GLsizei height = static_cast<GLsizei>(c.height);
7298 GLint border = static_cast<GLint>(c.border);
7299 GLenum format = static_cast<GLenum>(c.format);
7300 GLenum type = static_cast<GLenum>(c.type);
7301 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
7302 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:187303 uint32 pixels_size;
[email protected]3458a64a2012-04-10 17:39:347304 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247305 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
[email protected]3458a64a2012-04-10 17:39:347306 NULL)) {
[email protected]a76b0052010-03-05 00:33:187307 return error::kOutOfBounds;
7308 }
[email protected]b9849abf2009-11-25 19:13:197309 const void* pixels = NULL;
7310 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
7311 pixels = GetSharedMemoryAs<const void*>(
7312 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:467313 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:147314 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197315 }
7316 }
[email protected]a93bb842010-02-16 23:03:477317 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:197318 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:477319 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:197320}
7321
[email protected]f7a64ee2010-02-01 22:24:147322error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:197323 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
7324 GLenum target = static_cast<GLenum>(c.target);
7325 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:467326 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:197327 GLsizei width = static_cast<GLsizei>(c.width);
7328 GLsizei height = static_cast<GLsizei>(c.height);
7329 GLint border = static_cast<GLint>(c.border);
7330 GLenum format = static_cast<GLenum>(c.format);
7331 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:187332 uint32 size;
[email protected]3458a64a2012-04-10 17:39:347333 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247334 width, height, format, type, state_.unpack_alignment, &size,
7335 NULL, NULL)) {
[email protected]a76b0052010-03-05 00:33:187336 return error::kOutOfBounds;
7337 }
[email protected]07f54fcc2009-12-22 02:46:307338 const void* pixels = GetImmediateDataAs<const void*>(
7339 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:467340 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:147341 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:467342 }
[email protected]a93bb842010-02-16 23:03:477343 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:467344 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:477345 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:147346 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327347}
7348
[email protected]cadde4a2010-07-31 17:10:437349void GLES2DecoderImpl::DoCompressedTexSubImage2D(
7350 GLenum target,
7351 GLint level,
7352 GLint xoffset,
7353 GLint yoffset,
7354 GLsizei width,
7355 GLsizei height,
7356 GLenum format,
7357 GLsizei image_size,
7358 const void * data) {
7359 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7360 if (!info) {
7361 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437362 "glCompressedTexSubImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:437363 return;
7364 }
7365 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:527366 GLenum internal_format = 0;
7367 if (!info->GetLevelType(target, level, &type, &internal_format)) {
7368 SetGLError(
7369 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437370 "glCompressedTexSubImage2D", "level does not exist.");
[email protected]df6cf1ad2011-01-29 01:20:527371 return;
7372 }
7373 if (internal_format != format) {
7374 SetGLError(
7375 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437376 "glCompressedTexSubImage2D", "format does not match internal format.");
[email protected]df6cf1ad2011-01-29 01:20:527377 return;
7378 }
7379 if (!info->ValidForTexture(
7380 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:437381 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:437382 "glCompressedTexSubImage2D", "bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:437383 return;
7384 }
[email protected]ad84a3a2012-06-08 21:42:437385
7386 if (!ValidateCompressedTexFuncData(
7387 "glCompressedTexSubImage2D", width, height, format, image_size) ||
7388 !ValidateCompressedTexSubDimensions(
7389 "glCompressedTexSubImage2D",
7390 target, level, xoffset, yoffset, width, height, format, info)) {
7391 return;
7392 }
7393
7394
[email protected]0d6bfdc2011-11-02 01:32:207395 // Note: There is no need to deal with texture cleared tracking here
7396 // because the validation above means you can only get here if the level
7397 // is already a matching compressed format and in that case
7398 // CompressedTexImage2D already cleared the texture.
[email protected]cadde4a2010-07-31 17:10:437399 glCompressedTexSubImage2D(
7400 target, level, xoffset, yoffset, width, height, format, image_size, data);
7401}
7402
[email protected]6e288612010-12-21 20:45:037403static void Clip(
7404 GLint start, GLint range, GLint sourceRange,
7405 GLint* out_start, GLint* out_range) {
7406 DCHECK(out_start);
7407 DCHECK(out_range);
7408 if (start < 0) {
7409 range += start;
7410 start = 0;
7411 }
7412 GLint end = start + range;
7413 if (end > sourceRange) {
7414 range -= end - sourceRange;
7415 }
7416 *out_start = start;
7417 *out_range = range;
7418}
7419
[email protected]cadde4a2010-07-31 17:10:437420void GLES2DecoderImpl::DoCopyTexImage2D(
[email protected]a5d3dad2012-05-26 04:34:447421 GLenum target,
7422 GLint level,
7423 GLenum internal_format,
7424 GLint x,
7425 GLint y,
7426 GLsizei width,
7427 GLsizei height,
7428 GLint border) {
[email protected]09e17272012-11-30 10:30:447429 DCHECK(!ShouldDeferReads());
[email protected]cadde4a2010-07-31 17:10:437430 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7431 if (!info) {
7432 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437433 "glCopyTexImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:437434 return;
7435 }
[email protected]97dc7cbe2011-12-06 17:26:177436 if (info->IsImmutable()) {
7437 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437438 "glCopyTexImage2D", "texture is immutable");
[email protected]97dc7cbe2011-12-06 17:26:177439 }
[email protected]80eb6b52012-01-19 00:14:417440 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:187441 border != 0) {
[email protected]ad84a3a2012-06-08 21:42:437442 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
[email protected]f5719fb2010-08-04 18:27:187443 return;
7444 }
[email protected]81375742012-06-08 00:04:007445 if (!ValidateTextureParameters(
7446 "glCopyTexImage2D", target, internal_format, GL_UNSIGNED_BYTE, level)) {
7447 return;
7448 }
[email protected]f5719fb2010-08-04 18:27:187449
[email protected]9edc6b22010-12-23 02:00:267450 // Check we have compatible formats.
7451 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7452 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7453 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
7454
7455 if ((channels_needed & channels_exist) != channels_needed) {
[email protected]ad84a3a2012-06-08 21:42:437456 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
[email protected]9edc6b22010-12-23 02:00:267457 return;
7458 }
7459
[email protected]81375742012-06-08 00:04:007460 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
7461 SetGLError(
7462 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437463 "glCopyImage2D", "can not be used with depth or stencil textures");
[email protected]81375742012-06-08 00:04:007464 return;
7465 }
7466
[email protected]a0b78dc2011-11-11 10:43:107467 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
7468 return;
7469 }
7470
[email protected]cadde4a2010-07-31 17:10:437471 CopyRealGLErrorsToWrapper();
[email protected]de26b3c2011-08-03 21:54:277472 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:037473 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:267474
[email protected]297ca1c2011-06-20 23:08:467475 if (info->IsAttachedToFramebuffer()) {
[email protected]88a61bf2012-10-27 13:00:427476 clear_state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:517477 // TODO(gman): If textures tracked which framebuffers they were attached to
7478 // we could just mark those framebuffers as not complete.
7479 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:467480 }
7481
[email protected]9edc6b22010-12-23 02:00:267482 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:037483 GLint copyX = 0;
7484 GLint copyY = 0;
7485 GLint copyWidth = 0;
7486 GLint copyHeight = 0;
7487 Clip(x, width, size.width(), &copyX, &copyWidth);
7488 Clip(y, height, size.height(), &copyY, &copyHeight);
7489
7490 if (copyX != x ||
7491 copyY != y ||
7492 copyWidth != width ||
7493 copyHeight != height) {
7494 // some part was clipped so clear the texture.
[email protected]0d6bfdc2011-11-02 01:32:207495 if (!ClearLevel(
7496 info->service_id(), info->target(),
[email protected]4502e6492011-12-14 19:39:157497 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
7498 info->IsImmutable())) {
[email protected]ad84a3a2012-06-08 21:42:437499 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
[email protected]6e288612010-12-21 20:45:037500 return;
7501 }
[email protected]6e288612010-12-21 20:45:037502 if (copyHeight > 0 && copyWidth > 0) {
7503 GLint dx = copyX - x;
7504 GLint dy = copyY - y;
7505 GLint destX = dx;
7506 GLint destY = dy;
7507 glCopyTexSubImage2D(target, level,
7508 destX, destY, copyX, copyY,
7509 copyWidth, copyHeight);
7510 }
7511 } else {
7512 glCopyTexImage2D(target, level, internal_format,
7513 copyX, copyY, copyWidth, copyHeight, border);
7514 }
[email protected]1002c2d2011-06-28 22:39:047515 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:437516 if (error == GL_NO_ERROR) {
7517 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:417518 info, target, level, internal_format, width, height, 1,
[email protected]0d6bfdc2011-11-02 01:32:207519 border, internal_format, GL_UNSIGNED_BYTE, true);
[email protected]cadde4a2010-07-31 17:10:437520 }
7521}
7522
7523void GLES2DecoderImpl::DoCopyTexSubImage2D(
[email protected]a5d3dad2012-05-26 04:34:447524 GLenum target,
7525 GLint level,
7526 GLint xoffset,
7527 GLint yoffset,
7528 GLint x,
7529 GLint y,
7530 GLsizei width,
7531 GLsizei height) {
[email protected]09e17272012-11-30 10:30:447532 DCHECK(!ShouldDeferReads());
[email protected]cadde4a2010-07-31 17:10:437533 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7534 if (!info) {
7535 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437536 "glCopyTexSubImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:437537 return;
7538 }
7539 GLenum type = 0;
7540 GLenum format = 0;
7541 if (!info->GetLevelType(target, level, &type, &format) ||
7542 !info->ValidForTexture(
7543 target, level, xoffset, yoffset, width, height, format, type)) {
7544 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:437545 "glCopyTexSubImage2D", "bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:437546 return;
7547 }
[email protected]9edc6b22010-12-23 02:00:267548
7549 // Check we have compatible formats.
7550 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7551 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7552 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
7553
[email protected]2d3765b2012-10-03 00:31:077554 if (!channels_needed ||
7555 (channels_needed & channels_exist) != channels_needed) {
[email protected]9edc6b22010-12-23 02:00:267556 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:437557 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
[email protected]9edc6b22010-12-23 02:00:267558 return;
7559 }
7560
[email protected]81375742012-06-08 00:04:007561 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
7562 SetGLError(
7563 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437564 "glCopySubImage2D", "can not be used with depth or stencil textures");
[email protected]81375742012-06-08 00:04:007565 return;
7566 }
7567
[email protected]a0b78dc2011-11-11 10:43:107568 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
7569 return;
7570 }
7571
[email protected]de26b3c2011-08-03 21:54:277572 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:037573 gfx::Size size = GetBoundReadFrameBufferSize();
7574 GLint copyX = 0;
7575 GLint copyY = 0;
7576 GLint copyWidth = 0;
7577 GLint copyHeight = 0;
7578 Clip(x, width, size.width(), &copyX, &copyWidth);
7579 Clip(y, height, size.height(), &copyY, &copyHeight);
[email protected]0d6bfdc2011-11-02 01:32:207580
7581 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
[email protected]ad84a3a2012-06-08 21:42:437582 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
[email protected]0d6bfdc2011-11-02 01:32:207583 return;
7584 }
7585
[email protected]6e288612010-12-21 20:45:037586 if (copyX != x ||
7587 copyY != y ||
7588 copyWidth != width ||
7589 copyHeight != height) {
[email protected]0d6bfdc2011-11-02 01:32:207590 // some part was clipped so clear the sub rect.
[email protected]6e288612010-12-21 20:45:037591 uint32 pixels_size = 0;
[email protected]3458a64a2012-04-10 17:39:347592 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247593 width, height, format, type, state_.unpack_alignment, &pixels_size,
7594 NULL, NULL)) {
[email protected]ad84a3a2012-06-08 21:42:437595 SetGLError(
7596 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
[email protected]6e288612010-12-21 20:45:037597 return;
7598 }
7599 scoped_array<char> zero(new char[pixels_size]);
7600 memset(zero.get(), 0, pixels_size);
7601 glTexSubImage2D(
7602 target, level, xoffset, yoffset, width, height,
7603 format, type, zero.get());
7604 }
[email protected]0d6bfdc2011-11-02 01:32:207605
[email protected]6e288612010-12-21 20:45:037606 if (copyHeight > 0 && copyWidth > 0) {
7607 GLint dx = copyX - x;
7608 GLint dy = copyY - y;
7609 GLint destX = xoffset + dx;
7610 GLint destY = yoffset + dy;
7611 glCopyTexSubImage2D(target, level,
7612 destX, destY, copyX, copyY,
7613 copyWidth, copyHeight);
7614 }
[email protected]cadde4a2010-07-31 17:10:437615}
7616
7617void GLES2DecoderImpl::DoTexSubImage2D(
7618 GLenum target,
7619 GLint level,
7620 GLint xoffset,
7621 GLint yoffset,
7622 GLsizei width,
7623 GLsizei height,
7624 GLenum format,
7625 GLenum type,
7626 const void * data) {
7627 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7628 if (!info) {
7629 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437630 "glTexSubImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:437631 return;
7632 }
[email protected]df6cf1ad2011-01-29 01:20:527633 GLenum current_type = 0;
7634 GLenum internal_format = 0;
7635 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
7636 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:437637 GL_INVALID_OPERATION, "glTexSubImage2D", "level does not exist.");
[email protected]df6cf1ad2011-01-29 01:20:527638 return;
7639 }
7640 if (format != internal_format) {
7641 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437642 "glTexSubImage2D", "format does not match internal format.");
[email protected]df6cf1ad2011-01-29 01:20:527643 return;
7644 }
7645 if (type != current_type) {
7646 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437647 "glTexSubImage2D", "type does not match type of texture.");
[email protected]df6cf1ad2011-01-29 01:20:527648 return;
7649 }
7650
[email protected]cadde4a2010-07-31 17:10:437651 if (!info->ValidForTexture(
7652 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]ad84a3a2012-06-08 21:42:437653 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:437654 return;
7655 }
[email protected]473c01ccb2011-06-07 01:33:307656
[email protected]81375742012-06-08 00:04:007657 if ((GLES2Util::GetChannelsForFormat(format) &
7658 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
7659 SetGLError(
7660 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437661 "glTexSubImage2D", "can not supply data for depth or stencil textures");
[email protected]81375742012-06-08 00:04:007662 return;
7663 }
7664
[email protected]4502e6492011-12-14 19:39:157665 GLsizei tex_width = 0;
7666 GLsizei tex_height = 0;
7667 bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height);
7668 DCHECK(ok);
7669 if (xoffset != 0 || yoffset != 0 ||
7670 width != tex_width || height != tex_height) {
7671 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
[email protected]ad84a3a2012-06-08 21:42:437672 SetGLError(GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
[email protected]473c01ccb2011-06-07 01:33:307673 return;
7674 }
[email protected]63b465922012-09-06 02:04:527675 ScopedTextureUploadTimer timer(this);
[email protected]4502e6492011-12-14 19:39:157676 glTexSubImage2D(
7677 target, level, xoffset, yoffset, width, height, format, type, data);
[email protected]0d6bfdc2011-11-02 01:32:207678 return;
7679 }
[email protected]4502e6492011-12-14 19:39:157680
7681 if (teximage2d_faster_than_texsubimage2d_ && !info->IsImmutable()) {
[email protected]63b465922012-09-06 02:04:527682 ScopedTextureUploadTimer timer(this);
[email protected]4502e6492011-12-14 19:39:157683 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
7684 // same as internal_foramt. If that changes we'll need to look them up.
7685 WrappedTexImage2D(
7686 target, level, format, width, height, 0, format, type, data);
7687 } else {
[email protected]63b465922012-09-06 02:04:527688 ScopedTextureUploadTimer timer(this);
[email protected]4502e6492011-12-14 19:39:157689 glTexSubImage2D(
7690 target, level, xoffset, yoffset, width, height, format, type, data);
7691 }
7692 texture_manager()->SetLevelCleared(info, target, level);
[email protected]cadde4a2010-07-31 17:10:437693}
7694
[email protected]b493ee622011-04-13 23:52:007695error::Error GLES2DecoderImpl::HandleTexSubImage2D(
7696 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]43ed3a72012-05-30 22:55:387697 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:007698 GLboolean internal = static_cast<GLboolean>(c.internal);
7699 if (internal == GL_TRUE && tex_image_2d_failed_)
7700 return error::kNoError;
7701
7702 GLenum target = static_cast<GLenum>(c.target);
7703 GLint level = static_cast<GLint>(c.level);
7704 GLint xoffset = static_cast<GLint>(c.xoffset);
7705 GLint yoffset = static_cast<GLint>(c.yoffset);
7706 GLsizei width = static_cast<GLsizei>(c.width);
7707 GLsizei height = static_cast<GLsizei>(c.height);
7708 GLenum format = static_cast<GLenum>(c.format);
7709 GLenum type = static_cast<GLenum>(c.type);
7710 uint32 data_size;
[email protected]3458a64a2012-04-10 17:39:347711 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247712 width, height, format, type, state_.unpack_alignment, &data_size,
7713 NULL, NULL)) {
[email protected]b493ee622011-04-13 23:52:007714 return error::kOutOfBounds;
7715 }
7716 const void* pixels = GetSharedMemoryAs<const void*>(
7717 c.pixels_shm_id, c.pixels_shm_offset, data_size);
7718 if (!validators_->texture_target.IsValid(target)) {
[email protected]f80e6e12012-08-31 00:43:537719 SetGLErrorInvalidEnum("glTexSubImage2D", target, "target");
[email protected]b493ee622011-04-13 23:52:007720 return error::kNoError;
7721 }
7722 if (width < 0) {
[email protected]ad84a3a2012-06-08 21:42:437723 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "width < 0");
[email protected]b493ee622011-04-13 23:52:007724 return error::kNoError;
7725 }
7726 if (height < 0) {
[email protected]ad84a3a2012-06-08 21:42:437727 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "height < 0");
[email protected]b493ee622011-04-13 23:52:007728 return error::kNoError;
7729 }
7730 if (!validators_->texture_format.IsValid(format)) {
[email protected]f80e6e12012-08-31 00:43:537731 SetGLErrorInvalidEnum("glTexSubImage2D", format, "format");
[email protected]b493ee622011-04-13 23:52:007732 return error::kNoError;
7733 }
7734 if (!validators_->pixel_type.IsValid(type)) {
[email protected]f80e6e12012-08-31 00:43:537735 SetGLErrorInvalidEnum("glTexSubImage2D", type, "type");
[email protected]b493ee622011-04-13 23:52:007736 return error::kNoError;
7737 }
7738 if (pixels == NULL) {
7739 return error::kOutOfBounds;
7740 }
7741 DoTexSubImage2D(
7742 target, level, xoffset, yoffset, width, height, format, type, pixels);
7743 return error::kNoError;
7744}
7745
7746error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
7747 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
7748 GLboolean internal = static_cast<GLboolean>(c.internal);
7749 if (internal == GL_TRUE && tex_image_2d_failed_)
7750 return error::kNoError;
7751
7752 GLenum target = static_cast<GLenum>(c.target);
7753 GLint level = static_cast<GLint>(c.level);
7754 GLint xoffset = static_cast<GLint>(c.xoffset);
7755 GLint yoffset = static_cast<GLint>(c.yoffset);
7756 GLsizei width = static_cast<GLsizei>(c.width);
7757 GLsizei height = static_cast<GLsizei>(c.height);
7758 GLenum format = static_cast<GLenum>(c.format);
7759 GLenum type = static_cast<GLenum>(c.type);
7760 uint32 data_size;
[email protected]3458a64a2012-04-10 17:39:347761 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247762 width, height, format, type, state_.unpack_alignment, &data_size,
7763 NULL, NULL)) {
[email protected]b493ee622011-04-13 23:52:007764 return error::kOutOfBounds;
7765 }
7766 const void* pixels = GetImmediateDataAs<const void*>(
7767 c, data_size, immediate_data_size);
7768 if (!validators_->texture_target.IsValid(target)) {
[email protected]f80e6e12012-08-31 00:43:537769 SetGLErrorInvalidEnum("glTexSubImage2D", target, "target");
[email protected]b493ee622011-04-13 23:52:007770 return error::kNoError;
7771 }
7772 if (width < 0) {
[email protected]ad84a3a2012-06-08 21:42:437773 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "width < 0");
[email protected]b493ee622011-04-13 23:52:007774 return error::kNoError;
7775 }
7776 if (height < 0) {
[email protected]ad84a3a2012-06-08 21:42:437777 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "height < 0");
[email protected]b493ee622011-04-13 23:52:007778 return error::kNoError;
7779 }
7780 if (!validators_->texture_format.IsValid(format)) {
[email protected]f80e6e12012-08-31 00:43:537781 SetGLErrorInvalidEnum("glTexSubImage2D", format, "format");
[email protected]b493ee622011-04-13 23:52:007782 return error::kNoError;
7783 }
7784 if (!validators_->pixel_type.IsValid(type)) {
[email protected]f80e6e12012-08-31 00:43:537785 SetGLErrorInvalidEnum("glTexSubImage2D", type, "type");
[email protected]b493ee622011-04-13 23:52:007786 return error::kNoError;
7787 }
7788 if (pixels == NULL) {
7789 return error::kOutOfBounds;
7790 }
7791 DoTexSubImage2D(
7792 target, level, xoffset, yoffset, width, height, format, type, pixels);
7793 return error::kNoError;
7794}
7795
[email protected]f7a64ee2010-02-01 22:24:147796error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:197797 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:367798 GLuint index = static_cast<GLuint>(c.index);
7799 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:257800 typedef gles2::GetVertexAttribPointerv::Result Result;
7801 Result* result = GetSharedMemoryAs<Result*>(
7802 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:367803 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:147804 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:367805 }
[email protected]07d0cc82010-02-17 04:51:407806 // Check that the client initialized the result.
7807 if (result->size != 0) {
7808 return error::kInvalidArguments;
7809 }
[email protected]9438b012010-06-15 22:55:057810 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]f80e6e12012-08-31 00:43:537811 SetGLErrorInvalidEnum("glGetVertexAttribPointerv", pname, "pname");
[email protected]f7a64ee2010-02-01 22:24:147812 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367813 }
[email protected]3916c97e2010-02-25 03:20:507814 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:297815 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:437816 "glGetVertexAttribPointerv", "index out of range.");
[email protected]f7a64ee2010-02-01 22:24:147817 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367818 }
[email protected]0bfd9882010-02-05 23:02:257819 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:087820 *result->GetData() =
[email protected]e259eb412012-10-13 05:47:247821 state_.vertex_attrib_manager->GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:147822 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327823}
7824
[email protected]f7b85372010-02-03 01:11:377825bool GLES2DecoderImpl::GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127826 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:377827 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:127828 error::Error* error, GLint* real_location,
7829 GLuint* service_id, void** result_pointer, GLenum* result_type) {
[email protected]939e7362010-05-13 20:49:107830 DCHECK(error);
7831 DCHECK(service_id);
7832 DCHECK(result_pointer);
7833 DCHECK(result_type);
[email protected]1b0a6752012-02-22 03:44:127834 DCHECK(real_location);
[email protected]f7b85372010-02-03 01:11:377835 *error = error::kNoError;
7836 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:257837 SizedResult<GLint>* result;
7838 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7839 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
7840 if (!result) {
[email protected]f7b85372010-02-03 01:11:377841 *error = error::kOutOfBounds;
7842 return false;
7843 }
[email protected]0bfd9882010-02-05 23:02:257844 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:377845 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:257846 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:587847 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7848 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:377849 if (!info) {
[email protected]ae51d192010-04-27 00:48:037850 return false;
7851 }
7852 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:377853 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]ad84a3a2012-06-08 21:42:437854 SetGLError(GL_INVALID_OPERATION, "glGetUniform", "program not linked");
[email protected]f7b85372010-02-03 01:11:377855 return false;
7856 }
[email protected]ae51d192010-04-27 00:48:037857 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:367858 GLint array_index = -1;
7859 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
[email protected]1b0a6752012-02-22 03:44:127860 info->GetUniformInfoByFakeLocation(
7861 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:367862 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:377863 // No such location.
[email protected]ad84a3a2012-06-08 21:42:437864 SetGLError(GL_INVALID_OPERATION, "glGetUniform", "unknown location");
[email protected]f7b85372010-02-03 01:11:377865 return false;
7866 }
[email protected]43c2f1f2011-03-25 18:35:367867 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:507868 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:377869 if (size == 0) {
[email protected]ad84a3a2012-06-08 21:42:437870 SetGLError(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
[email protected]f7b85372010-02-03 01:11:377871 return false;
7872 }
[email protected]0bfd9882010-02-05 23:02:257873 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7874 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
7875 if (!result) {
[email protected]f7b85372010-02-03 01:11:377876 *error = error::kOutOfBounds;
7877 return false;
7878 }
[email protected]0bfd9882010-02-05 23:02:257879 result->size = size;
[email protected]939e7362010-05-13 20:49:107880 *result_type = type;
[email protected]f7b85372010-02-03 01:11:377881 return true;
7882}
7883
[email protected]f7a64ee2010-02-01 22:24:147884error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:197885 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:377886 GLuint program = c.program;
[email protected]2be6abf32012-06-26 00:28:337887 GLint fake_location = c.location;
[email protected]f7b85372010-02-03 01:11:377888 GLuint service_id;
[email protected]939e7362010-05-13 20:49:107889 GLenum result_type;
[email protected]1b0a6752012-02-22 03:44:127890 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:377891 Error error;
[email protected]0bfd9882010-02-05 23:02:257892 void* result;
[email protected]f7b85372010-02-03 01:11:377893 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127894 program, fake_location, c.params_shm_id, c.params_shm_offset,
7895 &error, &real_location, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:257896 glGetUniformiv(
[email protected]1b0a6752012-02-22 03:44:127897 service_id, real_location,
[email protected]0bfd9882010-02-05 23:02:257898 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:377899 }
7900 return error;
[email protected]96449d2c2009-11-25 00:01:327901}
7902
[email protected]f7a64ee2010-02-01 22:24:147903error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:197904 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:377905 GLuint program = c.program;
[email protected]2be6abf32012-06-26 00:28:337906 GLint fake_location = c.location;
[email protected]f7b85372010-02-03 01:11:377907 GLuint service_id;
[email protected]1b0a6752012-02-22 03:44:127908 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:377909 Error error;
[email protected]0bfd9882010-02-05 23:02:257910 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:107911 Result* result;
7912 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:377913 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127914 program, fake_location, c.params_shm_id, c.params_shm_offset,
7915 &error, &real_location, &service_id,
7916 reinterpret_cast<void**>(&result), &result_type)) {
[email protected]939e7362010-05-13 20:49:107917 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
7918 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
7919 GLsizei num_values = result->GetNumResults();
7920 scoped_array<GLint> temp(new GLint[num_values]);
[email protected]1b0a6752012-02-22 03:44:127921 glGetUniformiv(service_id, real_location, temp.get());
[email protected]939e7362010-05-13 20:49:107922 GLfloat* dst = result->GetData();
7923 for (GLsizei ii = 0; ii < num_values; ++ii) {
7924 dst[ii] = (temp[ii] != 0);
7925 }
7926 } else {
[email protected]1b0a6752012-02-22 03:44:127927 glGetUniformfv(service_id, real_location, result->GetData());
[email protected]939e7362010-05-13 20:49:107928 }
[email protected]f7b85372010-02-03 01:11:377929 }
7930 return error;
[email protected]96449d2c2009-11-25 00:01:327931}
7932
[email protected]f7a64ee2010-02-01 22:24:147933error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:197934 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:257935 GLenum shader_type = static_cast<GLenum>(c.shadertype);
7936 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
7937 typedef gles2::GetShaderPrecisionFormat::Result Result;
7938 Result* result = GetSharedMemoryAs<Result*>(
7939 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7940 if (!result) {
7941 return error::kOutOfBounds;
7942 }
[email protected]07d0cc82010-02-17 04:51:407943 // Check that the client initialized the result.
7944 if (result->success != 0) {
7945 return error::kInvalidArguments;
7946 }
[email protected]9438b012010-06-15 22:55:057947 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]f80e6e12012-08-31 00:43:537948 SetGLErrorInvalidEnum(
7949 "glGetShaderPrecisionFormat", shader_type, "shader_type");
[email protected]8eee29c2010-04-29 03:38:297950 return error::kNoError;
7951 }
[email protected]9438b012010-06-15 22:55:057952 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]f80e6e12012-08-31 00:43:537953 SetGLErrorInvalidEnum(
7954 "glGetShaderPrecisionFormat", precision_type, "precision_type");
[email protected]8eee29c2010-04-29 03:38:297955 return error::kNoError;
7956 }
7957
7958 result->success = 1; // true
7959 switch (precision_type) {
7960 case GL_LOW_INT:
7961 case GL_MEDIUM_INT:
7962 case GL_HIGH_INT:
[email protected]0a34b582012-04-09 22:42:567963 // These values are for a 32-bit twos-complement integer format.
7964 result->min_range = 31;
7965 result->max_range = 30;
[email protected]8eee29c2010-04-29 03:38:297966 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:107967 break;
[email protected]8eee29c2010-04-29 03:38:297968 case GL_LOW_FLOAT:
7969 case GL_MEDIUM_FLOAT:
7970 case GL_HIGH_FLOAT:
[email protected]0a34b582012-04-09 22:42:567971 // These values are for an IEEE single-precision floating-point format.
7972 result->min_range = 127;
7973 result->max_range = 127;
7974 result->precision = 23;
[email protected]8eee29c2010-04-29 03:38:297975 break;
7976 default:
7977 NOTREACHED();
7978 break;
[email protected]0bfd9882010-02-05 23:02:257979 }
[email protected]f7a64ee2010-02-01 22:24:147980 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327981}
7982
[email protected]f7a64ee2010-02-01 22:24:147983error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:197984 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:257985 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:587986 GLuint program = static_cast<GLuint>(c.program);
7987 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7988 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:037989 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257990 return error::kNoError;
7991 }
7992 typedef gles2::GetAttachedShaders::Result Result;
7993 uint32 max_count = Result::ComputeMaxResults(result_size);
7994 Result* result = GetSharedMemoryAs<Result*>(
7995 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
7996 if (!result) {
7997 return error::kOutOfBounds;
7998 }
[email protected]07d0cc82010-02-17 04:51:407999 // Check that the client initialized the result.
8000 if (result->size != 0) {
8001 return error::kInvalidArguments;
8002 }
[email protected]0bfd9882010-02-05 23:02:258003 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:038004 glGetAttachedShaders(
8005 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:258006 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:038007 if (!shader_manager()->GetClientId(result->GetData()[ii],
8008 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:258009 NOTREACHED();
8010 return error::kGenericError;
8011 }
8012 }
8013 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:148014 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328015}
8016
[email protected]f7a64ee2010-02-01 22:24:148017error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:198018 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:258019 GLuint program = c.program;
8020 GLuint index = c.index;
8021 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:258022 typedef gles2::GetActiveUniform::Result Result;
8023 Result* result = GetSharedMemoryAs<Result*>(
8024 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8025 if (!result) {
8026 return error::kOutOfBounds;
8027 }
[email protected]07d0cc82010-02-17 04:51:408028 // Check that the client initialized the result.
8029 if (result->success != 0) {
8030 return error::kInvalidArguments;
8031 }
[email protected]6b8cf1a2010-05-06 16:13:588032 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
8033 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:038034 if (!info) {
[email protected]0bfd9882010-02-05 23:02:258035 return error::kNoError;
8036 }
8037 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
8038 info->GetUniformInfo(index);
8039 if (!uniform_info) {
[email protected]ad84a3a2012-06-08 21:42:438040 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
[email protected]0bfd9882010-02-05 23:02:258041 return error::kNoError;
8042 }
8043 result->success = 1; // true.
8044 result->size = uniform_info->size;
8045 result->type = uniform_info->type;
8046 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:298047 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:148048 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328049}
8050
[email protected]f7a64ee2010-02-01 22:24:148051error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:198052 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:258053 GLuint program = c.program;
8054 GLuint index = c.index;
8055 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:258056 typedef gles2::GetActiveAttrib::Result Result;
8057 Result* result = GetSharedMemoryAs<Result*>(
8058 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8059 if (!result) {
8060 return error::kOutOfBounds;
8061 }
[email protected]07d0cc82010-02-17 04:51:408062 // Check that the client initialized the result.
8063 if (result->success != 0) {
8064 return error::kInvalidArguments;
8065 }
[email protected]6b8cf1a2010-05-06 16:13:588066 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
8067 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:038068 if (!info) {
[email protected]0bfd9882010-02-05 23:02:258069 return error::kNoError;
8070 }
8071 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
8072 info->GetAttribInfo(index);
8073 if (!attrib_info) {
[email protected]ad84a3a2012-06-08 21:42:438074 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
[email protected]0bfd9882010-02-05 23:02:258075 return error::kNoError;
8076 }
8077 result->success = 1; // true.
8078 result->size = attrib_info->size;
8079 result->type = attrib_info->type;
8080 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:298081 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:148082 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328083}
8084
[email protected]b273e432010-04-12 17:23:588085error::Error GLES2DecoderImpl::HandleShaderBinary(
8086 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
8087#if 1 // No binary shader support.
[email protected]ad84a3a2012-06-08 21:42:438088 SetGLError(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
[email protected]b273e432010-04-12 17:23:588089 return error::kNoError;
8090#else
8091 GLsizei n = static_cast<GLsizei>(c.n);
8092 if (n < 0) {
[email protected]ad84a3a2012-06-08 21:42:438093 SetGLError(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
[email protected]b273e432010-04-12 17:23:588094 return error::kNoError;
8095 }
8096 GLsizei length = static_cast<GLsizei>(c.length);
8097 if (length < 0) {
[email protected]ad84a3a2012-06-08 21:42:438098 SetGLError(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
[email protected]b273e432010-04-12 17:23:588099 return error::kNoError;
8100 }
8101 uint32 data_size;
8102 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
8103 return error::kOutOfBounds;
8104 }
8105 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
8106 c.shaders_shm_id, c.shaders_shm_offset, data_size);
8107 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
8108 const void* binary = GetSharedMemoryAs<const void*>(
8109 c.binary_shm_id, c.binary_shm_offset, length);
8110 if (shaders == NULL || binary == NULL) {
8111 return error::kOutOfBounds;
8112 }
8113 scoped_array<GLuint> service_ids(new GLuint[n]);
8114 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:038115 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
8116 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:438117 SetGLError(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
[email protected]b273e432010-04-12 17:23:588118 return error::kNoError;
8119 }
[email protected]ae51d192010-04-27 00:48:038120 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:588121 }
8122 // TODO(gman): call glShaderBinary
8123 return error::kNoError;
8124#endif
8125}
8126
[email protected]6217d392010-03-25 22:08:358127error::Error GLES2DecoderImpl::HandleSwapBuffers(
8128 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:498129 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
[email protected]a7266a92012-06-28 02:11:088130 if (!is_offscreen && surface_->DeferSwapBuffers()) {
8131 return error::kDeferCommandUntilLater;
8132 }
8133
[email protected]64ace852011-05-19 21:49:498134 int this_frame_number = frame_number_++;
[email protected]2ac620e52012-07-23 20:31:428135 // TRACE_EVENT for gpu tests:
8136 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
8137 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
8138 "width", (is_offscreen ? offscreen_size_.width() :
8139 surface_->GetSize().width()));
[email protected]64ace852011-05-19 21:49:498140 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
8141 "offscreen", is_offscreen,
8142 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:358143 // If offscreen then don't actually SwapBuffers to the display. Just copy
8144 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:498145 if (is_offscreen) {
[email protected]111975c62012-09-06 01:37:318146 TRACE_EVENT2("gpu", "Offscreen",
8147 "width", offscreen_size_.width(), "height", offscreen_size_.height());
[email protected]1fb8c482011-08-31 01:01:538148 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
8149 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
8150 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
8151 // fix this.
[email protected]62e155e2012-10-23 22:43:158152 if (workarounds().needs_offscreen_buffer_workaround) {
[email protected]1fb8c482011-08-31 01:01:538153 offscreen_saved_frame_buffer_->Create();
8154 glFinish();
8155 }
8156
8157 // Allocate the offscreen saved color texture.
8158 DCHECK(offscreen_saved_color_format_);
8159 offscreen_saved_color_texture_->AllocateStorage(
8160 offscreen_size_, offscreen_saved_color_format_);
8161
8162 offscreen_saved_frame_buffer_->AttachRenderTexture(
8163 offscreen_saved_color_texture_.get());
8164 if (offscreen_saved_frame_buffer_->CheckStatus() !=
8165 GL_FRAMEBUFFER_COMPLETE) {
8166 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
8167 << "because offscreen saved FBO was incomplete.";
8168 return error::kLostContext;
8169 }
8170
[email protected]1fb8c482011-08-31 01:01:538171 // Clear the offscreen color texture.
8172 // TODO(piman): Is this still necessary?
8173 {
8174 ScopedFrameBufferBinder binder(this,
8175 offscreen_saved_frame_buffer_->id());
8176 glClearColor(0, 0, 0, 0);
8177 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
8178 glDisable(GL_SCISSOR_TEST);
8179 glClear(GL_COLOR_BUFFER_BIT);
8180 RestoreClearState();
8181 }
8182
8183 UpdateParentTextureInfo();
8184 }
8185
[email protected]6217d392010-03-25 22:08:358186 ScopedGLErrorSuppressor suppressor(this);
8187
[email protected]34ff8b0c2010-10-01 20:06:028188 if (IsOffscreenBufferMultisampled()) {
[email protected]51411e32012-01-19 20:21:138189 // For multisampled buffers, resolve the frame buffer.
[email protected]de26b3c2011-08-03 21:54:278190 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]89d6ed02011-04-20 00:23:238191 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:488192 } else {
[email protected]069944672012-04-25 20:52:238193 ScopedFrameBufferBinder binder(this,
8194 offscreen_target_frame_buffer_->id());
[email protected]51411e32012-01-19 20:21:138195
[email protected]069944672012-04-25 20:52:238196 if (offscreen_target_buffer_preserved_) {
8197 // Copy the target frame buffer to the saved offscreen texture.
8198 offscreen_saved_color_texture_->Copy(
8199 offscreen_saved_color_texture_->size(),
8200 offscreen_saved_color_format_);
8201 } else {
8202 // Flip the textures in the parent context via the texture manager.
8203 if (!!offscreen_saved_color_texture_info_.get())
8204 offscreen_saved_color_texture_info_->
8205 SetServiceId(offscreen_target_color_texture_->id());
[email protected]8a61d872012-01-20 12:43:568206
[email protected]069944672012-04-25 20:52:238207 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
8208 offscreen_target_frame_buffer_->AttachRenderTexture(
8209 offscreen_target_color_texture_.get());
[email protected]b86b14982010-10-11 18:45:488210 }
[email protected]069944672012-04-25 20:52:238211
8212 // Ensure the side effects of the copy are visible to the parent
8213 // context. There is no need to do this for ANGLE because it uses a
8214 // single D3D device for all contexts.
8215 if (!IsAngle())
8216 glFlush();
[email protected]89d6ed02011-04-20 00:23:238217 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:398218 }
[email protected]6217d392010-03-25 22:08:358219 } else {
[email protected]111975c62012-09-06 01:37:318220 TRACE_EVENT2("gpu", "Onscreen",
8221 "width", surface_->GetSize().width(),
8222 "height", surface_->GetSize().height());
[email protected]f62a5ab2011-05-23 20:34:158223 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:018224 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:028225 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:018226 }
[email protected]6217d392010-03-25 22:08:358227 }
8228
[email protected]89d6ed02011-04-20 00:23:238229 return error::kNoError;
[email protected]6217d392010-03-25 22:08:358230}
8231
[email protected]d4239852011-08-12 04:51:228232error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
8233 uint32 immediate_data_size, const gles2::EnableFeatureCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:188234 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:288235 if (!bucket || bucket->size() == 0) {
8236 return error::kInvalidArguments;
8237 }
[email protected]d4239852011-08-12 04:51:228238 typedef gles2::EnableFeatureCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:188239 Result* result = GetSharedMemoryAs<Result*>(
8240 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8241 if (!result) {
8242 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:108243 }
[email protected]b1d2dcb2010-05-17 19:24:188244 // Check that the client initialized the result.
8245 if (*result != 0) {
8246 return error::kInvalidArguments;
8247 }
8248 std::string feature_str;
8249 if (!bucket->GetAsString(&feature_str)) {
8250 return error::kInvalidArguments;
8251 }
8252
8253 // TODO(gman): make this some kind of table to function pointer thingy.
[email protected]d4239852011-08-12 04:51:228254 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
[email protected]b1d2dcb2010-05-17 19:24:188255 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]d4239852011-08-12 04:51:228256 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
[email protected]8fbedc02010-11-18 18:43:408257 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
8258 // TODO(gman): decide how to remove the need for this const_cast.
8259 // I could make validators_ non const but that seems bad as this is the only
8260 // place it is needed. I could make some special friend class of validators
8261 // just to allow this to set them. That seems silly. I could refactor this
8262 // code to use the extension mechanism or the initialization attributes to
8263 // turn this feature on. Given that the only real point of this is to make
8264 // the conformance tests pass and given that there is lots of real work that
8265 // needs to be done it seems like refactoring for one to one of those
8266 // methods is a very low priority.
8267 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]f0d74742011-10-03 16:31:048268 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
8269 force_webgl_glsl_validation_ = true;
8270 InitializeShaderTranslator();
[email protected]b1d2dcb2010-05-17 19:24:188271 } else {
8272 return error::kNoError;
8273 }
8274
8275 *result = 1; // true.
8276 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:108277}
8278
[email protected]c2f8c8402010-12-06 18:07:248279error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
8280 uint32 immediate_data_size,
8281 const gles2::GetRequestableExtensionsCHROMIUM& c) {
8282 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]80eb6b52012-01-19 00:14:418283 FeatureInfo::Ref info(new FeatureInfo());
[email protected]e82fb792011-09-22 00:33:298284 info->Initialize(disallowed_features_, NULL);
[email protected]c2f8c8402010-12-06 18:07:248285 bucket->SetFromString(info->extensions().c_str());
8286 return error::kNoError;
8287}
8288
8289error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
8290 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
8291 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:288292 if (!bucket || bucket->size() == 0) {
8293 return error::kInvalidArguments;
8294 }
[email protected]c2f8c8402010-12-06 18:07:248295 std::string feature_str;
8296 if (!bucket->GetAsString(&feature_str)) {
8297 return error::kInvalidArguments;
8298 }
8299
[email protected]62e155e2012-10-23 22:43:158300 bool std_derivatives_enabled = features().oes_standard_derivatives;
8301 bool webglsl_enabled = features().chromium_webglsl;
[email protected]c2f8c8402010-12-06 18:07:248302
8303 feature_info_->AddFeatures(feature_str.c_str());
8304
[email protected]f0d74742011-10-03 16:31:048305 bool initialization_required = false;
8306 if (force_webgl_glsl_validation_ && !derivatives_explicitly_enabled_) {
8307 size_t derivatives_offset = feature_str.find(kOESDerivativeExtension);
8308 if (std::string::npos != derivatives_offset) {
8309 derivatives_explicitly_enabled_ = true;
8310 initialization_required = true;
8311 }
8312 }
8313
[email protected]c2f8c8402010-12-06 18:07:248314 // If we just enabled a feature which affects the shader translator,
8315 // we may need to re-initialize it.
[email protected]62e155e2012-10-23 22:43:158316 if (std_derivatives_enabled != features().oes_standard_derivatives ||
8317 webglsl_enabled != features().chromium_webglsl ||
[email protected]f0d74742011-10-03 16:31:048318 initialization_required) {
[email protected]c2f8c8402010-12-06 18:07:248319 InitializeShaderTranslator();
8320 }
8321
[email protected]302ce6d2011-07-07 23:28:118322 UpdateCapabilities();
8323
[email protected]c2f8c8402010-12-06 18:07:248324 return error::kNoError;
8325}
8326
[email protected]372e0412011-06-28 16:08:568327error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
8328 uint32 immediate_data_size, const gles2::GetMultipleIntegervCHROMIUM& c) {
8329 GLuint count = c.count;
8330 uint32 pnames_size;
8331 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
8332 return error::kOutOfBounds;
8333 }
8334 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
8335 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
8336 if (pnames == NULL) {
8337 return error::kOutOfBounds;
8338 }
8339
8340 // We have to copy them since we use them twice so the client
8341 // can't change them between the time we validate them and the time we use
8342 // them.
8343 scoped_array<GLenum> enums(new GLenum[count]);
8344 memcpy(enums.get(), pnames, pnames_size);
8345
8346 // Count up the space needed for the result.
8347 uint32 num_results = 0;
8348 for (GLuint ii = 0; ii < count; ++ii) {
8349 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
8350 if (num == 0) {
[email protected]f80e6e12012-08-31 00:43:538351 SetGLErrorInvalidEnum("glGetMulitpleCHROMIUM", enums[ii], "pname");
[email protected]372e0412011-06-28 16:08:568352 return error::kNoError;
8353 }
8354 // Num will never be more than 4.
8355 DCHECK_LE(num, 4u);
[email protected]3aad1a32012-09-07 20:54:478356 if (!SafeAddUint32(num_results, num, &num_results)) {
[email protected]372e0412011-06-28 16:08:568357 return error::kOutOfBounds;
8358 }
8359 }
8360
8361 uint32 result_size = 0;
8362 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
8363 return error::kOutOfBounds;
8364 }
8365
8366 if (result_size != static_cast<uint32>(c.size)) {
8367 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438368 "glGetMulitpleCHROMIUM", "bad size GL_INVALID_VALUE");
[email protected]372e0412011-06-28 16:08:568369 return error::kNoError;
8370 }
8371
8372 GLint* results = GetSharedMemoryAs<GLint*>(
8373 c.results_shm_id, c.results_shm_offset, result_size);
8374 if (results == NULL) {
8375 return error::kOutOfBounds;
8376 }
8377
8378 // Check the results have been cleared in case the context was lost.
8379 for (uint32 ii = 0; ii < num_results; ++ii) {
8380 if (results[ii]) {
8381 return error::kInvalidArguments;
8382 }
8383 }
8384
8385 // Get each result.
8386 GLint* start = results;
8387 for (GLuint ii = 0; ii < count; ++ii) {
8388 GLsizei num_written = 0;
[email protected]d058bca2012-11-26 10:27:268389 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
[email protected]f63b1232012-10-31 07:03:538390 !GetHelper(enums[ii], results, &num_written)) {
[email protected]372e0412011-06-28 16:08:568391 glGetIntegerv(enums[ii], results);
8392 }
8393 results += num_written;
8394 }
8395
8396 // Just to verify. Should this be a DCHECK?
8397 if (static_cast<uint32>(results - start) != num_results) {
8398 return error::kOutOfBounds;
8399 }
8400
8401 return error::kNoError;
8402}
8403
[email protected]2318d342011-07-11 22:27:428404error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
8405 uint32 immediate_data_size, const gles2::GetProgramInfoCHROMIUM& c) {
8406 GLuint program = static_cast<GLuint>(c.program);
8407 uint32 bucket_id = c.bucket_id;
8408 Bucket* bucket = CreateBucket(bucket_id);
8409 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
8410 ProgramManager::ProgramInfo* info = NULL;
[email protected]9a14ae612011-08-08 17:51:468411 info = GetProgramInfo(program);
8412 if (!info || !info->IsValid()) {
8413 return error::kNoError;
[email protected]2318d342011-07-11 22:27:428414 }
[email protected]5d4c6b22012-02-07 08:22:288415 info->GetProgramInfo(program_manager(), bucket);
[email protected]2318d342011-07-11 22:27:428416 return error::kNoError;
8417}
8418
[email protected]38d139d2011-07-14 00:38:438419error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
8420 switch (reset_status_) {
[email protected]ad84a3a2012-06-08 21:42:438421 case GL_NO_ERROR:
8422 // TODO(kbr): improve the precision of the error code in this case.
8423 // Consider delegating to context for error code if MakeCurrent fails.
8424 return error::kUnknown;
8425 case GL_GUILTY_CONTEXT_RESET_ARB:
8426 return error::kGuilty;
8427 case GL_INNOCENT_CONTEXT_RESET_ARB:
8428 return error::kInnocent;
8429 case GL_UNKNOWN_CONTEXT_RESET_ARB:
8430 return error::kUnknown;
[email protected]38d139d2011-07-14 00:38:438431 }
8432
8433 NOTREACHED();
8434 return error::kUnknown;
8435}
8436
8437bool GLES2DecoderImpl::WasContextLost() {
[email protected]706b69f2012-07-27 04:59:308438 if (context_->WasAllocatedUsingRobustnessExtension()) {
8439 GLenum status = GL_NO_ERROR;
8440 if (has_robustness_extension_)
8441 status = glGetGraphicsResetStatusARB();
[email protected]38d139d2011-07-14 00:38:438442 if (status != GL_NO_ERROR) {
8443 // The graphics card was reset. Signal a lost context to the application.
8444 reset_status_ = status;
8445 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
[email protected]706b69f2012-07-27 04:59:308446 << " context lost via ARB/EXT_robustness. Reset status = 0x"
[email protected]38d139d2011-07-14 00:38:438447 << std::hex << status << std::dec;
8448 return true;
8449 }
8450 }
8451 return false;
8452}
8453
[email protected]882ba1e22012-03-08 19:02:538454bool GLES2DecoderImpl::GenQueriesEXTHelper(
8455 GLsizei n, const GLuint* client_ids) {
8456 for (GLsizei ii = 0; ii < n; ++ii) {
8457 if (query_manager_->GetQuery(client_ids[ii])) {
8458 return false;
8459 }
8460 }
[email protected]c45f1972012-03-14 07:27:368461 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
[email protected]882ba1e22012-03-08 19:02:538462 return true;
8463}
8464
8465void GLES2DecoderImpl::DeleteQueriesEXTHelper(
8466 GLsizei n, const GLuint* client_ids) {
8467 for (GLsizei ii = 0; ii < n; ++ii) {
8468 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
8469 if (query && !query->IsDeleted()) {
[email protected]e259eb412012-10-13 05:47:248470 if (query == state_.current_query) {
8471 state_.current_query = NULL;
[email protected]882ba1e22012-03-08 19:02:538472 }
[email protected]c45f1972012-03-14 07:27:368473 query->Destroy(true);
[email protected]882ba1e22012-03-08 19:02:538474 query_manager_->RemoveQuery(client_ids[ii]);
8475 }
8476 }
8477}
8478
[email protected]22e3f552012-03-13 01:54:198479bool GLES2DecoderImpl::ProcessPendingQueries() {
8480 if (query_manager_.get() == NULL) {
8481 return false;
8482 }
[email protected]c45f1972012-03-14 07:27:368483 if (!query_manager_->ProcessPendingQueries()) {
[email protected]22e3f552012-03-13 01:54:198484 current_decoder_error_ = error::kOutOfBounds;
8485 }
8486 return query_manager_->HavePendingQueries();
8487}
8488
[email protected]882ba1e22012-03-08 19:02:538489error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
8490 uint32 immediate_data_size, const gles2::BeginQueryEXT& c) {
8491 GLenum target = static_cast<GLenum>(c.target);
8492 GLuint client_id = static_cast<GLuint>(c.id);
8493 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
8494 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
8495
[email protected]c45f1972012-03-14 07:27:368496 switch (target) {
8497 case GL_COMMANDS_ISSUED_CHROMIUM:
[email protected]fb4bf5822012-10-23 21:25:558498 case GL_LATENCY_QUERY_CHROMIUM:
[email protected]c45f1972012-03-14 07:27:368499 break;
8500 default:
[email protected]62e155e2012-10-23 22:43:158501 if (!features().occlusion_query_boolean) {
[email protected]ad84a3a2012-06-08 21:42:438502 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT", "not enabled");
[email protected]c45f1972012-03-14 07:27:368503 return error::kNoError;
8504 }
8505 break;
[email protected]882ba1e22012-03-08 19:02:538506 }
8507
[email protected]e259eb412012-10-13 05:47:248508 if (state_.current_query) {
[email protected]882ba1e22012-03-08 19:02:538509 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:438510 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
[email protected]882ba1e22012-03-08 19:02:538511 return error::kNoError;
8512 }
8513
8514 if (client_id == 0) {
[email protected]ad84a3a2012-06-08 21:42:438515 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
[email protected]882ba1e22012-03-08 19:02:538516 return error::kNoError;
8517 }
8518
8519 QueryManager::Query* query = query_manager_->GetQuery(client_id);
8520 if (!query) {
[email protected]c45f1972012-03-14 07:27:368521 // TODO(gman): Decide if we need this check.
8522 //
[email protected]882ba1e22012-03-08 19:02:538523 // Checks id was made by glGenQueries
[email protected]c45f1972012-03-14 07:27:368524 //
8525 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
8526 // for all Query ids but from the POV of the command buffer service maybe
8527 // you don't.
8528 //
8529 // The client can enforce this. I don't think the service cares.
8530 //
8531 // IdAllocatorInterface* id_allocator =
8532 // group_->GetIdAllocator(id_namespaces::kQueries);
8533 // if (!id_allocator->InUse(client_id)) {
8534 // SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438535 // "glBeginQueryEXT", "id not made by glGenQueriesEXT");
[email protected]c45f1972012-03-14 07:27:368536 // return error::kNoError;
8537 // }
8538 query = query_manager_->CreateQuery(
8539 target, client_id, sync_shm_id, sync_shm_offset);
[email protected]882ba1e22012-03-08 19:02:538540 }
8541
[email protected]c45f1972012-03-14 07:27:368542 if (query->target() != target) {
[email protected]ad84a3a2012-06-08 21:42:438543 SetGLError(
8544 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
[email protected]882ba1e22012-03-08 19:02:538545 return error::kNoError;
8546 } else if (query->shm_id() != sync_shm_id ||
8547 query->shm_offset() != sync_shm_offset) {
8548 DLOG(ERROR) << "Shared memory used by query not the same as before";
8549 return error::kInvalidArguments;
8550 }
8551
[email protected]c45f1972012-03-14 07:27:368552 if (!query_manager_->BeginQuery(query)) {
8553 return error::kOutOfBounds;
8554 }
[email protected]882ba1e22012-03-08 19:02:538555
[email protected]e259eb412012-10-13 05:47:248556 state_.current_query = query;
[email protected]882ba1e22012-03-08 19:02:538557 return error::kNoError;
8558}
8559
8560error::Error GLES2DecoderImpl::HandleEndQueryEXT(
8561 uint32 immediate_data_size, const gles2::EndQueryEXT& c) {
8562 GLenum target = static_cast<GLenum>(c.target);
8563 uint32 submit_count = static_cast<GLuint>(c.submit_count);
8564
[email protected]e259eb412012-10-13 05:47:248565 if (!state_.current_query) {
[email protected]ad84a3a2012-06-08 21:42:438566 SetGLError(GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
[email protected]882ba1e22012-03-08 19:02:538567 return error::kNoError;
8568 }
[email protected]e259eb412012-10-13 05:47:248569 if (state_.current_query->target() != target) {
[email protected]882ba1e22012-03-08 19:02:538570 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438571 "glEndQueryEXT", "target does not match active query");
[email protected]882ba1e22012-03-08 19:02:538572 return error::kNoError;
8573 }
[email protected]882ba1e22012-03-08 19:02:538574
[email protected]e259eb412012-10-13 05:47:248575 if (!query_manager_->EndQuery(state_.current_query, submit_count)) {
[email protected]c45f1972012-03-14 07:27:368576 return error::kOutOfBounds;
8577 }
8578
[email protected]e259eb412012-10-13 05:47:248579 state_.current_query = NULL;
[email protected]882ba1e22012-03-08 19:02:538580 return error::kNoError;
8581}
8582
[email protected]944b62f32012-09-27 02:20:468583bool GLES2DecoderImpl::GenVertexArraysOESHelper(
8584 GLsizei n, const GLuint* client_ids) {
[email protected]944b62f32012-09-27 02:20:468585 for (GLsizei ii = 0; ii < n; ++ii) {
8586 if (GetVertexAttribManager(client_ids[ii])) {
8587 return false;
8588 }
8589 }
[email protected]ab4fd7282012-10-12 16:25:578590
[email protected]62e155e2012-10-23 22:43:158591 if (!features().native_vertex_array_object) {
[email protected]ab4fd7282012-10-12 16:25:578592 // Emulated VAO
8593 for (GLsizei ii = 0; ii < n; ++ii) {
8594 CreateVertexAttribManager(client_ids[ii], 0);
8595 }
8596 } else {
8597 scoped_array<GLuint> service_ids(new GLuint[n]);
8598
8599 glGenVertexArraysOES(n, service_ids.get());
8600 for (GLsizei ii = 0; ii < n; ++ii) {
8601 CreateVertexAttribManager(client_ids[ii], service_ids[ii]);
8602 }
[email protected]944b62f32012-09-27 02:20:468603 }
[email protected]ab4fd7282012-10-12 16:25:578604
[email protected]944b62f32012-09-27 02:20:468605 return true;
8606}
8607
8608void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
8609 GLsizei n, const GLuint* client_ids) {
[email protected]944b62f32012-09-27 02:20:468610 for (GLsizei ii = 0; ii < n; ++ii) {
8611 VertexAttribManager* vao =
8612 GetVertexAttribManager(client_ids[ii]);
8613 if (vao && !vao->IsDeleted()) {
[email protected]e259eb412012-10-13 05:47:248614 if (state_.vertex_attrib_manager == vao) {
8615 state_.vertex_attrib_manager = default_vertex_attrib_manager_;
[email protected]944b62f32012-09-27 02:20:468616 }
8617 RemoveVertexAttribManager(client_ids[ii]);
8618 }
8619 }
8620}
8621
8622void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
[email protected]944b62f32012-09-27 02:20:468623 VertexAttribManager* vao = NULL;
8624 GLuint service_id = 0;
8625 if (client_id != 0) {
8626 vao = GetVertexAttribManager(client_id);
8627 if (!vao) {
8628 // Unlike most Bind* methods, the spec explicitly states that VertexArray
8629 // only allows names that have been previously generated. As such, we do
8630 // not generate new names here.
8631 SetGLError(GL_INVALID_OPERATION,
8632 "glBindVertexArrayOES", ""
8633 "bad vertex array id.");
8634 current_decoder_error_ = error::kNoError;
8635 return;
8636 } else {
8637 service_id = vao->service_id();
8638 }
[email protected]944b62f32012-09-27 02:20:468639 } else {
[email protected]ab4fd7282012-10-12 16:25:578640 vao = default_vertex_attrib_manager_;
[email protected]944b62f32012-09-27 02:20:468641 }
8642
[email protected]ab4fd7282012-10-12 16:25:578643 // Only set the VAO state if it's changed
[email protected]e259eb412012-10-13 05:47:248644 if (state_.vertex_attrib_manager != vao) {
8645 state_.vertex_attrib_manager = vao;
[email protected]62e155e2012-10-23 22:43:158646 if (!features().native_vertex_array_object) {
[email protected]ab4fd7282012-10-12 16:25:578647 EmulateVertexArrayState();
8648 } else {
8649 glBindVertexArrayOES(service_id);
8650 }
8651 }
8652}
8653
8654// Used when OES_vertex_array_object isn't natively supported
8655void GLES2DecoderImpl::EmulateVertexArrayState() {
8656 // Setup the Vertex attribute state
8657 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
8658 RestoreStateForAttrib(vv);
8659 }
8660
8661 // Setup the element buffer
8662 BufferManager::BufferInfo* element_array_buffer =
[email protected]e259eb412012-10-13 05:47:248663 state_.vertex_attrib_manager->element_array_buffer();
[email protected]ab4fd7282012-10-12 16:25:578664 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
8665 element_array_buffer ? element_array_buffer->service_id() : 0);
[email protected]944b62f32012-09-27 02:20:468666}
8667
8668bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
[email protected]944b62f32012-09-27 02:20:468669 const VertexAttribManager* vao =
8670 GetVertexAttribManager(client_id);
8671 return vao && vao->IsValid() && !vao->IsDeleted();
8672}
8673
[email protected]b0af4f52011-09-28 22:04:428674error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
8675 uint32 immediate_data_size,
8676 const gles2::CreateStreamTextureCHROMIUM& c) {
[email protected]62e155e2012-10-23 22:43:158677 if (!features().chromium_stream_texture) {
[email protected]b0af4f52011-09-28 22:04:428678 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438679 "glOpenStreamTextureCHROMIUM", ""
[email protected]b0af4f52011-09-28 22:04:428680 "not supported.");
8681 return error::kNoError;
8682 }
8683
8684 uint32 client_id = c.client_id;
8685 typedef gles2::CreateStreamTextureCHROMIUM::Result Result;
8686 Result* result = GetSharedMemoryAs<Result*>(
8687 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8688
[email protected]e5081262012-01-05 23:09:038689 if (!result)
8690 return error::kOutOfBounds;
[email protected]b0af4f52011-09-28 22:04:428691 *result = GL_ZERO;
8692 TextureManager::TextureInfo* info =
8693 texture_manager()->GetTextureInfo(client_id);
8694 if (!info) {
8695 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438696 "glCreateStreamTextureCHROMIUM", ""
[email protected]b0af4f52011-09-28 22:04:428697 "bad texture id.");
8698 return error::kNoError;
8699 }
8700
8701 if (info->IsStreamTexture()) {
8702 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438703 "glCreateStreamTextureCHROMIUM", ""
[email protected]b0af4f52011-09-28 22:04:428704 "is already a stream texture.");
8705 return error::kNoError;
8706 }
8707
8708 if (info->target() && info->target() != GL_TEXTURE_EXTERNAL_OES) {
8709 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438710 "glCreateStreamTextureCHROMIUM", ""
[email protected]b0af4f52011-09-28 22:04:428711 "is already bound to incompatible target.");
8712 return error::kNoError;
8713 }
8714
8715 if (!stream_texture_manager_)
8716 return error::kInvalidArguments;
8717
8718 GLuint object_id = stream_texture_manager_->CreateStreamTexture(
8719 info->service_id(), client_id);
8720
8721 if (object_id) {
8722 info->SetStreamTexture(true);
8723 } else {
8724 SetGLError(GL_OUT_OF_MEMORY,
[email protected]ad84a3a2012-06-08 21:42:438725 "glCreateStreamTextureCHROMIUM", ""
[email protected]b0af4f52011-09-28 22:04:428726 "failed to create platform texture.");
8727 }
8728
8729 *result = object_id;
8730 return error::kNoError;
8731}
8732
8733error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
8734 uint32 immediate_data_size,
8735 const gles2::DestroyStreamTextureCHROMIUM& c) {
8736 GLuint client_id = c.texture;
8737 TextureManager::TextureInfo* info =
8738 texture_manager()->GetTextureInfo(client_id);
8739 if (info && info->IsStreamTexture()) {
8740 if (!stream_texture_manager_)
8741 return error::kInvalidArguments;
8742
8743 stream_texture_manager_->DestroyStreamTexture(info->service_id());
8744 info->SetStreamTexture(false);
[email protected]80eb6b52012-01-19 00:14:418745 texture_manager()->SetInfoTarget(info, 0);
[email protected]b0af4f52011-09-28 22:04:428746 } else {
8747 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438748 "glDestroyStreamTextureCHROMIUM", "bad texture id.");
[email protected]b0af4f52011-09-28 22:04:428749 }
8750
8751 return error::kNoError;
8752}
8753
[email protected]e51bdf32011-11-23 22:21:468754#if defined(OS_MACOSX)
8755void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
8756 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
8757 texture_id);
8758 if (it != texture_to_io_surface_map_.end()) {
8759 // Found a previous IOSurface bound to this texture; release it.
8760 CFTypeRef surface = it->second;
8761 CFRelease(surface);
8762 texture_to_io_surface_map_.erase(it);
8763 }
8764}
8765#endif
8766
8767void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
8768 GLenum target, GLsizei width, GLsizei height,
8769 GLuint io_surface_id, GLuint plane) {
8770#if defined(OS_MACOSX)
8771 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
[email protected]ad84a3a2012-06-08 21:42:438772 SetGLError(
8773 GL_INVALID_OPERATION,
8774 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
[email protected]e51bdf32011-11-23 22:21:468775 return;
8776 }
8777
8778 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
8779 if (!surface_support) {
8780 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438781 "glTexImageIOSurface2DCHROMIUM", "only supported on 10.6.");
[email protected]e51bdf32011-11-23 22:21:468782 return;
8783 }
8784
8785 if (target != GL_TEXTURE_RECTANGLE_ARB) {
8786 // This might be supported in the future, and if we could require
8787 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
8788 // could delete a lot of code. For now, perform strict validation so we
8789 // know what's going on.
8790 SetGLError(
8791 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438792 "glTexImageIOSurface2DCHROMIUM",
8793 "requires TEXTURE_RECTANGLE_ARB target");
[email protected]e51bdf32011-11-23 22:21:468794 return;
8795 }
8796
[email protected]09d50362012-10-18 20:54:378797 // Default target might be conceptually valid, but disallow it to avoid
8798 // accidents.
8799 TextureManager::TextureInfo* info = GetTextureInfoForTargetUnlessDefault(
8800 target);
[email protected]e51bdf32011-11-23 22:21:468801 if (!info) {
8802 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438803 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
[email protected]e51bdf32011-11-23 22:21:468804 return;
8805 }
[email protected]e51bdf32011-11-23 22:21:468806
8807 // Look up the new IOSurface. Note that because of asynchrony
8808 // between processes this might fail; during live resizing the
8809 // plugin process might allocate and release an IOSurface before
8810 // this process gets a chance to look it up. Hold on to any old
8811 // IOSurface in this case.
8812 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
8813 if (!surface) {
[email protected]ad84a3a2012-06-08 21:42:438814 SetGLError(
8815 GL_INVALID_OPERATION,
8816 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
[email protected]e51bdf32011-11-23 22:21:468817 return;
8818 }
8819
8820 // Release any IOSurface previously bound to this texture.
8821 ReleaseIOSurfaceForTexture(info->service_id());
8822
8823 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
8824 texture_to_io_surface_map_.insert(
8825 std::make_pair(info->service_id(), surface));
8826
8827 CGLContextObj context =
8828 static_cast<CGLContextObj>(context_->GetHandle());
8829
8830 CGLError err = surface_support->CGLTexImageIOSurface2D(
8831 context,
8832 target,
8833 GL_RGBA,
8834 width,
8835 height,
8836 GL_BGRA,
8837 GL_UNSIGNED_INT_8_8_8_8_REV,
8838 surface,
8839 plane);
8840
8841 if (err != kCGLNoError) {
8842 SetGLError(
8843 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438844 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
[email protected]e51bdf32011-11-23 22:21:468845 return;
8846 }
8847
8848 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:418849 info, target, 0, GL_RGBA, width, height, 1, 0,
[email protected]e51bdf32011-11-23 22:21:468850 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
8851
8852#else
8853 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438854 "glTexImageIOSurface2DCHROMIUM", "not supported.");
[email protected]e51bdf32011-11-23 22:21:468855#endif
8856}
8857
[email protected]97dc7cbe2011-12-06 17:26:178858static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
8859 switch (internalformat) {
8860 case GL_RGB565:
8861 return GL_RGB;
8862 case GL_RGBA4:
8863 return GL_RGBA;
8864 case GL_RGB5_A1:
8865 return GL_RGBA;
8866 case GL_RGB8_OES:
8867 return GL_RGB;
8868 case GL_RGBA8_OES:
8869 return GL_RGBA;
8870 case GL_LUMINANCE8_ALPHA8_EXT:
8871 return GL_LUMINANCE_ALPHA;
8872 case GL_LUMINANCE8_EXT:
8873 return GL_LUMINANCE;
8874 case GL_ALPHA8_EXT:
8875 return GL_ALPHA;
8876 case GL_RGBA32F_EXT:
8877 return GL_RGBA;
8878 case GL_RGB32F_EXT:
8879 return GL_RGB;
8880 case GL_ALPHA32F_EXT:
8881 return GL_ALPHA;
8882 case GL_LUMINANCE32F_EXT:
8883 return GL_LUMINANCE;
8884 case GL_LUMINANCE_ALPHA32F_EXT:
8885 return GL_LUMINANCE_ALPHA;
8886 case GL_RGBA16F_EXT:
8887 return GL_RGBA;
8888 case GL_RGB16F_EXT:
8889 return GL_RGB;
8890 case GL_ALPHA16F_EXT:
8891 return GL_ALPHA;
8892 case GL_LUMINANCE16F_EXT:
8893 return GL_LUMINANCE;
8894 case GL_LUMINANCE_ALPHA16F_EXT:
8895 return GL_LUMINANCE_ALPHA;
8896 case GL_BGRA8_EXT:
8897 return GL_BGRA_EXT;
8898 default:
8899 return GL_NONE;
8900 }
8901}
8902
[email protected]43410e92012-04-20 17:06:288903void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
[email protected]0a1e9ad2012-05-04 21:13:038904 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
8905 GLenum internal_format) {
[email protected]43410e92012-04-20 17:06:288906 TextureManager::TextureInfo* dest_info = GetTextureInfo(dest_id);
8907 TextureManager::TextureInfo* source_info = GetTextureInfo(source_id);
8908
8909 if (!source_info || !dest_info) {
[email protected]ad84a3a2012-06-08 21:42:438910 SetGLError(GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
[email protected]43410e92012-04-20 17:06:288911 return;
8912 }
8913
8914 if (GL_TEXTURE_2D != target) {
8915 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438916 "glCopyTextureCHROMIUM", "invalid texture target");
[email protected]43410e92012-04-20 17:06:288917 return;
8918 }
8919
[email protected]0a1e9ad2012-05-04 21:13:038920 if (dest_info->target() != GL_TEXTURE_2D ||
8921 source_info->target() != GL_TEXTURE_2D) {
8922 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438923 "glCopyTextureCHROMIUM", "invalid texture target binding");
[email protected]0a1e9ad2012-05-04 21:13:038924 return;
8925 }
8926
[email protected]43410e92012-04-20 17:06:288927 int source_width, source_height, dest_width, dest_height;
8928 if (!source_info->GetLevelSize(GL_TEXTURE_2D, 0, &source_width,
8929 &source_height)) {
8930 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438931 "glCopyTextureChromium", "source texture has no level 0");
[email protected]43410e92012-04-20 17:06:288932 return;
8933 }
8934
[email protected]43410e92012-04-20 17:06:288935 // Check that this type of texture is allowed.
8936 if (!texture_manager()->ValidForTarget(GL_TEXTURE_2D, level, source_width,
8937 source_height, 1)) {
8938 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438939 "glCopyTextureCHROMIUM", "Bad dimensions");
[email protected]43410e92012-04-20 17:06:288940 return;
8941 }
8942
[email protected]cf6b8f62012-05-25 21:43:378943 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
8944 // needed because it takes 10s of milliseconds to initialize.
8945 if (!copy_texture_CHROMIUM_.get()) {
8946 CopyRealGLErrorsToWrapper();
8947 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
8948 copy_texture_CHROMIUM_->Initialize();
8949 RestoreCurrentFramebufferBindings();
8950 if (PeekGLError() != GL_NO_ERROR)
8951 return;
8952 }
8953
[email protected]0a1e9ad2012-05-04 21:13:038954 GLenum dest_type;
8955 GLenum dest_internal_format;
8956 bool dest_level_defined = dest_info->GetLevelSize(GL_TEXTURE_2D, level,
8957 &dest_width,
8958 &dest_height);
[email protected]43410e92012-04-20 17:06:288959
[email protected]0a1e9ad2012-05-04 21:13:038960 if (dest_level_defined) {
8961 dest_info->GetLevelType(GL_TEXTURE_2D, level, &dest_type,
8962 &dest_internal_format);
8963 } else {
8964 GLenum source_internal_format;
8965 source_info->GetLevelType(GL_TEXTURE_2D, 0, &dest_type,
8966 &source_internal_format);
8967 }
8968
8969 // Resize the destination texture to the dimensions of the source texture.
8970 if (!dest_level_defined || dest_width != source_width ||
8971 dest_height != source_height ||
8972 dest_internal_format != internal_format) {
[email protected]43410e92012-04-20 17:06:288973 // Ensure that the glTexImage2D succeeds.
8974 CopyRealGLErrorsToWrapper();
[email protected]0a1e9ad2012-05-04 21:13:038975 glBindTexture(GL_TEXTURE_2D, dest_info->service_id());
[email protected]43410e92012-04-20 17:06:288976 WrappedTexImage2D(
8977 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
[email protected]0a1e9ad2012-05-04 21:13:038978 0, internal_format, dest_type, NULL);
[email protected]43410e92012-04-20 17:06:288979 GLenum error = PeekGLError();
[email protected]0a1e9ad2012-05-04 21:13:038980 if (error != GL_NO_ERROR) {
8981 RestoreCurrentTexture2DBindings();
[email protected]43410e92012-04-20 17:06:288982 return;
[email protected]0a1e9ad2012-05-04 21:13:038983 }
[email protected]43410e92012-04-20 17:06:288984
8985 texture_manager()->SetLevelInfo(
8986 dest_info, GL_TEXTURE_2D, level, internal_format, source_width,
[email protected]0a1e9ad2012-05-04 21:13:038987 source_height, 1, 0, internal_format, dest_type, true);
[email protected]f7024712012-05-15 21:30:258988 } else {
8989 texture_manager()->SetLevelCleared(dest_info, GL_TEXTURE_2D, level);
[email protected]43410e92012-04-20 17:06:288990 }
8991
[email protected]88a61bf2012-10-27 13:00:428992 clear_state_dirty_ = true;
[email protected]0a1e9ad2012-05-04 21:13:038993 glViewport(0, 0, source_width, source_height);
[email protected]43410e92012-04-20 17:06:288994 copy_texture_CHROMIUM_->DoCopyTexture(target, source_info->service_id(),
8995 dest_info->service_id(), level,
8996 unpack_flip_y_,
[email protected]6c75c712012-06-19 15:43:178997 unpack_premultiply_alpha_,
8998 unpack_unpremultiply_alpha_);
[email protected]e259eb412012-10-13 05:47:248999 glViewport(
9000 state_.viewport_x, state_.viewport_y,
9001 state_.viewport_width, state_.viewport_height);
[email protected]43410e92012-04-20 17:06:289002
9003 // Restore all of the state touched by the extension.
[email protected]e259eb412012-10-13 05:47:249004 if (state_.current_program)
9005 glUseProgram(state_.current_program->service_id());
[email protected]43410e92012-04-20 17:06:289006 else
9007 glUseProgram(0);
9008
9009 RestoreCurrentFramebufferBindings();
9010 RestoreCurrentTexture2DBindings();
9011 RestoreStateForAttrib(
9012 CopyTextureCHROMIUMResourceManager::kVertexPositionAttrib);
9013 RestoreStateForAttrib(
9014 CopyTextureCHROMIUMResourceManager::kVertexTextureAttrib);
9015
9016 ApplyDirtyState();
9017}
9018
[email protected]97dc7cbe2011-12-06 17:26:179019static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
9020 switch (internalformat) {
9021 case GL_RGB565:
9022 return GL_UNSIGNED_SHORT_5_6_5;
9023 case GL_RGBA4:
9024 return GL_UNSIGNED_SHORT_4_4_4_4;
9025 case GL_RGB5_A1:
9026 return GL_UNSIGNED_SHORT_5_5_5_1;
9027 case GL_RGB8_OES:
9028 return GL_UNSIGNED_BYTE;
9029 case GL_RGBA8_OES:
9030 return GL_UNSIGNED_BYTE;
9031 case GL_LUMINANCE8_ALPHA8_EXT:
9032 return GL_UNSIGNED_BYTE;
9033 case GL_LUMINANCE8_EXT:
9034 return GL_UNSIGNED_BYTE;
9035 case GL_ALPHA8_EXT:
9036 return GL_UNSIGNED_BYTE;
9037 case GL_RGBA32F_EXT:
9038 return GL_FLOAT;
9039 case GL_RGB32F_EXT:
9040 return GL_FLOAT;
9041 case GL_ALPHA32F_EXT:
9042 return GL_FLOAT;
9043 case GL_LUMINANCE32F_EXT:
9044 return GL_FLOAT;
9045 case GL_LUMINANCE_ALPHA32F_EXT:
9046 return GL_FLOAT;
9047 case GL_RGBA16F_EXT:
9048 return GL_HALF_FLOAT_OES;
9049 case GL_RGB16F_EXT:
9050 return GL_HALF_FLOAT_OES;
9051 case GL_ALPHA16F_EXT:
9052 return GL_HALF_FLOAT_OES;
9053 case GL_LUMINANCE16F_EXT:
9054 return GL_HALF_FLOAT_OES;
9055 case GL_LUMINANCE_ALPHA16F_EXT:
9056 return GL_HALF_FLOAT_OES;
9057 case GL_BGRA8_EXT:
9058 return GL_UNSIGNED_BYTE;
9059 default:
9060 return GL_NONE;
9061 }
9062}
9063
9064void GLES2DecoderImpl::DoTexStorage2DEXT(
[email protected]a5d3dad2012-05-26 04:34:449065 GLenum target,
9066 GLint levels,
9067 GLenum internal_format,
9068 GLsizei width,
9069 GLsizei height) {
[email protected]43ed3a72012-05-30 22:55:389070 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
[email protected]80eb6b52012-01-19 00:14:419071 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
[email protected]97dc7cbe2011-12-06 17:26:179072 TextureManager::ComputeMipMapCount(width, height, 1) < levels) {
[email protected]ad84a3a2012-06-08 21:42:439073 SetGLError(
9074 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
[email protected]97dc7cbe2011-12-06 17:26:179075 return;
9076 }
9077 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
9078 if (!info) {
9079 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439080 "glTexStorage2DEXT", "unknown texture for target");
[email protected]97dc7cbe2011-12-06 17:26:179081 return;
9082 }
9083 if (info->IsAttachedToFramebuffer()) {
[email protected]88a61bf2012-10-27 13:00:429084 clear_state_dirty_ = true;
[email protected]97dc7cbe2011-12-06 17:26:179085 }
9086 if (info->IsImmutable()) {
9087 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439088 "glTexStorage2DEXT", "texture is immutable");
[email protected]97dc7cbe2011-12-06 17:26:179089 return;
9090 }
9091 CopyRealGLErrorsToWrapper();
[email protected]f0e6a34f2012-01-04 20:53:409092 glTexStorage2DEXT(target, levels, GetTexInternalFormat(internal_format),
9093 width, height);
[email protected]97dc7cbe2011-12-06 17:26:179094 GLenum error = PeekGLError();
9095 if (error == GL_NO_ERROR) {
9096 GLenum format = ExtractFormatFromStorageFormat(internal_format);
9097 GLenum type = ExtractTypeFromStorageFormat(internal_format);
[email protected]4502e6492011-12-14 19:39:159098 GLsizei level_width = width;
9099 GLsizei level_height = height;
9100 for (int ii = 0; ii < levels; ++ii) {
9101 texture_manager()->SetLevelInfo(
[email protected]e071ea72012-11-26 22:29:599102 info, target, ii, format, level_width, level_height, 1, 0, format,
[email protected]80eb6b52012-01-19 00:14:419103 type, false);
[email protected]4502e6492011-12-14 19:39:159104 level_width = std::max(1, level_width >> 1);
9105 level_height = std::max(1, level_height >> 1);
9106 }
[email protected]97dc7cbe2011-12-06 17:26:179107 info->SetImmutable(true);
9108 }
[email protected]97dc7cbe2011-12-06 17:26:179109}
[email protected]e51bdf32011-11-23 22:21:469110
[email protected]78b514b2012-05-01 21:50:599111error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
9112 uint32 immediate_data_size, const gles2::GenMailboxCHROMIUM& c) {
9113 MailboxName name;
9114 mailbox_manager()->GenerateMailboxName(&name);
9115 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
9116 Bucket* bucket = CreateBucket(bucket_id);
9117
9118 bucket->SetSize(GL_MAILBOX_SIZE_CHROMIUM);
9119 bucket->SetData(&name, 0, GL_MAILBOX_SIZE_CHROMIUM);
9120
9121 return error::kNoError;
9122}
9123
9124void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
9125 const GLbyte* mailbox) {
9126 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
9127 if (!info) {
9128 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439129 "glProduceTextureCHROMIUM", "unknown texture for target");
[email protected]78b514b2012-05-01 21:50:599130 return;
9131 }
9132
9133 TextureDefinition* definition = texture_manager()->Save(info);
9134 if (!definition) {
9135 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439136 "glProduceTextureCHROMIUM", "invalid texture");
[email protected]78b514b2012-05-01 21:50:599137 return;
9138 }
9139
9140 if (!group_->mailbox_manager()->ProduceTexture(
9141 target,
9142 *reinterpret_cast<const MailboxName*>(mailbox),
9143 definition,
9144 texture_manager())) {
9145 bool success = texture_manager()->Restore(info, definition);
9146 DCHECK(success);
9147 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439148 "glProduceTextureCHROMIUM", "invalid mailbox name");
[email protected]78b514b2012-05-01 21:50:599149 return;
9150 }
9151
9152 BindAndApplyTextureParameters(info);
9153}
9154
9155void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
9156 const GLbyte* mailbox) {
9157 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
9158 if (!info) {
9159 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439160 "glConsumeTextureCHROMIUM", "unknown texture for target");
[email protected]78b514b2012-05-01 21:50:599161 return;
9162 }
9163
9164 scoped_ptr<TextureDefinition> definition(
9165 group_->mailbox_manager()->ConsumeTexture(
9166 target,
9167 *reinterpret_cast<const MailboxName*>(mailbox)));
9168 if (!definition.get()) {
9169 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439170 "glConsumeTextureCHROMIUM", "invalid mailbox name");
[email protected]78b514b2012-05-01 21:50:599171 return;
9172 }
9173
9174 if (!texture_manager()->Restore(info, definition.release())) {
9175 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439176 "glConsumeTextureCHROMIUM", "invalid texture");
[email protected]78b514b2012-05-01 21:50:599177 return;
9178 }
9179
9180 BindAndApplyTextureParameters(info);
9181}
9182
[email protected]d2a0e1a2012-08-12 02:25:019183void GLES2DecoderImpl::DoInsertEventMarkerEXT(
9184 GLsizei length, const GLchar* marker) {
9185 if (!marker) {
9186 marker = "";
9187 }
9188 debug_marker_manager_.SetMarker(
9189 length ? std::string(marker, length) : std::string(marker));
9190}
9191
9192void GLES2DecoderImpl::DoPushGroupMarkerEXT(
9193 GLsizei length, const GLchar* marker) {
9194 if (!marker) {
9195 marker = "";
9196 }
9197 debug_marker_manager_.PushGroup(
9198 length ? std::string(marker, length) : std::string(marker));
9199}
9200
9201void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
9202 debug_marker_manager_.PopGroup();
9203}
9204
[email protected]09d50362012-10-18 20:54:379205void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
9206 GLenum target, GLint image_id) {
9207 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
9208 if (target != GL_TEXTURE_2D) {
9209 // This might be supported in the future.
9210 SetGLError(
9211 GL_INVALID_OPERATION,
9212 "glBindTexImage2DCHROMIUM", "requires TEXTURE_2D target");
9213 return;
9214 }
9215
9216 // Default target might be conceptually valid, but disallow it to avoid
9217 // accidents.
9218 TextureManager::TextureInfo* info = GetTextureInfoForTargetUnlessDefault(
9219 target);
9220 if (!info) {
9221 SetGLError(GL_INVALID_OPERATION,
9222 "glBindTexImage2DCHROMIUM", "no texture bound");
9223 return;
9224 }
9225
9226 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
9227 if (!gl_image) {
9228 SetGLError(GL_INVALID_OPERATION,
9229 "glBindTexImage2DCHROMIUM",
9230 "no image found with the given ID");
9231 return;
9232 }
9233
9234 if (!gl_image->BindTexImage()) {
9235 SetGLError(GL_INVALID_OPERATION,
9236 "glBindTexImage2DCHROMIUM",
9237 "fail to bind image with the given ID");
9238 return;
9239 }
9240
9241 gfx::Size size = gl_image->GetSize();
9242 texture_manager()->SetLevelInfo(
9243 info, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
9244 GL_RGBA, GL_UNSIGNED_BYTE, true);
9245 texture_manager()->SetLevelImage(info, target, 0, gl_image);
9246}
9247
9248void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
9249 GLenum target, GLint image_id) {
9250 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
9251 if (target != GL_TEXTURE_2D) {
9252 // This might be supported in the future.
9253 SetGLError(
9254 GL_INVALID_OPERATION,
9255 "glReleaseTexImage2DCHROMIUM", "requires TEXTURE_2D target");
9256 return;
9257 }
9258
9259 // Default target might be conceptually valid, but disallow it to avoid
9260 // accidents.
9261 TextureManager::TextureInfo* info = GetTextureInfoForTargetUnlessDefault(
9262 target);
9263 if (!info) {
9264 SetGLError(GL_INVALID_OPERATION,
9265 "glReleaseTexImage2DCHROMIUM", "no texture bound");
9266 return;
9267 }
9268
9269 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
9270 if (!gl_image) {
9271 SetGLError(GL_INVALID_OPERATION,
9272 "glReleaseTexImage2DCHROMIUM",
9273 "no image found with the given ID");
9274 return;
9275 }
9276
9277 // Do nothing when image is not currently bound.
9278 if (info->GetLevelImage(target, 0) != gl_image)
9279 return;
9280
9281 gl_image->ReleaseTexImage();
9282
9283 texture_manager()->SetLevelInfo(
9284 info, target, 0, GL_RGBA, 0, 0, 1, 0,
9285 GL_RGBA, GL_UNSIGNED_BYTE, false);
9286}
[email protected]d2a0e1a2012-08-12 02:25:019287
[email protected]94307712012-11-16 23:26:119288error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
9289 uint32 immediate_data_size, const gles2::TraceBeginCHROMIUM& c) {
9290 Bucket* bucket = GetBucket(c.bucket_id);
9291 if (!bucket || bucket->size() == 0) {
9292 return error::kInvalidArguments;
9293 }
9294 std::string command_name;
9295 if (!bucket->GetAsString(&command_name)) {
9296 return error::kInvalidArguments;
9297 }
9298
9299 linked_ptr<GPUTrace> trace(new GPUTrace(command_name));
9300 trace->EnableStartTrace();
9301 gpu_trace_stack_.push(trace);
9302
9303 return error::kNoError;
9304}
9305
9306void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
9307 if (gpu_trace_stack_.empty()) {
9308 SetGLError(GL_INVALID_OPERATION,
9309 "glTraceEndCHROMIUM", "no trace begin found");
9310 return;
9311 }
9312
9313 linked_ptr<GPUTrace> trace = gpu_trace_stack_.top();
9314 trace->EnableEndTrace();
9315 gpu_trace_stack_.pop();
9316}
9317
[email protected]96449d2c2009-11-25 00:01:329318// Include the auto-generated part of this file. We split this because it means
9319// we can easily edit the non-auto generated parts right here in this file
9320// instead of having to edit some template or the code generator.
9321#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
9322
9323} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:259324} // namespace gpu