blob: 8539dcd8da6169ba75e8131f9e0bc002312769c0 [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]f39f4b3f2010-05-12 17:04:0812#include <string>
13#include <vector>
[email protected]5a6db6c2010-04-22 18:32:0614
[email protected]1e6f58d2011-03-24 00:00:4015#include "base/atomicops.h"
[email protected]00eb49a2010-08-12 20:46:5716#include "base/at_exit.h"
[email protected]9d37f062011-11-22 01:24:5217#include "base/bind.h"
[email protected]e844ae22012-01-14 03:36:2618#include "base/command_line.h"
[email protected]1078f912011-12-23 13:12:1419#include "base/debug/trace_event.h"
[email protected]e51bdf32011-11-23 22:21:4620#if defined(OS_MACOSX)
21#include "base/mac/scoped_cftyperef.h"
22#endif
[email protected]3b63f8f42011-03-28 01:54:1523#include "base/memory/scoped_ptr.h"
24#include "base/memory/weak_ptr.h"
[email protected]d37231fa2010-04-09 21:16:0225#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3226#define GLES2_GPU_SERVICE 1
27#include "gpu/command_buffer/common/gles2_cmd_format.h"
28#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1029#include "gpu/command_buffer/common/id_allocator.h"
[email protected]3916c97e2010-02-25 03:20:5030#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3231#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5032#include "gpu/command_buffer/service/context_group.h"
[email protected]915a59a12010-09-30 21:29:1133#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5834#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3235#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4636#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]e844ae22012-01-14 03:36:2637#include "gpu/command_buffer/service/gpu_switches.h"
[email protected]a93bb842010-02-16 23:03:4738#include "gpu/command_buffer/service/program_manager.h"
[email protected]a25fa872010-03-25 02:57:5839#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4740#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4541#include "gpu/command_buffer/service/shader_translator.h"
[email protected]b0af4f52011-09-28 22:04:4242#include "gpu/command_buffer/service/stream_texture.h"
43#include "gpu/command_buffer/service/stream_texture_manager.h"
[email protected]a93bb842010-02-16 23:03:4744#include "gpu/command_buffer/service/texture_manager.h"
[email protected]d8ea9772011-07-11 18:11:4345#include "gpu/command_buffer/service/vertex_attrib_manager.h"
[email protected]5ae0b282011-03-28 19:24:4946#include "ui/gfx/gl/gl_context.h"
47#include "ui/gfx/gl/gl_implementation.h"
[email protected]f62a5ab2011-05-23 20:34:1548#include "ui/gfx/gl/gl_surface.h"
[email protected]e51bdf32011-11-23 22:21:4649#if defined(OS_MACOSX)
50#include "ui/gfx/surface/io_surface_support_mac.h"
51#endif
[email protected]de17df392010-04-23 21:09:4152
[email protected]6217d392010-03-25 22:08:3553#if !defined(GL_DEPTH24_STENCIL8)
54#define GL_DEPTH24_STENCIL8 0x88F0
55#endif
56
[email protected]a7a27ace2009-12-12 00:11:2557namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3258namespace gles2 {
59
[email protected]f0d74742011-10-03 16:31:0460namespace {
61static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
62}
63
[email protected]6217d392010-03-25 22:08:3564class GLES2DecoderImpl;
65
[email protected]07f54fcc2009-12-22 02:46:3066// Check that certain assumptions the code makes are true. There are places in
67// the code where shared memory is passed direclty to GL. Example, glUniformiv,
68// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
69// a few others) are 32bits. If they are not 32bits the code will have to change
70// to call those GL functions with service side memory and then copy the results
71// to shared memory, converting the sizes.
72COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
73 GLint_not_same_size_as_uint32);
74COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
75 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3776COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
77 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3078
[email protected]43f28f832010-02-03 02:28:4879// TODO(kbr): the use of this anonymous namespace core dumps the
80// linker on Mac OS X 10.6 when the symbol ordering file is used
81// namespace {
[email protected]96449d2c2009-11-25 00:01:3282
83// Returns the address of the first byte after a struct.
84template <typename T>
85const void* AddressAfterStruct(const T& pod) {
86 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
87}
88
[email protected]07f54fcc2009-12-22 02:46:3089// Returns the address of the frst byte after the struct or NULL if size >
90// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3291template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3092RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
93 uint32 size,
94 uint32 immediate_data_size) {
95 return (size <= immediate_data_size) ?
96 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
97 NULL;
[email protected]96449d2c2009-11-25 00:01:3298}
99
[email protected]07f54fcc2009-12-22 02:46:30100// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:18101bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:32102 GLuint count,
103 size_t size,
[email protected]a76b0052010-03-05 00:33:18104 unsigned int elements_per_unit,
105 uint32* dst) {
106 uint32 value;
107 if (!SafeMultiplyUint32(count, size, &value)) {
108 return false;
109 }
110 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
111 return false;
112 }
113 *dst = value;
114 return true;
[email protected]96449d2c2009-11-25 00:01:32115}
116
117// A struct to hold info about each command.
118struct CommandInfo {
119 int arg_flags; // How to handle the arguments for this command
120 int arg_count; // How many arguments are expected for this command.
121};
122
123// A table of CommandInfo for all the commands.
124const CommandInfo g_command_info[] = {
125 #define GLES2_CMD_OP(name) { \
126 name::kArgFlags, \
127 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
128
129 GLES2_COMMAND_LIST(GLES2_CMD_OP)
130
131 #undef GLES2_CMD_OP
132};
133
[email protected]258a3313f2011-10-18 20:13:57134// Return true if a character belongs to the ASCII subset as defined in
135// GLSL ES 1.0 spec section 3.1.
136static bool CharacterIsValidForGLES(unsigned char c) {
137 // Printing characters are valid except " $ ` @ \ ' DEL.
138 if (c >= 32 && c <= 126 &&
139 c != '"' &&
140 c != '$' &&
141 c != '`' &&
142 c != '@' &&
143 c != '\\' &&
144 c != '\'') {
145 return true;
146 }
147 // Horizontal tab, line feed, vertical tab, form feed, carriage return
148 // are also valid.
149 if (c >= 9 && c <= 13) {
150 return true;
151 }
152
153 return false;
154}
155
156static bool StringIsValidForGLES(const char* str) {
157 for (; *str; ++str) {
158 if (!CharacterIsValidForGLES(*str)) {
159 return false;
160 }
161 }
162 return true;
163}
164
[email protected]f0e6a34f2012-01-04 20:53:40165static inline GLenum GetTexInternalFormat(GLenum internal_format) {
166 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
167 if (internal_format == GL_BGRA_EXT || internal_format == GL_BGRA8_EXT)
168 return GL_RGBA8;
169 }
170 return internal_format;
171}
172
[email protected]297ca1c2011-06-20 23:08:46173static void WrappedTexImage2D(
[email protected]473c01ccb2011-06-07 01:33:30174 GLenum target,
175 GLint level,
176 GLenum internal_format,
177 GLsizei width,
178 GLsizei height,
179 GLint border,
180 GLenum format,
181 GLenum type,
182 const void* pixels) {
[email protected]f0e6a34f2012-01-04 20:53:40183 GLenum gl_internal_format = GetTexInternalFormat(internal_format);
[email protected]473c01ccb2011-06-07 01:33:30184 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]f0e6a34f2012-01-04 20:53:40185 if (type == GL_FLOAT) {
[email protected]473c01ccb2011-06-07 01:33:30186 if (format == GL_RGBA) {
187 gl_internal_format = GL_RGBA32F_ARB;
188 } else if (format == GL_RGB) {
189 gl_internal_format = GL_RGB32F_ARB;
190 }
191 } else if (type == GL_HALF_FLOAT_OES) {
192 if (format == GL_RGBA) {
193 gl_internal_format = GL_RGBA16F_ARB;
194 } else if (format == GL_RGB) {
195 gl_internal_format = GL_RGB16F_ARB;
196 }
197 }
198 }
199 glTexImage2D(
200 target, level, gl_internal_format, width, height, border, format, type,
201 pixels);
202}
203
[email protected]297ca1c2011-06-20 23:08:46204// Wrapper for glEnable/glDisable that doesn't suck.
205static void EnableDisable(GLenum pname, bool enable) {
206 if (enable) {
207 glEnable(pname);
208 } else {
209 glDisable(pname);
210 }
211}
212
[email protected]6217d392010-03-25 22:08:35213// This class prevents any GL errors that occur when it is in scope from
214// being reported to the client.
215class ScopedGLErrorSuppressor {
216 public:
217 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
218 ~ScopedGLErrorSuppressor();
219 private:
220 GLES2DecoderImpl* decoder_;
221 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
222};
223
224// Temporarily changes a decoder's bound 2D texture and restore it when this
225// object goes out of scope. Also temporarily switches to using active texture
226// unit zero in case the client has changed that to something invalid.
227class ScopedTexture2DBinder {
228 public:
229 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
230 ~ScopedTexture2DBinder();
231
232 private:
233 GLES2DecoderImpl* decoder_;
234 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
235};
236
237// Temporarily changes a decoder's bound render buffer and restore it when this
238// object goes out of scope.
239class ScopedRenderBufferBinder {
240 public:
241 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
242 ~ScopedRenderBufferBinder();
243
244 private:
245 GLES2DecoderImpl* decoder_;
246 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
247};
248
249// Temporarily changes a decoder's bound frame buffer and restore it when this
250// object goes out of scope.
251class ScopedFrameBufferBinder {
252 public:
253 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
254 ~ScopedFrameBufferBinder();
255
256 private:
257 GLES2DecoderImpl* decoder_;
258 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
259};
260
[email protected]34ff8b0c2010-10-01 20:06:02261// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52262// the multisampled offscreen render buffer if that buffer is multisampled, and,
[email protected]de26b3c2011-08-03 21:54:27263// if it is bound or enforce_internal_framebuffer is true. If internal is
264// true, the resolved framebuffer is not visible to the parent.
[email protected]34ff8b0c2010-10-01 20:06:02265class ScopedResolvedFrameBufferBinder {
266 public:
[email protected]e7e38032011-07-26 17:25:25267 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
[email protected]de26b3c2011-08-03 21:54:27268 bool enforce_internal_framebuffer,
269 bool internal);
[email protected]34ff8b0c2010-10-01 20:06:02270 ~ScopedResolvedFrameBufferBinder();
271
272 private:
273 GLES2DecoderImpl* decoder_;
274 bool resolve_and_bind_;
275 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
276};
277
[email protected]6217d392010-03-25 22:08:35278// Encapsulates an OpenGL texture.
279class Texture {
280 public:
281 explicit Texture(GLES2DecoderImpl* decoder);
282 ~Texture();
283
284 // Create a new render texture.
285 void Create();
286
287 // Set the initial size and format of a render texture or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02288 bool AllocateStorage(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35289
290 // Copy the contents of the currently bound frame buffer.
[email protected]3a4d0c52011-06-29 23:11:58291 void Copy(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35292
293 // Destroy the render texture. This must be explicitly called before
294 // destroying this object.
295 void Destroy();
296
[email protected]97872062010-11-03 19:07:05297 // Invalidate the texture. This can be used when a context is lost and it is
298 // not possible to make it current in order to free the resource.
299 void Invalidate();
300
[email protected]6217d392010-03-25 22:08:35301 GLuint id() const {
302 return id_;
303 }
304
[email protected]d37231fa2010-04-09 21:16:02305 gfx::Size size() const {
306 return size_;
307 }
308
[email protected]1078f912011-12-23 13:12:14309 size_t estimated_size() const {
310 return estimated_size_;
311 }
312
[email protected]6217d392010-03-25 22:08:35313 private:
314 GLES2DecoderImpl* decoder_;
315 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02316 gfx::Size size_;
[email protected]1078f912011-12-23 13:12:14317 size_t estimated_size_;
[email protected]6217d392010-03-25 22:08:35318 DISALLOW_COPY_AND_ASSIGN(Texture);
319};
320
321// Encapsulates an OpenGL render buffer of any format.
322class RenderBuffer {
323 public:
324 explicit RenderBuffer(GLES2DecoderImpl* decoder);
325 ~RenderBuffer();
326
327 // Create a new render buffer.
328 void Create();
329
330 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02331 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35332
333 // Destroy the render buffer. This must be explicitly called before destroying
334 // this object.
335 void Destroy();
336
[email protected]97872062010-11-03 19:07:05337 // Invalidate the render buffer. This can be used when a context is lost and
338 // it is not possible to make it current in order to free the resource.
339 void Invalidate();
340
[email protected]6217d392010-03-25 22:08:35341 GLuint id() const {
342 return id_;
343 }
344
[email protected]1078f912011-12-23 13:12:14345 size_t estimated_size() const {
346 return estimated_size_;
347 }
348
[email protected]6217d392010-03-25 22:08:35349 private:
350 GLES2DecoderImpl* decoder_;
351 GLuint id_;
[email protected]1078f912011-12-23 13:12:14352 size_t estimated_size_;
[email protected]6217d392010-03-25 22:08:35353 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
354};
355
356// Encapsulates an OpenGL frame buffer.
357class FrameBuffer {
358 public:
359 explicit FrameBuffer(GLES2DecoderImpl* decoder);
360 ~FrameBuffer();
361
362 // Create a new frame buffer.
363 void Create();
364
365 // Attach a color render buffer to a frame buffer.
366 void AttachRenderTexture(Texture* texture);
367
[email protected]b9363b22010-06-09 22:06:15368 // Attach a render buffer to a frame buffer. Note that this unbinds any
369 // currently bound frame buffer.
370 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35371
[email protected]6217d392010-03-25 22:08:35372 // Destroy the frame buffer. This must be explicitly called before destroying
373 // this object.
374 void Destroy();
375
[email protected]97872062010-11-03 19:07:05376 // Invalidate the frame buffer. This can be used when a context is lost and it
377 // is not possible to make it current in order to free the resource.
378 void Invalidate();
379
[email protected]6217d392010-03-25 22:08:35380 // See glCheckFramebufferStatusEXT.
381 GLenum CheckStatus();
382
383 GLuint id() const {
384 return id_;
385 }
386
387 private:
388 GLES2DecoderImpl* decoder_;
389 GLuint id_;
390 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
391};
[email protected]34ff8b0c2010-10-01 20:06:02392
393class ContextCreationAttribParser {
394 public:
395 ContextCreationAttribParser();
396 bool Parse(const std::vector<int32>& attribs);
397
398 // -1 if invalid or unspecified.
399 int32 alpha_size_;
400 int32 blue_size_;
401 int32 green_size_;
402 int32 red_size_;
403 int32 depth_size_;
404 int32 stencil_size_;
405 int32 samples_;
406 int32 sample_buffers_;
[email protected]8a61d872012-01-20 12:43:56407 bool buffer_preserved_;
[email protected]34ff8b0c2010-10-01 20:06:02408};
409
410ContextCreationAttribParser::ContextCreationAttribParser()
411 : alpha_size_(-1),
412 blue_size_(-1),
413 green_size_(-1),
414 red_size_(-1),
415 depth_size_(-1),
416 stencil_size_(-1),
417 samples_(-1),
[email protected]8a61d872012-01-20 12:43:56418 sample_buffers_(-1),
419 buffer_preserved_(true) {
[email protected]34ff8b0c2010-10-01 20:06:02420}
421
422bool ContextCreationAttribParser::Parse(const std::vector<int32>& attribs) {
423 // From <EGL/egl.h>.
424 const int32 EGL_ALPHA_SIZE = 0x3021;
425 const int32 EGL_BLUE_SIZE = 0x3022;
426 const int32 EGL_GREEN_SIZE = 0x3023;
427 const int32 EGL_RED_SIZE = 0x3024;
428 const int32 EGL_DEPTH_SIZE = 0x3025;
429 const int32 EGL_STENCIL_SIZE = 0x3026;
430 const int32 EGL_SAMPLES = 0x3031;
431 const int32 EGL_SAMPLE_BUFFERS = 0x3032;
432 const int32 EGL_NONE = 0x3038;
[email protected]8a61d872012-01-20 12:43:56433 const int32 EGL_SWAP_BEHAVIOR = 0x3093;
434 const int32 EGL_BUFFER_PRESERVED = 0x3094;
[email protected]34ff8b0c2010-10-01 20:06:02435
436 for (size_t i = 0; i < attribs.size(); i += 2) {
437 const int32 attrib = attribs[i];
438 if (i + 1 >= attribs.size()) {
439 if (attrib == EGL_NONE)
440 return true;
441
442 DLOG(ERROR) << "Missing value after context creation attribute: "
443 << attrib;
444 return false;
445 }
446
447 const int32 value = attribs[i+1];
448 switch (attrib) {
449 case EGL_ALPHA_SIZE:
450 alpha_size_ = value;
451 break;
452 case EGL_BLUE_SIZE:
453 blue_size_ = value;
454 break;
455 case EGL_GREEN_SIZE:
456 green_size_ = value;
457 break;
458 case EGL_RED_SIZE:
459 red_size_ = value;
460 break;
461 case EGL_DEPTH_SIZE:
462 depth_size_ = value;
463 break;
464 case EGL_STENCIL_SIZE:
465 stencil_size_ = value;
466 break;
467 case EGL_SAMPLES:
468 samples_ = value;
469 break;
470 case EGL_SAMPLE_BUFFERS:
471 sample_buffers_ = value;
472 break;
[email protected]8a61d872012-01-20 12:43:56473 case EGL_SWAP_BEHAVIOR:
474 buffer_preserved_ = value == EGL_BUFFER_PRESERVED;
475 break;
[email protected]34ff8b0c2010-10-01 20:06:02476 case EGL_NONE:
477 // Terminate list, even if more attributes.
478 return true;
479 default:
480 DLOG(ERROR) << "Invalid context creation attribute: " << attrib;
481 return false;
482 }
483 }
484
485 return true;
486}
487
[email protected]43f28f832010-02-03 02:28:48488// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32489
[email protected]ddb1e5a2010-12-13 20:10:45490bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
491 uint32* service_texture_id) {
492 return false;
493}
494
[email protected]a3ded6d2010-10-19 06:44:39495GLES2Decoder::GLES2Decoder()
[email protected]e844ae22012-01-14 03:36:26496 : debug_(false),
[email protected]b5d647c2012-02-10 01:41:32497 log_commands_(false),
498 log_synthesized_gl_errors_(true) {
[email protected]96449d2c2009-11-25 00:01:32499}
500
[email protected]3916c97e2010-02-25 03:20:50501GLES2Decoder::~GLES2Decoder() {
502}
503
[email protected]57edfdad2012-02-07 04:57:15504bool GLES2Decoder::testing_force_is_angle_;
505
506void GLES2Decoder::set_testing_force_is_angle(bool force) {
507 testing_force_is_angle_ = force;
508}
509
510bool GLES2Decoder::IsAngle() {
511#if defined(OS_WIN)
512 return testing_force_is_angle_ ||
513 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
514#else
515 return testing_force_is_angle_;
516#endif
517}
518
[email protected]f39f4b3f2010-05-12 17:04:08519// This class implements GLES2Decoder so we don't have to expose all the GLES2
520// cmd stuff to outside this class.
521class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
522 public GLES2Decoder {
523 public:
[email protected]aa7666122011-09-02 19:45:52524 explicit GLES2DecoderImpl(ContextGroup* group);
[email protected]80eb6b52012-01-19 00:14:41525 ~GLES2DecoderImpl();
[email protected]f39f4b3f2010-05-12 17:04:08526
[email protected]96449d2c2009-11-25 00:01:32527 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14528 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50529 unsigned int arg_count,
530 const void* args);
[email protected]96449d2c2009-11-25 00:01:32531
532 // Overridden from AsyncAPIInterface.
533 virtual const char* GetCommandName(unsigned int command_id) const;
534
535 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38536 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
537 const scoped_refptr<gfx::GLContext>& context,
[email protected]6217d392010-03-25 22:08:35538 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:29539 const DisallowedFeatures& disallowed_features,
[email protected]a3ded6d2010-10-19 06:44:39540 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:24541 const std::vector<int32>& attribs);
[email protected]96449d2c2009-11-25 00:01:32542 virtual void Destroy();
[email protected]3c644d82011-06-20 19:58:24543 virtual bool SetParent(GLES2Decoder* parent_decoder,
544 uint32 parent_texture_id);
[email protected]799b4b22011-08-22 17:09:59545 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]9a5afa432011-07-22 18:16:39546 void UpdateParentTextureInfo();
[email protected]eb54a562010-01-20 21:55:18547 virtual bool MakeCurrent();
[email protected]a96a6022011-11-04 00:58:12548 virtual void ReleaseCurrent();
[email protected]56ac89b2010-03-17 21:16:55549 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30550 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]f62a5ab2011-05-23 20:34:15551 virtual gfx::GLSurface* GetGLSurface() { return surface_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39552 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]43f28f832010-02-03 02:28:48553
[email protected]0d6bfdc2011-11-02 01:32:20554 virtual void SetGLError(GLenum error, const char* msg);
[email protected]9d37f062011-11-22 01:24:52555 virtual void SetResizeCallback(
556 const base::Callback<void(gfx::Size)>& callback);
[email protected]22f320a2011-08-30 01:17:00557
[email protected]6b6e7ee2011-12-13 08:04:52558 virtual void SetMsgCallback(const MsgCallback& callback);
[email protected]22f320a2011-08-30 01:17:00559
[email protected]b0af4f52011-09-28 22:04:42560 virtual void SetStreamTextureManager(StreamTextureManager* manager);
[email protected]1318e922010-09-17 22:03:16561 virtual bool GetServiceTextureId(uint32 client_texture_id,
562 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48563
[email protected]8e3e0662010-08-23 18:46:30564 // Restores the current state to the user's settings.
565 void RestoreCurrentFramebufferBindings();
566 void RestoreCurrentRenderbufferBindings();
567 void RestoreCurrentTexture2DBindings();
568
[email protected]297ca1c2011-06-20 23:08:46569 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
570 void ApplyDirtyState();
571
572 // These check the state of the currently bound framebuffer or the
573 // backbuffer if no framebuffer is bound.
574 bool BoundFramebufferHasColorAttachmentWithAlpha();
575 bool BoundFramebufferHasDepthAttachment();
576 bool BoundFramebufferHasStencilAttachment();
577
[email protected]38d139d2011-07-14 00:38:43578 virtual error::ContextLostReason GetContextLostReason();
579
[email protected]96449d2c2009-11-25 00:01:32580 private:
[email protected]6217d392010-03-25 22:08:35581 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02582 friend class ScopedResolvedFrameBufferBinder;
[email protected]1078f912011-12-23 13:12:14583 friend class Texture;
[email protected]6217d392010-03-25 22:08:35584 friend class RenderBuffer;
585 friend class FrameBuffer;
586
[email protected]3916c97e2010-02-25 03:20:50587 // State associated with each texture unit.
588 struct TextureUnit {
589 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
590
591 // The last target that was bound to this texture unit.
592 GLenum bind_target;
593
594 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
595 TextureManager::TextureInfo::Ref bound_texture_2d;
596
597 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
598 // glBindTexture
599 TextureManager::TextureInfo::Ref bound_texture_cube_map;
[email protected]61eeb33f2011-07-26 15:30:31600
601 // texture currently bound to this unit's GL_TEXTURE_EXTERNAL_OES with
602 // glBindTexture
603 TextureManager::TextureInfo::Ref bound_texture_external_oes;
604
[email protected]e51bdf32011-11-23 22:21:46605 // texture currently bound to this unit's GL_TEXTURE_RECTANGLE_ARB with
606 // glBindTexture
607 TextureManager::TextureInfo::Ref bound_texture_rectangle_arb;
608
[email protected]61eeb33f2011-07-26 15:30:31609 TextureManager::TextureInfo::Ref GetInfoForSamplerType(GLenum type) {
610 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:46611 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
612 switch (type) {
613 case GL_SAMPLER_2D:
614 return bound_texture_2d;
615 case GL_SAMPLER_CUBE:
616 return bound_texture_cube_map;
617 case GL_SAMPLER_EXTERNAL_OES:
618 return bound_texture_external_oes;
619 case GL_SAMPLER_2D_RECT_ARB:
620 return bound_texture_rectangle_arb;
621 }
622
623 NOTREACHED();
624 return NULL;
[email protected]61eeb33f2011-07-26 15:30:31625 }
[email protected]a0b78dc2011-11-11 10:43:10626
627 void Unbind(TextureManager::TextureInfo* texture) {
628 if (bound_texture_2d == texture) {
629 bound_texture_2d = NULL;
630 }
631 if (bound_texture_cube_map == texture) {
632 bound_texture_cube_map = NULL;
633 }
634 if (bound_texture_external_oes == texture) {
635 bound_texture_external_oes = NULL;
636 }
637 }
[email protected]3916c97e2010-02-25 03:20:50638 };
639
[email protected]c2f8c8402010-12-06 18:07:24640 // Initialize or re-initialize the shader translator.
641 bool InitializeShaderTranslator();
642
[email protected]302ce6d2011-07-07 23:28:11643 void UpdateCapabilities();
644
[email protected]ae51d192010-04-27 00:48:03645 // Helpers for the glGen and glDelete functions.
646 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
647 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
648 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
649 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
650 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
651 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
652 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
653 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47654
[email protected]3916c97e2010-02-25 03:20:50655 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50656 BufferManager* buffer_manager() {
657 return group_->buffer_manager();
658 }
659
[email protected]a25fa872010-03-25 02:57:58660 RenderbufferManager* renderbuffer_manager() {
661 return group_->renderbuffer_manager();
662 }
663
664 FramebufferManager* framebuffer_manager() {
665 return group_->framebuffer_manager();
666 }
667
[email protected]3916c97e2010-02-25 03:20:50668 ProgramManager* program_manager() {
669 return group_->program_manager();
670 }
671
672 ShaderManager* shader_manager() {
673 return group_->shader_manager();
674 }
675
676 TextureManager* texture_manager() {
677 return group_->texture_manager();
678 }
679
[email protected]34ff8b0c2010-10-01 20:06:02680 bool IsOffscreenBufferMultisampled() const {
681 return offscreen_target_samples_ > 1;
682 }
683
[email protected]a93bb842010-02-16 23:03:47684 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03685 TextureManager::TextureInfo* CreateTextureInfo(
686 GLuint client_id, GLuint service_id) {
[email protected]80eb6b52012-01-19 00:14:41687 return texture_manager()->CreateTextureInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47688 }
689
690 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03691 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50692 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03693 texture_manager()->GetTextureInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10694 return info;
[email protected]a93bb842010-02-16 23:03:47695 }
696
697 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03698 void RemoveTextureInfo(GLuint client_id) {
[email protected]80eb6b52012-01-19 00:14:41699 texture_manager()->RemoveTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50700 }
[email protected]a93bb842010-02-16 23:03:47701
[email protected]d37231fa2010-04-09 21:16:02702 // Get the size (in pixels) of the currently bound frame buffer (either FBO
703 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30704 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02705
[email protected]9edc6b22010-12-23 02:00:26706 // Get the format of the currently bound frame buffer (either FBO or regular
707 // back buffer)
708 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46709 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26710
[email protected]a93bb842010-02-16 23:03:47711 // Wrapper for CompressedTexImage2D commands.
712 error::Error DoCompressedTexImage2D(
713 GLenum target,
714 GLint level,
715 GLenum internal_format,
716 GLsizei width,
717 GLsizei height,
718 GLint border,
719 GLsizei image_size,
720 const void* data);
721
[email protected]cadde4a2010-07-31 17:10:43722 // Wrapper for CompressedTexSubImage2D.
723 void DoCompressedTexSubImage2D(
724 GLenum target,
725 GLint level,
726 GLint xoffset,
727 GLint yoffset,
728 GLsizei width,
729 GLsizei height,
730 GLenum format,
731 GLsizei imageSize,
732 const void * data);
733
734 // Wrapper for CopyTexImage2D.
735 void DoCopyTexImage2D(
736 GLenum target,
737 GLint level,
738 GLenum internal_format,
739 GLint x,
740 GLint y,
741 GLsizei width,
742 GLsizei height,
743 GLint border);
744
745 // Wrapper for CopyTexSubImage2D.
746 void DoCopyTexSubImage2D(
747 GLenum target,
748 GLint level,
749 GLint xoffset,
750 GLint yoffset,
751 GLint x,
752 GLint y,
753 GLsizei width,
754 GLsizei height);
755
[email protected]a93bb842010-02-16 23:03:47756 // Wrapper for TexImage2D commands.
757 error::Error DoTexImage2D(
758 GLenum target,
759 GLint level,
760 GLenum internal_format,
761 GLsizei width,
762 GLsizei height,
763 GLint border,
764 GLenum format,
765 GLenum type,
766 const void* pixels,
767 uint32 pixels_size);
768
[email protected]cadde4a2010-07-31 17:10:43769 // Wrapper for TexSubImage2D.
770 void DoTexSubImage2D(
771 GLenum target,
772 GLint level,
773 GLint xoffset,
774 GLint yoffset,
775 GLsizei width,
776 GLsizei height,
777 GLenum format,
778 GLenum type,
779 const void * data);
780
[email protected]e51bdf32011-11-23 22:21:46781 // Wrapper for TexImageIOSurface2DCHROMIUM.
782 void DoTexImageIOSurface2DCHROMIUM(
783 GLenum target,
784 GLsizei width,
785 GLsizei height,
786 GLuint io_surface_id,
787 GLuint plane);
788
[email protected]97dc7cbe2011-12-06 17:26:17789 // Wrapper for TexStorage2DEXT.
790 void DoTexStorage2DEXT(
791 GLenum target,
792 GLint levels,
793 GLenum internal_format,
794 GLsizei width,
795 GLsizei height);
796
[email protected]a93bb842010-02-16 23:03:47797 // Creates a ProgramInfo for the given program.
[email protected]d685a682011-04-29 16:19:57798 ProgramManager::ProgramInfo* CreateProgramInfo(
799 GLuint client_id, GLuint service_id) {
800 return program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47801 }
802
[email protected]07f54fcc2009-12-22 02:46:30803 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03804 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14805 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46806 }
[email protected]07f54fcc2009-12-22 02:46:30807
[email protected]6b8cf1a2010-05-06 16:13:58808 // Gets the program info for the given program. If it's not a program
809 // generates a GL error. Returns NULL if not program.
810 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
811 GLuint client_id, const char* function_name) {
812 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
813 if (!info) {
814 if (GetShaderInfo(client_id)) {
815 SetGLError(GL_INVALID_OPERATION,
816 (std::string(function_name) +
817 ": shader passed for program").c_str());
818 } else {
819 SetGLError(GL_INVALID_VALUE,
820 (std::string(function_name) + ": unknown program").c_str());
821 }
822 }
823 return info;
824 }
825
826
[email protected]45bf5152010-02-12 00:11:31827 // Creates a ShaderInfo for the given shader.
[email protected]d685a682011-04-29 16:19:57828 ShaderManager::ShaderInfo* CreateShaderInfo(
829 GLuint client_id,
830 GLuint service_id,
831 GLenum shader_type) {
832 return shader_manager()->CreateShaderInfo(
833 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31834 }
835
836 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03837 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14838 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31839 }
840
[email protected]6b8cf1a2010-05-06 16:13:58841 // Gets the shader info for the given shader. If it's not a shader generates a
842 // GL error. Returns NULL if not shader.
843 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
844 GLuint client_id, const char* function_name) {
845 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
846 if (!info) {
847 if (GetProgramInfo(client_id)) {
848 SetGLError(
849 GL_INVALID_OPERATION,
850 (std::string(function_name) +
851 ": program passed for shader").c_str());
852 } else {
853 SetGLError(GL_INVALID_VALUE,
854 (std::string(function_name) + ": unknown shader").c_str());
855 }
856 }
857 return info;
858 }
859
[email protected]a93bb842010-02-16 23:03:47860 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03861 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
862 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47863 }
864
[email protected]07f54fcc2009-12-22 02:46:30865 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03866 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
867 BufferManager::BufferInfo* info =
868 buffer_manager()->GetBufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10869 return info;
[email protected]1d32bc82010-01-13 22:06:46870 }
[email protected]07f54fcc2009-12-22 02:46:30871
[email protected]a93bb842010-02-16 23:03:47872 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
873 // on glDeleteBuffers so we can make sure the user does not try to render
874 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03875 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47876
[email protected]a25fa872010-03-25 02:57:58877 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03878 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
879 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58880 }
881
882 // Gets the framebuffer info for the given framebuffer.
883 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03884 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58885 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03886 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10887 return info;
[email protected]a25fa872010-03-25 02:57:58888 }
889
890 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03891 void RemoveFramebufferInfo(GLuint client_id) {
892 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58893 }
894
895 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03896 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
897 return renderbuffer_manager()->CreateRenderbufferInfo(
898 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58899 }
900
901 // Gets the renderbuffer info for the given renderbuffer.
902 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03903 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58904 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03905 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10906 return info;
[email protected]a25fa872010-03-25 02:57:58907 }
908
909 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03910 void RemoveRenderbufferInfo(GLuint client_id) {
911 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58912 }
913
[email protected]258a3313f2011-10-18 20:13:57914 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
915
[email protected]558847a2010-03-24 07:02:54916 error::Error GetAttribLocationHelper(
917 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
918 const std::string& name_str);
919
920 error::Error GetUniformLocationHelper(
921 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
922 const std::string& name_str);
923
[email protected]3916c97e2010-02-25 03:20:50924 // Helper for glShaderSource.
925 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03926 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30927
[email protected]0d6bfdc2011-11-02 01:32:20928 // Clear any textures used by the current program.
929 bool ClearUnclearedTextures();
930
931 // Clear any uncleared level in texture.
932 // Returns false if there was a generated GL error.
933 bool ClearTexture(TextureManager::TextureInfo* info);
934
935 // Clears any uncleared attachments attached to the given frame buffer.
936 // Returns false if there was a generated GL error.
937 void ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:30938 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28939
[email protected]0d6bfdc2011-11-02 01:32:20940 // overridden from GLES2Decoder
941 virtual bool ClearLevel(
942 unsigned service_id,
943 unsigned bind_target,
944 unsigned target,
945 int level,
946 unsigned format,
947 unsigned type,
948 int width,
[email protected]4502e6492011-12-14 19:39:15949 int height,
950 bool is_texture_immutable);
[email protected]0d6bfdc2011-11-02 01:32:20951
[email protected]c007aa02010-09-02 22:22:40952 // Restore all GL state that affects clearing.
953 void RestoreClearState();
954
[email protected]3a2e7c7b2010-08-06 01:12:28955 // Remembers the state of some capabilities.
[email protected]297ca1c2011-06-20 23:08:46956 // Returns: true if glEnable/glDisable should actually be called.
957 bool SetCapabilityState(GLenum cap, bool enabled);
[email protected]3a2e7c7b2010-08-06 01:12:28958
[email protected]0d6bfdc2011-11-02 01:32:20959 // Check that the currently bound framebuffers are valid.
960 // Generates GL error if not.
961 bool CheckBoundFramebuffersValid(const char* func_name);
962
963 // Check if a framebuffer meets our requirements.
964 bool CheckFramebufferValid(
965 FramebufferManager::FramebufferInfo* framebuffer,
966 GLenum target,
967 const char* func_name);
[email protected]3a03a8f2011-03-19 00:51:27968
[email protected]939e7362010-05-13 20:49:10969 // Checks if the current program exists and is valid. If not generates the
970 // appropriate GL error. Returns true if the current program is in a usable
971 // state.
972 bool CheckCurrentProgram(const char* function_name);
973
974 // Checks if the current program exists and is valid and that location is not
975 // -1. If the current program is not valid generates the appropriate GL
976 // error. Returns true if the current program is in a usable state and
977 // location is not -1.
978 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
979
980 // Gets the type of a uniform for a location in the current program. Sets GL
981 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:36982 // program is valid and the location exists. Adjusts count so it
983 // does not overflow the uniform.
984 bool PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:12985 GLint fake_location, const char* function_name,
986 GLint* real_location, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:10987
[email protected]b177ae22011-11-01 03:29:11988 // Gets the service id for any simulated backbuffer fbo.
989 GLuint GetBackbufferServiceId();
990
[email protected]b273e432010-04-12 17:23:58991 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
992 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
993
[email protected]96449d2c2009-11-25 00:01:32994 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03995 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32996
997 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03998 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32999
[email protected]3916c97e2010-02-25 03:20:501000 // Wrapper for glActiveTexture
1001 void DoActiveTexture(GLenum texture_unit);
1002
[email protected]ae51d192010-04-27 00:48:031003 // Wrapper for glAttachShader
1004 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1005
[email protected]96449d2c2009-11-25 00:01:321006 // Wrapper for glBindBuffer since we need to track the current targets.
1007 void DoBindBuffer(GLenum target, GLuint buffer);
1008
[email protected]86093972010-03-11 00:13:561009 // Wrapper for glBindFramebuffer since we need to track the current targets.
1010 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1011
1012 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1013 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1014
[email protected]a93bb842010-02-16 23:03:471015 // Wrapper for glBindTexture since we need to track the current targets.
1016 void DoBindTexture(GLenum target, GLuint texture);
1017
[email protected]8e3e0662010-08-23 18:46:301018 // Wrapper for glBlitFramebufferEXT.
1019 void DoBlitFramebufferEXT(
1020 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1021 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1022 GLbitfield mask, GLenum filter);
1023
[email protected]36cef8ce2010-03-16 07:34:451024 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:111025 void DoBufferData(
1026 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
1027
[email protected]36cef8ce2010-03-16 07:34:451028 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:111029 void DoBufferSubData(
1030 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1031
[email protected]36cef8ce2010-03-16 07:34:451032 // Wrapper for glCheckFramebufferStatus
1033 GLenum DoCheckFramebufferStatus(GLenum target);
1034
[email protected]3a03a8f2011-03-19 00:51:271035 // Wrapper for glClear
1036 void DoClear(GLbitfield mask);
1037
[email protected]3a2e7c7b2010-08-06 01:12:281038 // Wrappers for clear and mask settings functions.
1039 void DoClearColor(
1040 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
1041 void DoClearDepthf(GLclampf depth);
1042 void DoClearStencil(GLint s);
1043 void DoColorMask(
1044 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
1045 void DoDepthMask(GLboolean depth);
1046 void DoStencilMask(GLuint mask);
1047 void DoStencilMaskSeparate(GLenum face, GLuint mask);
1048
[email protected]45bf5152010-02-12 00:11:311049 // Wrapper for glCompileShader.
1050 void DoCompileShader(GLuint shader);
1051
[email protected]269200b12010-11-18 22:53:061052 // Helper for DeleteSharedIdsCHROMIUM commands.
1053 void DoDeleteSharedIdsCHROMIUM(
1054 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101055
[email protected]ae51d192010-04-27 00:48:031056 // Wrapper for glDetachShader
1057 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1058
[email protected]3a2e7c7b2010-08-06 01:12:281059 // Wrapper for glDisable
1060 void DoDisable(GLenum cap);
1061
[email protected]07f54fcc2009-12-22 02:46:301062 // Wrapper for glDisableVertexAttribArray.
1063 void DoDisableVertexAttribArray(GLuint index);
1064
[email protected]3a2e7c7b2010-08-06 01:12:281065 // Wrapper for glEnable
1066 void DoEnable(GLenum cap);
1067
[email protected]07f54fcc2009-12-22 02:46:301068 // Wrapper for glEnableVertexAttribArray.
1069 void DoEnableVertexAttribArray(GLuint index);
1070
[email protected]36cef8ce2010-03-16 07:34:451071 // Wrapper for glFramebufferRenderbufffer.
1072 void DoFramebufferRenderbuffer(
1073 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1074 GLuint renderbuffer);
1075
1076 // Wrapper for glFramebufferTexture2D.
1077 void DoFramebufferTexture2D(
1078 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1079 GLint level);
1080
[email protected]a93bb842010-02-16 23:03:471081 // Wrapper for glGenerateMipmap
1082 void DoGenerateMipmap(GLenum target);
1083
[email protected]269200b12010-11-18 22:53:061084 // Helper for GenSharedIdsCHROMIUM commands.
1085 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:101086 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1087
[email protected]b273e432010-04-12 17:23:581088 // Wrapper for DoGetBooleanv.
1089 void DoGetBooleanv(GLenum pname, GLboolean* params);
1090
1091 // Wrapper for DoGetFloatv.
1092 void DoGetFloatv(GLenum pname, GLfloat* params);
1093
[email protected]36cef8ce2010-03-16 07:34:451094 // Wrapper for glGetFramebufferAttachmentParameteriv.
1095 void DoGetFramebufferAttachmentParameteriv(
1096 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1097
[email protected]a0c3e972010-04-21 00:49:131098 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581099 void DoGetIntegerv(GLenum pname, GLint* params);
1100
[email protected]29a9eb52010-04-13 09:04:231101 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:061102 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:231103 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1104
[email protected]a0c3e972010-04-21 00:49:131105 // Wrapper for glGetProgramiv.
1106 void DoGetProgramiv(
1107 GLuint program_id, GLenum pname, GLint* params);
1108
[email protected]36cef8ce2010-03-16 07:34:451109 // Wrapper for glRenderbufferParameteriv.
1110 void DoGetRenderbufferParameteriv(
1111 GLenum target, GLenum pname, GLint* params);
1112
[email protected]ddd968b82010-03-02 00:44:291113 // Wrapper for glGetShaderiv
1114 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1115
[email protected]b1122982010-05-17 23:04:241116 // Wrappers for glGetVertexAttrib.
1117 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1118 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1119
[email protected]1958e0e2010-04-22 05:17:151120 // Wrappers for glIsXXX functions.
1121 bool DoIsBuffer(GLuint client_id);
1122 bool DoIsFramebuffer(GLuint client_id);
1123 bool DoIsProgram(GLuint client_id);
1124 bool DoIsRenderbuffer(GLuint client_id);
1125 bool DoIsShader(GLuint client_id);
1126 bool DoIsTexture(GLuint client_id);
1127
[email protected]07f54fcc2009-12-22 02:46:301128 // Wrapper for glLinkProgram
1129 void DoLinkProgram(GLuint program);
1130
[email protected]269200b12010-11-18 22:53:061131 // Helper for RegisterSharedIdsCHROMIUM.
1132 void DoRegisterSharedIdsCHROMIUM(
1133 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101134
[email protected]36cef8ce2010-03-16 07:34:451135 // Wrapper for glRenderbufferStorage.
1136 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031137 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451138
[email protected]8e3e0662010-08-23 18:46:301139 // Wrapper for glRenderbufferStorageMultisampleEXT.
1140 void DoRenderbufferStorageMultisample(
1141 GLenum target, GLsizei samples, GLenum internalformat,
1142 GLsizei width, GLsizei height);
1143
[email protected]b273e432010-04-12 17:23:581144 // Wrapper for glReleaseShaderCompiler.
1145 void DoReleaseShaderCompiler() { }
1146
[email protected]3916c97e2010-02-25 03:20:501147 // Wrappers for glTexParameter functions.
1148 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1149 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1150 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1151 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1152
1153 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1154 // spec only these 2 functions can be used to set sampler uniforms.
[email protected]1b0a6752012-02-22 03:44:121155 void DoUniform1i(GLint fake_location, GLint v0);
1156 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1157 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1158 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1159 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101160
1161 // Wrappers for glUniformfv because some drivers don't correctly accept
1162 // bool uniforms.
[email protected]1b0a6752012-02-22 03:44:121163 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1164 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1165 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1166 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501167
[email protected]43c2f1f2011-03-25 18:35:361168 void DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:121169 GLint fake_location, GLsizei count, GLboolean transpose,
1170 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361171 void DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:121172 GLint fake_location, GLsizei count, GLboolean transpose,
1173 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361174 void DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:121175 GLint fake_location, GLsizei count, GLboolean transpose,
1176 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361177
[email protected]b1122982010-05-17 23:04:241178 // Wrappers for glVertexAttrib??
1179 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1180 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1181 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1182 void DoVertexAttrib4f(
1183 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1184 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1185 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1186 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1187 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1188
[email protected]07f54fcc2009-12-22 02:46:301189 // Wrapper for glUseProgram
1190 void DoUseProgram(GLuint program);
1191
[email protected]ae51d192010-04-27 00:48:031192 // Wrapper for glValidateProgram.
1193 void DoValidateProgram(GLuint program_client_id);
1194
[email protected]4e8a5b122010-05-08 22:00:101195 // Gets the number of values that will be returned by glGetXXX. Returns
1196 // false if pname is unknown.
1197 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1198
[email protected]96449d2c2009-11-25 00:01:321199 // Gets the GLError through our wrapper.
1200 GLenum GetGLError();
1201
[email protected]1002c2d2011-06-28 22:39:041202 // Gets the GLError and stores it in our wrapper. Effectively
1203 // this lets us peek at the error without losing it.
1204 GLenum PeekGLError();
1205
[email protected]07f54fcc2009-12-22 02:46:301206 // Copies the real GL errors to the wrapper. This is so we can
1207 // make sure there are no native GL errors before calling some GL function
1208 // so that on return we know any error generated was for that specific
1209 // command.
1210 void CopyRealGLErrorsToWrapper();
1211
[email protected]6217d392010-03-25 22:08:351212 // Clear all real GL errors. This is to prevent the client from seeing any
1213 // errors caused by GL calls that it was not responsible for issuing.
1214 void ClearRealGLErrors();
1215
[email protected]07f54fcc2009-12-22 02:46:301216 // Checks if the current program and vertex attributes are valid for drawing.
[email protected]c6aef902012-02-14 03:31:421217 bool IsDrawValid(GLuint max_vertex_accessed, GLsizei primcount);
[email protected]07f54fcc2009-12-22 02:46:301218
[email protected]c13e1da62011-09-09 21:48:301219 // Returns true if successful, simulated will be true if attrib0 was
1220 // simulated.
[email protected]c6aef902012-02-14 03:31:421221 bool SimulateAttrib0(
1222 GLuint max_vertex_accessed, bool* simulated);
[email protected]b1122982010-05-17 23:04:241223 void RestoreStateForSimulatedAttrib0();
1224
[email protected]ef526492010-06-02 23:12:251225 // Returns true if textures were set.
1226 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501227 void RestoreStateForNonRenderableTextures();
1228
[email protected]8fbedc02010-11-18 18:43:401229 // Returns true if GL_FIXED attribs were simulated.
[email protected]c6aef902012-02-14 03:31:421230 bool SimulateFixedAttribs(
1231 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
[email protected]8fbedc02010-11-18 18:43:401232 void RestoreStateForSimulatedFixedAttribs();
1233
[email protected]c6aef902012-02-14 03:31:421234 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1235 // cases (primcount is 0 for non-instanced).
1236 error::Error DoDrawArrays(
1237 bool instanced, GLenum mode, GLint first, GLsizei count,
1238 GLsizei primcount);
1239 error::Error DoDrawElements(
1240 bool instanced, GLenum mode, GLsizei count, GLenum type,
1241 int32 offset, GLsizei primcount);
1242
[email protected]07f54fcc2009-12-22 02:46:301243 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501244 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301245 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501246 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1247 bound_array_buffer_ : bound_element_array_buffer_;
[email protected]a0b78dc2011-11-11 10:43:101248 return info;
[email protected]07f54fcc2009-12-22 02:46:301249 }
1250
[email protected]a93bb842010-02-16 23:03:471251 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501252 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1253 TextureUnit& unit = texture_units_[active_texture_unit_];
1254 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471255 switch (target) {
1256 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501257 info = unit.bound_texture_2d;
1258 break;
[email protected]a93bb842010-02-16 23:03:471259 case GL_TEXTURE_CUBE_MAP:
1260 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1261 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1262 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1263 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1264 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1265 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501266 info = unit.bound_texture_cube_map;
1267 break;
[email protected]61eeb33f2011-07-26 15:30:311268 case GL_TEXTURE_EXTERNAL_OES:
1269 info = unit.bound_texture_external_oes;
1270 break;
[email protected]e51bdf32011-11-23 22:21:461271 case GL_TEXTURE_RECTANGLE_ARB:
1272 info = unit.bound_texture_rectangle_arb;
1273 break;
[email protected]a93bb842010-02-16 23:03:471274 default:
1275 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501276 return NULL;
[email protected]a93bb842010-02-16 23:03:471277 }
[email protected]a0b78dc2011-11-11 10:43:101278 return info;
[email protected]a93bb842010-02-16 23:03:471279 }
1280
[email protected]61eeb33f2011-07-26 15:30:311281 GLenum GetBindTargetForSamplerType(GLenum type) {
1282 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:461283 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1284 switch (type) {
1285 case GL_SAMPLER_2D:
1286 return GL_TEXTURE_2D;
1287 case GL_SAMPLER_CUBE:
1288 return GL_TEXTURE_CUBE_MAP;
1289 case GL_SAMPLER_EXTERNAL_OES:
1290 return GL_TEXTURE_EXTERNAL_OES;
1291 case GL_SAMPLER_2D_RECT_ARB:
1292 return GL_TEXTURE_RECTANGLE_ARB;
1293 }
1294
1295 NOTREACHED();
1296 return 0;
[email protected]61eeb33f2011-07-26 15:30:311297 }
1298
[email protected]8e3e0662010-08-23 18:46:301299 // Gets the framebuffer info for a particular target.
1300 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1301 GLenum target) {
1302 FramebufferManager::FramebufferInfo* info = NULL;
1303 switch (target) {
1304 case GL_FRAMEBUFFER:
1305 case GL_DRAW_FRAMEBUFFER:
1306 info = bound_draw_framebuffer_;
1307 break;
1308 case GL_READ_FRAMEBUFFER:
1309 info = bound_read_framebuffer_;
1310 break;
1311 default:
1312 NOTREACHED();
1313 break;
1314 }
[email protected]a0b78dc2011-11-11 10:43:101315 return info;
[email protected]8e3e0662010-08-23 18:46:301316 }
1317
[email protected]0d6bfdc2011-11-02 01:32:201318 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfoForTarget(
1319 GLenum target) {
1320 RenderbufferManager::RenderbufferInfo* info = NULL;
1321 switch (target) {
1322 case GL_RENDERBUFFER:
1323 info = bound_renderbuffer_;
1324 break;
1325 default:
1326 NOTREACHED();
1327 break;
1328 }
[email protected]a0b78dc2011-11-11 10:43:101329 return info;
[email protected]0d6bfdc2011-11-02 01:32:201330 }
1331
[email protected]f7b85372010-02-03 01:11:371332 // Validates the program and location for a glGetUniform call and returns
1333 // a SizeResult setup to receive the result. Returns true if glGetUniform
1334 // should be called.
1335 bool GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:121336 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:371337 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:121338 error::Error* error, GLint* real_location, GLuint* service_id,
1339 void** result, GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371340
[email protected]1078f912011-12-23 13:12:141341 // Computes the estimated memory used for the backbuffer and passes it to
1342 // the tracing system.
1343 void UpdateBackbufferMemoryAccounting();
1344
[email protected]38d139d2011-07-14 00:38:431345 // Returns true if the context was just lost due to e.g. GL_ARB_robustness.
1346 bool WasContextLost();
1347
[email protected]e51bdf32011-11-23 22:21:461348#if defined(OS_MACOSX)
1349 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1350#endif
1351
[email protected]96449d2c2009-11-25 00:01:321352 // Generate a member function prototype for each command in an automated and
1353 // typesafe way.
1354 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141355 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191356 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321357 const gles2::name& args); \
1358
1359 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1360
1361 #undef GLES2_CMD_OP
1362
[email protected]2f2d7042010-04-14 21:45:581363 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381364 scoped_refptr<gfx::GLSurface> surface_;
1365 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021366
[email protected]a3ded6d2010-10-19 06:44:391367 // The ContextGroup for this decoder uses to track resources.
1368 ContextGroup::Ref group_;
1369
[email protected]6217d392010-03-25 22:08:351370 // A parent decoder can access this decoders saved offscreen frame buffer.
1371 // The parent pointer is reset if the parent is destroyed.
1372 base::WeakPtr<GLES2DecoderImpl> parent_;
1373
[email protected]34ff8b0c2010-10-01 20:06:021374 // Current width and height of the offscreen frame buffer.
1375 gfx::Size offscreen_size_;
1376
[email protected]96449d2c2009-11-25 00:01:321377 // Current GL error bits.
1378 uint32 error_bits_;
1379
[email protected]96449d2c2009-11-25 00:01:321380 // Util to help with GL.
1381 GLES2Util util_;
1382
1383 // pack alignment as last set by glPixelStorei
1384 GLint pack_alignment_;
1385
1386 // unpack alignment as last set by glPixelStorei
1387 GLint unpack_alignment_;
1388
1389 // The currently bound array buffer. If this is 0 it is illegal to call
1390 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501391 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321392
1393 // The currently bound element array buffer. If this is 0 it is illegal
1394 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501395 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301396
[email protected]f39f4b3f2010-05-12 17:04:081397 // Class that manages vertex attribs.
[email protected]3757a372012-01-19 05:20:441398 scoped_ptr<VertexAttribManager> vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301399
[email protected]b1122982010-05-17 23:04:241400 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1401 GLuint attrib_0_buffer_id_;
1402
1403 // The value currently in attrib_0.
1404 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1405
[email protected]fc753442011-02-04 19:49:491406 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1407 bool attrib_0_buffer_matches_value_;
1408
[email protected]b1122982010-05-17 23:04:241409 // The size of attrib 0.
1410 GLsizei attrib_0_size_;
1411
[email protected]8fbedc02010-11-18 18:43:401412 // The buffer used to simulate GL_FIXED attribs.
1413 GLuint fixed_attrib_buffer_id_;
1414
1415 // The size of fiixed attrib buffer.
1416 GLsizei fixed_attrib_buffer_size_;
1417
[email protected]3916c97e2010-02-25 03:20:501418 // Current active texture by 0 - n index.
1419 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1420 // be 2.
1421 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301422
[email protected]3916c97e2010-02-25 03:20:501423 // Which textures are bound to texture units through glActiveTexture.
1424 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471425
[email protected]3a2e7c7b2010-08-06 01:12:281426 // state saved for clearing so we can clear render buffers and then
1427 // restore to these values.
1428 GLclampf clear_red_;
1429 GLclampf clear_green_;
1430 GLclampf clear_blue_;
1431 GLclampf clear_alpha_;
1432 GLboolean mask_red_;
1433 GLboolean mask_green_;
1434 GLboolean mask_blue_;
1435 GLboolean mask_alpha_;
1436 GLint clear_stencil_;
1437 GLuint mask_stencil_front_;
1438 GLuint mask_stencil_back_;
1439 GLclampf clear_depth_;
1440 GLboolean mask_depth_;
1441 bool enable_scissor_test_;
[email protected]297ca1c2011-06-20 23:08:461442 bool enable_depth_test_;
1443 bool enable_stencil_test_;
1444 bool state_dirty_;
[email protected]3a2e7c7b2010-08-06 01:12:281445
[email protected]1d32bc82010-01-13 22:06:461446 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501447 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301448
[email protected]8e3e0662010-08-23 18:46:301449 // The currently bound framebuffers
1450 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1451 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561452
1453 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081454 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561455
[email protected]b9363b22010-06-09 22:06:151456 // The offscreen frame buffer that the client renders to. With EGL, the
1457 // depth and stencil buffers are separate. With regular GL there is a single
1458 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1459 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351460 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1461 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021462 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151463 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1464 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021465 GLenum offscreen_target_color_format_;
1466 GLenum offscreen_target_depth_format_;
1467 GLenum offscreen_target_stencil_format_;
1468 GLsizei offscreen_target_samples_;
[email protected]8a61d872012-01-20 12:43:561469 GLboolean offscreen_target_buffer_preserved_;
[email protected]6217d392010-03-25 22:08:351470
[email protected]de26b3c2011-08-03 21:54:271471 // The copy that is saved when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021472 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351473 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]8a61d872012-01-20 12:43:561474 TextureManager::TextureInfo::Ref offscreen_saved_color_texture_info_;
[email protected]de26b3c2011-08-03 21:54:271475
1476 // The copy that is used as the destination for multi-sample resolves.
1477 scoped_ptr<FrameBuffer> offscreen_resolved_frame_buffer_;
1478 scoped_ptr<Texture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051479 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351480
[email protected]9d37f062011-11-22 01:24:521481 base::Callback<void(gfx::Size)> resize_callback_;
[email protected]22f320a2011-08-30 01:17:001482
[email protected]6b6e7ee2011-12-13 08:04:521483 MsgCallback msg_callback_;
[email protected]43f28f832010-02-03 02:28:481484
[email protected]b0af4f52011-09-28 22:04:421485 StreamTextureManager* stream_texture_manager_;
1486
[email protected]32fe9aa2011-01-21 23:47:131487 // The format of the back buffer_
1488 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461489 bool back_buffer_has_depth_;
1490 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131491
[email protected]473c01ccb2011-06-07 01:33:301492 bool teximage2d_faster_than_texsubimage2d_;
1493 bool bufferdata_faster_than_buffersubdata_;
1494
[email protected]8eee29c2010-04-29 03:38:291495 // The last error message set.
1496 std::string last_error_;
1497
[email protected]a3a93e7b2010-08-28 00:48:561498 // The current decoder error.
1499 error::Error current_decoder_error_;
1500
[email protected]b1d2dcb2010-05-17 19:24:181501 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451502 scoped_ptr<ShaderTranslator> vertex_translator_;
1503 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181504
[email protected]e82fb792011-09-22 00:33:291505 DisallowedFeatures disallowed_features_;
[email protected]c410da802011-03-14 19:17:411506
[email protected]915a59a12010-09-30 21:29:111507 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051508 const Validators* validators_;
[email protected]80eb6b52012-01-19 00:14:411509 FeatureInfo::Ref feature_info_;
[email protected]9438b012010-06-15 22:55:051510
[email protected]b493ee622011-04-13 23:52:001511 // This indicates all the following texSubImage2D calls that are part of the
1512 // failed texImage2D call should be ignored.
1513 bool tex_image_2d_failed_;
1514
[email protected]65225772011-05-12 21:10:241515 int frame_number_;
1516
[email protected]38d139d2011-07-14 00:38:431517 bool has_arb_robustness_;
1518 GLenum reset_status_;
1519
[email protected]75c023c2011-08-22 23:54:511520 bool needs_mac_nvidia_driver_workaround_;
[email protected]a2a0fe762011-09-20 00:59:121521 bool needs_glsl_built_in_function_emulation_;
[email protected]75c023c2011-08-22 23:54:511522
[email protected]f0d74742011-10-03 16:31:041523 // These flags are used to override the state of the shared feature_info_
1524 // member. Because the same FeatureInfo instance may be shared among many
1525 // contexts, the assumptions on the availablity of extensions in WebGL
1526 // contexts may be broken. These flags override the shared state to preserve
1527 // WebGL semantics.
1528 bool force_webgl_glsl_validation_;
1529 bool derivatives_explicitly_enabled_;
1530
[email protected]062c38b2012-01-18 03:25:101531 bool compile_shader_always_succeeds_;
1532
[email protected]e51bdf32011-11-23 22:21:461533#if defined(OS_MACOSX)
1534 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1535 TextureToIOSurfaceMap texture_to_io_surface_map_;
1536#endif
1537
[email protected]c826d732012-02-09 04:40:261538 typedef std::vector<GLES2DecoderImpl*> ChildList;
1539 ChildList children_;
1540
[email protected]96449d2c2009-11-25 00:01:321541 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1542};
1543
[email protected]6217d392010-03-25 22:08:351544ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1545 : decoder_(decoder) {
1546 decoder_->CopyRealGLErrorsToWrapper();
1547}
1548
1549ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1550 decoder_->ClearRealGLErrors();
1551}
1552
1553ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1554 GLuint id)
1555 : decoder_(decoder) {
1556 ScopedGLErrorSuppressor suppressor(decoder_);
1557
1558 // TODO(apatrick): Check if there are any other states that need to be reset
1559 // before binding a new texture.
1560 glActiveTexture(GL_TEXTURE0);
1561 glBindTexture(GL_TEXTURE_2D, id);
1562}
1563
1564ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1565 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301566 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351567}
1568
1569ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1570 GLuint id)
1571 : decoder_(decoder) {
1572 ScopedGLErrorSuppressor suppressor(decoder_);
1573 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1574}
1575
1576ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1577 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301578 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351579}
1580
1581ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1582 GLuint id)
1583 : decoder_(decoder) {
1584 ScopedGLErrorSuppressor suppressor(decoder_);
1585 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1586}
1587
1588ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1589 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301590 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351591}
1592
[email protected]34ff8b0c2010-10-01 20:06:021593ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271594 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521595 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021596 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1597 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]c0701082011-04-20 00:34:521598 (!decoder_->bound_read_framebuffer_.get() ||
1599 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021600 if (!resolve_and_bind_)
1601 return;
1602
1603 ScopedGLErrorSuppressor suppressor(decoder_);
1604 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1605 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271606 GLuint targetid;
1607 if (internal) {
1608 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1609 decoder_->offscreen_resolved_frame_buffer_.reset(
1610 new FrameBuffer(decoder_));
1611 decoder_->offscreen_resolved_frame_buffer_->Create();
1612 decoder_->offscreen_resolved_color_texture_.reset(new Texture(decoder_));
1613 decoder_->offscreen_resolved_color_texture_->Create();
1614
1615 DCHECK(decoder_->offscreen_saved_color_format_);
1616 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1617 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_);
[email protected]de26b3c2011-08-03 21:54:271618 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1619 decoder_->offscreen_resolved_color_texture_.get());
1620 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1621 GL_FRAMEBUFFER_COMPLETE) {
1622 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1623 << "because offscreen resolved FBO was incomplete.";
1624 return;
1625 }
1626 }
1627 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1628 } else {
1629 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1630 }
1631 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021632 const int width = decoder_->offscreen_size_.width();
1633 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181634 glDisable(GL_SCISSOR_TEST);
[email protected]57edfdad2012-02-07 04:57:151635 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021636 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1637 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1638 } else {
1639 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1640 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1641 }
[email protected]de26b3c2011-08-03 21:54:271642 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021643}
1644
1645ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1646 if (!resolve_and_bind_)
1647 return;
1648
1649 ScopedGLErrorSuppressor suppressor(decoder_);
1650 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181651 if (decoder_->enable_scissor_test_) {
1652 glEnable(GL_SCISSOR_TEST);
1653 }
[email protected]34ff8b0c2010-10-01 20:06:021654}
1655
[email protected]6217d392010-03-25 22:08:351656Texture::Texture(GLES2DecoderImpl* decoder)
1657 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141658 id_(0),
1659 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351660}
1661
1662Texture::~Texture() {
1663 // This does not destroy the render texture because that would require that
1664 // the associated GL context was current. Just check that it was explicitly
1665 // destroyed.
1666 DCHECK_EQ(id_, 0u);
1667}
1668
1669void Texture::Create() {
1670 ScopedGLErrorSuppressor suppressor(decoder_);
1671 Destroy();
1672 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581673 ScopedTexture2DBinder binder(decoder_, id_);
1674 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1675 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1676 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1677 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]62788802011-10-03 17:57:161678
1679 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1680 // never called on an offscreen context, no data will ever be uploaded to the
1681 // saved offscreen color texture (it is deferred until to when SwapBuffers
1682 // is called). My idea is that some nvidia drivers might have a bug where
1683 // deleting a texture that has never been populated might cause a
1684 // crash.
1685 glTexImage2D(
1686 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
[email protected]1078f912011-12-23 13:12:141687 estimated_size_ = 16u * 16u * 4u;
1688 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351689}
1690
[email protected]34ff8b0c2010-10-01 20:06:021691bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351692 DCHECK_NE(id_, 0u);
1693 ScopedGLErrorSuppressor suppressor(decoder_);
1694 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]6217d392010-03-25 22:08:351695
[email protected]f0e6a34f2012-01-04 20:53:401696 WrappedTexImage2D(GL_TEXTURE_2D,
1697 0, // mip level
1698 format,
1699 size.width(),
1700 size.height(),
1701 0, // border
1702 format,
1703 GL_UNSIGNED_BYTE,
1704 NULL);
[email protected]6217d392010-03-25 22:08:351705
[email protected]d37231fa2010-04-09 21:16:021706 size_ = size;
1707
[email protected]1078f912011-12-23 13:12:141708 bool success = glGetError() == GL_NO_ERROR;
1709 if (success) {
1710 uint32 image_size = 0;
1711 GLES2Util::ComputeImageDataSize(
1712 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 4, &image_size);
1713 estimated_size_ = image_size;
1714 decoder_->UpdateBackbufferMemoryAccounting();
1715 }
1716 return success;
[email protected]6217d392010-03-25 22:08:351717}
1718
[email protected]3a4d0c52011-06-29 23:11:581719void Texture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351720 DCHECK_NE(id_, 0u);
1721 ScopedGLErrorSuppressor suppressor(decoder_);
1722 ScopedTexture2DBinder binder(decoder_, id_);
1723 glCopyTexImage2D(GL_TEXTURE_2D,
1724 0, // level
[email protected]3a4d0c52011-06-29 23:11:581725 format,
[email protected]6217d392010-03-25 22:08:351726 0, 0,
1727 size.width(),
1728 size.height(),
1729 0); // border
1730}
1731
1732void Texture::Destroy() {
1733 if (id_ != 0) {
1734 ScopedGLErrorSuppressor suppressor(decoder_);
1735 glDeleteTextures(1, &id_);
1736 id_ = 0;
[email protected]1078f912011-12-23 13:12:141737 estimated_size_ = 0;
1738 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351739 }
1740}
1741
[email protected]97872062010-11-03 19:07:051742void Texture::Invalidate() {
1743 id_ = 0;
1744}
1745
[email protected]6217d392010-03-25 22:08:351746RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1747 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141748 id_(0),
1749 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351750}
1751
1752RenderBuffer::~RenderBuffer() {
1753 // This does not destroy the render buffer because that would require that
1754 // the associated GL context was current. Just check that it was explicitly
1755 // destroyed.
1756 DCHECK_EQ(id_, 0u);
1757}
1758
1759void RenderBuffer::Create() {
1760 ScopedGLErrorSuppressor suppressor(decoder_);
1761 Destroy();
1762 glGenRenderbuffersEXT(1, &id_);
1763}
1764
[email protected]34ff8b0c2010-10-01 20:06:021765bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1766 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351767 ScopedGLErrorSuppressor suppressor(decoder_);
1768 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021769 if (samples <= 1) {
1770 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1771 format,
1772 size.width(),
1773 size.height());
1774 } else {
[email protected]57edfdad2012-02-07 04:57:151775 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021776 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1777 samples,
1778 format,
1779 size.width(),
1780 size.height());
1781 } else {
1782 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1783 samples,
1784 format,
1785 size.width(),
1786 size.height());
1787 }
1788 }
[email protected]1078f912011-12-23 13:12:141789 bool success = glGetError() == GL_NO_ERROR;
1790 if (success) {
1791 estimated_size_ = size.width() * size.height() * samples *
1792 GLES2Util::RenderbufferBytesPerPixel(format);
1793 decoder_->UpdateBackbufferMemoryAccounting();
1794 }
1795 return success;
[email protected]6217d392010-03-25 22:08:351796}
1797
1798void RenderBuffer::Destroy() {
1799 if (id_ != 0) {
1800 ScopedGLErrorSuppressor suppressor(decoder_);
1801 glDeleteRenderbuffersEXT(1, &id_);
1802 id_ = 0;
[email protected]1078f912011-12-23 13:12:141803 estimated_size_ = 0;
1804 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351805 }
1806}
1807
[email protected]97872062010-11-03 19:07:051808void RenderBuffer::Invalidate() {
1809 id_ = 0;
1810}
1811
[email protected]6217d392010-03-25 22:08:351812FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1813 : decoder_(decoder),
1814 id_(0) {
1815}
1816
1817FrameBuffer::~FrameBuffer() {
1818 // This does not destroy the frame buffer because that would require that
1819 // the associated GL context was current. Just check that it was explicitly
1820 // destroyed.
1821 DCHECK_EQ(id_, 0u);
1822}
1823
1824void FrameBuffer::Create() {
1825 ScopedGLErrorSuppressor suppressor(decoder_);
1826 Destroy();
1827 glGenFramebuffersEXT(1, &id_);
1828}
1829
1830void FrameBuffer::AttachRenderTexture(Texture* texture) {
1831 DCHECK_NE(id_, 0u);
1832 ScopedGLErrorSuppressor suppressor(decoder_);
1833 ScopedFrameBufferBinder binder(decoder_, id_);
1834 GLuint attach_id = texture ? texture->id() : 0;
1835 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1836 GL_COLOR_ATTACHMENT0,
1837 GL_TEXTURE_2D,
1838 attach_id,
1839 0);
1840}
1841
[email protected]b9363b22010-06-09 22:06:151842void FrameBuffer::AttachRenderBuffer(GLenum target,
1843 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351844 DCHECK_NE(id_, 0u);
1845 ScopedGLErrorSuppressor suppressor(decoder_);
1846 ScopedFrameBufferBinder binder(decoder_, id_);
1847 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1848 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151849 target,
[email protected]6217d392010-03-25 22:08:351850 GL_RENDERBUFFER,
1851 attach_id);
1852}
1853
[email protected]6217d392010-03-25 22:08:351854void FrameBuffer::Destroy() {
1855 if (id_ != 0) {
1856 ScopedGLErrorSuppressor suppressor(decoder_);
1857 glDeleteFramebuffersEXT(1, &id_);
1858 id_ = 0;
1859 }
1860}
1861
[email protected]97872062010-11-03 19:07:051862void FrameBuffer::Invalidate() {
1863 id_ = 0;
1864}
1865
[email protected]6217d392010-03-25 22:08:351866GLenum FrameBuffer::CheckStatus() {
1867 DCHECK_NE(id_, 0u);
1868 ScopedGLErrorSuppressor suppressor(decoder_);
1869 ScopedFrameBufferBinder binder(decoder_, id_);
1870 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1871}
1872
[email protected]aa7666122011-09-02 19:45:521873GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1874 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321875}
1876
[email protected]aa7666122011-09-02 19:45:521877GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391878 : GLES2Decoder(),
[email protected]3b1ecc262011-08-03 22:49:571879 group_(group),
[email protected]96449d2c2009-11-25 00:01:321880 error_bits_(0),
[email protected]96449d2c2009-11-25 00:01:321881 pack_alignment_(4),
1882 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241883 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491884 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241885 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401886 fixed_attrib_buffer_id_(0),
1887 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501888 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281889 clear_red_(0),
1890 clear_green_(0),
1891 clear_blue_(0),
1892 clear_alpha_(0),
1893 mask_red_(true),
1894 mask_green_(true),
1895 mask_blue_(true),
1896 mask_alpha_(true),
1897 clear_stencil_(0),
1898 mask_stencil_front_(-1),
1899 mask_stencil_back_(-1),
1900 clear_depth_(1.0f),
1901 mask_depth_(true),
1902 enable_scissor_test_(false),
[email protected]297ca1c2011-06-20 23:08:461903 enable_depth_test_(false),
1904 enable_stencil_test_(false),
1905 state_dirty_(true),
[email protected]34ff8b0c2010-10-01 20:06:021906 offscreen_target_color_format_(0),
1907 offscreen_target_depth_format_(0),
1908 offscreen_target_stencil_format_(0),
1909 offscreen_target_samples_(0),
[email protected]8a61d872012-01-20 12:43:561910 offscreen_target_buffer_preserved_(true),
[email protected]97872062010-11-03 19:07:051911 offscreen_saved_color_format_(0),
[email protected]b0af4f52011-09-28 22:04:421912 stream_texture_manager_(NULL),
[email protected]32fe9aa2011-01-21 23:47:131913 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:461914 back_buffer_has_depth_(false),
1915 back_buffer_has_stencil_(false),
[email protected]473c01ccb2011-06-07 01:33:301916 teximage2d_faster_than_texsubimage2d_(true),
1917 bufferdata_faster_than_buffersubdata_(true),
[email protected]a3a93e7b2010-08-28 00:48:561918 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051919 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111920 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001921 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241922 tex_image_2d_failed_(false),
[email protected]38d139d2011-07-14 00:38:431923 frame_number_(0),
1924 has_arb_robustness_(false),
[email protected]75c023c2011-08-22 23:54:511925 reset_status_(GL_NO_ERROR),
[email protected]a2a0fe762011-09-20 00:59:121926 needs_mac_nvidia_driver_workaround_(false),
[email protected]f0d74742011-10-03 16:31:041927 needs_glsl_built_in_function_emulation_(false),
1928 force_webgl_glsl_validation_(false),
[email protected]062c38b2012-01-18 03:25:101929 derivatives_explicitly_enabled_(false),
1930 compile_shader_always_succeeds_(false) {
[email protected]3b1ecc262011-08-03 22:49:571931 DCHECK(group);
1932
[email protected]b1122982010-05-17 23:04:241933 attrib_0_value_.v[0] = 0.0f;
1934 attrib_0_value_.v[1] = 0.0f;
1935 attrib_0_value_.v[2] = 0.0f;
1936 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151937
[email protected]c2f8c8402010-12-06 18:07:241938 // The shader translator is used for WebGL even when running on EGL
1939 // because additional restrictions are needed (like only enabling
1940 // GL_OES_standard_derivatives on demand). It is used for the unit
1941 // tests because
1942 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1943 // empty string to CompileShader and this is not a valid shader.
1944 // TODO(apatrick): fix this test.
1945 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:041946 !feature_info_->feature_flags().chromium_webglsl &&
1947 !force_webgl_glsl_validation_) ||
[email protected]b9363b22010-06-09 22:06:151948 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) {
1949 use_shader_translator_ = false;
1950 }
[email protected]473c01ccb2011-06-07 01:33:301951
1952 // TODO(gman): Consider setting these based on GPU and/or driver.
1953 if (IsAngle()) {
1954 teximage2d_faster_than_texsubimage2d_ = false;
1955 bufferdata_faster_than_buffersubdata_ = false;
1956 }
[email protected]96449d2c2009-11-25 00:01:321957}
1958
[email protected]80eb6b52012-01-19 00:14:411959GLES2DecoderImpl::~GLES2DecoderImpl() {
1960}
1961
[email protected]c410da802011-03-14 19:17:411962bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:381963 const scoped_refptr<gfx::GLSurface>& surface,
1964 const scoped_refptr<gfx::GLContext>& context,
[email protected]c410da802011-03-14 19:17:411965 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:291966 const DisallowedFeatures& disallowed_features,
[email protected]c410da802011-03-14 19:17:411967 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:241968 const std::vector<int32>& attribs) {
[email protected]4bedba72010-04-20 22:08:541969 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301970 DCHECK(!context_.get());
1971
[email protected]e844ae22012-01-14 03:36:261972 if (CommandLine::ForCurrentProcess()->HasSwitch(
1973 switches::kEnableGPUDebugging)) {
1974 set_debug(true);
1975 }
1976
[email protected]062c38b2012-01-18 03:25:101977 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
1978 switches::kCompileShaderAlwaysSucceeds);
1979
[email protected]fbe20372011-06-01 01:46:381980 // Take ownership of the GLSurface. TODO(apatrick): once the parent / child
1981 // context is retired, the decoder should not take an initial surface as
1982 // an argument to this function.
1983 // Maybe create a short lived offscreen GLSurface for the purpose of
1984 // initializing the decoder's GLContext.
1985 surface_ = surface;
[email protected]f62a5ab2011-05-23 20:34:151986
[email protected]66791e382010-07-14 20:48:301987 // Take ownership of the GLContext.
[email protected]fbe20372011-06-01 01:46:381988 context_ = context;
[email protected]d37231fa2010-04-09 21:16:021989
[email protected]246a70452010-03-05 21:53:501990 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:011991 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
1992 << "MakeCurrent failed.";
[email protected]1871a092011-10-10 21:46:421993 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]246a70452010-03-05 21:53:501994 Destroy();
1995 return false;
[email protected]eb54a562010-01-20 21:55:181996 }
1997
[email protected]e82fb792011-09-22 00:33:291998 if (!group_->Initialize(disallowed_features, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:221999 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:392000 << "failed to initialize.";
[email protected]1871a092011-10-10 21:46:422001 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]a3ded6d2010-10-19 06:44:392002 Destroy();
[email protected]ae1741092010-11-17 19:16:032003 return false;
[email protected]a3ded6d2010-10-19 06:44:392004 }
2005
[email protected]246a70452010-03-05 21:53:502006 CHECK_GL_ERROR();
[email protected]e82fb792011-09-22 00:33:292007 disallowed_features_ = disallowed_features;
[email protected]246a70452010-03-05 21:53:502008
[email protected]3757a372012-01-19 05:20:442009 vertex_attrib_manager_.reset(new VertexAttribManager());
2010 vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:322011
[email protected]302ce6d2011-07-07 23:28:112012 util_.set_num_compressed_texture_formats(
2013 validators_->compressed_texture_format.GetValues().size());
2014
[email protected]1071e572011-02-09 20:00:122015 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2016 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2017 // OpenGL ES 2.0 does not have this issue.
2018 glEnableVertexAttribArray(0);
2019 }
[email protected]b1122982010-05-17 23:04:242020 glGenBuffersARB(1, &attrib_0_buffer_id_);
2021 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2022 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2023 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:402024 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:082025
[email protected]246a70452010-03-05 21:53:502026 texture_units_.reset(
2027 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:152028 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:492029 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:312030 // We want the last bind to be 2D.
2031 TextureManager::TextureInfo* info;
2032 if (feature_info_->feature_flags().oes_egl_image_external) {
2033 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_EXTERNAL_OES);
2034 texture_units_[tt].bound_texture_external_oes = info;
2035 glBindTexture(GL_TEXTURE_EXTERNAL_OES, info->service_id());
2036 }
[email protected]e51bdf32011-11-23 22:21:462037 if (feature_info_->feature_flags().arb_texture_rectangle) {
2038 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_RECTANGLE_ARB);
2039 texture_units_[tt].bound_texture_rectangle_arb = info;
2040 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, info->service_id());
2041 }
[email protected]61eeb33f2011-07-26 15:30:312042 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:492043 texture_units_[tt].bound_texture_cube_map = info;
2044 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
2045 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2046 texture_units_[tt].bound_texture_2d = info;
2047 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:152048 }
[email protected]00f893d2010-08-24 18:55:492049 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:502050 CHECK_GL_ERROR();
2051
[email protected]297ca1c2011-06-20 23:08:462052 ContextCreationAttribParser attrib_parser;
2053 if (!attrib_parser.Parse(attribs))
2054 return false;
[email protected]41c56362011-06-14 16:47:432055
[email protected]297ca1c2011-06-20 23:08:462056 // These are NOT if the back buffer has these proprorties. They are
2057 // if we want the command buffer to enforce them regardless of what
2058 // the real backbuffer is assuming the real back buffer gives us more than
2059 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2060 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2061 // can't do anything about that.
2062
2063 GLint v = 0;
2064 glGetIntegerv(GL_ALPHA_BITS, &v);
2065 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2066 // user requested RGB then RGB. If the user did not specify a preference than
2067 // use whatever we were given. Same for DEPTH and STENCIL.
2068 back_buffer_color_format_ =
2069 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2070 glGetIntegerv(GL_DEPTH_BITS, &v);
2071 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2072 glGetIntegerv(GL_STENCIL_BITS, &v);
2073 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2074
2075 if (surface_->IsOffscreen()) {
[email protected]34ff8b0c2010-10-01 20:06:022076 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:542077 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:022078 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
2079 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:432080 // max_sample_count must be initialized to a sane value. If
2081 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2082 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:022083 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2084 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2085 max_sample_count);
2086 } else {
2087 offscreen_target_samples_ = 1;
2088 }
[email protected]8a61d872012-01-20 12:43:562089 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
[email protected]34ff8b0c2010-10-01 20:06:022090
2091 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2092 const bool rgb8_supported =
2093 context_->HasExtension("GL_OES_rgb8_rgba8");
2094 // The only available default render buffer formats in GLES2 have very
2095 // little precision. Don't enable multisampling unless 8-bit render
2096 // buffer formats are available--instead fall back to 8-bit textures.
2097 if (rgb8_supported && offscreen_target_samples_ > 1) {
2098 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2099 GL_RGBA8 : GL_RGB8;
2100 } else {
2101 offscreen_target_samples_ = 1;
2102 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2103 GL_RGBA : GL_RGB;
2104 }
2105
2106 // ANGLE only supports packed depth/stencil formats, so use it if it is
2107 // available.
2108 const bool depth24_stencil8_supported =
2109 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272110 VLOG(1) << "GL_OES_packed_depth_stencil "
2111 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:002112 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2113 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022114 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2115 offscreen_target_stencil_format_ = 0;
2116 } else {
2117 // It may be the case that this depth/stencil combination is not
2118 // supported, but this will be checked later by CheckFramebufferStatus.
2119 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2120 GL_DEPTH_COMPONENT16 : 0;
2121 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2122 GL_STENCIL_INDEX8 : 0;
2123 }
2124 } else {
2125 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2126 GL_RGBA : GL_RGB;
2127
2128 // If depth is requested at all, use the packed depth stencil format if
2129 // it's available, as some desktop GL drivers don't support any non-packed
2130 // formats for depth attachments.
2131 const bool depth24_stencil8_supported =
2132 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272133 VLOG(1) << "GL_EXT_packed_depth_stencil "
2134 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:022135
[email protected]71ee3642010-10-14 18:08:002136 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2137 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022138 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2139 offscreen_target_stencil_format_ = 0;
2140 } else {
2141 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2142 GL_DEPTH_COMPONENT : 0;
2143 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2144 GL_STENCIL_INDEX : 0;
2145 }
2146 }
2147
[email protected]97872062010-11-03 19:07:052148 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2149 GL_RGBA : GL_RGB;
2150
[email protected]6217d392010-03-25 22:08:352151 // Create the target frame buffer. This is the one that the client renders
2152 // directly to.
2153 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
2154 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022155 // Due to GLES2 format limitations, either the color texture (for
2156 // non-multisampling) or the color render buffer (for multisampling) will be
2157 // attached to the offscreen frame buffer. The render buffer has more
2158 // limited formats available to it, but the texture can't do multisampling.
2159 if (IsOffscreenBufferMultisampled()) {
2160 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
2161 offscreen_target_color_render_buffer_->Create();
2162 } else {
2163 offscreen_target_color_texture_.reset(new Texture(this));
2164 offscreen_target_color_texture_->Create();
2165 }
2166 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152167 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022168 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152169 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:352170
2171 // Create the saved offscreen texture. The target frame buffer is copied
2172 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:022173 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
2174 offscreen_saved_frame_buffer_->Create();
2175 //
[email protected]6217d392010-03-25 22:08:352176 offscreen_saved_color_texture_.reset(new Texture(this));
2177 offscreen_saved_color_texture_->Create();
2178
[email protected]6217d392010-03-25 22:08:352179 // Allocate the render buffers at their initial size and check the status
2180 // of the frame buffers is okay.
[email protected]799b4b22011-08-22 17:09:592181 if (!ResizeOffscreenFrameBuffer(size)) {
[email protected]d0498742010-09-20 20:27:012182 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:352183 Destroy();
2184 return false;
2185 }
2186
2187 // Bind to the new default frame buffer (the offscreen target frame buffer).
2188 // This should now be associated with ID zero.
2189 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2190 }
2191
[email protected]295faf4b2012-01-25 23:31:412192 // Clear the backbuffer.
2193 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2194
[email protected]76a0ee102010-04-07 21:03:042195 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2196 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2197 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372198 // mailing list archives. It also implicitly enables the desktop GL
2199 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2200 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152201 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2202 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372203 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152204 }
[email protected]de17df392010-04-23 21:09:412205
[email protected]38d139d2011-07-14 00:38:432206 has_arb_robustness_ = context->HasExtension("GL_ARB_robustness");
2207
[email protected]e82fb792011-09-22 00:33:292208 if (!disallowed_features_.driver_bug_workarounds) {
[email protected]75c023c2011-08-22 23:54:512209#if defined(OS_MACOSX)
[email protected]a2a0fe762011-09-20 00:59:122210 const char* vendor_str = reinterpret_cast<const char*>(
2211 glGetString(GL_VENDOR));
2212 needs_mac_nvidia_driver_workaround_ =
2213 vendor_str && strstr(vendor_str, "NVIDIA");
2214 needs_glsl_built_in_function_emulation_ =
2215 vendor_str && (strstr(vendor_str, "ATI") || strstr(vendor_str, "AMD"));
2216#elif defined(OS_WIN)
2217 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
2218 needs_glsl_built_in_function_emulation_ = true;
[email protected]75c023c2011-08-22 23:54:512219#endif
[email protected]a2a0fe762011-09-20 00:59:122220 }
[email protected]75c023c2011-08-22 23:54:512221
[email protected]c2f8c8402010-12-06 18:07:242222 if (!InitializeShaderTranslator()) {
2223 return false;
[email protected]de17df392010-04-23 21:09:412224 }
[email protected]76a0ee102010-04-07 21:03:042225
[email protected]246a70452010-03-05 21:53:502226 return true;
[email protected]96449d2c2009-11-25 00:01:322227}
2228
[email protected]302ce6d2011-07-07 23:28:112229void GLES2DecoderImpl::UpdateCapabilities() {
2230 util_.set_num_compressed_texture_formats(
2231 validators_->compressed_texture_format.GetValues().size());
2232 util_.set_num_shader_binary_formats(
2233 validators_->shader_binary_format.GetValues().size());
2234}
2235
[email protected]c2f8c8402010-12-06 18:07:242236bool GLES2DecoderImpl::InitializeShaderTranslator() {
2237 // Re-check the state of use_shader_translator_ each time this is called.
2238 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:042239 (feature_info_->feature_flags().chromium_webglsl ||
2240 force_webgl_glsl_validation_) &&
[email protected]c2f8c8402010-12-06 18:07:242241 !use_shader_translator_) {
2242 use_shader_translator_ = true;
2243 }
2244 if (!use_shader_translator_) {
2245 return true;
2246 }
2247 ShBuiltInResources resources;
2248 ShInitBuiltInResources(&resources);
2249 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2250 resources.MaxVertexUniformVectors =
2251 group_->max_vertex_uniform_vectors();
2252 resources.MaxVaryingVectors = group_->max_varying_vectors();
2253 resources.MaxVertexTextureImageUnits =
2254 group_->max_vertex_texture_image_units();
2255 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2256 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2257 resources.MaxFragmentUniformVectors =
2258 group_->max_fragment_uniform_vectors();
2259 resources.MaxDrawBuffers = 1;
[email protected]f0d74742011-10-03 16:31:042260
2261 if (force_webgl_glsl_validation_) {
2262 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2263 } else {
2264 resources.OES_standard_derivatives =
2265 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
[email protected]e51bdf32011-11-23 22:21:462266 resources.ARB_texture_rectangle =
2267 feature_info_->feature_flags().arb_texture_rectangle ? 1 : 0;
[email protected]f0d74742011-10-03 16:31:042268 }
2269
[email protected]c2f8c8402010-12-06 18:07:242270 vertex_translator_.reset(new ShaderTranslator);
[email protected]f0d74742011-10-03 16:31:042271 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ||
2272 feature_info_->feature_flags().chromium_webglsl ?
2273 SH_WEBGL_SPEC : SH_GLES2_SPEC;
[email protected]a2a0fe762011-09-20 00:59:122274 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2275 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2276 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2277 ShaderTranslatorInterface::GlslBuiltInFunctionBehavior function_behavior =
2278 needs_glsl_built_in_function_emulation_ ?
2279 ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated :
2280 ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal;
[email protected]c2f8c8402010-12-06 18:07:242281 if (!vertex_translator_->Init(
[email protected]a2a0fe762011-09-20 00:59:122282 SH_VERTEX_SHADER, shader_spec, &resources,
2283 implementation_type, function_behavior)) {
[email protected]c2f8c8402010-12-06 18:07:242284 LOG(ERROR) << "Could not initialize vertex shader translator.";
2285 Destroy();
2286 return false;
2287 }
2288 fragment_translator_.reset(new ShaderTranslator);
2289 if (!fragment_translator_->Init(
[email protected]a2a0fe762011-09-20 00:59:122290 SH_FRAGMENT_SHADER, shader_spec, &resources,
2291 implementation_type, function_behavior)) {
[email protected]c2f8c8402010-12-06 18:07:242292 LOG(ERROR) << "Could not initialize fragment shader translator.";
2293 Destroy();
2294 return false;
2295 }
2296 return true;
2297}
2298
[email protected]ae51d192010-04-27 00:48:032299bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472300 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032301 if (GetBufferInfo(client_ids[ii])) {
2302 return false;
2303 }
2304 }
2305 scoped_array<GLuint> service_ids(new GLuint[n]);
2306 glGenBuffersARB(n, service_ids.get());
2307 for (GLsizei ii = 0; ii < n; ++ii) {
2308 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2309 }
2310 return true;
2311}
2312
2313bool GLES2DecoderImpl::GenFramebuffersHelper(
2314 GLsizei n, const GLuint* client_ids) {
2315 for (GLsizei ii = 0; ii < n; ++ii) {
2316 if (GetFramebufferInfo(client_ids[ii])) {
2317 return false;
2318 }
2319 }
2320 scoped_array<GLuint> service_ids(new GLuint[n]);
2321 glGenFramebuffersEXT(n, service_ids.get());
2322 for (GLsizei ii = 0; ii < n; ++ii) {
2323 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2324 }
2325 return true;
2326}
2327
2328bool GLES2DecoderImpl::GenRenderbuffersHelper(
2329 GLsizei n, const GLuint* client_ids) {
2330 for (GLsizei ii = 0; ii < n; ++ii) {
2331 if (GetRenderbufferInfo(client_ids[ii])) {
2332 return false;
2333 }
2334 }
2335 scoped_array<GLuint> service_ids(new GLuint[n]);
2336 glGenRenderbuffersEXT(n, service_ids.get());
2337 for (GLsizei ii = 0; ii < n; ++ii) {
2338 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2339 }
2340 return true;
2341}
2342
2343bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2344 for (GLsizei ii = 0; ii < n; ++ii) {
2345 if (GetTextureInfo(client_ids[ii])) {
2346 return false;
2347 }
2348 }
2349 scoped_array<GLuint> service_ids(new GLuint[n]);
2350 glGenTextures(n, service_ids.get());
2351 for (GLsizei ii = 0; ii < n; ++ii) {
2352 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2353 }
2354 return true;
2355}
2356
2357void GLES2DecoderImpl::DeleteBuffersHelper(
2358 GLsizei n, const GLuint* client_ids) {
2359 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102360 BufferManager::BufferInfo* buffer = GetBufferInfo(client_ids[ii]);
2361 if (buffer && !buffer->IsDeleted()) {
[email protected]3757a372012-01-19 05:20:442362 vertex_attrib_manager_->Unbind(buffer);
[email protected]a0b78dc2011-11-11 10:43:102363 if (bound_array_buffer_ == buffer) {
2364 bound_array_buffer_ = NULL;
2365 }
2366 if (bound_element_array_buffer_ == buffer) {
2367 bound_element_array_buffer_ = NULL;
2368 }
2369 GLuint service_id = buffer->service_id();
[email protected]ae51d192010-04-27 00:48:032370 glDeleteBuffersARB(1, &service_id);
2371 RemoveBufferInfo(client_ids[ii]);
2372 }
[email protected]a93bb842010-02-16 23:03:472373 }
[email protected]07f54fcc2009-12-22 02:46:302374}
2375
[email protected]ae51d192010-04-27 00:48:032376void GLES2DecoderImpl::DeleteFramebuffersHelper(
2377 GLsizei n, const GLuint* client_ids) {
[email protected]b177ae22011-11-01 03:29:112378 bool supports_seperate_framebuffer_binds =
2379 feature_info_->feature_flags().chromium_framebuffer_multisample;
2380
[email protected]a25fa872010-03-25 02:57:582381 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102382 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ae51d192010-04-27 00:48:032383 GetFramebufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102384 if (framebuffer && !framebuffer->IsDeleted()) {
2385 if (framebuffer == bound_draw_framebuffer_) {
[email protected]297ca1c2011-06-20 23:08:462386 bound_draw_framebuffer_ = NULL;
2387 state_dirty_ = true;
[email protected]b177ae22011-11-01 03:29:112388 GLenum target = supports_seperate_framebuffer_binds ?
2389 GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER;
2390 glBindFramebufferEXT(target, GetBackbufferServiceId());
2391 }
[email protected]a0b78dc2011-11-11 10:43:102392 if (framebuffer == bound_read_framebuffer_) {
[email protected]b177ae22011-11-01 03:29:112393 bound_read_framebuffer_ = NULL;
2394 GLenum target = supports_seperate_framebuffer_binds ?
2395 GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER;
2396 glBindFramebufferEXT(target, GetBackbufferServiceId());
[email protected]297ca1c2011-06-20 23:08:462397 }
[email protected]a0b78dc2011-11-11 10:43:102398 GLuint service_id = framebuffer->service_id();
[email protected]ae51d192010-04-27 00:48:032399 glDeleteFramebuffersEXT(1, &service_id);
2400 RemoveFramebufferInfo(client_ids[ii]);
2401 }
[email protected]a25fa872010-03-25 02:57:582402 }
[email protected]07f54fcc2009-12-22 02:46:302403}
2404
[email protected]ae51d192010-04-27 00:48:032405void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2406 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102407 bool supports_seperate_framebuffer_binds =
2408 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a25fa872010-03-25 02:57:582409 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102410 RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]ae51d192010-04-27 00:48:032411 GetRenderbufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102412 if (renderbuffer && !renderbuffer->IsDeleted()) {
2413 if (bound_renderbuffer_ == renderbuffer) {
2414 bound_renderbuffer_ = NULL;
2415 }
2416 // Unbind from current framebuffers.
2417 if (supports_seperate_framebuffer_binds) {
2418 if (bound_read_framebuffer_) {
2419 bound_read_framebuffer_->UnbindRenderbuffer(
2420 GL_READ_FRAMEBUFFER, renderbuffer);
2421 }
2422 if (bound_draw_framebuffer_) {
2423 bound_draw_framebuffer_->UnbindRenderbuffer(
2424 GL_DRAW_FRAMEBUFFER, renderbuffer);
2425 }
2426 } else {
2427 if (bound_draw_framebuffer_) {
2428 bound_draw_framebuffer_->UnbindRenderbuffer(
2429 GL_FRAMEBUFFER, renderbuffer);
2430 }
2431 }
[email protected]297ca1c2011-06-20 23:08:462432 state_dirty_ = true;
[email protected]a0b78dc2011-11-11 10:43:102433 GLuint service_id = renderbuffer->service_id();
[email protected]ae51d192010-04-27 00:48:032434 glDeleteRenderbuffersEXT(1, &service_id);
2435 RemoveRenderbufferInfo(client_ids[ii]);
2436 }
[email protected]a25fa872010-03-25 02:57:582437 }
[email protected]07f54fcc2009-12-22 02:46:302438}
2439
[email protected]ae51d192010-04-27 00:48:032440void GLES2DecoderImpl::DeleteTexturesHelper(
2441 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102442 bool supports_seperate_framebuffer_binds =
2443 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a93bb842010-02-16 23:03:472444 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102445 TextureManager::TextureInfo* texture = GetTextureInfo(client_ids[ii]);
2446 if (texture && !texture->IsDeleted()) {
2447 if (texture->IsAttachedToFramebuffer()) {
[email protected]297ca1c2011-06-20 23:08:462448 state_dirty_ = true;
2449 }
[email protected]a0b78dc2011-11-11 10:43:102450 // Unbind texture from texture units.
2451 for (size_t jj = 0; jj < group_->max_texture_units(); ++jj) {
2452 texture_units_[ii].Unbind(texture);
2453 }
2454 // Unbind from current framebuffers.
2455 if (supports_seperate_framebuffer_binds) {
2456 if (bound_read_framebuffer_) {
2457 bound_read_framebuffer_->UnbindTexture(GL_READ_FRAMEBUFFER, texture);
2458 }
2459 if (bound_draw_framebuffer_) {
2460 bound_draw_framebuffer_->UnbindTexture(GL_DRAW_FRAMEBUFFER, texture);
2461 }
2462 } else {
2463 if (bound_draw_framebuffer_) {
2464 bound_draw_framebuffer_->UnbindTexture(GL_FRAMEBUFFER, texture);
2465 }
2466 }
2467 GLuint service_id = texture->service_id();
2468 if (texture->IsStreamTexture() && stream_texture_manager_) {
[email protected]b0af4f52011-09-28 22:04:422469 stream_texture_manager_->DestroyStreamTexture(service_id);
2470 }
[email protected]e51bdf32011-11-23 22:21:462471#if defined(OS_MACOSX)
2472 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2473 ReleaseIOSurfaceForTexture(service_id);
2474 }
2475#endif
[email protected]5f4f2a732011-07-30 00:47:552476 glDeleteTextures(1, &service_id);
[email protected]ae51d192010-04-27 00:48:032477 RemoveTextureInfo(client_ids[ii]);
2478 }
[email protected]a93bb842010-02-16 23:03:472479 }
[email protected]07f54fcc2009-12-22 02:46:302480}
2481
[email protected]43f28f832010-02-03 02:28:482482// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322483
[email protected]eb54a562010-01-20 21:55:182484bool GLES2DecoderImpl::MakeCurrent() {
[email protected]38d139d2011-07-14 00:38:432485 bool result = context_.get() ? context_->MakeCurrent(surface_.get()) : false;
2486 if (result && WasContextLost()) {
2487 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2488 result = false;
2489 }
2490
2491 return result;
[email protected]eb54a562010-01-20 21:55:182492}
2493
[email protected]a96a6022011-11-04 00:58:122494void GLES2DecoderImpl::ReleaseCurrent() {
2495 if (context_.get())
2496 context_->ReleaseCurrent(surface_.get());
2497}
2498
[email protected]8e3e0662010-08-23 18:46:302499void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
[email protected]0d6bfdc2011-11-02 01:32:202500 RenderbufferManager::RenderbufferInfo* renderbuffer =
2501 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
[email protected]8e3e0662010-08-23 18:46:302502 glBindRenderbufferEXT(
[email protected]0d6bfdc2011-11-02 01:32:202503 GL_RENDERBUFFER, renderbuffer ? renderbuffer->service_id() : 0);
[email protected]8e3e0662010-08-23 18:46:302504}
2505
2506static void RebindCurrentFramebuffer(
2507 GLenum target,
2508 FramebufferManager::FramebufferInfo* info,
[email protected]a3783712012-01-20 22:18:242509 GLuint back_buffer_service_id) {
[email protected]8e3e0662010-08-23 18:46:302510 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462511
[email protected]a3783712012-01-20 22:18:242512 if (framebuffer_id == 0) {
2513 framebuffer_id = back_buffer_service_id;
[email protected]8e3e0662010-08-23 18:46:302514 }
[email protected]297ca1c2011-06-20 23:08:462515
[email protected]8e3e0662010-08-23 18:46:302516 glBindFramebufferEXT(target, framebuffer_id);
2517}
2518
2519void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]297ca1c2011-06-20 23:08:462520 state_dirty_ = true;
2521
[email protected]a3ded6d2010-10-19 06:44:392522 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302523 RebindCurrentFramebuffer(
2524 GL_FRAMEBUFFER,
2525 bound_draw_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242526 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302527 } else {
2528 RebindCurrentFramebuffer(
2529 GL_READ_FRAMEBUFFER_EXT,
2530 bound_read_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242531 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302532 RebindCurrentFramebuffer(
2533 GL_DRAW_FRAMEBUFFER_EXT,
2534 bound_draw_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242535 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302536 }
2537}
2538
2539void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2540 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2541 GLuint last_id;
2542 if (info.bound_texture_2d) {
2543 last_id = info.bound_texture_2d->service_id();
2544 } else {
2545 last_id = 0;
2546 }
2547
2548 glBindTexture(GL_TEXTURE_2D, last_id);
2549 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2550}
2551
[email protected]0d6bfdc2011-11-02 01:32:202552bool GLES2DecoderImpl::CheckFramebufferValid(
2553 FramebufferManager::FramebufferInfo* framebuffer,
2554 GLenum target, const char* func_name) {
[email protected]a0b78dc2011-11-11 10:43:102555 if (!framebuffer) {
[email protected]0d6bfdc2011-11-02 01:32:202556 return true;
2557 }
2558
[email protected]968351b2011-12-20 08:26:512559 if (framebuffer_manager()->IsComplete(framebuffer)) {
2560 return true;
2561 }
2562
[email protected]0d6bfdc2011-11-02 01:32:202563 GLenum completeness = framebuffer->IsPossiblyComplete();
2564 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
2565 SetGLError(
2566 GL_INVALID_FRAMEBUFFER_OPERATION,
2567 (std::string(func_name) + " framebuffer incomplete").c_str());
[email protected]3a03a8f2011-03-19 00:51:272568 return false;
2569 }
[email protected]0d6bfdc2011-11-02 01:32:202570
2571 // Are all the attachments cleared?
2572 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2573 texture_manager()->HaveUnclearedMips()) {
2574 if (!framebuffer->IsCleared()) {
2575 // Can we clear them?
2576 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2577 SetGLError(
2578 GL_INVALID_FRAMEBUFFER_OPERATION,
2579 (std::string(func_name) +
2580 " framebuffer incomplete (clear)").c_str());
2581 return false;
2582 }
2583 ClearUnclearedAttachments(target, framebuffer);
2584 }
2585 }
2586
[email protected]968351b2011-12-20 08:26:512587 if (!framebuffer_manager()->IsComplete(framebuffer)) {
2588 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2589 SetGLError(
2590 GL_INVALID_FRAMEBUFFER_OPERATION,
2591 (std::string(func_name) +
2592 " framebuffer incomplete (check)").c_str());
2593 return false;
2594 }
2595 framebuffer_manager()->MarkAsComplete(framebuffer);
2596 }
2597
[email protected]0d6bfdc2011-11-02 01:32:202598 // NOTE: At this point we don't know if the framebuffer is complete but
2599 // we DO know that everything that needs to be cleared has been cleared.
[email protected]3a03a8f2011-03-19 00:51:272600 return true;
2601}
2602
[email protected]0d6bfdc2011-11-02 01:32:202603bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
2604 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
2605 return CheckFramebufferValid(
2606 bound_draw_framebuffer_, GL_FRAMEBUFFER_EXT, func_name);
2607 }
2608 return CheckFramebufferValid(
2609 bound_draw_framebuffer_, GL_DRAW_FRAMEBUFFER_EXT, func_name) &&
2610 CheckFramebufferValid(
2611 bound_read_framebuffer_, GL_READ_FRAMEBUFFER_EXT, func_name);
2612}
2613
[email protected]8e3e0662010-08-23 18:46:302614gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
[email protected]0d6bfdc2011-11-02 01:32:202615 FramebufferManager::FramebufferInfo* framebuffer =
2616 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2617 if (framebuffer != NULL) {
[email protected]9edc6b22010-12-23 02:00:262618 const FramebufferManager::FramebufferInfo::Attachment* attachment =
[email protected]0d6bfdc2011-11-02 01:32:202619 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
[email protected]9edc6b22010-12-23 02:00:262620 if (attachment) {
2621 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502622 }
[email protected]9edc6b22010-12-23 02:00:262623 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022624 } else if (offscreen_target_frame_buffer_.get()) {
2625 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352626 } else {
[email protected]f62a5ab2011-05-23 20:34:152627 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022628 }
[email protected]246a70452010-03-05 21:53:502629}
2630
[email protected]9edc6b22010-12-23 02:00:262631GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202632 FramebufferManager::FramebufferInfo* framebuffer =
2633 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2634 if (framebuffer != NULL) {
2635 return framebuffer->GetColorAttachmentFormat();
[email protected]297ca1c2011-06-20 23:08:462636 } else if (offscreen_target_frame_buffer_.get()) {
2637 return offscreen_target_color_format_;
2638 } else {
2639 return back_buffer_color_format_;
2640 }
2641}
2642
2643GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202644 FramebufferManager::FramebufferInfo* framebuffer =
2645 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
2646 if (framebuffer != NULL) {
2647 return framebuffer->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262648 } else if (offscreen_target_frame_buffer_.get()) {
2649 return offscreen_target_color_format_;
2650 } else {
[email protected]32fe9aa2011-01-21 23:47:132651 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262652 }
2653}
2654
[email protected]9a5afa432011-07-22 18:16:392655void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]34ff8b0c2010-10-01 20:06:022656 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582657 // Update the info about the offscreen saved color texture in the parent.
2658 // The reference to the parent is a weak pointer and will become null if the
2659 // parent is later destroyed.
[email protected]262d7aa2010-12-03 22:07:292660 TextureManager* parent_texture_manager = parent_->texture_manager();
[email protected]262d7aa2010-12-03 22:07:292661 parent_texture_manager->SetLevelInfo(
[email protected]8a61d872012-01-20 12:43:562662 offscreen_saved_color_texture_info_,
[email protected]ef526492010-06-02 23:12:252663 GL_TEXTURE_2D,
2664 0, // level
2665 GL_RGBA,
[email protected]799b4b22011-08-22 17:09:592666 offscreen_size_.width(),
2667 offscreen_size_.height(),
[email protected]ef526492010-06-02 23:12:252668 1, // depth
2669 0, // border
2670 GL_RGBA,
[email protected]0d6bfdc2011-11-02 01:32:202671 GL_UNSIGNED_BYTE,
2672 true);
[email protected]262d7aa2010-12-03 22:07:292673 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562674 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042675 GL_TEXTURE_MAG_FILTER,
2676 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292677 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562678 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042679 GL_TEXTURE_MIN_FILTER,
2680 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292681 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562682 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042683 GL_TEXTURE_WRAP_S,
2684 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292685 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562686 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042687 GL_TEXTURE_WRAP_T,
2688 GL_CLAMP_TO_EDGE);
[email protected]8a61d872012-01-20 12:43:562689 } else {
2690 offscreen_saved_color_texture_info_ = NULL;
[email protected]0c8c9d22010-06-25 17:36:392691 }
[email protected]6217d392010-03-25 22:08:352692}
2693
[email protected]799b4b22011-08-22 17:09:592694void GLES2DecoderImpl::SetResizeCallback(
[email protected]9d37f062011-11-22 01:24:522695 const base::Callback<void(gfx::Size)>& callback) {
2696 resize_callback_ = callback;
[email protected]7ff86b92010-11-25 17:50:002697}
2698
[email protected]6b6e7ee2011-12-13 08:04:522699void GLES2DecoderImpl::SetMsgCallback(const MsgCallback& callback) {
2700 msg_callback_ = callback;
2701}
2702
[email protected]b0af4f52011-09-28 22:04:422703void GLES2DecoderImpl::SetStreamTextureManager(StreamTextureManager* manager) {
2704 stream_texture_manager_ = manager;
2705}
2706
[email protected]1318e922010-09-17 22:03:162707bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2708 uint32* service_texture_id) {
2709 TextureManager::TextureInfo* texture =
2710 texture_manager()->GetTextureInfo(client_texture_id);
2711 if (texture) {
2712 *service_texture_id = texture->service_id();
2713 return true;
2714 }
2715 return false;
2716}
2717
[email protected]96449d2c2009-11-25 00:01:322718void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392719 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052720
[email protected]c826d732012-02-09 04:40:262721 ChildList children = children_;
2722 for (ChildList::iterator it = children.begin(); it != children.end(); ++it)
2723 (*it)->SetParent(NULL, 0);
2724 DCHECK(children_.empty());
[email protected]3c644d82011-06-20 19:58:242725 SetParent(NULL, 0);
2726
[email protected]80eb6b52012-01-19 00:14:412727 // Unbind everything.
[email protected]3757a372012-01-19 05:20:442728 vertex_attrib_manager_.reset();
[email protected]80eb6b52012-01-19 00:14:412729 texture_units_.reset();
2730 bound_array_buffer_ = NULL;
2731 bound_element_array_buffer_ = NULL;
2732 current_program_ = NULL;
2733 bound_read_framebuffer_ = NULL;
2734 bound_draw_framebuffer_ = NULL;
2735 bound_renderbuffer_ = NULL;
2736
[email protected]eadc96792010-10-27 19:39:392737 if (have_context) {
[email protected]ca488e12010-12-13 20:06:142738 if (current_program_) {
2739 program_manager()->UnuseProgram(shader_manager(), current_program_);
2740 current_program_ = NULL;
2741 }
2742
[email protected]b1122982010-05-17 23:04:242743 if (attrib_0_buffer_id_) {
2744 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2745 }
[email protected]8fbedc02010-11-18 18:43:402746 if (fixed_attrib_buffer_id_) {
2747 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2748 }
[email protected]b1122982010-05-17 23:04:242749
[email protected]97872062010-11-03 19:07:052750 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542751 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052752 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542753 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052754 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022755 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052756 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152757 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052758 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152759 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052760 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022761 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052762 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542763 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:272764 if (offscreen_resolved_frame_buffer_.get())
2765 offscreen_resolved_frame_buffer_->Destroy();
2766 if (offscreen_resolved_color_texture_.get())
2767 offscreen_resolved_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052768 } else {
2769 if (offscreen_target_frame_buffer_.get())
2770 offscreen_target_frame_buffer_->Invalidate();
2771 if (offscreen_target_color_texture_.get())
2772 offscreen_target_color_texture_->Invalidate();
2773 if (offscreen_target_color_render_buffer_.get())
2774 offscreen_target_color_render_buffer_->Invalidate();
2775 if (offscreen_target_depth_render_buffer_.get())
2776 offscreen_target_depth_render_buffer_->Invalidate();
2777 if (offscreen_target_stencil_render_buffer_.get())
2778 offscreen_target_stencil_render_buffer_->Invalidate();
2779 if (offscreen_saved_frame_buffer_.get())
2780 offscreen_saved_frame_buffer_->Invalidate();
2781 if (offscreen_saved_color_texture_.get())
2782 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:272783 if (offscreen_resolved_frame_buffer_.get())
2784 offscreen_resolved_frame_buffer_->Invalidate();
2785 if (offscreen_resolved_color_texture_.get())
2786 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022787 }
[email protected]97872062010-11-03 19:07:052788
[email protected]1871a092011-10-10 21:46:422789 if (group_) {
2790 group_->Destroy(have_context);
2791 group_ = NULL;
2792 }
[email protected]3ae019382011-10-05 19:42:412793
[email protected]fe871662011-06-16 20:43:052794 if (context_.get()) {
2795 context_->ReleaseCurrent(NULL);
[email protected]79311e82011-09-20 00:40:502796 context_ = NULL;
[email protected]fe871662011-06-16 20:43:052797 }
[email protected]0fc35742011-04-13 17:57:542798
[email protected]97872062010-11-03 19:07:052799 offscreen_target_frame_buffer_.reset();
2800 offscreen_target_color_texture_.reset();
2801 offscreen_target_color_render_buffer_.reset();
2802 offscreen_target_depth_render_buffer_.reset();
2803 offscreen_target_stencil_render_buffer_.reset();
2804 offscreen_saved_frame_buffer_.reset();
2805 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:272806 offscreen_resolved_frame_buffer_.reset();
2807 offscreen_resolved_color_texture_.reset();
[email protected]e51bdf32011-11-23 22:21:462808
2809#if defined(OS_MACOSX)
2810 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
2811 it != texture_to_io_surface_map_.end(); ++it) {
2812 CFRelease(it->second);
2813 }
2814 texture_to_io_surface_map_.clear();
2815#endif
[email protected]96449d2c2009-11-25 00:01:322816}
2817
[email protected]3c644d82011-06-20 19:58:242818bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
2819 uint32 new_parent_texture_id) {
[email protected]9a5afa432011-07-22 18:16:392820 if (!offscreen_saved_color_texture_.get())
2821 return false;
2822
[email protected]3c644d82011-06-20 19:58:242823 // Remove the saved frame buffer mapping from the parent decoder. The
2824 // parent pointer is a weak pointer so it will be null if the parent has
2825 // already been destroyed.
2826 if (parent_) {
[email protected]c826d732012-02-09 04:40:262827 ChildList::iterator it = std::find(
2828 parent_->children_.begin(),
2829 parent_->children_.end(),
2830 this);
2831 DCHECK(it != parent_->children_.end());
2832 parent_->children_.erase(it);
[email protected]3c644d82011-06-20 19:58:242833 // First check the texture has been mapped into the parent. This might not
2834 // be the case if initialization failed midway through.
2835 GLuint service_id = offscreen_saved_color_texture_->id();
2836 GLuint client_id = 0;
2837 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
[email protected]80eb6b52012-01-19 00:14:412838 parent_->texture_manager()->RemoveTextureInfo(client_id);
[email protected]3c644d82011-06-20 19:58:242839 }
2840 }
2841
2842 GLES2DecoderImpl* new_parent_impl = static_cast<GLES2DecoderImpl*>(
2843 new_parent);
2844 if (new_parent_impl) {
[email protected]c826d732012-02-09 04:40:262845#ifndef NDEBUG
2846 ChildList::iterator it = std::find(
2847 new_parent_impl->children_.begin(),
2848 new_parent_impl->children_.end(),
2849 this);
2850 DCHECK(it == new_parent_impl->children_.end());
2851#endif
2852 new_parent_impl->children_.push_back(this);
[email protected]3c644d82011-06-20 19:58:242853 // Map the ID of the saved offscreen texture into the parent so that
2854 // it can reference it.
2855 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]98687862011-07-11 23:31:302856
2857 // Replace texture info when ID is already in use by parent.
2858 if (new_parent_impl->texture_manager()->GetTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412859 new_parent_texture_id))
[email protected]98687862011-07-11 23:31:302860 new_parent_impl->texture_manager()->RemoveTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412861 new_parent_texture_id);
[email protected]98687862011-07-11 23:31:302862
[email protected]8a61d872012-01-20 12:43:562863 offscreen_saved_color_texture_info_ =
[email protected]5f4f2a732011-07-30 00:47:552864 new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id);
[email protected]8a61d872012-01-20 12:43:562865 offscreen_saved_color_texture_info_->SetNotOwned();
2866 new_parent_impl->texture_manager()->
2867 SetInfoTarget(offscreen_saved_color_texture_info_, GL_TEXTURE_2D);
[email protected]3c644d82011-06-20 19:58:242868
2869 parent_ = new_parent_impl->AsWeakPtr();
[email protected]9a5afa432011-07-22 18:16:392870
2871 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:242872 } else {
2873 parent_.reset();
[email protected]8a61d872012-01-20 12:43:562874 offscreen_saved_color_texture_info_ = NULL;
[email protected]3c644d82011-06-20 19:58:242875 }
2876
2877 return true;
2878}
2879
[email protected]1078f912011-12-23 13:12:142880void GLES2DecoderImpl::UpdateBackbufferMemoryAccounting() {
2881 size_t total = 0;
2882 if (offscreen_target_frame_buffer_.get()) {
2883 if (offscreen_target_color_texture_.get()) {
2884 total += offscreen_target_color_texture_->estimated_size();
2885 }
2886 if (offscreen_target_color_render_buffer_.get()) {
2887 total += offscreen_target_color_render_buffer_->estimated_size();
2888 }
2889 if (offscreen_target_depth_render_buffer_.get()) {
2890 total += offscreen_target_depth_render_buffer_->estimated_size();
2891 }
2892 if (offscreen_target_stencil_render_buffer_.get()) {
2893 total += offscreen_target_stencil_render_buffer_->estimated_size();
2894 }
2895 if (offscreen_saved_color_texture_.get()) {
2896 total += offscreen_saved_color_texture_->estimated_size();
2897 }
2898 if (offscreen_resolved_color_texture_.get()) {
2899 total += offscreen_resolved_color_texture_->estimated_size();
2900 }
2901 } else {
2902 gfx::Size size = surface_->GetSize();
2903 total += size.width() * size.height() *
2904 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_);
2905 }
2906 TRACE_COUNTER_ID1(
2907 "GLES2DecoderImpl", "BackbufferMemory", this, total);
2908}
2909
[email protected]799b4b22011-08-22 17:09:592910bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2911 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
2912 if (!is_offscreen) {
2913 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
2914 << " with an onscreen framebuffer.";
2915 return false;
2916 }
2917
2918 if (offscreen_size_ == size)
2919 return true;
2920
2921 offscreen_size_ = size;
2922 int w = offscreen_size_.width();
2923 int h = offscreen_size_.height();
2924 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
2925 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2926 << "to allocate storage due to excessive dimensions.";
2927 return false;
2928 }
2929
2930 // Reallocate the offscreen target buffers.
2931 DCHECK(offscreen_target_color_format_);
2932 if (IsOffscreenBufferMultisampled()) {
2933 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2934 offscreen_size_, offscreen_target_color_format_,
2935 offscreen_target_samples_)) {
2936 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2937 << "to allocate storage for offscreen target color buffer.";
2938 return false;
2939 }
2940 } else {
2941 if (!offscreen_target_color_texture_->AllocateStorage(
2942 offscreen_size_, offscreen_target_color_format_)) {
2943 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2944 << "to allocate storage for offscreen target color texture.";
2945 return false;
2946 }
2947 }
2948 if (offscreen_target_depth_format_ &&
2949 !offscreen_target_depth_render_buffer_->AllocateStorage(
2950 offscreen_size_, offscreen_target_depth_format_,
2951 offscreen_target_samples_)) {
2952 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2953 << "to allocate storage for offscreen target depth buffer.";
2954 return false;
2955 }
2956 if (offscreen_target_stencil_format_ &&
2957 !offscreen_target_stencil_render_buffer_->AllocateStorage(
2958 offscreen_size_, offscreen_target_stencil_format_,
2959 offscreen_target_samples_)) {
2960 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2961 << "to allocate storage for offscreen target stencil buffer.";
2962 return false;
2963 }
[email protected]1078f912011-12-23 13:12:142964 UpdateBackbufferMemoryAccounting();
[email protected]799b4b22011-08-22 17:09:592965
2966 // Attach the offscreen target buffers to the target frame buffer.
2967 if (IsOffscreenBufferMultisampled()) {
2968 offscreen_target_frame_buffer_->AttachRenderBuffer(
2969 GL_COLOR_ATTACHMENT0,
2970 offscreen_target_color_render_buffer_.get());
2971 } else {
2972 offscreen_target_frame_buffer_->AttachRenderTexture(
2973 offscreen_target_color_texture_.get());
2974 }
2975 if (offscreen_target_depth_format_) {
2976 offscreen_target_frame_buffer_->AttachRenderBuffer(
2977 GL_DEPTH_ATTACHMENT,
2978 offscreen_target_depth_render_buffer_.get());
2979 }
2980 const bool packed_depth_stencil =
2981 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2982 if (packed_depth_stencil) {
2983 offscreen_target_frame_buffer_->AttachRenderBuffer(
2984 GL_STENCIL_ATTACHMENT,
2985 offscreen_target_depth_render_buffer_.get());
2986 } else if (offscreen_target_stencil_format_) {
2987 offscreen_target_frame_buffer_->AttachRenderBuffer(
2988 GL_STENCIL_ATTACHMENT,
2989 offscreen_target_stencil_render_buffer_.get());
2990 }
2991
2992 if (offscreen_target_frame_buffer_->CheckStatus() !=
2993 GL_FRAMEBUFFER_COMPLETE) {
2994 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2995 << "because offscreen FBO was incomplete.";
2996 return false;
2997 }
2998
2999 // Clear the target frame buffer.
3000 {
3001 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3002 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3003 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3004 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3005 glClearStencil(0);
3006 glStencilMaskSeparate(GL_FRONT, -1);
3007 glStencilMaskSeparate(GL_BACK, -1);
3008 glClearDepth(0);
3009 glDepthMask(GL_TRUE);
3010 glDisable(GL_SCISSOR_TEST);
3011 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3012 RestoreClearState();
3013 }
[email protected]d85ef76d2011-09-08 22:21:433014
3015 // Destroy the offscreen resolved framebuffers.
3016 if (offscreen_resolved_frame_buffer_.get())
3017 offscreen_resolved_frame_buffer_->Destroy();
3018 if (offscreen_resolved_color_texture_.get())
3019 offscreen_resolved_color_texture_->Destroy();
3020 offscreen_resolved_color_texture_.reset();
3021 offscreen_resolved_frame_buffer_.reset();
3022
[email protected]799b4b22011-08-22 17:09:593023 return true;
[email protected]6217d392010-03-25 22:08:353024}
3025
[email protected]799b4b22011-08-22 17:09:593026error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3027 uint32 immediate_data_size, const gles2::ResizeCHROMIUM& c) {
3028 GLuint width = static_cast<GLuint>(c.width);
3029 GLuint height = static_cast<GLuint>(c.height);
3030 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
[email protected]a0d989162011-11-22 13:15:073031#if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3032 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
[email protected]7ff86b92010-11-25 17:50:003033 // Make sure that we are done drawing to the back buffer before resizing.
3034 glFinish();
3035#endif
[email protected]799b4b22011-08-22 17:09:593036 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3037 if (is_offscreen) {
3038 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height)))
3039 return error::kLostContext;
[email protected]7ff86b92010-11-25 17:50:003040 }
[email protected]799b4b22011-08-22 17:09:593041
[email protected]9d37f062011-11-22 01:24:523042 if (!resize_callback_.is_null()) {
3043 resize_callback_.Run(gfx::Size(width, height));
[email protected]c777de52011-09-09 23:08:563044 DCHECK(context_->IsCurrent(surface_.get()));
3045 if (!context_->IsCurrent(surface_.get()))
[email protected]658f7562011-09-09 05:24:053046 return error::kLostContext;
[email protected]658f7562011-09-09 05:24:053047 }
[email protected]799b4b22011-08-22 17:09:593048
[email protected]1078f912011-12-23 13:12:143049 UpdateBackbufferMemoryAccounting();
3050
[email protected]799b4b22011-08-22 17:09:593051 return error::kNoError;
[email protected]43ecf372010-11-16 19:19:393052}
3053
[email protected]96449d2c2009-11-25 00:01:323054const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3055 if (command_id > kStartPoint && command_id < kNumCommands) {
3056 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3057 }
3058 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3059}
3060
3061// Decode command with its arguments, and call the corresponding GL function.
3062// Note: args is a pointer to the command buffer. As such, it could be changed
3063// by a (malicious) client at any time, so if validation has to happen, it
3064// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:143065error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:323066 unsigned int command,
3067 unsigned int arg_count,
3068 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:143069 error::Error result = error::kNoError;
[email protected]e844ae22012-01-14 03:36:263070 if (log_commands()) {
[email protected]4297cbe2011-11-03 18:04:003071 LOG(INFO) << "[" << this << "]" << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193072 }
[email protected]96449d2c2009-11-25 00:01:323073 unsigned int command_index = command - kStartPoint - 1;
3074 if (command_index < arraysize(g_command_info)) {
3075 const CommandInfo& info = g_command_info[command_index];
3076 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3077 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3078 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:193079 uint32 immediate_data_size =
3080 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:323081 switch (command) {
3082 #define GLES2_CMD_OP(name) \
3083 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:193084 result = Handle ## name( \
3085 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:323086 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:193087 break; \
[email protected]96449d2c2009-11-25 00:01:323088
3089 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:323090 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:383091 }
3092 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:303093 GLenum error;
3094 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]e844ae22012-01-14 03:36:263095 SetGLError(error, "GL error from driver");
3096 LOG(INFO) << "[" << this << "]"
3097 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3098 << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193099 }
[email protected]96449d2c2009-11-25 00:01:323100 }
3101 } else {
[email protected]f7a64ee2010-02-01 22:24:143102 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:323103 }
[email protected]b9849abf2009-11-25 19:13:193104 } else {
3105 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:323106 }
[email protected]a3a93e7b2010-08-28 00:48:563107 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3108 result = current_decoder_error_;
3109 current_decoder_error_ = error::kNoError;
3110 }
[email protected]b9849abf2009-11-25 19:13:193111 return result;
[email protected]96449d2c2009-11-25 00:01:323112}
3113
[email protected]ae51d192010-04-27 00:48:033114void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
3115 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:503116}
3117
[email protected]ae51d192010-04-27 00:48:033118bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3119 if (GetProgramInfo(client_id)) {
3120 return false;
3121 }
[email protected]96449d2c2009-11-25 00:01:323122 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:033123 if (service_id != 0) {
3124 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:323125 }
[email protected]ae51d192010-04-27 00:48:033126 return true;
[email protected]96449d2c2009-11-25 00:01:323127}
3128
[email protected]ae51d192010-04-27 00:48:033129bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3130 if (GetShaderInfo(client_id)) {
3131 return false;
[email protected]96449d2c2009-11-25 00:01:323132 }
[email protected]ae51d192010-04-27 00:48:033133 GLuint service_id = glCreateShader(type);
3134 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:383135 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:033136 }
3137 return true;
[email protected]96449d2c2009-11-25 00:01:323138}
3139
[email protected]3916c97e2010-02-25 03:20:503140void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:453141 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]660858b2011-07-13 23:16:143142 if (texture_index >= group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:293143 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:503144 return;
3145 }
[email protected]36cef8ce2010-03-16 07:34:453146 active_texture_unit_ = texture_index;
3147 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:503148}
3149
[email protected]051b1372010-04-12 02:42:083150void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:503151 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083152 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033153 if (client_id != 0) {
3154 info = GetBufferInfo(client_id);
3155 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353156 if (!group_->bind_generates_resource()) {
3157 SetGLError(GL_INVALID_VALUE,
3158 "glBindBuffer: id not generated by glGenBuffers");
3159 return;
3160 }
3161
[email protected]ae51d192010-04-27 00:48:033162 // It's a new id so make a buffer info for it.
3163 glGenBuffersARB(1, &service_id);
3164 CreateBufferInfo(client_id, service_id);
3165 info = GetBufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573166 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103167 group_->GetIdAllocator(id_namespaces::kBuffers);
3168 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033169 }
[email protected]051b1372010-04-12 02:42:083170 }
[email protected]ae51d192010-04-27 00:48:033171 if (info) {
[email protected]4e8a5b122010-05-08 22:00:103172 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:293173 SetGLError(GL_INVALID_OPERATION,
3174 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:473175 return;
3176 }
[email protected]ae51d192010-04-27 00:48:033177 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:473178 }
[email protected]96449d2c2009-11-25 00:01:323179 switch (target) {
3180 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503181 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323182 break;
3183 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503184 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323185 break;
3186 default:
[email protected]a93bb842010-02-16 23:03:473187 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:323188 break;
3189 }
[email protected]051b1372010-04-12 02:42:083190 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:323191}
3192
[email protected]297ca1c2011-06-20 23:08:463193bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
3194 return (GLES2Util::GetChannelsForFormat(
3195 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3196}
3197
3198bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203199 FramebufferManager::FramebufferInfo* framebuffer =
3200 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3201 if (framebuffer) {
3202 return framebuffer->HasDepthAttachment();
[email protected]297ca1c2011-06-20 23:08:463203 }
3204 if (offscreen_target_frame_buffer_.get()) {
3205 return offscreen_target_depth_format_ != 0;
3206 }
3207 return back_buffer_has_depth_;
3208}
3209
3210bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203211 FramebufferManager::FramebufferInfo* framebuffer =
3212 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3213 if (framebuffer) {
3214 return framebuffer->HasStencilAttachment();
[email protected]297ca1c2011-06-20 23:08:463215 }
3216 if (offscreen_target_frame_buffer_.get()) {
3217 return offscreen_target_stencil_format_ != 0 ||
3218 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3219 }
3220 return back_buffer_has_stencil_;
3221}
3222
3223void GLES2DecoderImpl::ApplyDirtyState() {
3224 if (state_dirty_) {
3225 glColorMask(
3226 mask_red_, mask_green_, mask_blue_,
3227 mask_alpha_ && BoundFramebufferHasColorAttachmentWithAlpha());
3228 bool have_depth = BoundFramebufferHasDepthAttachment();
3229 glDepthMask(mask_depth_ && have_depth);
3230 EnableDisable(GL_DEPTH_TEST, enable_depth_test_ && have_depth);
3231 bool have_stencil = BoundFramebufferHasStencilAttachment();
3232 glStencilMaskSeparate(GL_FRONT, have_stencil ? mask_stencil_front_ : 0);
3233 glStencilMaskSeparate(GL_BACK, have_stencil ? mask_stencil_back_ : 0);
3234 EnableDisable(GL_STENCIL_TEST, enable_stencil_test_ && have_stencil);
3235 state_dirty_ = false;
3236 }
3237}
3238
[email protected]b177ae22011-11-01 03:29:113239GLuint GLES2DecoderImpl::GetBackbufferServiceId() {
3240 return (offscreen_target_frame_buffer_.get()) ?
3241 offscreen_target_frame_buffer_->id() :
3242 surface_->GetBackingFrameBufferObject();
3243}
3244
[email protected]051b1372010-04-12 02:42:083245void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3246 FramebufferManager::FramebufferInfo* info = NULL;
3247 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033248 if (client_id != 0) {
3249 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083250 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353251 if (!group_->bind_generates_resource()) {
3252 SetGLError(GL_INVALID_VALUE,
3253 "glBindFramebuffer: id not generated by glGenFramebuffers");
3254 return;
3255 }
3256
[email protected]ae51d192010-04-27 00:48:033257 // It's a new id so make a framebuffer info for it.
3258 glGenFramebuffersEXT(1, &service_id);
3259 CreateFramebufferInfo(client_id, service_id);
3260 info = GetFramebufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573261 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103262 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3263 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033264 } else {
3265 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083266 }
[email protected]06c8b082011-01-05 18:00:363267 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083268 }
[email protected]8e3e0662010-08-23 18:46:303269
3270 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
3271 bound_draw_framebuffer_ = info;
3272 }
3273 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
3274 bound_read_framebuffer_ = info;
3275 }
[email protected]6217d392010-03-25 22:08:353276
[email protected]297ca1c2011-06-20 23:08:463277 state_dirty_ = true;
3278
[email protected]b177ae22011-11-01 03:29:113279 // If we are rendering to the backbuffer get the FBO id for any simulated
3280 // backbuffer.
3281 if (info == NULL) {
3282 service_id = GetBackbufferServiceId();
[email protected]297ca1c2011-06-20 23:08:463283 }
[email protected]6217d392010-03-25 22:08:353284
[email protected]051b1372010-04-12 02:42:083285 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563286}
3287
[email protected]051b1372010-04-12 02:42:083288void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
3289 RenderbufferManager::RenderbufferInfo* info = NULL;
3290 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033291 if (client_id != 0) {
3292 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083293 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353294 if (!group_->bind_generates_resource()) {
3295 SetGLError(
3296 GL_INVALID_VALUE,
3297 "glBindRenderbuffer: id not generated by glGenRenderbuffers");
3298 return;
3299 }
3300
[email protected]ae51d192010-04-27 00:48:033301 // It's a new id so make a renderbuffer info for it.
3302 glGenRenderbuffersEXT(1, &service_id);
3303 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:103304 info = GetRenderbufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573305 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103306 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3307 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033308 } else {
3309 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083310 }
[email protected]06c8b082011-01-05 18:00:363311 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083312 }
3313 bound_renderbuffer_ = info;
3314 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563315}
3316
[email protected]051b1372010-04-12 02:42:083317void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033318 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083319 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033320 if (client_id != 0) {
3321 info = GetTextureInfo(client_id);
3322 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353323 if (!group_->bind_generates_resource()) {
3324 SetGLError(GL_INVALID_VALUE,
3325 "glBindTexture: id not generated by glGenTextures");
3326 return;
3327 }
3328
[email protected]ae51d192010-04-27 00:48:033329 // It's a new id so make a texture info for it.
3330 glGenTextures(1, &service_id);
[email protected]80eb6b52012-01-19 00:14:413331 DCHECK_NE(0u, service_id);
[email protected]ae51d192010-04-27 00:48:033332 CreateTextureInfo(client_id, service_id);
3333 info = GetTextureInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573334 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103335 group_->GetIdAllocator(id_namespaces::kTextures);
3336 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033337 }
3338 } else {
3339 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:083340 }
[email protected]ae51d192010-04-27 00:48:033341
[email protected]1958e0e2010-04-22 05:17:153342 // Check the texture exists
3343 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:033344 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:293345 SetGLError(GL_INVALID_OPERATION,
3346 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:153347 return;
3348 }
[email protected]b0af4f52011-09-28 22:04:423349 if (info->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
3350 SetGLError(GL_INVALID_OPERATION,
3351 "glBindTexture: illegal target for stream texture.");
3352 return;
3353 }
[email protected]1958e0e2010-04-22 05:17:153354 if (info->target() == 0) {
[email protected]80eb6b52012-01-19 00:14:413355 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:473356 }
[email protected]ae51d192010-04-27 00:48:033357 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:503358 TextureUnit& unit = texture_units_[active_texture_unit_];
3359 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:473360 switch (target) {
3361 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:503362 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:473363 break;
3364 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:503365 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:473366 break;
[email protected]61eeb33f2011-07-26 15:30:313367 case GL_TEXTURE_EXTERNAL_OES:
3368 unit.bound_texture_external_oes = info;
[email protected]b0af4f52011-09-28 22:04:423369 if (info->IsStreamTexture()) {
3370 DCHECK(stream_texture_manager_);
3371 StreamTexture* stream_tex =
3372 stream_texture_manager_->LookupStreamTexture(info->service_id());
3373 if (stream_tex)
3374 stream_tex->Update();
3375 }
[email protected]61eeb33f2011-07-26 15:30:313376 break;
[email protected]e51bdf32011-11-23 22:21:463377 case GL_TEXTURE_RECTANGLE_ARB:
3378 unit.bound_texture_rectangle_arb = info;
3379 break;
[email protected]a93bb842010-02-16 23:03:473380 default:
3381 NOTREACHED(); // Validation should prevent us getting here.
3382 break;
3383 }
3384}
3385
[email protected]07f54fcc2009-12-22 02:46:303386void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443387 if (vertex_attrib_manager_->Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:123388 if (index != 0 ||
3389 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:243390 glDisableVertexAttribArray(index);
3391 }
[email protected]07f54fcc2009-12-22 02:46:303392 } else {
[email protected]8eee29c2010-04-29 03:38:293393 SetGLError(GL_INVALID_VALUE,
3394 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:303395 }
3396}
3397
3398void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443399 if (vertex_attrib_manager_->Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:303400 glEnableVertexAttribArray(index);
3401 } else {
[email protected]8eee29c2010-04-29 03:38:293402 SetGLError(GL_INVALID_VALUE,
3403 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:303404 }
3405}
3406
[email protected]a93bb842010-02-16 23:03:473407void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:503408 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]97dc7cbe2011-12-06 17:26:173409 if (!info ||
[email protected]80eb6b52012-01-19 00:14:413410 !texture_manager()->MarkMipmapsGenerated(info)) {
[email protected]8eee29c2010-04-29 03:38:293411 SetGLError(GL_INVALID_OPERATION,
3412 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:473413 return;
3414 }
[email protected]59f3ca02011-03-26 22:24:193415 // Workaround for Mac driver bug. In the large scheme of things setting
3416 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
[email protected]a8bad262011-10-21 18:28:563417 // hit so there's probably no need to make this conditional. The bug appears
3418 // to be that if the filtering mode is set to something that doesn't require
3419 // mipmaps for rendering, or is never set to something other than the default,
3420 // then glGenerateMipmap misbehaves.
3421 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
[email protected]a93bb842010-02-16 23:03:473422 glGenerateMipmapEXT(target);
[email protected]59f3ca02011-03-26 22:24:193423 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
[email protected]a93bb842010-02-16 23:03:473424}
3425
[email protected]b273e432010-04-12 17:23:583426bool GLES2DecoderImpl::GetHelper(
3427 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:583428 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:153429 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
3430 switch (pname) {
[email protected]b273e432010-04-12 17:23:583431 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
3432 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103433 if (params) {
[email protected]5094b0f2010-11-09 19:45:243434 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:103435 }
[email protected]b273e432010-04-12 17:23:583436 return true;
3437 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3438 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103439 if (params) {
[email protected]5094b0f2010-11-09 19:45:243440 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:103441 }
[email protected]b273e432010-04-12 17:23:583442 return true;
3443 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
3444 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103445 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483446 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:103447 }
[email protected]b273e432010-04-12 17:23:583448 return true;
3449 case GL_MAX_VARYING_VECTORS:
3450 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103451 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483452 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:103453 }
[email protected]b273e432010-04-12 17:23:583454 return true;
3455 case GL_MAX_VERTEX_UNIFORM_VECTORS:
3456 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103457 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483458 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:103459 }
[email protected]b273e432010-04-12 17:23:583460 return true;
[email protected]5cb735d2011-10-13 01:37:233461 }
3462 }
3463 switch (pname) {
[email protected]5094b0f2010-11-09 19:45:243464 case GL_MAX_VIEWPORT_DIMS:
3465 if (offscreen_target_frame_buffer_.get()) {
3466 *num_written = 2;
3467 if (params) {
3468 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3469 params[1] = renderbuffer_manager()->max_renderbuffer_size();
3470 }
3471 return true;
3472 }
[email protected]5cb735d2011-10-13 01:37:233473 return false;
[email protected]84afefa2011-10-19 21:45:533474 case GL_MAX_SAMPLES:
3475 *num_written = 1;
3476 if (params) {
3477 params[0] = renderbuffer_manager()->max_samples();
3478 }
3479 return true;
3480 case GL_MAX_RENDERBUFFER_SIZE:
3481 *num_written = 1;
3482 if (params) {
3483 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3484 }
3485 return true;
[email protected]5cb735d2011-10-13 01:37:233486 case GL_MAX_TEXTURE_SIZE:
3487 *num_written = 1;
3488 if (params) {
3489 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
3490 }
3491 return true;
3492 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
3493 *num_written = 1;
3494 if (params) {
3495 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
3496 }
3497 return true;
[email protected]297ca1c2011-06-20 23:08:463498 case GL_COLOR_WRITEMASK:
3499 *num_written = 4;
3500 if (params) {
3501 params[0] = mask_red_;
3502 params[1] = mask_green_;
3503 params[2] = mask_blue_;
3504 params[3] = mask_alpha_;
3505 }
3506 return true;
3507 case GL_DEPTH_WRITEMASK:
3508 *num_written = 1;
3509 if (params) {
3510 params[0] = mask_depth_;
3511 }
3512 return true;
3513 case GL_STENCIL_BACK_WRITEMASK:
3514 *num_written = 1;
3515 if (params) {
3516 params[0] = mask_stencil_back_;
3517 }
3518 return true;
3519 case GL_STENCIL_WRITEMASK:
3520 *num_written = 1;
3521 if (params) {
3522 params[0] = mask_stencil_front_;
3523 }
3524 return true;
3525 case GL_DEPTH_TEST:
3526 *num_written = 1;
3527 if (params) {
3528 params[0] = enable_depth_test_;
3529 }
3530 return true;
3531 case GL_STENCIL_TEST:
3532 *num_written = 1;
3533 if (params) {
3534 params[0] = enable_stencil_test_;
3535 }
3536 return true;
3537 case GL_ALPHA_BITS:
3538 *num_written = 1;
3539 if (params) {
3540 GLint v = 0;
3541 glGetIntegerv(GL_ALPHA_BITS, &v);
3542 params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0;
3543 }
3544 return true;
3545 case GL_DEPTH_BITS:
3546 *num_written = 1;
3547 if (params) {
3548 GLint v = 0;
3549 glGetIntegerv(GL_DEPTH_BITS, &v);
3550 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
3551 }
3552 return true;
3553 case GL_STENCIL_BITS:
3554 *num_written = 1;
3555 if (params) {
3556 GLint v = 0;
3557 glGetIntegerv(GL_STENCIL_BITS, &v);
3558 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
3559 }
3560 return true;
[email protected]656dcaad2010-05-07 17:18:373561 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113562 *num_written = validators_->compressed_texture_format.GetValues().size();
3563 if (params) {
3564 for (GLint ii = 0; ii < *num_written; ++ii) {
3565 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
3566 }
3567 }
[email protected]656dcaad2010-05-07 17:18:373568 return true;
[email protected]b273e432010-04-12 17:23:583569 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
3570 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103571 if (params) {
[email protected]302ce6d2011-07-07 23:28:113572 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103573 }
[email protected]b273e432010-04-12 17:23:583574 return true;
3575 case GL_NUM_SHADER_BINARY_FORMATS:
3576 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103577 if (params) {
[email protected]302ce6d2011-07-07 23:28:113578 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103579 }
[email protected]b273e432010-04-12 17:23:583580 return true;
3581 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113582 *num_written = validators_->shader_binary_format.GetValues().size();
3583 if (params) {
3584 for (GLint ii = 0; ii < *num_written; ++ii) {
3585 params[ii] = validators_->shader_binary_format.GetValues()[ii];
3586 }
3587 }
3588 return true;
[email protected]b273e432010-04-12 17:23:583589 case GL_SHADER_COMPILER:
3590 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103591 if (params) {
3592 *params = GL_TRUE;
3593 }
[email protected]b273e432010-04-12 17:23:583594 return true;
[email protected]6b8cf1a2010-05-06 16:13:583595 case GL_ARRAY_BUFFER_BINDING:
3596 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103597 if (params) {
3598 if (bound_array_buffer_) {
3599 GLuint client_id = 0;
3600 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
3601 &client_id);
3602 *params = client_id;
3603 } else {
3604 *params = 0;
3605 }
[email protected]6b8cf1a2010-05-06 16:13:583606 }
3607 return true;
3608 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3609 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103610 if (params) {
3611 if (bound_element_array_buffer_) {
3612 GLuint client_id = 0;
3613 buffer_manager()->GetClientId(
3614 bound_element_array_buffer_->service_id(),
3615 &client_id);
3616 *params = client_id;
3617 } else {
3618 *params = 0;
3619 }
[email protected]6b8cf1a2010-05-06 16:13:583620 }
3621 return true;
3622 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:303623 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:583624 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103625 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203626 FramebufferManager::FramebufferInfo* framebuffer =
3627 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3628 if (framebuffer) {
[email protected]4e8a5b122010-05-08 22:00:103629 GLuint client_id = 0;
3630 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203631 framebuffer->service_id(), &client_id);
[email protected]8e3e0662010-08-23 18:46:303632 *params = client_id;
3633 } else {
3634 *params = 0;
3635 }
3636 }
3637 return true;
3638 case GL_READ_FRAMEBUFFER_BINDING:
3639 *num_written = 1;
3640 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203641 FramebufferManager::FramebufferInfo* framebuffer =
3642 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
3643 if (framebuffer) {
[email protected]8e3e0662010-08-23 18:46:303644 GLuint client_id = 0;
3645 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203646 framebuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103647 *params = client_id;
3648 } else {
3649 *params = 0;
3650 }
[email protected]6b8cf1a2010-05-06 16:13:583651 }
3652 return true;
3653 case GL_RENDERBUFFER_BINDING:
3654 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103655 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203656 RenderbufferManager::RenderbufferInfo* renderbuffer =
3657 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
3658 if (renderbuffer) {
[email protected]4e8a5b122010-05-08 22:00:103659 GLuint client_id = 0;
3660 renderbuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203661 renderbuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103662 *params = client_id;
3663 } else {
3664 *params = 0;
3665 }
[email protected]6b8cf1a2010-05-06 16:13:583666 }
3667 return true;
3668 case GL_CURRENT_PROGRAM:
3669 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103670 if (params) {
3671 if (current_program_) {
3672 GLuint client_id = 0;
3673 program_manager()->GetClientId(
3674 current_program_->service_id(), &client_id);
3675 *params = client_id;
3676 } else {
3677 *params = 0;
3678 }
[email protected]6b8cf1a2010-05-06 16:13:583679 }
3680 return true;
[email protected]4e8a5b122010-05-08 22:00:103681 case GL_TEXTURE_BINDING_2D:
3682 *num_written = 1;
3683 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583684 TextureUnit& unit = texture_units_[active_texture_unit_];
3685 if (unit.bound_texture_2d) {
3686 GLuint client_id = 0;
3687 texture_manager()->GetClientId(
3688 unit.bound_texture_2d->service_id(), &client_id);
3689 *params = client_id;
3690 } else {
3691 *params = 0;
3692 }
[email protected]6b8cf1a2010-05-06 16:13:583693 }
[email protected]4e8a5b122010-05-08 22:00:103694 return true;
3695 case GL_TEXTURE_BINDING_CUBE_MAP:
3696 *num_written = 1;
3697 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583698 TextureUnit& unit = texture_units_[active_texture_unit_];
3699 if (unit.bound_texture_cube_map) {
3700 GLuint client_id = 0;
3701 texture_manager()->GetClientId(
3702 unit.bound_texture_cube_map->service_id(), &client_id);
3703 *params = client_id;
3704 } else {
3705 *params = 0;
3706 }
[email protected]6b8cf1a2010-05-06 16:13:583707 }
[email protected]4e8a5b122010-05-08 22:00:103708 return true;
[email protected]61eeb33f2011-07-26 15:30:313709 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3710 *num_written = 1;
3711 if (params) {
3712 TextureUnit& unit = texture_units_[active_texture_unit_];
3713 if (unit.bound_texture_external_oes) {
3714 GLuint client_id = 0;
3715 texture_manager()->GetClientId(
3716 unit.bound_texture_external_oes->service_id(), &client_id);
3717 *params = client_id;
3718 } else {
3719 *params = 0;
3720 }
3721 }
3722 return true;
[email protected]e51bdf32011-11-23 22:21:463723 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
3724 *num_written = 1;
3725 if (params) {
3726 TextureUnit& unit = texture_units_[active_texture_unit_];
3727 if (unit.bound_texture_rectangle_arb) {
3728 GLuint client_id = 0;
3729 texture_manager()->GetClientId(
3730 unit.bound_texture_rectangle_arb->service_id(), &client_id);
3731 *params = client_id;
3732 } else {
3733 *params = 0;
3734 }
3735 }
3736 return true;
[email protected]b273e432010-04-12 17:23:583737 default:
[email protected]4e8a5b122010-05-08 22:00:103738 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533739 return false;
[email protected]b273e432010-04-12 17:23:583740 }
3741}
3742
[email protected]4e8a5b122010-05-08 22:00:103743bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3744 GLenum pname, GLsizei* num_values) {
3745 return GetHelper(pname, NULL, num_values);
3746}
3747
[email protected]b273e432010-04-12 17:23:583748void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3749 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103750 GLsizei num_written = 0;
3751 if (GetHelper(pname, NULL, &num_written)) {
3752 scoped_array<GLint> values(new GLint[num_written]);
3753 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583754 for (GLsizei ii = 0; ii < num_written; ++ii) {
3755 params[ii] = static_cast<GLboolean>(values[ii]);
3756 }
3757 } else {
3758 glGetBooleanv(pname, params);
3759 }
3760}
3761
3762void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3763 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103764 GLsizei num_written = 0;
3765 if (GetHelper(pname, NULL, &num_written)) {
3766 scoped_array<GLint> values(new GLint[num_written]);
3767 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583768 for (GLsizei ii = 0; ii < num_written; ++ii) {
3769 params[ii] = static_cast<GLfloat>(values[ii]);
3770 }
3771 } else {
3772 glGetFloatv(pname, params);
3773 }
3774}
3775
3776void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3777 DCHECK(params);
3778 GLsizei num_written;
3779 if (!GetHelper(pname, params, &num_written)) {
3780 glGetIntegerv(pname, params);
3781 }
3782}
3783
[email protected]a0c3e972010-04-21 00:49:133784void GLES2DecoderImpl::DoGetProgramiv(
3785 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583786 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3787 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133788 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133789 return;
3790 }
3791 info->GetProgramiv(pname, params);
3792}
3793
[email protected]258a3313f2011-10-18 20:13:573794void GLES2DecoderImpl::DoBindAttribLocation(
3795 GLuint program, GLuint index, const char* name) {
3796 if (!StringIsValidForGLES(name)) {
3797 SetGLError(GL_INVALID_VALUE, "glBindAttribLocation: Invalid character");
3798 return;
3799 }
[email protected]6b8cf1a2010-05-06 16:13:583800 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3801 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033802 if (!info) {
[email protected]258a3313f2011-10-18 20:13:573803 return;
[email protected]558847a2010-03-24 07:02:543804 }
[email protected]258a3313f2011-10-18 20:13:573805 glBindAttribLocation(info->service_id(), index, name);
3806}
3807
3808error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3809 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
3810 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543811 GLuint index = static_cast<GLuint>(c.index);
3812 uint32 name_size = c.data_size;
3813 const char* name = GetSharedMemoryAs<const char*>(
3814 c.name_shm_id, c.name_shm_offset, name_size);
3815 if (name == NULL) {
3816 return error::kOutOfBounds;
3817 }
3818 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573819 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543820 return error::kNoError;
3821}
3822
3823error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3824 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583825 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543826 GLuint index = static_cast<GLuint>(c.index);
3827 uint32 name_size = c.data_size;
3828 const char* name = GetImmediateDataAs<const char*>(
3829 c, name_size, immediate_data_size);
3830 if (name == NULL) {
3831 return error::kOutOfBounds;
3832 }
3833 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573834 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543835 return error::kNoError;
3836}
3837
3838error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3839 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583840 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543841 GLuint index = static_cast<GLuint>(c.index);
3842 Bucket* bucket = GetBucket(c.name_bucket_id);
3843 if (!bucket || bucket->size() == 0) {
3844 return error::kInvalidArguments;
3845 }
3846 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183847 if (!bucket->GetAsString(&name_str)) {
3848 return error::kInvalidArguments;
3849 }
[email protected]258a3313f2011-10-18 20:13:573850 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543851 return error::kNoError;
3852}
3853
[email protected]f7a64ee2010-02-01 22:24:143854error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463855 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033856 GLuint client_id = c.shader;
3857 if (client_id) {
3858 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3859 if (info) {
[email protected]ca488e12010-12-13 20:06:143860 if (!info->IsDeleted()) {
3861 glDeleteShader(info->service_id());
3862 shader_manager()->MarkAsDeleted(info);
3863 }
[email protected]ae51d192010-04-27 00:48:033864 } else {
[email protected]8eee29c2010-04-29 03:38:293865 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033866 }
[email protected]96449d2c2009-11-25 00:01:323867 }
[email protected]f7a64ee2010-02-01 22:24:143868 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323869}
3870
[email protected]f7a64ee2010-02-01 22:24:143871error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463872 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033873 GLuint client_id = c.program;
3874 if (client_id) {
3875 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3876 if (info) {
[email protected]ca488e12010-12-13 20:06:143877 if (!info->IsDeleted()) {
3878 glDeleteProgram(info->service_id());
3879 program_manager()->MarkAsDeleted(shader_manager(), info);
3880 }
[email protected]ae51d192010-04-27 00:48:033881 } else {
[email protected]8eee29c2010-04-29 03:38:293882 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033883 }
[email protected]96449d2c2009-11-25 00:01:323884 }
[email protected]f7a64ee2010-02-01 22:24:143885 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323886}
3887
[email protected]269200b12010-11-18 22:53:063888void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103889 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573890 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103891 for (GLsizei ii = 0; ii < n; ++ii) {
3892 id_allocator->FreeID(ids[ii]);
3893 }
3894}
3895
[email protected]269200b12010-11-18 22:53:063896error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
3897 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103898 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3899 GLsizei n = static_cast<GLsizei>(c.n);
3900 uint32 data_size;
3901 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3902 return error::kOutOfBounds;
3903 }
3904 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3905 c.ids_shm_id, c.ids_shm_offset, data_size);
3906 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063907 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103908 return error::kNoError;
3909 }
3910 if (ids == NULL) {
3911 return error::kOutOfBounds;
3912 }
[email protected]269200b12010-11-18 22:53:063913 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103914 return error::kNoError;
3915}
3916
[email protected]269200b12010-11-18 22:53:063917void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103918 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573919 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103920 if (id_offset == 0) {
3921 for (GLsizei ii = 0; ii < n; ++ii) {
3922 ids[ii] = id_allocator->AllocateID();
3923 }
3924 } else {
3925 for (GLsizei ii = 0; ii < n; ++ii) {
3926 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
3927 id_offset = ids[ii] + 1;
3928 }
3929 }
3930}
3931
[email protected]269200b12010-11-18 22:53:063932error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
3933 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103934 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3935 GLuint id_offset = static_cast<GLuint>(c.id_offset);
3936 GLsizei n = static_cast<GLsizei>(c.n);
3937 uint32 data_size;
3938 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3939 return error::kOutOfBounds;
3940 }
3941 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3942 c.ids_shm_id, c.ids_shm_offset, data_size);
3943 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063944 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103945 return error::kNoError;
3946 }
3947 if (ids == NULL) {
3948 return error::kOutOfBounds;
3949 }
[email protected]269200b12010-11-18 22:53:063950 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:103951 return error::kNoError;
3952}
3953
[email protected]269200b12010-11-18 22:53:063954void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103955 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573956 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103957 for (GLsizei ii = 0; ii < n; ++ii) {
3958 if (!id_allocator->MarkAsUsed(ids[ii])) {
3959 for (GLsizei jj = 0; jj < ii; ++jj) {
3960 id_allocator->FreeID(ids[jj]);
3961 }
3962 SetGLError(
3963 GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:063964 "RegisterSharedIdsCHROMIUM: attempt to register "
3965 "id that already exists");
[email protected]066849e32010-05-03 19:14:103966 return;
3967 }
3968 }
3969}
3970
[email protected]269200b12010-11-18 22:53:063971error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
3972 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103973 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3974 GLsizei n = static_cast<GLsizei>(c.n);
3975 uint32 data_size;
3976 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3977 return error::kOutOfBounds;
3978 }
3979 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3980 c.ids_shm_id, c.ids_shm_offset, data_size);
3981 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063982 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103983 return error::kNoError;
3984 }
3985 if (ids == NULL) {
3986 return error::kOutOfBounds;
3987 }
[email protected]269200b12010-11-18 22:53:063988 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103989 return error::kNoError;
3990}
3991
[email protected]3a03a8f2011-03-19 00:51:273992void GLES2DecoderImpl::DoClear(GLbitfield mask) {
[email protected]0d6bfdc2011-11-02 01:32:203993 if (CheckBoundFramebuffersValid("glClear")) {
[email protected]529c6672012-01-04 02:18:263994 UNSHIPPED_TRACE_EVENT_INSTANT2("test_gpu", "DoClear", "red", clear_red_,
3995 "green", clear_green_);
[email protected]297ca1c2011-06-20 23:08:463996 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:273997 glClear(mask);
3998 }
3999}
4000
[email protected]36cef8ce2010-03-16 07:34:454001void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4002 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:034003 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:304004 FramebufferManager::FramebufferInfo* framebuffer_info =
4005 GetFramebufferInfoForTarget(target);
4006 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294007 SetGLError(GL_INVALID_OPERATION,
4008 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454009 return;
4010 }
[email protected]ae51d192010-04-27 00:48:034011 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:284012 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:034013 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:284014 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:034015 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294016 SetGLError(GL_INVALID_OPERATION,
4017 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:034018 return;
4019 }
4020 service_id = info->service_id();
4021 }
[email protected]9edc6b22010-12-23 02:00:264022 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034023 glFramebufferRenderbufferEXT(
4024 target, attachment, renderbuffertarget, service_id);
[email protected]1002c2d2011-06-28 22:39:044025 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264026 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:304027 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]3a2e7c7b2010-08-06 01:12:284028 }
[email protected]297ca1c2011-06-20 23:08:464029 if (framebuffer_info == bound_draw_framebuffer_) {
4030 state_dirty_ = true;
4031 }
[email protected]3a2e7c7b2010-08-06 01:12:284032}
4033
[email protected]297ca1c2011-06-20 23:08:464034bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
[email protected]3a2e7c7b2010-08-06 01:12:284035 switch (cap) {
4036 case GL_SCISSOR_TEST:
4037 enable_scissor_test_ = enabled;
[email protected]297ca1c2011-06-20 23:08:464038 return true;
4039 case GL_DEPTH_TEST: {
4040 if (enable_depth_test_ != enabled) {
4041 enable_depth_test_ = enabled;
4042 state_dirty_ = true;
4043 }
4044 return false;
4045 }
4046 case GL_STENCIL_TEST:
4047 if (enable_stencil_test_ != enabled) {
4048 enable_stencil_test_ = enabled;
4049 state_dirty_ = true;
4050 }
4051 return false;
[email protected]3a2e7c7b2010-08-06 01:12:284052 default:
[email protected]297ca1c2011-06-20 23:08:464053 return true;
[email protected]3a2e7c7b2010-08-06 01:12:284054 }
4055}
4056
4057void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464058 if (SetCapabilityState(cap, false)) {
4059 glDisable(cap);
4060 }
[email protected]3a2e7c7b2010-08-06 01:12:284061}
4062
4063void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464064 if (SetCapabilityState(cap, true)) {
4065 glEnable(cap);
4066 }
[email protected]3a2e7c7b2010-08-06 01:12:284067}
4068
4069void GLES2DecoderImpl::DoClearColor(
4070 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
4071 clear_red_ = red;
4072 clear_green_ = green;
4073 clear_blue_ = blue;
4074 clear_alpha_ = alpha;
4075 glClearColor(red, green, blue, alpha);
4076}
4077
4078void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
4079 clear_depth_ = depth;
4080 glClearDepth(depth);
4081}
4082
4083void GLES2DecoderImpl::DoClearStencil(GLint s) {
4084 clear_stencil_ = s;
4085 glClearStencil(s);
4086}
4087
4088void GLES2DecoderImpl::DoColorMask(
4089 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
4090 mask_red_ = red;
4091 mask_green_ = green;
4092 mask_blue_ = blue;
4093 mask_alpha_ = alpha;
[email protected]297ca1c2011-06-20 23:08:464094 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284095}
4096
4097void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
4098 mask_depth_ = depth;
[email protected]297ca1c2011-06-20 23:08:464099 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284100}
4101
4102void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
4103 mask_stencil_front_ = mask;
4104 mask_stencil_back_ = mask;
[email protected]297ca1c2011-06-20 23:08:464105 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284106}
4107
4108void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
[email protected]297ca1c2011-06-20 23:08:464109 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284110 mask_stencil_front_ = mask;
[email protected]297ca1c2011-06-20 23:08:464111 }
4112 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284113 mask_stencil_back_ = mask;
4114 }
[email protected]297ca1c2011-06-20 23:08:464115 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284116}
4117
[email protected]0d6bfdc2011-11-02 01:32:204118// Assumes framebuffer is complete.
4119void GLES2DecoderImpl::ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:304120 GLenum target, FramebufferManager::FramebufferInfo* info) {
4121 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204122 // bind this to the DRAW point, clear then bind back to READ
4123 // TODO(gman): I don't think there is any guarantee that an FBO that
4124 // is complete on the READ attachment will be complete as a DRAW
4125 // attachment.
4126 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
4127 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, info->service_id());
[email protected]8e3e0662010-08-23 18:46:304128 }
[email protected]3a2e7c7b2010-08-06 01:12:284129 GLbitfield clear_bits = 0;
4130 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:464131 glClearColor(
[email protected]0d6bfdc2011-11-02 01:32:204132 0.0f, 0.0f, 0.0f,
[email protected]297ca1c2011-06-20 23:08:464133 (GLES2Util::GetChannelsForFormat(
[email protected]0d6bfdc2011-11-02 01:32:204134 info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f : 1.0f);
[email protected]3a2e7c7b2010-08-06 01:12:284135 glColorMask(true, true, true, true);
4136 clear_bits |= GL_COLOR_BUFFER_BIT;
4137 }
4138
4139 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4140 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4141 glClearStencil(0);
4142 glStencilMask(-1);
4143 clear_bits |= GL_STENCIL_BUFFER_BIT;
4144 }
4145
4146 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4147 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4148 glClearDepth(1.0f);
4149 glDepthMask(true);
4150 clear_bits |= GL_DEPTH_BUFFER_BIT;
4151 }
4152
4153 glDisable(GL_SCISSOR_TEST);
4154 glClear(clear_bits);
4155
[email protected]968351b2011-12-20 08:26:514156 framebuffer_manager()->MarkAttachmentsAsCleared(
4157 info, renderbuffer_manager(), texture_manager());
[email protected]3a2e7c7b2010-08-06 01:12:284158
[email protected]c007aa02010-09-02 22:22:404159 RestoreClearState();
4160
4161 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204162 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, info->service_id());
[email protected]87d1a3fe2011-12-01 04:25:484163 FramebufferManager::FramebufferInfo* framebuffer =
4164 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4165 GLuint service_id =
4166 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
4167 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
[email protected]c007aa02010-09-02 22:22:404168 }
4169}
4170
4171void GLES2DecoderImpl::RestoreClearState() {
[email protected]297ca1c2011-06-20 23:08:464172 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284173 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
[email protected]3a2e7c7b2010-08-06 01:12:284174 glClearStencil(clear_stencil_);
[email protected]3a2e7c7b2010-08-06 01:12:284175 glClearDepth(clear_depth_);
[email protected]3a2e7c7b2010-08-06 01:12:284176 if (enable_scissor_test_) {
4177 glEnable(GL_SCISSOR_TEST);
4178 }
[email protected]36cef8ce2010-03-16 07:34:454179}
4180
4181GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]0d6bfdc2011-11-02 01:32:204182 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]8e3e0662010-08-23 18:46:304183 GetFramebufferInfoForTarget(target);
[email protected]0d6bfdc2011-11-02 01:32:204184 if (!framebuffer) {
[email protected]36cef8ce2010-03-16 07:34:454185 return GL_FRAMEBUFFER_COMPLETE;
4186 }
[email protected]0d6bfdc2011-11-02 01:32:204187 GLenum completeness = framebuffer->IsPossiblyComplete();
4188 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4189 return completeness;
4190 }
[email protected]36cef8ce2010-03-16 07:34:454191 return glCheckFramebufferStatusEXT(target);
4192}
4193
4194void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:034195 GLenum target, GLenum attachment, GLenum textarget,
4196 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:304197 FramebufferManager::FramebufferInfo* framebuffer_info =
4198 GetFramebufferInfoForTarget(target);
4199 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294200 SetGLError(GL_INVALID_OPERATION,
4201 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:454202 return;
4203 }
[email protected]ae51d192010-04-27 00:48:034204 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:284205 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:034206 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:284207 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:034208 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294209 SetGLError(GL_INVALID_OPERATION,
4210 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:034211 return;
4212 }
4213 service_id = info->service_id();
4214 }
[email protected]0d6bfdc2011-11-02 01:32:204215
[email protected]80eb6b52012-01-19 00:14:414216 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
[email protected]0d6bfdc2011-11-02 01:32:204217 SetGLError(GL_INVALID_VALUE,
4218 "glFramebufferTexture2D: level out of range");
4219 return;
4220 }
4221
[email protected]9edc6b22010-12-23 02:00:264222 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034223 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]1002c2d2011-06-28 22:39:044224 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264225 if (error == GL_NO_ERROR) {
4226 framebuffer_info->AttachTexture(attachment, info, textarget, level);
[email protected]3a2e7c7b2010-08-06 01:12:284227 }
[email protected]297ca1c2011-06-20 23:08:464228 if (framebuffer_info == bound_draw_framebuffer_) {
4229 state_dirty_ = true;
4230 }
[email protected]36cef8ce2010-03-16 07:34:454231}
4232
4233void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4234 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:304235 FramebufferManager::FramebufferInfo* framebuffer_info =
4236 GetFramebufferInfoForTarget(target);
4237 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294238 SetGLError(GL_INVALID_OPERATION,
4239 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454240 return;
4241 }
4242 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:574243 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4244 GLint type = 0;
4245 GLuint client_id = 0;
4246 glGetFramebufferAttachmentParameterivEXT(
4247 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
4248 switch (type) {
4249 case GL_RENDERBUFFER: {
4250 renderbuffer_manager()->GetClientId(*params, &client_id);
4251 break;
4252 }
4253 case GL_TEXTURE: {
4254 texture_manager()->GetClientId(*params, &client_id);
4255 break;
4256 }
4257 default:
4258 break;
4259 }
4260 *params = client_id;
4261 }
[email protected]36cef8ce2010-03-16 07:34:454262}
4263
4264void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4265 GLenum target, GLenum pname, GLint* params) {
[email protected]0d6bfdc2011-11-02 01:32:204266 RenderbufferManager::RenderbufferInfo* renderbuffer =
4267 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4268 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294269 SetGLError(GL_INVALID_OPERATION,
4270 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454271 return;
4272 }
[email protected]3a03a8f2011-03-19 00:51:274273 switch (pname) {
4274 case GL_RENDERBUFFER_INTERNAL_FORMAT:
[email protected]0d6bfdc2011-11-02 01:32:204275 *params = renderbuffer->internal_format();
[email protected]3a03a8f2011-03-19 00:51:274276 break;
4277 case GL_RENDERBUFFER_WIDTH:
[email protected]0d6bfdc2011-11-02 01:32:204278 *params = renderbuffer->width();
[email protected]3a03a8f2011-03-19 00:51:274279 break;
4280 case GL_RENDERBUFFER_HEIGHT:
[email protected]0d6bfdc2011-11-02 01:32:204281 *params = renderbuffer->height();
[email protected]3a03a8f2011-03-19 00:51:274282 break;
4283 default:
4284 glGetRenderbufferParameterivEXT(target, pname, params);
4285 break;
[email protected]b71f52c2010-06-18 22:20:204286 }
[email protected]36cef8ce2010-03-16 07:34:454287}
4288
[email protected]8e3e0662010-08-23 18:46:304289void GLES2DecoderImpl::DoBlitFramebufferEXT(
4290 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
4291 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
4292 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:394293 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304294 SetGLError(GL_INVALID_OPERATION,
4295 "glBlitFramebufferEXT: function not available");
4296 }
[email protected]5094b0f2010-11-09 19:45:244297 if (IsAngle()) {
4298 glBlitFramebufferANGLE(
4299 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4300 } else {
4301 glBlitFramebufferEXT(
4302 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4303 }
[email protected]529c6672012-01-04 02:18:264304 UNSHIPPED_TRACE_EVENT_INSTANT1("test_gpu", "DoBlit", "width", srcX1 - srcX0);
[email protected]8e3e0662010-08-23 18:46:304305}
4306
4307void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
4308 GLenum target, GLsizei samples, GLenum internalformat,
4309 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:394310 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304311 SetGLError(GL_INVALID_OPERATION,
4312 "glRenderbufferStorageMultisampleEXT: function not available");
4313 return;
4314 }
[email protected]8e3e0662010-08-23 18:46:304315
[email protected]0d6bfdc2011-11-02 01:32:204316 RenderbufferManager::RenderbufferInfo* renderbuffer =
4317 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4318 if (!renderbuffer) {
4319 SetGLError(GL_INVALID_OPERATION,
4320 "glGetRenderbufferStorageMultisample: no renderbuffer bound");
4321 return;
4322 }
4323
[email protected]84afefa2011-10-19 21:45:534324 if (samples > renderbuffer_manager()->max_samples()) {
4325 SetGLError(GL_INVALID_VALUE,
4326 "glGetRenderbufferStorageMultisample: samples too large");
4327 return;
4328 }
4329
4330 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4331 height > renderbuffer_manager()->max_renderbuffer_size()) {
4332 SetGLError(GL_INVALID_VALUE,
4333 "glGetRenderbufferStorageMultisample: size too large");
4334 return;
4335 }
4336
[email protected]9edc6b22010-12-23 02:00:264337 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:304338 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264339 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:304340 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264341 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:304342 break;
4343 case GL_RGBA4:
4344 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264345 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:304346 break;
4347 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264348 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:304349 break;
4350 }
4351 }
4352
[email protected]9edc6b22010-12-23 02:00:264353 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:084354 if (IsAngle()) {
4355 glRenderbufferStorageMultisampleANGLE(
4356 target, samples, impl_format, width, height);
4357 } else {
4358 glRenderbufferStorageMultisampleEXT(
4359 target, samples, impl_format, width, height);
4360 }
[email protected]1002c2d2011-06-28 22:39:044361 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264362 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514363 // TODO(gman): If renderbuffers tracked which framebuffers they were
4364 // attached to we could just mark those framebuffers as not complete.
4365 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204366 renderbuffer_manager()->SetInfo(
4367 renderbuffer, samples, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264368 }
[email protected]8e3e0662010-08-23 18:46:304369}
4370
[email protected]36cef8ce2010-03-16 07:34:454371void GLES2DecoderImpl::DoRenderbufferStorage(
4372 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]0d6bfdc2011-11-02 01:32:204373 RenderbufferManager::RenderbufferInfo* renderbuffer =
4374 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4375 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294376 SetGLError(GL_INVALID_OPERATION,
4377 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454378 return;
4379 }
[email protected]876f6fee2010-08-02 23:10:324380
[email protected]84afefa2011-10-19 21:45:534381 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4382 height > renderbuffer_manager()->max_renderbuffer_size()) {
4383 SetGLError(GL_INVALID_VALUE,
4384 "glGetRenderbufferStorage: size too large");
4385 return;
4386 }
4387
[email protected]9edc6b22010-12-23 02:00:264388 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:324389 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264390 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:324391 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264392 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:324393 break;
4394 case GL_RGBA4:
4395 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264396 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:324397 break;
4398 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264399 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:324400 break;
4401 }
[email protected]b71f52c2010-06-18 22:20:204402 }
[email protected]876f6fee2010-08-02 23:10:324403
[email protected]9edc6b22010-12-23 02:00:264404 CopyRealGLErrorsToWrapper();
4405 glRenderbufferStorageEXT(target, impl_format, width, height);
[email protected]1002c2d2011-06-28 22:39:044406 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264407 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514408 // TODO(gman): If tetxures tracked which framebuffers they were attached to
4409 // we could just mark those framebuffers as not complete.
4410 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204411 renderbuffer_manager()->SetInfo(
4412 renderbuffer, 0, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264413 }
[email protected]36cef8ce2010-03-16 07:34:454414}
4415
[email protected]07f54fcc2009-12-22 02:46:304416void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]0c8fabf2011-06-14 19:35:224417 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]6b8cf1a2010-05-06 16:13:584418 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4419 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:474420 if (!info) {
[email protected]a93bb842010-02-16 23:03:474421 return;
4422 }
[email protected]05afda12011-01-20 00:17:344423
[email protected]d685a682011-04-29 16:19:574424 info->Link();
[email protected]07f54fcc2009-12-22 02:46:304425};
4426
[email protected]3916c97e2010-02-25 03:20:504427void GLES2DecoderImpl::DoTexParameterf(
4428 GLenum target, GLenum pname, GLfloat param) {
4429 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:304430 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294431 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244432 return;
[email protected]07f54fcc2009-12-22 02:46:304433 }
[email protected]cbb22e42011-05-12 23:36:244434
4435 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414436 info, pname, static_cast<GLint>(param))) {
[email protected]cbb22e42011-05-12 23:36:244437 SetGLError(GL_INVALID_ENUM, "glTexParameterf: param GL_INVALID_ENUM");
4438 return;
4439 }
4440 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:304441}
4442
[email protected]3916c97e2010-02-25 03:20:504443void GLES2DecoderImpl::DoTexParameteri(
4444 GLenum target, GLenum pname, GLint param) {
4445 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4446 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294447 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244448 return;
[email protected]3916c97e2010-02-25 03:20:504449 }
[email protected]cbb22e42011-05-12 23:36:244450
[email protected]80eb6b52012-01-19 00:14:414451 if (!texture_manager()->SetParameter(info, pname, param)) {
[email protected]cbb22e42011-05-12 23:36:244452 SetGLError(GL_INVALID_ENUM, "glTexParameteri: param GL_INVALID_ENUM");
4453 return;
4454 }
4455 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:504456}
4457
4458void GLES2DecoderImpl::DoTexParameterfv(
4459 GLenum target, GLenum pname, const GLfloat* params) {
4460 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4461 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294462 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244463 return;
[email protected]3916c97e2010-02-25 03:20:504464 }
[email protected]cbb22e42011-05-12 23:36:244465
4466 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414467 info, pname, static_cast<GLint>(params[0]))) {
[email protected]cbb22e42011-05-12 23:36:244468 SetGLError(GL_INVALID_ENUM, "glTexParameterfv: param GL_INVALID_ENUM");
4469 return;
4470 }
4471 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504472}
4473
4474void GLES2DecoderImpl::DoTexParameteriv(
4475 GLenum target, GLenum pname, const GLint* params) {
4476 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4477 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294478 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244479 return;
[email protected]3916c97e2010-02-25 03:20:504480 }
[email protected]cbb22e42011-05-12 23:36:244481
[email protected]80eb6b52012-01-19 00:14:414482 if (!texture_manager()->SetParameter(info, pname, *params)) {
[email protected]cbb22e42011-05-12 23:36:244483 SetGLError(GL_INVALID_ENUM, "glTexParameteriv: param GL_INVALID_ENUM");
4484 return;
4485 }
4486 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504487}
4488
[email protected]939e7362010-05-13 20:49:104489bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:144490 if (!current_program_) {
[email protected]939e7362010-05-13 20:49:104491 // The program does not exist.
4492 SetGLError(GL_INVALID_OPERATION,
4493 (std::string(function_name) + ": no program in use").c_str());
4494 return false;
4495 }
[email protected]ca488e12010-12-13 20:06:144496 if (!current_program_->InUse()) {
[email protected]939e7362010-05-13 20:49:104497 SetGLError(GL_INVALID_OPERATION,
4498 (std::string(function_name) + ": program not linked").c_str());
4499 return false;
4500 }
4501 return true;
4502}
4503
4504bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
4505 GLint location, const char* function_name) {
4506 if (!CheckCurrentProgram(function_name)) {
4507 return false;
4508 }
4509 return location != -1;
4510}
4511
[email protected]43c2f1f2011-03-25 18:35:364512bool GLES2DecoderImpl::PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124513 GLint fake_location, const char* function_name,
4514 GLint* real_location, GLenum* type, GLsizei* count) {
[email protected]43c2f1f2011-03-25 18:35:364515 DCHECK(type);
4516 DCHECK(count);
[email protected]1b0a6752012-02-22 03:44:124517 DCHECK(real_location);
4518 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
[email protected]939e7362010-05-13 20:49:104519 return false;
4520 }
[email protected]43c2f1f2011-03-25 18:35:364521 GLint array_index = -1;
4522 const ProgramManager::ProgramInfo::UniformInfo* info =
[email protected]1b0a6752012-02-22 03:44:124523 current_program_->GetUniformInfoByFakeLocation(
4524 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:364525 if (!info) {
[email protected]939e7362010-05-13 20:49:104526 SetGLError(GL_INVALID_OPERATION,
[email protected]43c2f1f2011-03-25 18:35:364527 (std::string(function_name) + ": unknown location").c_str());
[email protected]939e7362010-05-13 20:49:104528 return false;
4529 }
[email protected]43c2f1f2011-03-25 18:35:364530 if (*count > 1 && !info->is_array) {
4531 SetGLError(
4532 GL_INVALID_OPERATION,
4533 (std::string(function_name) + ": count > 1 for non-array").c_str());
4534 return false;
4535 }
4536 *count = std::min(info->size - array_index, *count);
4537 if (*count <= 0) {
4538 return false;
4539 }
4540 *type = info->type;
[email protected]939e7362010-05-13 20:49:104541 return true;
4542}
4543
[email protected]1b0a6752012-02-22 03:44:124544void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
4545 GLenum type = 0;
4546 GLsizei count = 1;
4547 GLint real_location = -1;
4548 if (!PrepForSetUniformByLocation(
4549 fake_location, "glUniform1iv", &real_location, &type, &count)) {
[email protected]3916c97e2010-02-25 03:20:504550 return;
4551 }
[email protected]1b0a6752012-02-22 03:44:124552 current_program_->SetSamplers(fake_location, 1, &v0);
4553 glUniform1i(real_location, v0);
[email protected]3916c97e2010-02-25 03:20:504554}
4555
4556void GLES2DecoderImpl::DoUniform1iv(
[email protected]1b0a6752012-02-22 03:44:124557 GLint fake_location, GLsizei count, const GLint *value) {
[email protected]43c2f1f2011-03-25 18:35:364558 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124559 GLint real_location = -1;
4560 if (!PrepForSetUniformByLocation(
4561 fake_location, "glUniform1iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364562 return;
4563 }
[email protected]61eeb33f2011-07-26 15:30:314564 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
4565 type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]1b0a6752012-02-22 03:44:124566 current_program_->SetSamplers(fake_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364567 }
[email protected]1b0a6752012-02-22 03:44:124568 glUniform1iv(real_location, count, value);
[email protected]3916c97e2010-02-25 03:20:504569}
4570
[email protected]939e7362010-05-13 20:49:104571void GLES2DecoderImpl::DoUniform1fv(
[email protected]1b0a6752012-02-22 03:44:124572 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364573 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124574 GLint real_location = -1;
4575 if (!PrepForSetUniformByLocation(
4576 fake_location, "glUniform1fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104577 return;
4578 }
4579 if (type == GL_BOOL) {
4580 scoped_array<GLint> temp(new GLint[count]);
4581 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:534582 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104583 }
[email protected]1b0a6752012-02-22 03:44:124584 DoUniform1iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104585 } else {
[email protected]1b0a6752012-02-22 03:44:124586 glUniform1fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104587 }
4588}
4589
4590void GLES2DecoderImpl::DoUniform2fv(
[email protected]1b0a6752012-02-22 03:44:124591 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364592 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124593 GLint real_location = -1;
4594 if (!PrepForSetUniformByLocation(
4595 fake_location, "glUniform2fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104596 return;
4597 }
4598 if (type == GL_BOOL_VEC2) {
4599 GLsizei num_values = count * 2;
4600 scoped_array<GLint> temp(new GLint[num_values]);
4601 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534602 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104603 }
[email protected]1b0a6752012-02-22 03:44:124604 glUniform2iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104605 } else {
[email protected]1b0a6752012-02-22 03:44:124606 glUniform2fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104607 }
4608}
4609
4610void GLES2DecoderImpl::DoUniform3fv(
[email protected]1b0a6752012-02-22 03:44:124611 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364612 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124613 GLint real_location = -1;
4614 if (!PrepForSetUniformByLocation(
4615 fake_location, "glUniform3fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104616 return;
4617 }
4618 if (type == GL_BOOL_VEC3) {
4619 GLsizei num_values = count * 3;
4620 scoped_array<GLint> temp(new GLint[num_values]);
4621 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534622 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104623 }
[email protected]1b0a6752012-02-22 03:44:124624 glUniform3iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104625 } else {
[email protected]1b0a6752012-02-22 03:44:124626 glUniform3fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104627 }
4628}
4629
4630void GLES2DecoderImpl::DoUniform4fv(
[email protected]1b0a6752012-02-22 03:44:124631 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364632 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124633 GLint real_location = -1;
4634 if (!PrepForSetUniformByLocation(
4635 fake_location, "glUniform4fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104636 return;
4637 }
4638 if (type == GL_BOOL_VEC4) {
4639 GLsizei num_values = count * 4;
4640 scoped_array<GLint> temp(new GLint[num_values]);
4641 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534642 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104643 }
[email protected]1b0a6752012-02-22 03:44:124644 glUniform4iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104645 } else {
[email protected]1b0a6752012-02-22 03:44:124646 glUniform4fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104647 }
4648}
4649
[email protected]43c2f1f2011-03-25 18:35:364650void GLES2DecoderImpl::DoUniform2iv(
[email protected]1b0a6752012-02-22 03:44:124651 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364652 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124653 GLint real_location = -1;
4654 if (!PrepForSetUniformByLocation(
4655 fake_location, "glUniform2iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364656 return;
4657 }
[email protected]1b0a6752012-02-22 03:44:124658 glUniform2iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364659}
4660
4661void GLES2DecoderImpl::DoUniform3iv(
[email protected]1b0a6752012-02-22 03:44:124662 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364663 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124664 GLint real_location = -1;
4665 if (!PrepForSetUniformByLocation(
4666 fake_location, "glUniform3iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364667 return;
4668 }
[email protected]1b0a6752012-02-22 03:44:124669 glUniform3iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364670}
4671
4672void GLES2DecoderImpl::DoUniform4iv(
[email protected]1b0a6752012-02-22 03:44:124673 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364674 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124675 GLint real_location = -1;
4676 if (!PrepForSetUniformByLocation(
4677 fake_location, "glUniform4iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364678 return;
4679 }
[email protected]1b0a6752012-02-22 03:44:124680 glUniform4iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364681}
4682
4683void GLES2DecoderImpl::DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:124684 GLint fake_location, GLsizei count, GLboolean transpose,
4685 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364686 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124687 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364688 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124689 fake_location, "glUniformMatrix2fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364690 return;
4691 }
[email protected]1b0a6752012-02-22 03:44:124692 glUniformMatrix2fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364693}
4694
4695void GLES2DecoderImpl::DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:124696 GLint fake_location, GLsizei count, GLboolean transpose,
4697 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364698 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124699 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364700 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124701 fake_location, "glUniformMatrix3fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364702 return;
4703 }
[email protected]1b0a6752012-02-22 03:44:124704 glUniformMatrix3fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364705}
4706
4707void GLES2DecoderImpl::DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:124708 GLint fake_location, GLsizei count, GLboolean transpose,
4709 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364710 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124711 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364712 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124713 fake_location, "glUniformMatrix4fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364714 return;
4715 }
[email protected]1b0a6752012-02-22 03:44:124716 glUniformMatrix4fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364717}
4718
[email protected]3916c97e2010-02-25 03:20:504719void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:034720 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:504721 ProgramManager::ProgramInfo* info = NULL;
4722 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:584723 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:504724 if (!info) {
[email protected]ae51d192010-04-27 00:48:034725 return;
4726 }
4727 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:504728 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:294729 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:504730 return;
4731 }
[email protected]ae51d192010-04-27 00:48:034732 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:504733 }
[email protected]ca488e12010-12-13 20:06:144734 if (current_program_) {
4735 program_manager()->UnuseProgram(shader_manager(), current_program_);
4736 }
[email protected]3916c97e2010-02-25 03:20:504737 current_program_ = info;
[email protected]ca488e12010-12-13 20:06:144738 if (current_program_) {
4739 program_manager()->UseProgram(current_program_);
4740 }
[email protected]ae51d192010-04-27 00:48:034741 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:504742}
4743
[email protected]96449d2c2009-11-25 00:01:324744GLenum GLES2DecoderImpl::GetGLError() {
4745 // Check the GL error first, then our wrapped error.
4746 GLenum error = glGetError();
4747 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:374748 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:324749 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:294750 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:324751 break;
4752 }
4753 }
4754 }
4755
4756 if (error != GL_NO_ERROR) {
4757 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:294758 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324759 }
4760 return error;
4761}
4762
[email protected]1002c2d2011-06-28 22:39:044763GLenum GLES2DecoderImpl::PeekGLError() {
4764 GLenum error = glGetError();
4765 if (error != GL_NO_ERROR) {
4766 SetGLError(error, "");
4767 }
4768 return error;
4769}
4770
[email protected]8eee29c2010-04-29 03:38:294771void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
4772 if (msg) {
4773 last_error_ = msg;
[email protected]b5d647c2012-02-10 01:41:324774 // LOG this unless logging is turned off as any chromium code that generates
4775 // these errors probably has a bug.
4776 if (log_synthesized_gl_errors()) {
4777 LOG(ERROR) << last_error_;
4778 }
[email protected]6b6e7ee2011-12-13 08:04:524779 if (!msg_callback_.is_null()) {
4780 msg_callback_.Run(0, GLES2Util::GetStringEnum(error) + " : " + msg);
4781 }
[email protected]8eee29c2010-04-29 03:38:294782 }
[email protected]ddd968b82010-03-02 00:44:294783 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324784}
4785
[email protected]07f54fcc2009-12-22 02:46:304786void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
4787 GLenum error;
4788 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294789 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:304790 }
4791}
4792
[email protected]6217d392010-03-25 22:08:354793void GLES2DecoderImpl::ClearRealGLErrors() {
4794 GLenum error;
4795 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]3ed14d112011-12-13 22:05:514796 if (error != GL_OUT_OF_MEMORY) {
4797 // GL_OUT_OF_MEMORY can legally happen on lost device.
4798 NOTREACHED() << "GL error " << error << " was unhandled.";
4799 }
[email protected]6217d392010-03-25 22:08:354800 }
4801}
4802
[email protected]ef526492010-06-02 23:12:254803bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:504804 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:254805 // Only check if there are some unrenderable textures.
4806 if (!texture_manager()->HaveUnrenderableTextures()) {
4807 return false;
4808 }
4809 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:504810 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4811 current_program_->sampler_indices();
4812 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4813 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4814 current_program_->GetUniformInfo(sampler_indices[ii]);
4815 DCHECK(uniform_info);
4816 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4817 GLuint texture_unit_index = uniform_info->texture_units[jj];
4818 if (texture_unit_index < group_->max_texture_units()) {
4819 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4820 TextureManager::TextureInfo* texture_info =
[email protected]61eeb33f2011-07-26 15:30:314821 texture_unit.GetInfoForSamplerType(uniform_info->type);
[email protected]80eb6b52012-01-19 00:14:414822 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]ef526492010-06-02 23:12:254823 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:504824 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4825 glBindTexture(
[email protected]61eeb33f2011-07-26 15:30:314826 GetBindTargetForSamplerType(uniform_info->type),
[email protected]00f893d2010-08-24 18:55:494827 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:504828 }
4829 }
4830 // else: should this be an error?
4831 }
4832 }
[email protected]ef526492010-06-02 23:12:254833 return textures_set;
[email protected]3916c97e2010-02-25 03:20:504834}
4835
4836void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
4837 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:504838 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4839 current_program_->sampler_indices();
4840 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4841 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4842 current_program_->GetUniformInfo(sampler_indices[ii]);
4843 DCHECK(uniform_info);
4844 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4845 GLuint texture_unit_index = uniform_info->texture_units[jj];
4846 if (texture_unit_index < group_->max_texture_units()) {
4847 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4848 TextureManager::TextureInfo* texture_info =
4849 uniform_info->type == GL_SAMPLER_2D ?
4850 texture_unit.bound_texture_2d :
4851 texture_unit.bound_texture_cube_map;
[email protected]80eb6b52012-01-19 00:14:414852 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]3916c97e2010-02-25 03:20:504853 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4854 // Get the texture info that was previously bound here.
4855 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
4856 texture_unit.bound_texture_2d :
4857 texture_unit.bound_texture_cube_map;
4858 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:034859 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:504860 }
4861 }
4862 }
4863 }
4864 // Set the active texture back to whatever the user had it as.
4865 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:304866}
4867
[email protected]0d6bfdc2011-11-02 01:32:204868bool GLES2DecoderImpl::ClearUnclearedTextures() {
4869 // Only check if there are some uncleared textures.
4870 if (!texture_manager()->HaveUnsafeTextures()) {
4871 return true;
4872 }
4873
4874 // 1: Check all textures we are about to render with.
4875 if (current_program_) {
4876 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4877 current_program_->sampler_indices();
4878 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4879 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4880 current_program_->GetUniformInfo(sampler_indices[ii]);
4881 DCHECK(uniform_info);
4882 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4883 GLuint texture_unit_index = uniform_info->texture_units[jj];
4884 if (texture_unit_index < group_->max_texture_units()) {
4885 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4886 TextureManager::TextureInfo* texture_info =
4887 texture_unit.GetInfoForSamplerType(uniform_info->type);
4888 if (texture_info && !texture_info->SafeToRenderFrom()) {
4889 if (!texture_manager()->ClearRenderableLevels(this, texture_info)) {
4890 return false;
4891 }
4892 }
4893 }
4894 }
4895 }
4896 }
4897 return true;
4898}
4899
[email protected]c6aef902012-02-14 03:31:424900bool GLES2DecoderImpl::IsDrawValid(
4901 GLuint max_vertex_accessed, GLsizei primcount) {
[email protected]689fa1c52010-06-09 18:35:034902 // NOTE: We specifically do not check current_program->IsValid() because
4903 // it could never be invalid since glUseProgram would have failed. While
4904 // glLinkProgram could later mark the program as invalid the previous
4905 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:144906 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:504907 // The program does not exist.
4908 // But GL says no ERROR.
4909 return false;
4910 }
[email protected]c6aef902012-02-14 03:31:424911
4912 // true if any enabled, used divisor is zero
4913 bool divisor0 = false;
[email protected]f39f4b3f2010-05-12 17:04:084914 // Validate all attribs currently enabled. If they are used by the current
4915 // program then check that they have enough elements to handle the draw call.
4916 // If they are not used by the current program check that they have a buffer
4917 // assigned.
4918 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:444919 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]f39f4b3f2010-05-12 17:04:084920 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:404921 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:084922 const VertexAttribManager::VertexAttribInfo* info = *it;
4923 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4924 current_program_->GetAttribInfoByLocation(info->index());
4925 if (attrib_info) {
[email protected]c6aef902012-02-14 03:31:424926 divisor0 |= (info->divisor() == 0);
4927 GLuint count = info->MaxVertexAccessed(primcount, max_vertex_accessed);
[email protected]f39f4b3f2010-05-12 17:04:084928 // This attrib is used in the current program.
[email protected]c6aef902012-02-14 03:31:424929 if (!info->CanAccess(count)) {
[email protected]f39f4b3f2010-05-12 17:04:084930 SetGLError(GL_INVALID_OPERATION,
4931 "glDrawXXX: attempt to access out of range vertices");
4932 return false;
4933 }
4934 } else {
4935 // This attrib is not used in the current program.
[email protected]a0b78dc2011-11-11 10:43:104936 if (!info->buffer()) {
[email protected]f39f4b3f2010-05-12 17:04:084937 SetGLError(
4938 GL_INVALID_OPERATION,
4939 "glDrawXXX: attempt to render with no buffer attached to enabled "
4940 "attrib");
4941 return false;
4942 }
[email protected]1d32bc82010-01-13 22:06:464943 }
[email protected]07f54fcc2009-12-22 02:46:304944 }
[email protected]c6aef902012-02-14 03:31:424945
4946 if (primcount && !divisor0) {
4947 SetGLError(
4948 GL_INVALID_OPERATION,
4949 "glDrawXXX: attempt instanced render with all attributes having "
4950 "non-zero divisors");
4951 return false;
4952 }
4953
[email protected]3916c97e2010-02-25 03:20:504954 return true;
[email protected]b1122982010-05-17 23:04:244955}
4956
[email protected]c13e1da62011-09-09 21:48:304957bool GLES2DecoderImpl::SimulateAttrib0(
4958 GLuint max_vertex_accessed, bool* simulated) {
4959 DCHECK(simulated);
4960 *simulated = false;
4961
[email protected]876f6fee2010-08-02 23:10:324962 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
[email protected]c13e1da62011-09-09 21:48:304963 return true;
[email protected]876f6fee2010-08-02 23:10:324964
[email protected]b1122982010-05-17 23:04:244965 const VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:444966 vertex_attrib_manager_->GetVertexAttribInfo(0);
[email protected]b1122982010-05-17 23:04:244967 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:494968 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
4969 if (info->enabled() && attrib_0_used) {
[email protected]c13e1da62011-09-09 21:48:304970 return true;
[email protected]b1122982010-05-17 23:04:244971 }
4972
[email protected]b1122982010-05-17 23:04:244973 // Make a buffer with a single repeated vec4 value enough to
4974 // simulate the constant value that is supposed to be here.
4975 // This is required to emulate GLES2 on GL.
[email protected]c13e1da62011-09-09 21:48:304976 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
4977
4978 GLuint num_vertices = max_vertex_accessed + 1;
4979 GLuint size_needed = 0;
4980
4981 if (num_vertices == 0 ||
4982 !SafeMultiply(num_vertices, static_cast<GLuint>(sizeof(Vec4)),
4983 &size_needed) ||
4984 size_needed > 0x7FFFFFFFU) {
4985 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
4986 return false;
4987 }
4988
4989 CopyRealGLErrorsToWrapper();
4990 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
4991
4992 if (static_cast<GLsizei>(size_needed) > attrib_0_size_) {
[email protected]fc753442011-02-04 19:49:494993 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:304994 GLenum error = glGetError();
4995 if (error != GL_NO_ERROR) {
4996 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
4997 return false;
4998 }
[email protected]fc753442011-02-04 19:49:494999 attrib_0_buffer_matches_value_ = false;
5000 }
5001 if (attrib_0_used &&
5002 (!attrib_0_buffer_matches_value_ ||
5003 (info->value().v[0] != attrib_0_value_.v[0] ||
5004 info->value().v[1] != attrib_0_value_.v[1] ||
5005 info->value().v[2] != attrib_0_value_.v[2] ||
5006 info->value().v[3] != attrib_0_value_.v[3]))) {
5007 std::vector<Vec4> temp(num_vertices, info->value());
5008 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
5009 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:245010 attrib_0_value_ = info->value();
5011 attrib_0_size_ = size_needed;
5012 }
5013
5014 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5015
[email protected]c6aef902012-02-14 03:31:425016 if (info->divisor())
5017 glVertexAttribDivisorANGLE(0, 0);
5018
[email protected]c13e1da62011-09-09 21:48:305019 *simulated = true;
[email protected]b1122982010-05-17 23:04:245020 return true;
[email protected]b1122982010-05-17 23:04:245021}
5022
5023void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
5024 const VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445025 vertex_attrib_manager_->GetVertexAttribInfo(0);
[email protected]b1122982010-05-17 23:04:245026 const void* ptr = reinterpret_cast<const void*>(info->offset());
5027 BufferManager::BufferInfo* buffer_info = info->buffer();
5028 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
5029 glVertexAttribPointer(
5030 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
5031 ptr);
[email protected]c6aef902012-02-14 03:31:425032 if (info->divisor())
5033 glVertexAttribDivisorANGLE(0, info->divisor());
[email protected]b1122982010-05-17 23:04:245034 glBindBuffer(GL_ARRAY_BUFFER,
5035 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
5036}
[email protected]07f54fcc2009-12-22 02:46:305037
[email protected]8fbedc02010-11-18 18:43:405038bool GLES2DecoderImpl::SimulateFixedAttribs(
[email protected]c6aef902012-02-14 03:31:425039 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
[email protected]8fbedc02010-11-18 18:43:405040 DCHECK(simulated);
5041 *simulated = false;
5042 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
5043 return true;
5044
[email protected]3757a372012-01-19 05:20:445045 if (!vertex_attrib_manager_->HaveFixedAttribs()) {
[email protected]8fbedc02010-11-18 18:43:405046 return true;
5047 }
5048
5049 // NOTE: we could be smart and try to check if a buffer is used
5050 // twice in 2 different attribs, find the overlapping parts and therefore
5051 // duplicate the minimum amount of data but this whole code path is not meant
5052 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
5053 // tests so we just add to the buffer attrib used.
5054
[email protected]c13e1da62011-09-09 21:48:305055 GLuint elements_needed = 0;
[email protected]8fbedc02010-11-18 18:43:405056 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:445057 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]8fbedc02010-11-18 18:43:405058 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5059 infos.begin(); it != infos.end(); ++it) {
5060 const VertexAttribManager::VertexAttribInfo* info = *it;
5061 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5062 current_program_->GetAttribInfoByLocation(info->index());
[email protected]c6aef902012-02-14 03:31:425063 GLuint max_accessed = info->MaxVertexAccessed(primcount,
5064 max_vertex_accessed);
5065 GLuint num_vertices = max_accessed + 1;
5066 if (num_vertices == 0) {
5067 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
5068 return false;
5069 }
[email protected]8fbedc02010-11-18 18:43:405070 if (attrib_info &&
[email protected]c6aef902012-02-14 03:31:425071 info->CanAccess(max_accessed) &&
[email protected]8fbedc02010-11-18 18:43:405072 info->type() == GL_FIXED) {
[email protected]c13e1da62011-09-09 21:48:305073 GLuint elements_used = 0;
5074 if (!SafeMultiply(num_vertices,
5075 static_cast<GLuint>(info->size()), &elements_used) ||
[email protected]8fbedc02010-11-18 18:43:405076 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
5077 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5078 return false;
5079 }
5080 }
5081 }
5082
[email protected]c13e1da62011-09-09 21:48:305083 const GLuint kSizeOfFloat = sizeof(float); // NOLINT
5084 GLuint size_needed = 0;
5085 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed) ||
5086 size_needed > 0x7FFFFFFFU) {
[email protected]8fbedc02010-11-18 18:43:405087 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5088 return false;
5089 }
5090
[email protected]c13e1da62011-09-09 21:48:305091 CopyRealGLErrorsToWrapper();
[email protected]8fbedc02010-11-18 18:43:405092
5093 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
[email protected]c13e1da62011-09-09 21:48:305094 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
[email protected]8fbedc02010-11-18 18:43:405095 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305096 GLenum error = glGetError();
5097 if (error != GL_NO_ERROR) {
5098 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5099 return false;
5100 }
[email protected]8fbedc02010-11-18 18:43:405101 }
5102
5103 // Copy the elements and convert to float
5104 GLintptr offset = 0;
5105 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5106 infos.begin(); it != infos.end(); ++it) {
5107 const VertexAttribManager::VertexAttribInfo* info = *it;
5108 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5109 current_program_->GetAttribInfoByLocation(info->index());
[email protected]c6aef902012-02-14 03:31:425110 GLuint max_accessed = info->MaxVertexAccessed(primcount,
5111 max_vertex_accessed);
5112 GLuint num_vertices = max_accessed + 1;
5113 if (num_vertices == 0) {
5114 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
5115 return false;
5116 }
[email protected]8fbedc02010-11-18 18:43:405117 if (attrib_info &&
[email protected]c6aef902012-02-14 03:31:425118 info->CanAccess(max_accessed) &&
[email protected]8fbedc02010-11-18 18:43:405119 info->type() == GL_FIXED) {
5120 int num_elements = info->size() * kSizeOfFloat;
5121 int size = num_elements * num_vertices;
5122 scoped_array<float> data(new float[size]);
5123 const int32* src = reinterpret_cast<const int32 *>(
5124 info->buffer()->GetRange(info->offset(), size));
5125 const int32* end = src + num_elements;
5126 float* dst = data.get();
5127 while (src != end) {
5128 *dst++ = static_cast<float>(*src++) / 65536.0f;
5129 }
5130 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
5131 glVertexAttribPointer(
5132 info->index(), info->size(), GL_FLOAT, false, 0,
5133 reinterpret_cast<GLvoid*>(offset));
5134 offset += size;
5135 }
5136 }
5137 *simulated = true;
5138 return true;
5139}
5140
5141void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
5142 // There's no need to call glVertexAttribPointer because we shadow all the
5143 // settings and passing GL_FIXED to it will not work.
5144 glBindBuffer(GL_ARRAY_BUFFER,
5145 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
5146}
5147
[email protected]c6aef902012-02-14 03:31:425148error::Error GLES2DecoderImpl::DoDrawArrays(bool instanced,
5149 GLenum mode,
5150 GLint first,
5151 GLsizei count,
5152 GLsizei primcount) {
[email protected]38d139d2011-07-14 00:38:435153 if (!validators_->draw_mode.IsValid(mode)) {
5154 SetGLError(GL_INVALID_ENUM, "glDrawArrays: mode GL_INVALID_ENUM");
5155 return error::kNoError;
5156 }
5157 if (count < 0) {
5158 SetGLError(GL_INVALID_VALUE, "glDrawArrays: count < 0");
5159 return error::kNoError;
5160 }
[email protected]c6aef902012-02-14 03:31:425161 if (primcount < 0) {
5162 SetGLError(GL_INVALID_VALUE, "glDrawArrays: primcount < 0");
5163 return error::kNoError;
5164 }
[email protected]0d6bfdc2011-11-02 01:32:205165 if (!CheckBoundFramebuffersValid("glDrawArrays")) {
[email protected]38d139d2011-07-14 00:38:435166 return error::kNoError;
5167 }
5168 // We have to check this here because the prototype for glDrawArrays
5169 // is GLint not GLsizei.
5170 if (first < 0) {
5171 SetGLError(GL_INVALID_VALUE, "glDrawArrays: first < 0");
5172 return error::kNoError;
5173 }
5174
[email protected]c6aef902012-02-14 03:31:425175 if (count == 0 || (instanced && primcount == 0)) {
[email protected]38d139d2011-07-14 00:38:435176 return error::kNoError;
5177 }
5178
5179 GLuint max_vertex_accessed = first + count - 1;
[email protected]c6aef902012-02-14 03:31:425180 if (IsDrawValid(max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:205181 if (!ClearUnclearedTextures()) {
5182 SetGLError(GL_INVALID_VALUE, "glDrawArrays: out of memory");
5183 return error::kNoError;
5184 }
[email protected]c13e1da62011-09-09 21:48:305185 bool simulated_attrib_0 = false;
5186 if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
5187 return error::kNoError;
5188 }
[email protected]38d139d2011-07-14 00:38:435189 bool simulated_fixed_attribs = false;
[email protected]c6aef902012-02-14 03:31:425190 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs,
5191 primcount)) {
[email protected]38d139d2011-07-14 00:38:435192 bool textures_set = SetBlackTextureForNonRenderableTextures();
5193 ApplyDirtyState();
[email protected]c6aef902012-02-14 03:31:425194 if (!instanced) {
5195 glDrawArrays(mode, first, count);
5196 } else {
5197 glDrawArraysInstancedANGLE(mode, first, count, primcount);
5198 }
[email protected]38d139d2011-07-14 00:38:435199 if (textures_set) {
5200 RestoreStateForNonRenderableTextures();
5201 }
5202 if (simulated_fixed_attribs) {
5203 RestoreStateForSimulatedFixedAttribs();
5204 }
5205 }
5206 if (simulated_attrib_0) {
5207 RestoreStateForSimulatedAttrib0();
5208 }
5209 if (WasContextLost()) {
5210 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawArrays.";
5211 return error::kLostContext;
5212 }
5213 }
5214 return error::kNoError;
5215}
5216
[email protected]c6aef902012-02-14 03:31:425217error::Error GLES2DecoderImpl::HandleDrawArrays(
5218 uint32 immediate_data_size, const gles2::DrawArrays& c) {
5219 return DoDrawArrays(false,
5220 static_cast<GLenum>(c.mode),
5221 static_cast<GLint>(c.first),
5222 static_cast<GLsizei>(c.count),
5223 0);
5224}
5225
5226error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
5227 uint32 immediate_data_size, const gles2::DrawArraysInstancedANGLE& c) {
5228 if (!feature_info_->feature_flags().angle_instanced_arrays) {
5229 SetGLError(GL_INVALID_OPERATION,
5230 "glDrawArraysInstancedANGLE: function not available");
5231 return error::kNoError;
5232 }
5233 return DoDrawArrays(true,
5234 static_cast<GLenum>(c.mode),
5235 static_cast<GLint>(c.first),
5236 static_cast<GLsizei>(c.count),
5237 static_cast<GLsizei>(c.primcount));
5238}
5239
5240error::Error GLES2DecoderImpl::DoDrawElements(bool instanced,
5241 GLenum mode,
5242 GLsizei count,
5243 GLenum type,
5244 int32 offset,
5245 GLsizei primcount) {
[email protected]a0b78dc2011-11-11 10:43:105246 if (!bound_element_array_buffer_) {
[email protected]8eee29c2010-04-29 03:38:295247 SetGLError(GL_INVALID_OPERATION,
5248 "glDrawElements: No element array buffer bound");
5249 return error::kNoError;
5250 }
5251
[email protected]8eee29c2010-04-29 03:38:295252 if (count < 0) {
5253 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
5254 return error::kNoError;
5255 }
5256 if (offset < 0) {
5257 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
5258 return error::kNoError;
5259 }
[email protected]9438b012010-06-15 22:55:055260 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:295261 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
5262 return error::kNoError;
5263 }
[email protected]9438b012010-06-15 22:55:055264 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295265 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
5266 return error::kNoError;
5267 }
[email protected]c6aef902012-02-14 03:31:425268 if (primcount < 0) {
5269 SetGLError(GL_INVALID_VALUE, "glDrawElements: primcount < 0");
5270 return error::kNoError;
5271 }
[email protected]8eee29c2010-04-29 03:38:295272
[email protected]0d6bfdc2011-11-02 01:32:205273 if (!CheckBoundFramebuffersValid("glDrawElements")) {
[email protected]3a03a8f2011-03-19 00:51:275274 return error::kNoError;
5275 }
5276
[email protected]c6aef902012-02-14 03:31:425277 if (count == 0 || (instanced && primcount == 0)) {
[email protected]6c788fb72010-08-26 02:16:315278 return error::kNoError;
5279 }
5280
[email protected]8eee29c2010-04-29 03:38:295281 GLuint max_vertex_accessed;
5282 if (!bound_element_array_buffer_->GetMaxValueForRange(
5283 offset, count, type, &max_vertex_accessed)) {
5284 SetGLError(GL_INVALID_OPERATION,
5285 "glDrawElements: range out of bounds for buffer");
5286 return error::kNoError;
5287 }
5288
[email protected]c6aef902012-02-14 03:31:425289 if (IsDrawValid(max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:205290 if (!ClearUnclearedTextures()) {
5291 SetGLError(GL_INVALID_VALUE, "glDrawElements: out of memory");
5292 return error::kNoError;
5293 }
[email protected]c13e1da62011-09-09 21:48:305294 bool simulated_attrib_0 = false;
5295 if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
5296 return error::kNoError;
5297 }
[email protected]8fbedc02010-11-18 18:43:405298 bool simulated_fixed_attribs = false;
[email protected]c6aef902012-02-14 03:31:425299 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs,
5300 primcount)) {
[email protected]8fbedc02010-11-18 18:43:405301 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:465302 ApplyDirtyState();
[email protected]8fbedc02010-11-18 18:43:405303 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
[email protected]c6aef902012-02-14 03:31:425304 if (!instanced) {
5305 glDrawElements(mode, count, type, indices);
5306 } else {
5307 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
5308 }
[email protected]8fbedc02010-11-18 18:43:405309 if (textures_set) {
5310 RestoreStateForNonRenderableTextures();
5311 }
5312 if (simulated_fixed_attribs) {
5313 RestoreStateForSimulatedFixedAttribs();
5314 }
[email protected]ba3176a2009-12-16 18:19:465315 }
[email protected]b1122982010-05-17 23:04:245316 if (simulated_attrib_0) {
5317 RestoreStateForSimulatedAttrib0();
5318 }
[email protected]38d139d2011-07-14 00:38:435319 if (WasContextLost()) {
5320 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawElements.";
5321 return error::kLostContext;
5322 }
[email protected]96449d2c2009-11-25 00:01:325323 }
[email protected]f7a64ee2010-02-01 22:24:145324 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325325}
5326
[email protected]c6aef902012-02-14 03:31:425327error::Error GLES2DecoderImpl::HandleDrawElements(
5328 uint32 immediate_data_size, const gles2::DrawElements& c) {
5329 return DoDrawElements(false,
5330 static_cast<GLenum>(c.mode),
5331 static_cast<GLsizei>(c.count),
5332 static_cast<GLenum>(c.type),
5333 static_cast<int32>(c.index_offset),
5334 0);
5335}
5336
5337error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
5338 uint32 immediate_data_size, const gles2::DrawElementsInstancedANGLE& c) {
5339 if (!feature_info_->feature_flags().angle_instanced_arrays) {
5340 SetGLError(GL_INVALID_OPERATION,
5341 "glDrawElementsInstancedANGLE: function not available");
5342 return error::kNoError;
5343 }
5344 return DoDrawElements(true,
5345 static_cast<GLenum>(c.mode),
5346 static_cast<GLsizei>(c.count),
5347 static_cast<GLenum>(c.type),
5348 static_cast<int32>(c.index_offset),
5349 static_cast<GLsizei>(c.primcount));
5350}
5351
[email protected]269200b12010-11-18 22:53:065352GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:235353 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
5354 GLuint max_vertex_accessed = 0;
5355 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:295356 if (!info) {
[email protected]ae51d192010-04-27 00:48:035357 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:295358 SetGLError(GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:065359 "GetMaxValueInBufferCHROMIUM: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:235360 } else {
5361 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:035362 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:065363 SetGLError(
5364 GL_INVALID_OPERATION,
5365 "GetMaxValueInBufferCHROMIUM: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:235366 }
5367 }
5368 return max_vertex_accessed;
5369}
5370
[email protected]96449d2c2009-11-25 00:01:325371// Calls glShaderSource for the various versions of the ShaderSource command.
5372// Assumes that data / data_size points to a piece of memory that is in range
5373// of whatever context it came from (shared memory, immediate memory, bucket
5374// memory.)
[email protected]45bf5152010-02-12 00:11:315375error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035376 GLuint client_id, const char* data, uint32 data_size) {
[email protected]258a3313f2011-10-18 20:13:575377 std::string str(data, data + data_size);
[email protected]6b8cf1a2010-05-06 16:13:585378 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5379 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:315380 if (!info) {
[email protected]45bf5152010-02-12 00:11:315381 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325382 }
[email protected]45bf5152010-02-12 00:11:315383 // Note: We don't actually call glShaderSource here. We wait until
5384 // the call to glCompileShader.
[email protected]258a3313f2011-10-18 20:13:575385 info->UpdateSource(str.c_str());
[email protected]f7a64ee2010-02-01 22:24:145386 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325387}
5388
[email protected]f7a64ee2010-02-01 22:24:145389error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:195390 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:325391 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315392 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:325393 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:465394 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145395 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325396 }
[email protected]ae51d192010-04-27 00:48:035397 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:325398}
5399
[email protected]f7a64ee2010-02-01 22:24:145400error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:195401 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:325402 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315403 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:305404 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465405 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145406 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325407 }
[email protected]ae51d192010-04-27 00:48:035408 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:315409}
5410
[email protected]558847a2010-03-24 07:02:545411error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
5412 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:545413 Bucket* bucket = GetBucket(c.data_bucket_id);
5414 if (!bucket || bucket->size() == 0) {
5415 return error::kInvalidArguments;
5416 }
5417 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035418 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:545419 bucket->size() - 1);
5420}
5421
[email protected]ae51d192010-04-27 00:48:035422void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]0c8fabf2011-06-14 19:35:225423 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]6b8cf1a2010-05-06 16:13:585424 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5425 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:315426 if (!info) {
[email protected]45bf5152010-02-12 00:11:315427 return;
5428 }
[email protected]de17df392010-04-23 21:09:415429 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
5430 // glShaderSource and then glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:525431 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:345432 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:185433 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:345434 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:455435 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:235436
[email protected]a550584e2010-09-17 18:01:455437 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:345438 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:185439 return;
5440 }
[email protected]a550584e2010-09-17 18:01:455441 shader_src = translator->translated_shader();
[email protected]93297702011-11-05 05:09:465442 if (!feature_info_->feature_flags().angle_translated_shader_source)
[email protected]d6a53e42011-10-05 00:09:365443 info->UpdateTranslatedSource(shader_src);
[email protected]de17df392010-04-23 21:09:415444 }
[email protected]de17df392010-04-23 21:09:415445
[email protected]ae51d192010-04-27 00:48:035446 glShaderSource(info->service_id(), 1, &shader_src, NULL);
5447 glCompileShader(info->service_id());
[email protected]93297702011-11-05 05:09:465448 if (feature_info_->feature_flags().angle_translated_shader_source) {
[email protected]d6a53e42011-10-05 00:09:365449 GLint max_len = 0;
5450 glGetShaderiv(info->service_id(),
5451 GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
5452 &max_len);
5453 scoped_array<char> temp(new char[max_len]);
5454 GLint len = 0;
5455 glGetTranslatedShaderSourceANGLE(
5456 info->service_id(), max_len, &len, temp.get());
5457 DCHECK(max_len == 0 || len < max_len);
5458 DCHECK(len == 0 || temp[len] == '\0');
5459 info->UpdateTranslatedSource(temp.get());
5460 }
5461
[email protected]e5186162010-06-14 18:54:415462 GLint status = GL_FALSE;
5463 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
5464 if (status) {
[email protected]f57bb282010-11-12 00:51:345465 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:415466 } else {
[email protected]d9977d42010-09-01 20:27:025467 // We cannot reach here if we are using the shader translator.
5468 // All invalid shaders must be rejected by the translator.
5469 // All translated shaders must compile.
5470 LOG_IF(ERROR, use_shader_translator_)
5471 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:335472 GLint max_len = 0;
5473 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
5474 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:415475 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:335476 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
5477 DCHECK(max_len == 0 || len < max_len);
[email protected]d6a53e42011-10-05 00:09:365478 DCHECK(len == 0 || temp[len] == '\0');
[email protected]df6cf1ad2011-01-29 01:20:525479 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
[email protected]e5186162010-06-14 18:54:415480 }
[email protected]45bf5152010-02-12 00:11:315481};
5482
[email protected]ddd968b82010-03-02 00:44:295483void GLES2DecoderImpl::DoGetShaderiv(
5484 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:585485 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5486 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:295487 if (!info) {
[email protected]ddd968b82010-03-02 00:44:295488 return;
5489 }
[email protected]8f1ccdac2010-05-19 21:01:485490 switch (pname) {
5491 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525492 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:485493 return;
5494 case GL_COMPILE_STATUS:
[email protected]062c38b2012-01-18 03:25:105495 *params = compile_shader_always_succeeds_ ? true : info->IsValid();
[email protected]e5186162010-06-14 18:54:415496 return;
[email protected]8f1ccdac2010-05-19 21:01:485497 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525498 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:415499 return;
[email protected]d6a53e42011-10-05 00:09:365500 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5501 *params = info->translated_source() ?
5502 info->translated_source()->size() + 1 : 0;
5503 return;
[email protected]8f1ccdac2010-05-19 21:01:485504 default:
5505 break;
[email protected]ddd968b82010-03-02 00:44:295506 }
[email protected]8f1ccdac2010-05-19 21:01:485507 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:295508}
5509
[email protected]ae51d192010-04-27 00:48:035510error::Error GLES2DecoderImpl::HandleGetShaderSource(
5511 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
5512 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:035513 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5514 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:585515 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5516 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:525517 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:295518 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:295519 return error::kNoError;
5520 }
[email protected]df6cf1ad2011-01-29 01:20:525521 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:035522 return error::kNoError;
5523}
5524
[email protected]d6a53e42011-10-05 00:09:365525error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
5526 uint32 immediate_data_size,
5527 const gles2::GetTranslatedShaderSourceANGLE& c) {
5528 GLuint shader = c.shader;
5529
5530 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5531 Bucket* bucket = CreateBucket(bucket_id);
5532 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5533 shader, "glTranslatedGetShaderSourceANGLE");
5534 if (!info) {
5535 bucket->SetSize(0);
5536 return error::kNoError;
5537 }
5538
5539 bucket->SetFromString(info->translated_source() ?
5540 info->translated_source()->c_str() : NULL);
5541 return error::kNoError;
5542}
5543
[email protected]ae51d192010-04-27 00:48:035544error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
5545 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
5546 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:585547 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5548 Bucket* bucket = CreateBucket(bucket_id);
5549 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5550 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525551 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465552 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035553 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:315554 }
[email protected]df6cf1ad2011-01-29 01:20:525555 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035556 return error::kNoError;
5557}
5558
5559error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
5560 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
5561 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:585562 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5563 Bucket* bucket = CreateBucket(bucket_id);
5564 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5565 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525566 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465567 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035568 return error::kNoError;
5569 }
[email protected]df6cf1ad2011-01-29 01:20:525570 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035571 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325572}
5573
[email protected]1958e0e2010-04-22 05:17:155574bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105575 const BufferManager::BufferInfo* buffer = GetBufferInfo(client_id);
5576 return buffer && buffer->IsValid() && !buffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155577}
5578
5579bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105580 const FramebufferManager::FramebufferInfo* framebuffer =
[email protected]06c8b082011-01-05 18:00:365581 GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105582 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155583}
5584
5585bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365586 // IsProgram is true for programs as soon as they are created, until they are
5587 // deleted and no longer in use.
[email protected]a0b78dc2011-11-11 10:43:105588 const ProgramManager::ProgramInfo* program = GetProgramInfo(client_id);
5589 return program != NULL && !program->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155590}
5591
5592bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105593 const RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]06c8b082011-01-05 18:00:365594 GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105595 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155596}
5597
5598bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365599 // IsShader is true for shaders as soon as they are created, until they
5600 // are deleted and not attached to any programs.
[email protected]a0b78dc2011-11-11 10:43:105601 const ShaderManager::ShaderInfo* shader = GetShaderInfo(client_id);
5602 return shader != NULL && !shader->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155603}
5604
5605bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105606 const TextureManager::TextureInfo* texture = GetTextureInfo(client_id);
5607 return texture && texture->IsValid() && !texture->IsDeleted();
[email protected]ae51d192010-04-27 00:48:035608}
5609
5610void GLES2DecoderImpl::DoAttachShader(
5611 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585612 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5613 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035614 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035615 return;
[email protected]1958e0e2010-04-22 05:17:155616 }
[email protected]6b8cf1a2010-05-06 16:13:585617 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5618 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035619 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035620 return;
5621 }
[email protected]ca488e12010-12-13 20:06:145622 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:315623 SetGLError(GL_INVALID_OPERATION,
5624 "glAttachShader: can not attach more than"
5625 " one shader of the same type.");
5626 return;
5627 }
[email protected]ae51d192010-04-27 00:48:035628 glAttachShader(program_info->service_id(), shader_info->service_id());
5629}
5630
5631void GLES2DecoderImpl::DoDetachShader(
5632 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585633 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5634 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035635 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035636 return;
5637 }
[email protected]6b8cf1a2010-05-06 16:13:585638 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5639 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035640 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035641 return;
5642 }
[email protected]9a0ccd42011-03-16 23:58:225643 if (!program_info->DetachShader(shader_manager(), shader_info)) {
5644 SetGLError(GL_INVALID_OPERATION,
5645 "glDetachShader: shader not attached to program");
5646 return;
5647 }
[email protected]ae51d192010-04-27 00:48:035648 glDetachShader(program_info->service_id(), shader_info->service_id());
5649}
5650
5651void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585652 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5653 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:035654 if (!info) {
[email protected]ae51d192010-04-27 00:48:035655 return;
5656 }
[email protected]d685a682011-04-29 16:19:575657 info->Validate();
[email protected]1958e0e2010-04-22 05:17:155658}
5659
[email protected]b1122982010-05-17 23:04:245660void GLES2DecoderImpl::DoGetVertexAttribfv(
5661 GLuint index, GLenum pname, GLfloat* params) {
5662 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445663 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245664 if (!info) {
5665 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
5666 return;
5667 }
5668 switch (pname) {
5669 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5670 BufferManager::BufferInfo* buffer = info->buffer();
5671 if (buffer && !buffer->IsDeleted()) {
5672 GLuint client_id;
5673 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5674 *params = static_cast<GLfloat>(client_id);
5675 }
5676 break;
5677 }
5678 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5679 *params = static_cast<GLfloat>(info->enabled());
5680 break;
5681 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5682 *params = static_cast<GLfloat>(info->size());
5683 break;
5684 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5685 *params = static_cast<GLfloat>(info->gl_stride());
5686 break;
5687 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5688 *params = static_cast<GLfloat>(info->type());
5689 break;
5690 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5691 *params = static_cast<GLfloat>(info->normalized());
5692 break;
5693 case GL_CURRENT_VERTEX_ATTRIB:
5694 params[0] = info->value().v[0];
5695 params[1] = info->value().v[1];
5696 params[2] = info->value().v[2];
5697 params[3] = info->value().v[3];
5698 break;
[email protected]c6aef902012-02-14 03:31:425699 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
5700 *params = static_cast<GLfloat>(info->divisor());
5701 break;
[email protected]b1122982010-05-17 23:04:245702 default:
5703 NOTREACHED();
5704 break;
5705 }
5706}
5707
5708void GLES2DecoderImpl::DoGetVertexAttribiv(
5709 GLuint index, GLenum pname, GLint* params) {
5710 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445711 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245712 if (!info) {
5713 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
5714 return;
5715 }
5716 switch (pname) {
5717 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5718 BufferManager::BufferInfo* buffer = info->buffer();
5719 if (buffer && !buffer->IsDeleted()) {
5720 GLuint client_id;
5721 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5722 *params = client_id;
5723 }
5724 break;
5725 }
5726 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5727 *params = info->enabled();
5728 break;
5729 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5730 *params = info->size();
5731 break;
5732 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5733 *params = info->gl_stride();
5734 break;
5735 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5736 *params = info->type();
5737 break;
5738 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5739 *params = static_cast<GLint>(info->normalized());
5740 break;
[email protected]c6aef902012-02-14 03:31:425741 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
5742 *params = info->divisor();
5743 break;
[email protected]b1122982010-05-17 23:04:245744 case GL_CURRENT_VERTEX_ATTRIB:
5745 params[0] = static_cast<GLint>(info->value().v[0]);
5746 params[1] = static_cast<GLint>(info->value().v[1]);
5747 params[2] = static_cast<GLint>(info->value().v[2]);
5748 params[3] = static_cast<GLint>(info->value().v[3]);
5749 break;
5750 default:
5751 NOTREACHED();
5752 break;
5753 }
5754}
5755
5756void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
5757 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445758 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245759 if (!info) {
5760 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
5761 return;
5762 }
5763 VertexAttribManager::VertexAttribInfo::Vec4 value;
5764 value.v[0] = v0;
5765 value.v[1] = 0.0f;
5766 value.v[2] = 0.0f;
5767 value.v[3] = 1.0f;
5768 info->set_value(value);
5769 glVertexAttrib1f(index, v0);
5770}
5771
5772void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
5773 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445774 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245775 if (!info) {
5776 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
5777 return;
5778 }
5779 VertexAttribManager::VertexAttribInfo::Vec4 value;
5780 value.v[0] = v0;
5781 value.v[1] = v1;
5782 value.v[2] = 0.0f;
5783 value.v[3] = 1.0f;
5784 info->set_value(value);
5785 glVertexAttrib2f(index, v0, v1);
5786}
5787
5788void GLES2DecoderImpl::DoVertexAttrib3f(
5789 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
5790 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445791 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245792 if (!info) {
5793 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
5794 return;
5795 }
5796 VertexAttribManager::VertexAttribInfo::Vec4 value;
5797 value.v[0] = v0;
5798 value.v[1] = v1;
5799 value.v[2] = v2;
5800 value.v[3] = 1.0f;
5801 info->set_value(value);
5802 glVertexAttrib3f(index, v0, v1, v2);
5803}
5804
5805void GLES2DecoderImpl::DoVertexAttrib4f(
5806 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
5807 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445808 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245809 if (!info) {
5810 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
5811 return;
5812 }
5813 VertexAttribManager::VertexAttribInfo::Vec4 value;
5814 value.v[0] = v0;
5815 value.v[1] = v1;
5816 value.v[2] = v2;
5817 value.v[3] = v3;
5818 info->set_value(value);
5819 glVertexAttrib4f(index, v0, v1, v2, v3);
5820}
5821
5822void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
5823 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445824 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245825 if (!info) {
5826 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
5827 return;
5828 }
5829 VertexAttribManager::VertexAttribInfo::Vec4 value;
5830 value.v[0] = v[0];
5831 value.v[1] = 0.0f;
5832 value.v[2] = 0.0f;
5833 value.v[3] = 1.0f;
5834 info->set_value(value);
5835 glVertexAttrib1fv(index, v);
5836}
5837
5838void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
5839 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445840 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245841 if (!info) {
5842 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
5843 return;
5844 }
5845 VertexAttribManager::VertexAttribInfo::Vec4 value;
5846 value.v[0] = v[0];
5847 value.v[1] = v[1];
5848 value.v[2] = 0.0f;
5849 value.v[3] = 1.0f;
5850 info->set_value(value);
5851 glVertexAttrib2fv(index, v);
5852}
5853
5854void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
5855 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445856 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245857 if (!info) {
5858 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
5859 return;
5860 }
5861 VertexAttribManager::VertexAttribInfo::Vec4 value;
5862 value.v[0] = v[0];
5863 value.v[1] = v[1];
5864 value.v[2] = v[2];
5865 value.v[3] = 1.0f;
5866 info->set_value(value);
5867 glVertexAttrib3fv(index, v);
5868}
5869
5870void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
5871 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445872 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245873 if (!info) {
5874 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
5875 return;
5876 }
5877 VertexAttribManager::VertexAttribInfo::Vec4 value;
5878 value.v[0] = v[0];
5879 value.v[1] = v[1];
5880 value.v[2] = v[2];
5881 value.v[3] = v[3];
5882 info->set_value(value);
5883 glVertexAttrib4fv(index, v);
5884}
5885
[email protected]f7a64ee2010-02-01 22:24:145886error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:195887 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:295888 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
5889 SetGLError(GL_INVALID_VALUE,
5890 "glVertexAttribPointer: no array buffer bound");
5891 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325892 }
[email protected]8eee29c2010-04-29 03:38:295893
5894 GLuint indx = c.indx;
5895 GLint size = c.size;
5896 GLenum type = c.type;
5897 GLboolean normalized = c.normalized;
5898 GLsizei stride = c.stride;
5899 GLsizei offset = c.offset;
5900 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:055901 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295902 SetGLError(GL_INVALID_ENUM,
5903 "glVertexAttribPointer: type GL_INVALID_ENUM");
5904 return error::kNoError;
5905 }
[email protected]9438b012010-06-15 22:55:055906 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:315907 SetGLError(GL_INVALID_VALUE,
[email protected]8eee29c2010-04-29 03:38:295908 "glVertexAttribPointer: size GL_INVALID_VALUE");
5909 return error::kNoError;
5910 }
5911 if (indx >= group_->max_vertex_attribs()) {
5912 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
5913 return error::kNoError;
5914 }
5915 if (stride < 0) {
5916 SetGLError(GL_INVALID_VALUE,
5917 "glVertexAttribPointer: stride < 0");
5918 return error::kNoError;
5919 }
5920 if (stride > 255) {
5921 SetGLError(GL_INVALID_VALUE,
5922 "glVertexAttribPointer: stride > 255");
5923 return error::kNoError;
5924 }
5925 if (offset < 0) {
5926 SetGLError(GL_INVALID_VALUE,
5927 "glVertexAttribPointer: offset < 0");
5928 return error::kNoError;
5929 }
5930 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:315931 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:295932 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:315933 SetGLError(GL_INVALID_OPERATION,
5934 "glVertexAttribPointer: offset not valid for type");
5935 return error::kNoError;
5936 }
5937 if (stride % component_size > 0) {
5938 SetGLError(GL_INVALID_OPERATION,
[email protected]8eee29c2010-04-29 03:38:295939 "glVertexAttribPointer: stride not valid for type");
5940 return error::kNoError;
5941 }
[email protected]3757a372012-01-19 05:20:445942 vertex_attrib_manager_->SetAttribInfo(
[email protected]8fbedc02010-11-18 18:43:405943 indx,
[email protected]8eee29c2010-04-29 03:38:295944 bound_array_buffer_,
5945 size,
5946 type,
[email protected]b1122982010-05-17 23:04:245947 normalized,
5948 stride,
5949 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:295950 offset);
[email protected]8fbedc02010-11-18 18:43:405951 if (type != GL_FIXED) {
5952 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
5953 }
[email protected]f7a64ee2010-02-01 22:24:145954 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325955}
5956
[email protected]c6aef902012-02-14 03:31:425957error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
5958 uint32 immediate_data_size, const gles2::VertexAttribDivisorANGLE& c) {
5959 if (!feature_info_->feature_flags().angle_instanced_arrays) {
5960 SetGLError(GL_INVALID_OPERATION,
5961 "glVertexAttribDivisorANGLE: function not available");
5962 }
5963 GLuint index = c.index;
5964 GLuint divisor = c.divisor;
5965 if (index >= group_->max_vertex_attribs()) {
5966 SetGLError(GL_INVALID_VALUE,
5967 "glVertexAttribDivisorANGLE: index out of range");
5968 return error::kNoError;
5969 }
5970
5971 vertex_attrib_manager_->SetDivisor(
5972 index,
5973 divisor);
5974 glVertexAttribDivisorANGLE(index, divisor);
5975 return error::kNoError;
5976}
5977
[email protected]f7a64ee2010-02-01 22:24:145978error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:195979 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:315980 GLint x = c.x;
5981 GLint y = c.y;
5982 GLsizei width = c.width;
5983 GLsizei height = c.height;
5984 GLenum format = c.format;
5985 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:565986 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:295987 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:565988 return error::kNoError;
5989 }
[email protected]a51788e2010-02-24 21:54:255990 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:185991 uint32 pixels_size;
5992 if (!GLES2Util::ComputeImageDataSize(
5993 width, height, format, type, pack_alignment_, &pixels_size)) {
5994 return error::kOutOfBounds;
5995 }
[email protected]612d2f82009-12-08 20:49:315996 void* pixels = GetSharedMemoryAs<void*>(
5997 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:255998 Result* result = GetSharedMemoryAs<Result*>(
5999 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6000 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:146001 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466002 }
[email protected]a51788e2010-02-24 21:54:256003
[email protected]9438b012010-06-15 22:55:056004 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:296005 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
6006 return error::kNoError;
6007 }
[email protected]9438b012010-06-15 22:55:056008 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:296009 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:126010 return error::kNoError;
6011 }
[email protected]57f223832010-03-19 01:57:566012 if (width == 0 || height == 0) {
6013 return error::kNoError;
6014 }
6015
[email protected]57f223832010-03-19 01:57:566016 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:306017 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:566018
6019 GLint max_x;
6020 GLint max_y;
6021 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:296022 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:146023 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:316024 }
[email protected]57f223832010-03-19 01:57:566025
[email protected]0d6bfdc2011-11-02 01:32:206026 if (!CheckBoundFramebuffersValid("glReadPixels")) {
6027 return error::kNoError;
6028 }
6029
[email protected]a0b78dc2011-11-11 10:43:106030 CopyRealGLErrorsToWrapper();
6031
6032 ScopedResolvedFrameBufferBinder binder(this, false, true);
6033
[email protected]d37231fa2010-04-09 21:16:026034 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:566035 // The user requested an out of range area. Get the results 1 line
6036 // at a time.
6037 uint32 temp_size;
6038 if (!GLES2Util::ComputeImageDataSize(
6039 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:296040 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:566041 return error::kNoError;
6042 }
6043 GLsizei unpadded_row_size = temp_size;
6044 if (!GLES2Util::ComputeImageDataSize(
6045 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:296046 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:566047 return error::kNoError;
6048 }
6049 GLsizei padded_row_size = temp_size - unpadded_row_size;
6050 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:296051 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:566052 return error::kNoError;
6053 }
6054
6055 GLint dest_x_offset = std::max(-x, 0);
6056 uint32 dest_row_offset;
6057 if (!GLES2Util::ComputeImageDataSize(
6058 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:296059 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:566060 return error::kNoError;
6061 }
6062
6063 // Copy each row into the larger dest rect.
6064 int8* dst = static_cast<int8*>(pixels);
6065 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:026066 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:566067 GLint read_width = read_end_x - read_x;
6068 for (GLint yy = 0; yy < height; ++yy) {
6069 GLint ry = y + yy;
6070
6071 // Clear the row.
6072 memset(dst, 0, unpadded_row_size);
6073
6074 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:026075 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:566076 glReadPixels(
6077 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
6078 }
6079 dst += padded_row_size;
6080 }
6081 } else {
6082 glReadPixels(x, y, width, height, format, type, pixels);
6083 }
[email protected]1002c2d2011-06-28 22:39:046084 GLenum error = PeekGLError();
[email protected]a51788e2010-02-24 21:54:256085 if (error == GL_NO_ERROR) {
6086 *result = true;
[email protected]4848b9f82011-03-10 18:37:566087
6088 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6089 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6090 if ((channels_exist & 0x0008) == 0) {
6091 // Set the alpha to 255 because some drivers are buggy in this regard.
6092 uint32 temp_size;
6093 if (!GLES2Util::ComputeImageDataSize(
6094 width, 1, format, type, pack_alignment_, &temp_size)) {
6095 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
6096 return error::kNoError;
6097 }
6098 GLsizei unpadded_row_size = temp_size;
6099 if (!GLES2Util::ComputeImageDataSize(
6100 width, 2, format, type, pack_alignment_, &temp_size)) {
6101 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
6102 return error::kNoError;
6103 }
6104 GLsizei padded_row_size = temp_size - unpadded_row_size;
6105 if (padded_row_size < 0 || unpadded_row_size < 0) {
6106 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
6107 return error::kNoError;
6108 }
6109 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
6110 // of this implementation.
6111 if (type != GL_UNSIGNED_BYTE) {
6112 SetGLError(GL_INVALID_OPERATION, "unsupported readPixel format");
6113 return error::kNoError;
6114 }
6115 switch (format) {
6116 case GL_RGBA:
[email protected]297ca1c2011-06-20 23:08:466117 case GL_BGRA_EXT:
[email protected]4848b9f82011-03-10 18:37:566118 case GL_ALPHA: {
6119 int offset = (format == GL_ALPHA) ? 0 : 3;
6120 int step = (format == GL_ALPHA) ? 1 : 4;
6121 uint8* dst = static_cast<uint8*>(pixels) + offset;
6122 for (GLint yy = 0; yy < height; ++yy) {
6123 uint8* end = dst + unpadded_row_size;
6124 for (uint8* d = dst; d < end; d += step) {
6125 *d = 255;
6126 }
6127 dst += padded_row_size;
6128 }
6129 break;
6130 }
6131 default:
6132 break;
6133 }
6134 }
[email protected]a51788e2010-02-24 21:54:256135 }
[email protected]4848b9f82011-03-10 18:37:566136
[email protected]f7a64ee2010-02-01 22:24:146137 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326138}
6139
[email protected]f7a64ee2010-02-01 22:24:146140error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:196141 uint32 immediate_data_size, const gles2::PixelStorei& c) {
6142 GLenum pname = c.pname;
6143 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:056144 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:296145 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:126146 return error::kNoError;
6147 }
[email protected]222471d2011-11-30 18:06:396148 switch (pname) {
6149 case GL_PACK_ALIGNMENT:
6150 case GL_UNPACK_ALIGNMENT:
6151 if (!validators_->pixel_store_alignment.IsValid(param)) {
6152 SetGLError(GL_INVALID_VALUE,
6153 "glPixelSTore: param GL_INVALID_VALUE");
6154 return error::kNoError;
6155 }
6156 default:
6157 break;
[email protected]b9849abf2009-11-25 19:13:196158 }
6159 glPixelStorei(pname, param);
6160 switch (pname) {
6161 case GL_PACK_ALIGNMENT:
6162 pack_alignment_ = param;
6163 break;
[email protected]222471d2011-11-30 18:06:396164 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
6165 break;
[email protected]b9849abf2009-11-25 19:13:196166 case GL_UNPACK_ALIGNMENT:
6167 unpack_alignment_ = param;
6168 break;
6169 default:
6170 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:376171 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:196172 break;
6173 }
[email protected]f7a64ee2010-02-01 22:24:146174 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196175}
6176
[email protected]1c75a3702011-11-11 14:15:286177error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
6178 uint32 immediate_data_size, const gles2::PostSubBufferCHROMIUM& c) {
6179 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
[email protected]aa258822011-11-22 13:52:256180 if (!context_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
[email protected]1c75a3702011-11-11 14:15:286181 SetGLError(GL_INVALID_OPERATION,
6182 "glPostSubBufferCHROMIUM: command not supported by surface");
6183 return error::kNoError;
6184 }
6185 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height))
6186 return error::kNoError;
6187 else
6188 return error::kLostContext;
6189}
6190
[email protected]558847a2010-03-24 07:02:546191error::Error GLES2DecoderImpl::GetAttribLocationHelper(
6192 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6193 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576194 if (!StringIsValidForGLES(name_str.c_str())) {
6195 SetGLError(GL_INVALID_VALUE, "glGetAttribLocation: Invalid character");
6196 return error::kNoError;
6197 }
[email protected]6b8cf1a2010-05-06 16:13:586198 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6199 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:036200 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146201 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196202 }
[email protected]ae51d192010-04-27 00:48:036203 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:296204 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:256205 return error::kNoError;
6206 }
[email protected]b9849abf2009-11-25 19:13:196207 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546208 location_shm_id, location_shm_offset, sizeof(GLint));
6209 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146210 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196211 }
[email protected]558847a2010-03-24 07:02:546212 // Require the client to init this incase the context is lost and we are no
6213 // longer executing commands.
6214 if (*location != -1) {
6215 return error::kGenericError;
6216 }
[email protected]0bfd9882010-02-05 23:02:256217 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:146218 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196219}
6220
[email protected]558847a2010-03-24 07:02:546221error::Error GLES2DecoderImpl::HandleGetAttribLocation(
6222 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
6223 uint32 name_size = c.data_size;
6224 const char* name = GetSharedMemoryAs<const char*>(
6225 c.name_shm_id, c.name_shm_offset, name_size);
6226 if (!name) {
6227 return error::kOutOfBounds;
6228 }
6229 String name_str(name, name_size);
6230 return GetAttribLocationHelper(
6231 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6232}
6233
[email protected]f7a64ee2010-02-01 22:24:146234error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196235 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:546236 uint32 name_size = c.data_size;
6237 const char* name = GetImmediateDataAs<const char*>(
6238 c, name_size, immediate_data_size);
6239 if (!name) {
6240 return error::kOutOfBounds;
6241 }
6242 String name_str(name, name_size);
6243 return GetAttribLocationHelper(
6244 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6245}
6246
6247error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
6248 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
6249 Bucket* bucket = GetBucket(c.name_bucket_id);
6250 if (!bucket) {
6251 return error::kInvalidArguments;
6252 }
6253 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186254 if (!bucket->GetAsString(&name_str)) {
6255 return error::kInvalidArguments;
6256 }
[email protected]558847a2010-03-24 07:02:546257 return GetAttribLocationHelper(
6258 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6259}
6260
6261error::Error GLES2DecoderImpl::GetUniformLocationHelper(
6262 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6263 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576264 if (!StringIsValidForGLES(name_str.c_str())) {
6265 SetGLError(GL_INVALID_VALUE, "glGetUniformLocation: Invalid character");
6266 return error::kNoError;
6267 }
[email protected]6b8cf1a2010-05-06 16:13:586268 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6269 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:036270 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146271 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196272 }
[email protected]ae51d192010-04-27 00:48:036273 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:296274 SetGLError(GL_INVALID_OPERATION,
6275 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:256276 return error::kNoError;
6277 }
[email protected]b9849abf2009-11-25 19:13:196278 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546279 location_shm_id, location_shm_offset, sizeof(GLint));
6280 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146281 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196282 }
[email protected]558847a2010-03-24 07:02:546283 // Require the client to init this incase the context is lost an we are no
6284 // longer executing commands.
6285 if (*location != -1) {
6286 return error::kGenericError;
6287 }
[email protected]5d4c6b22012-02-07 08:22:286288 *location = program_manager()->SwizzleLocation(
[email protected]1b0a6752012-02-22 03:44:126289 info->GetUniformFakeLocation(name_str));
[email protected]f7a64ee2010-02-01 22:24:146290 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196291}
6292
[email protected]f7a64ee2010-02-01 22:24:146293error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:196294 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:196295 uint32 name_size = c.data_size;
6296 const char* name = GetSharedMemoryAs<const char*>(
6297 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:546298 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146299 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196300 }
6301 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546302 return GetUniformLocationHelper(
6303 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196304}
6305
[email protected]f7a64ee2010-02-01 22:24:146306error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196307 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:196308 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:306309 const char* name = GetImmediateDataAs<const char*>(
6310 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:546311 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146312 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196313 }
6314 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546315 return GetUniformLocationHelper(
6316 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6317}
6318
6319error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
6320 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
6321 Bucket* bucket = GetBucket(c.name_bucket_id);
6322 if (!bucket) {
6323 return error::kInvalidArguments;
6324 }
6325 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186326 if (!bucket->GetAsString(&name_str)) {
6327 return error::kInvalidArguments;
6328 }
[email protected]558847a2010-03-24 07:02:546329 return GetUniformLocationHelper(
6330 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196331}
6332
[email protected]ddd968b82010-03-02 00:44:296333error::Error GLES2DecoderImpl::HandleGetString(
6334 uint32 immediate_data_size, const gles2::GetString& c) {
6335 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:056336 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:296337 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:296338 return error::kNoError;
6339 }
[email protected]1958e0e2010-04-22 05:17:156340 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
6341 const char* str = NULL;
[email protected]f0d74742011-10-03 16:31:046342 std::string extensions;
[email protected]1958e0e2010-04-22 05:17:156343 switch (name) {
6344 case GL_VERSION:
6345 str = "OpenGL ES 2.0 Chromium";
6346 break;
6347 case GL_SHADING_LANGUAGE_VERSION:
6348 str = "OpenGL ES GLSL ES 1.0 Chromium";
6349 break;
6350 case GL_EXTENSIONS:
[email protected]f0d74742011-10-03 16:31:046351 {
6352 // For WebGL contexts, strip out the OES derivatives extension if it has
6353 // not been enabled.
6354 if (force_webgl_glsl_validation_ &&
6355 !derivatives_explicitly_enabled_) {
6356 extensions = feature_info_->extensions();
6357 size_t offset = extensions.find(kOESDerivativeExtension);
6358 if (std::string::npos != offset) {
6359 extensions.replace(offset,
6360 offset + arraysize(kOESDerivativeExtension),
6361 std::string());
6362 }
6363 str = extensions.c_str();
6364 } else {
6365 str = feature_info_->extensions().c_str();
6366 }
[email protected]f0d74742011-10-03 16:31:046367 }
[email protected]1958e0e2010-04-22 05:17:156368 break;
6369 default:
6370 str = gl_str;
6371 break;
6372 }
[email protected]ddd968b82010-03-02 00:44:296373 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:156374 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:296375 return error::kNoError;
6376}
6377
[email protected]0c86dbf2010-03-05 08:14:116378void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:156379 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:056380 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296381 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
6382 return;
6383 }
[email protected]9438b012010-06-15 22:55:056384 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:296385 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:116386 return;
[email protected]3b6ec202010-03-05 05:16:236387 }
6388 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:296389 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:286390 return;
[email protected]3b6ec202010-03-05 05:16:236391 }
6392 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
6393 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296394 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:286395 return;
[email protected]3b6ec202010-03-05 05:16:236396 }
6397 // Clear the buffer to 0 if no initial data was passed in.
6398 scoped_array<int8> zero;
6399 if (!data) {
6400 zero.reset(new int8[size]);
6401 memset(zero.get(), 0, size);
6402 data = zero.get();
6403 }
[email protected]473c01ccb2011-06-07 01:33:306404
6405 if (!bufferdata_faster_than_buffersubdata_ &&
6406 size == info->size() && usage == info->usage()) {
6407 glBufferSubData(target, 0, size, data);
6408 info->SetRange(0, size, data);
6409 return;
6410 }
6411
[email protected]3b6ec202010-03-05 05:16:236412 CopyRealGLErrorsToWrapper();
6413 glBufferData(target, size, data, usage);
[email protected]1002c2d2011-06-28 22:39:046414 GLenum error = PeekGLError();
6415 if (error == GL_NO_ERROR) {
[email protected]473c01ccb2011-06-07 01:33:306416 buffer_manager()->SetInfo(info, size, usage);
[email protected]0c86dbf2010-03-05 08:14:116417 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:236418 }
[email protected]0c86dbf2010-03-05 08:14:116419}
6420
6421error::Error GLES2DecoderImpl::HandleBufferData(
6422 uint32 immediate_data_size, const gles2::BufferData& c) {
6423 GLenum target = static_cast<GLenum>(c.target);
6424 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
6425 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6426 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6427 GLenum usage = static_cast<GLenum>(c.usage);
6428 const void* data = NULL;
6429 if (data_shm_id != 0 || data_shm_offset != 0) {
6430 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
6431 if (!data) {
6432 return error::kOutOfBounds;
6433 }
6434 }
6435 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:146436 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196437}
6438
[email protected]f7a64ee2010-02-01 22:24:146439error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:196440 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
6441 GLenum target = static_cast<GLenum>(c.target);
6442 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:306443 const void* data = GetImmediateDataAs<const void*>(
6444 c, size, immediate_data_size);
6445 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146446 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:306447 }
[email protected]b9849abf2009-11-25 19:13:196448 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:116449 DoBufferData(target, size, data, usage);
6450 return error::kNoError;
6451}
6452
6453void GLES2DecoderImpl::DoBufferSubData(
6454 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:506455 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476456 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296457 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:286458 return;
[email protected]a93bb842010-02-16 23:03:476459 }
[email protected]0c86dbf2010-03-05 08:14:116460 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:296461 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]473c01ccb2011-06-07 01:33:306462 return;
[email protected]07f54fcc2009-12-22 02:46:306463 }
[email protected]473c01ccb2011-06-07 01:33:306464 if (bufferdata_faster_than_buffersubdata_ &&
6465 offset == 0 && size == info->size()) {
6466 glBufferData(target, size, data, info->usage());
6467 return;
6468 }
6469 glBufferSubData(target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:196470}
6471
[email protected]0d6bfdc2011-11-02 01:32:206472bool GLES2DecoderImpl::ClearLevel(
6473 unsigned service_id,
6474 unsigned bind_target,
6475 unsigned target,
6476 int level,
6477 unsigned format,
6478 unsigned type,
6479 int width,
[email protected]4502e6492011-12-14 19:39:156480 int height,
6481 bool is_texture_immutable) {
[email protected]0d6bfdc2011-11-02 01:32:206482 // Assumes the size has already been checked.
6483 uint32 pixels_size = 0;
6484 if (!GLES2Util::ComputeImageDataSize(
6485 width, height, format, type, unpack_alignment_, &pixels_size)) {
6486 return false;
6487 }
6488 scoped_array<char> zero(new char[pixels_size]);
6489 memset(zero.get(), 0, pixels_size);
6490 glBindTexture(bind_target, service_id);
[email protected]4502e6492011-12-14 19:39:156491 if (is_texture_immutable) {
6492 glTexSubImage2D(
6493 target, level, 0, 0, width, height, format, type, zero.get());
6494 } else {
6495 WrappedTexImage2D(
6496 target, level, format, width, height, 0, format, type, zero.get());
6497 }
[email protected]0d6bfdc2011-11-02 01:32:206498 TextureManager::TextureInfo* info = GetTextureInfoForTarget(bind_target);
6499 glBindTexture(bind_target, info ? info->service_id() : 0);
6500 return true;
6501}
6502
[email protected]a93bb842010-02-16 23:03:476503error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
6504 GLenum target,
6505 GLint level,
6506 GLenum internal_format,
6507 GLsizei width,
6508 GLsizei height,
6509 GLint border,
6510 GLsizei image_size,
6511 const void* data) {
[email protected]a93bb842010-02-16 23:03:476512 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:056513 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296514 SetGLError(GL_INVALID_ENUM,
6515 "glCompressedTexImage2D: target GL_INVALID_ENUM");
6516 return error::kNoError;
6517 }
[email protected]9438b012010-06-15 22:55:056518 if (!validators_->compressed_texture_format.IsValid(
6519 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296520 SetGLError(GL_INVALID_ENUM,
6521 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:476522 return error::kNoError;
6523 }
[email protected]80eb6b52012-01-19 00:14:416524 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476525 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296526 SetGLError(GL_INVALID_VALUE,
6527 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476528 return error::kNoError;
6529 }
[email protected]3916c97e2010-02-25 03:20:506530 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476531 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296532 SetGLError(GL_INVALID_VALUE,
6533 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:476534 return error::kNoError;
6535 }
[email protected]97dc7cbe2011-12-06 17:26:176536 if (info->IsImmutable()) {
6537 SetGLError(GL_INVALID_OPERATION,
6538 "glCompressedTexImage2D: texture is immutable");
6539 return error::kNoError;
6540 }
[email protected]968351b2011-12-20 08:26:516541
6542 if (info->IsAttachedToFramebuffer()) {
6543 state_dirty_ = true;
6544 // TODO(gman): If textures tracked which framebuffers they were attached to
6545 // we could just mark those framebuffers as not complete.
6546 framebuffer_manager()->IncFramebufferStateChangeCount();
6547 }
6548
[email protected]a93bb842010-02-16 23:03:476549 scoped_array<int8> zero;
6550 if (!data) {
6551 zero.reset(new int8[image_size]);
6552 memset(zero.get(), 0, image_size);
6553 data = zero.get();
6554 }
[email protected]cadde4a2010-07-31 17:10:436555 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:476556 glCompressedTexImage2D(
6557 target, level, internal_format, width, height, border, image_size, data);
[email protected]1002c2d2011-06-28 22:39:046558 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436559 if (error == GL_NO_ERROR) {
6560 texture_manager()->SetLevelInfo(
[email protected]0d6bfdc2011-11-02 01:32:206561 info, target, level, internal_format, width, height, 1, border, 0, 0,
6562 true);
[email protected]cadde4a2010-07-31 17:10:436563 }
[email protected]a93bb842010-02-16 23:03:476564 return error::kNoError;
6565}
6566
[email protected]f7a64ee2010-02-01 22:24:146567error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196568 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
6569 GLenum target = static_cast<GLenum>(c.target);
6570 GLint level = static_cast<GLint>(c.level);
6571 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6572 GLsizei width = static_cast<GLsizei>(c.width);
6573 GLsizei height = static_cast<GLsizei>(c.height);
6574 GLint border = static_cast<GLint>(c.border);
6575 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
6576 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6577 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6578 const void* data = NULL;
6579 if (data_shm_id != 0 || data_shm_offset != 0) {
6580 data = GetSharedMemoryAs<const void*>(
6581 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:466582 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146583 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196584 }
6585 }
[email protected]a93bb842010-02-16 23:03:476586 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196587 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:196588}
6589
[email protected]f7a64ee2010-02-01 22:24:146590error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:196591 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
6592 GLenum target = static_cast<GLenum>(c.target);
6593 GLint level = static_cast<GLint>(c.level);
6594 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6595 GLsizei width = static_cast<GLsizei>(c.width);
6596 GLsizei height = static_cast<GLsizei>(c.height);
6597 GLint border = static_cast<GLint>(c.border);
6598 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:306599 const void* data = GetImmediateDataAs<const void*>(
6600 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466601 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146602 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466603 }
[email protected]a93bb842010-02-16 23:03:476604 return DoCompressedTexImage2D(
6605 target, level, internal_format, width, height, border, image_size, data);
6606}
6607
[email protected]b6140d02010-05-17 14:47:166608error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
6609 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
6610 GLenum target = static_cast<GLenum>(c.target);
6611 GLint level = static_cast<GLint>(c.level);
6612 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6613 GLsizei width = static_cast<GLsizei>(c.width);
6614 GLsizei height = static_cast<GLsizei>(c.height);
6615 GLint border = static_cast<GLint>(c.border);
6616 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:286617 if (!bucket) {
6618 return error::kInvalidArguments;
6619 }
6620 uint32 data_size = bucket->size();
6621 GLsizei imageSize = data_size;
6622 const void* data = bucket->GetData(0, data_size);
6623 if (!data) {
6624 return error::kInvalidArguments;
6625 }
[email protected]b6140d02010-05-17 14:47:166626 return DoCompressedTexImage2D(
6627 target, level, internal_format, width, height, border,
[email protected]12f93d82011-10-17 21:16:286628 imageSize, data);
[email protected]b6140d02010-05-17 14:47:166629}
6630
6631error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
6632 uint32 immediate_data_size,
6633 const gles2::CompressedTexSubImage2DBucket& c) {
6634 GLenum target = static_cast<GLenum>(c.target);
6635 GLint level = static_cast<GLint>(c.level);
6636 GLint xoffset = static_cast<GLint>(c.xoffset);
6637 GLint yoffset = static_cast<GLint>(c.yoffset);
6638 GLsizei width = static_cast<GLsizei>(c.width);
6639 GLsizei height = static_cast<GLsizei>(c.height);
6640 GLenum format = static_cast<GLenum>(c.format);
6641 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:286642 if (!bucket) {
6643 return error::kInvalidArguments;
6644 }
[email protected]b6140d02010-05-17 14:47:166645 uint32 data_size = bucket->size();
6646 GLsizei imageSize = data_size;
6647 const void* data = bucket->GetData(0, data_size);
[email protected]12f93d82011-10-17 21:16:286648 if (!data) {
6649 return error::kInvalidArguments;
6650 }
[email protected]9438b012010-06-15 22:55:056651 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:166652 SetGLError(
6653 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
6654 return error::kNoError;
6655 }
[email protected]9438b012010-06-15 22:55:056656 if (!validators_->compressed_texture_format.IsValid(format)) {
6657 SetGLError(GL_INVALID_ENUM,
6658 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
6659 return error::kNoError;
6660 }
[email protected]b6140d02010-05-17 14:47:166661 if (width < 0) {
6662 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
6663 return error::kNoError;
6664 }
6665 if (height < 0) {
6666 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
6667 return error::kNoError;
6668 }
6669 if (imageSize < 0) {
6670 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
6671 return error::kNoError;
6672 }
[email protected]cadde4a2010-07-31 17:10:436673 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:166674 target, level, xoffset, yoffset, width, height, format, imageSize, data);
6675 return error::kNoError;
6676}
6677
[email protected]a93bb842010-02-16 23:03:476678error::Error GLES2DecoderImpl::DoTexImage2D(
6679 GLenum target,
6680 GLint level,
6681 GLenum internal_format,
6682 GLsizei width,
6683 GLsizei height,
6684 GLint border,
6685 GLenum format,
6686 GLenum type,
6687 const void* pixels,
6688 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:056689 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296690 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
6691 return error::kNoError;
6692 }
[email protected]9438b012010-06-15 22:55:056693 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296694 SetGLError(GL_INVALID_ENUM,
6695 "glTexImage2D: internal_format GL_INVALID_ENUM");
6696 return error::kNoError;
6697 }
[email protected]9438b012010-06-15 22:55:056698 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:296699 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
6700 return error::kNoError;
6701 }
[email protected]9438b012010-06-15 22:55:056702 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:296703 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:146704 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196705 }
[email protected]7b92c412010-07-20 17:48:256706 if (format != internal_format) {
6707 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
6708 return error::kNoError;
6709 }
[email protected]80eb6b52012-01-19 00:14:416710 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476711 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296712 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476713 return error::kNoError;
6714 }
[email protected]3916c97e2010-02-25 03:20:506715 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476716 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296717 SetGLError(GL_INVALID_OPERATION,
6718 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:476719 return error::kNoError;
6720 }
[email protected]0226c112011-07-22 03:25:076721
[email protected]97dc7cbe2011-12-06 17:26:176722 if (info->IsImmutable()) {
6723 SetGLError(GL_INVALID_OPERATION,
6724 "glTexImage2D: texture is immutable");
6725 return error::kNoError;
6726 }
6727
[email protected]0226c112011-07-22 03:25:076728 GLsizei tex_width = 0;
6729 GLsizei tex_height = 0;
6730 GLenum tex_type = 0;
6731 GLenum tex_format = 0;
6732 bool level_is_same =
6733 info->GetLevelSize(target, level, &tex_width, &tex_height) &&
6734 info->GetLevelType(target, level, &tex_type, &tex_format) &&
6735 width == tex_width && height == tex_height &&
6736 type == tex_type && format == tex_format;
6737
6738 if (level_is_same && !pixels) {
[email protected]1bed6222011-12-21 11:21:396739 // Just set the level info but mark the texture as uncleared.
6740 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416741 info,
[email protected]1bed6222011-12-21 11:21:396742 target, level, internal_format, width, height, 1, border, format, type,
6743 false);
[email protected]ea72ed222011-08-17 18:58:436744 tex_image_2d_failed_ = false;
[email protected]0226c112011-07-22 03:25:076745 return error::kNoError;
6746 }
6747
[email protected]297ca1c2011-06-20 23:08:466748 if (info->IsAttachedToFramebuffer()) {
6749 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:516750 // TODO(gman): If textures tracked which framebuffers they were attached to
6751 // we could just mark those framebuffers as not complete.
6752 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:466753 }
6754
[email protected]1bed6222011-12-21 11:21:396755 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same && pixels) {
[email protected]0226c112011-07-22 03:25:076756 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
[email protected]57edfdad2012-02-07 04:57:156757 texture_manager()->SetLevelCleared(info, target, level);
[email protected]0226c112011-07-22 03:25:076758 tex_image_2d_failed_ = false;
6759 return error::kNoError;
[email protected]7488d962010-07-16 02:41:586760 }
[email protected]876f6fee2010-08-02 23:10:326761
[email protected]cadde4a2010-07-31 17:10:436762 CopyRealGLErrorsToWrapper();
[email protected]473c01ccb2011-06-07 01:33:306763 WrappedTexImage2D(
6764 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476765 pixels);
[email protected]1002c2d2011-06-28 22:39:046766 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436767 if (error == GL_NO_ERROR) {
[email protected]0d6bfdc2011-11-02 01:32:206768 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416769 info,
[email protected]0d6bfdc2011-11-02 01:32:206770 target, level, internal_format, width, height, 1, border, format, type,
6771 pixels != NULL);
[email protected]b493ee622011-04-13 23:52:006772 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:436773 }
[email protected]f7a64ee2010-02-01 22:24:146774 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196775}
6776
[email protected]f7a64ee2010-02-01 22:24:146777error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196778 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]366ae242011-05-10 02:23:586779 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:006780 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:196781 GLenum target = static_cast<GLenum>(c.target);
6782 GLint level = static_cast<GLint>(c.level);
6783 GLint internal_format = static_cast<GLint>(c.internalformat);
6784 GLsizei width = static_cast<GLsizei>(c.width);
6785 GLsizei height = static_cast<GLsizei>(c.height);
6786 GLint border = static_cast<GLint>(c.border);
6787 GLenum format = static_cast<GLenum>(c.format);
6788 GLenum type = static_cast<GLenum>(c.type);
6789 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
6790 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:186791 uint32 pixels_size;
6792 if (!GLES2Util::ComputeImageDataSize(
6793 width, height, format, type, unpack_alignment_, &pixels_size)) {
6794 return error::kOutOfBounds;
6795 }
[email protected]b9849abf2009-11-25 19:13:196796 const void* pixels = NULL;
6797 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
6798 pixels = GetSharedMemoryAs<const void*>(
6799 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:466800 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146801 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196802 }
6803 }
[email protected]a93bb842010-02-16 23:03:476804 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196805 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476806 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:196807}
6808
[email protected]f7a64ee2010-02-01 22:24:146809error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:196810 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
6811 GLenum target = static_cast<GLenum>(c.target);
6812 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:466813 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:196814 GLsizei width = static_cast<GLsizei>(c.width);
6815 GLsizei height = static_cast<GLsizei>(c.height);
6816 GLint border = static_cast<GLint>(c.border);
6817 GLenum format = static_cast<GLenum>(c.format);
6818 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:186819 uint32 size;
6820 if (!GLES2Util::ComputeImageDataSize(
6821 width, height, format, type, unpack_alignment_, &size)) {
6822 return error::kOutOfBounds;
6823 }
[email protected]07f54fcc2009-12-22 02:46:306824 const void* pixels = GetImmediateDataAs<const void*>(
6825 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466826 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146827 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466828 }
[email protected]a93bb842010-02-16 23:03:476829 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:466830 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476831 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:146832 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326833}
6834
[email protected]cadde4a2010-07-31 17:10:436835void GLES2DecoderImpl::DoCompressedTexSubImage2D(
6836 GLenum target,
6837 GLint level,
6838 GLint xoffset,
6839 GLint yoffset,
6840 GLsizei width,
6841 GLsizei height,
6842 GLenum format,
6843 GLsizei image_size,
6844 const void * data) {
6845 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6846 if (!info) {
6847 SetGLError(GL_INVALID_OPERATION,
6848 "glCompressedTexSubImage2D: unknown texture for target");
6849 return;
6850 }
6851 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:526852 GLenum internal_format = 0;
6853 if (!info->GetLevelType(target, level, &type, &internal_format)) {
6854 SetGLError(
6855 GL_INVALID_OPERATION,
[email protected]4502e6492011-12-14 19:39:156856 "glCompressedTexSubImage2D: level does not exist.");
[email protected]df6cf1ad2011-01-29 01:20:526857 return;
6858 }
6859 if (internal_format != format) {
6860 SetGLError(
6861 GL_INVALID_OPERATION,
[email protected]4502e6492011-12-14 19:39:156862 "glCompressedTexSubImage2D: format does not match internal format.");
[email protected]df6cf1ad2011-01-29 01:20:526863 return;
6864 }
6865 if (!info->ValidForTexture(
6866 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:436867 SetGLError(GL_INVALID_VALUE,
[email protected]4502e6492011-12-14 19:39:156868 "glCompressedTexSubImage2D: bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:436869 return;
6870 }
[email protected]0d6bfdc2011-11-02 01:32:206871 // Note: There is no need to deal with texture cleared tracking here
6872 // because the validation above means you can only get here if the level
6873 // is already a matching compressed format and in that case
6874 // CompressedTexImage2D already cleared the texture.
[email protected]cadde4a2010-07-31 17:10:436875 glCompressedTexSubImage2D(
6876 target, level, xoffset, yoffset, width, height, format, image_size, data);
6877}
6878
[email protected]6e288612010-12-21 20:45:036879static void Clip(
6880 GLint start, GLint range, GLint sourceRange,
6881 GLint* out_start, GLint* out_range) {
6882 DCHECK(out_start);
6883 DCHECK(out_range);
6884 if (start < 0) {
6885 range += start;
6886 start = 0;
6887 }
6888 GLint end = start + range;
6889 if (end > sourceRange) {
6890 range -= end - sourceRange;
6891 }
6892 *out_start = start;
6893 *out_range = range;
6894}
6895
[email protected]cadde4a2010-07-31 17:10:436896void GLES2DecoderImpl::DoCopyTexImage2D(
6897 GLenum target,
6898 GLint level,
6899 GLenum internal_format,
6900 GLint x,
6901 GLint y,
6902 GLsizei width,
6903 GLsizei height,
6904 GLint border) {
6905 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6906 if (!info) {
6907 SetGLError(GL_INVALID_OPERATION,
6908 "glCopyTexImage2D: unknown texture for target");
6909 return;
6910 }
[email protected]97dc7cbe2011-12-06 17:26:176911 if (info->IsImmutable()) {
6912 SetGLError(GL_INVALID_OPERATION,
6913 "glCopyTexImage2D: texture is immutable");
6914 }
[email protected]80eb6b52012-01-19 00:14:416915 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:186916 border != 0) {
6917 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
6918 return;
6919 }
6920
[email protected]9edc6b22010-12-23 02:00:266921 // Check we have compatible formats.
6922 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6923 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6924 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
6925
6926 if ((channels_needed & channels_exist) != channels_needed) {
6927 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
6928 return;
6929 }
6930
[email protected]a0b78dc2011-11-11 10:43:106931 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
6932 return;
6933 }
6934
[email protected]cadde4a2010-07-31 17:10:436935 CopyRealGLErrorsToWrapper();
[email protected]de26b3c2011-08-03 21:54:276936 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:036937 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:266938
[email protected]297ca1c2011-06-20 23:08:466939 if (info->IsAttachedToFramebuffer()) {
6940 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:516941 // TODO(gman): If textures tracked which framebuffers they were attached to
6942 // we could just mark those framebuffers as not complete.
6943 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:466944 }
6945
[email protected]9edc6b22010-12-23 02:00:266946 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:036947 GLint copyX = 0;
6948 GLint copyY = 0;
6949 GLint copyWidth = 0;
6950 GLint copyHeight = 0;
6951 Clip(x, width, size.width(), &copyX, &copyWidth);
6952 Clip(y, height, size.height(), &copyY, &copyHeight);
6953
6954 if (copyX != x ||
6955 copyY != y ||
6956 copyWidth != width ||
6957 copyHeight != height) {
6958 // some part was clipped so clear the texture.
[email protected]0d6bfdc2011-11-02 01:32:206959 if (!ClearLevel(
6960 info->service_id(), info->target(),
[email protected]4502e6492011-12-14 19:39:156961 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
6962 info->IsImmutable())) {
[email protected]0d6bfdc2011-11-02 01:32:206963 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexImage2D: dimensions too big");
[email protected]6e288612010-12-21 20:45:036964 return;
6965 }
[email protected]6e288612010-12-21 20:45:036966 if (copyHeight > 0 && copyWidth > 0) {
6967 GLint dx = copyX - x;
6968 GLint dy = copyY - y;
6969 GLint destX = dx;
6970 GLint destY = dy;
6971 glCopyTexSubImage2D(target, level,
6972 destX, destY, copyX, copyY,
6973 copyWidth, copyHeight);
6974 }
6975 } else {
6976 glCopyTexImage2D(target, level, internal_format,
6977 copyX, copyY, copyWidth, copyHeight, border);
6978 }
[email protected]1002c2d2011-06-28 22:39:046979 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436980 if (error == GL_NO_ERROR) {
6981 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416982 info, target, level, internal_format, width, height, 1,
[email protected]0d6bfdc2011-11-02 01:32:206983 border, internal_format, GL_UNSIGNED_BYTE, true);
[email protected]cadde4a2010-07-31 17:10:436984 }
6985}
6986
6987void GLES2DecoderImpl::DoCopyTexSubImage2D(
6988 GLenum target,
6989 GLint level,
6990 GLint xoffset,
6991 GLint yoffset,
6992 GLint x,
6993 GLint y,
6994 GLsizei width,
6995 GLsizei height) {
6996 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6997 if (!info) {
6998 SetGLError(GL_INVALID_OPERATION,
6999 "glCopyTexSubImage2D: unknown texture for target");
7000 return;
7001 }
7002 GLenum type = 0;
7003 GLenum format = 0;
7004 if (!info->GetLevelType(target, level, &type, &format) ||
7005 !info->ValidForTexture(
7006 target, level, xoffset, yoffset, width, height, format, type)) {
7007 SetGLError(GL_INVALID_VALUE,
7008 "glCopyTexSubImage2D: bad dimensions.");
7009 return;
7010 }
[email protected]9edc6b22010-12-23 02:00:267011
7012 // Check we have compatible formats.
7013 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7014 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7015 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
7016
7017 if ((channels_needed & channels_exist) != channels_needed) {
7018 SetGLError(
7019 GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
7020 return;
7021 }
7022
[email protected]a0b78dc2011-11-11 10:43:107023 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
7024 return;
7025 }
7026
[email protected]de26b3c2011-08-03 21:54:277027 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:037028 gfx::Size size = GetBoundReadFrameBufferSize();
7029 GLint copyX = 0;
7030 GLint copyY = 0;
7031 GLint copyWidth = 0;
7032 GLint copyHeight = 0;
7033 Clip(x, width, size.width(), &copyX, &copyWidth);
7034 Clip(y, height, size.height(), &copyY, &copyHeight);
[email protected]0d6bfdc2011-11-02 01:32:207035
7036 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
7037 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D: dimensions too big");
7038 return;
7039 }
7040
[email protected]6e288612010-12-21 20:45:037041 if (copyX != x ||
7042 copyY != y ||
7043 copyWidth != width ||
7044 copyHeight != height) {
[email protected]0d6bfdc2011-11-02 01:32:207045 // some part was clipped so clear the sub rect.
[email protected]6e288612010-12-21 20:45:037046 uint32 pixels_size = 0;
7047 if (!GLES2Util::ComputeImageDataSize(
7048 width, height, format, type, unpack_alignment_, &pixels_size)) {
7049 SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large");
7050 return;
7051 }
7052 scoped_array<char> zero(new char[pixels_size]);
7053 memset(zero.get(), 0, pixels_size);
7054 glTexSubImage2D(
7055 target, level, xoffset, yoffset, width, height,
7056 format, type, zero.get());
7057 }
[email protected]0d6bfdc2011-11-02 01:32:207058
[email protected]6e288612010-12-21 20:45:037059 if (copyHeight > 0 && copyWidth > 0) {
7060 GLint dx = copyX - x;
7061 GLint dy = copyY - y;
7062 GLint destX = xoffset + dx;
7063 GLint destY = yoffset + dy;
7064 glCopyTexSubImage2D(target, level,
7065 destX, destY, copyX, copyY,
7066 copyWidth, copyHeight);
7067 }
[email protected]cadde4a2010-07-31 17:10:437068}
7069
7070void GLES2DecoderImpl::DoTexSubImage2D(
7071 GLenum target,
7072 GLint level,
7073 GLint xoffset,
7074 GLint yoffset,
7075 GLsizei width,
7076 GLsizei height,
7077 GLenum format,
7078 GLenum type,
7079 const void * data) {
7080 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7081 if (!info) {
7082 SetGLError(GL_INVALID_OPERATION,
7083 "glTexSubImage2D: unknown texture for target");
7084 return;
7085 }
[email protected]df6cf1ad2011-01-29 01:20:527086 GLenum current_type = 0;
7087 GLenum internal_format = 0;
7088 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
7089 SetGLError(
7090 GL_INVALID_OPERATION,
7091 "glTexSubImage2D: level does not exist.");
7092 return;
7093 }
7094 if (format != internal_format) {
7095 SetGLError(GL_INVALID_OPERATION,
7096 "glTexSubImage2D: format does not match internal format.");
7097 return;
7098 }
7099 if (type != current_type) {
7100 SetGLError(GL_INVALID_OPERATION,
7101 "glTexSubImage2D: type does not match type of texture.");
7102 return;
7103 }
7104
[email protected]cadde4a2010-07-31 17:10:437105 if (!info->ValidForTexture(
7106 target, level, xoffset, yoffset, width, height, format, type)) {
7107 SetGLError(GL_INVALID_VALUE,
7108 "glTexSubImage2D: bad dimensions.");
7109 return;
7110 }
[email protected]473c01ccb2011-06-07 01:33:307111
[email protected]4502e6492011-12-14 19:39:157112 GLsizei tex_width = 0;
7113 GLsizei tex_height = 0;
7114 bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height);
7115 DCHECK(ok);
7116 if (xoffset != 0 || yoffset != 0 ||
7117 width != tex_width || height != tex_height) {
7118 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
7119 SetGLError(GL_OUT_OF_MEMORY, "glTexSubImage2D: dimensions too big");
[email protected]473c01ccb2011-06-07 01:33:307120 return;
7121 }
[email protected]4502e6492011-12-14 19:39:157122 glTexSubImage2D(
7123 target, level, xoffset, yoffset, width, height, format, type, data);
[email protected]0d6bfdc2011-11-02 01:32:207124 return;
7125 }
[email protected]4502e6492011-12-14 19:39:157126
7127 if (teximage2d_faster_than_texsubimage2d_ && !info->IsImmutable()) {
7128 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
7129 // same as internal_foramt. If that changes we'll need to look them up.
7130 WrappedTexImage2D(
7131 target, level, format, width, height, 0, format, type, data);
7132 } else {
7133 glTexSubImage2D(
7134 target, level, xoffset, yoffset, width, height, format, type, data);
7135 }
7136 texture_manager()->SetLevelCleared(info, target, level);
[email protected]cadde4a2010-07-31 17:10:437137}
7138
[email protected]b493ee622011-04-13 23:52:007139error::Error GLES2DecoderImpl::HandleTexSubImage2D(
7140 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]366ae242011-05-10 02:23:587141 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:007142 GLboolean internal = static_cast<GLboolean>(c.internal);
7143 if (internal == GL_TRUE && tex_image_2d_failed_)
7144 return error::kNoError;
7145
7146 GLenum target = static_cast<GLenum>(c.target);
7147 GLint level = static_cast<GLint>(c.level);
7148 GLint xoffset = static_cast<GLint>(c.xoffset);
7149 GLint yoffset = static_cast<GLint>(c.yoffset);
7150 GLsizei width = static_cast<GLsizei>(c.width);
7151 GLsizei height = static_cast<GLsizei>(c.height);
7152 GLenum format = static_cast<GLenum>(c.format);
7153 GLenum type = static_cast<GLenum>(c.type);
7154 uint32 data_size;
7155 if (!GLES2Util::ComputeImageDataSize(
7156 width, height, format, type, unpack_alignment_, &data_size)) {
7157 return error::kOutOfBounds;
7158 }
7159 const void* pixels = GetSharedMemoryAs<const void*>(
7160 c.pixels_shm_id, c.pixels_shm_offset, data_size);
7161 if (!validators_->texture_target.IsValid(target)) {
7162 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
7163 return error::kNoError;
7164 }
7165 if (width < 0) {
7166 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
7167 return error::kNoError;
7168 }
7169 if (height < 0) {
7170 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
7171 return error::kNoError;
7172 }
7173 if (!validators_->texture_format.IsValid(format)) {
7174 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
7175 return error::kNoError;
7176 }
7177 if (!validators_->pixel_type.IsValid(type)) {
7178 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
7179 return error::kNoError;
7180 }
7181 if (pixels == NULL) {
7182 return error::kOutOfBounds;
7183 }
7184 DoTexSubImage2D(
7185 target, level, xoffset, yoffset, width, height, format, type, pixels);
7186 return error::kNoError;
7187}
7188
7189error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
7190 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
7191 GLboolean internal = static_cast<GLboolean>(c.internal);
7192 if (internal == GL_TRUE && tex_image_2d_failed_)
7193 return error::kNoError;
7194
7195 GLenum target = static_cast<GLenum>(c.target);
7196 GLint level = static_cast<GLint>(c.level);
7197 GLint xoffset = static_cast<GLint>(c.xoffset);
7198 GLint yoffset = static_cast<GLint>(c.yoffset);
7199 GLsizei width = static_cast<GLsizei>(c.width);
7200 GLsizei height = static_cast<GLsizei>(c.height);
7201 GLenum format = static_cast<GLenum>(c.format);
7202 GLenum type = static_cast<GLenum>(c.type);
7203 uint32 data_size;
7204 if (!GLES2Util::ComputeImageDataSize(
7205 width, height, format, type, unpack_alignment_, &data_size)) {
7206 return error::kOutOfBounds;
7207 }
7208 const void* pixels = GetImmediateDataAs<const void*>(
7209 c, data_size, immediate_data_size);
7210 if (!validators_->texture_target.IsValid(target)) {
7211 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
7212 return error::kNoError;
7213 }
7214 if (width < 0) {
7215 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
7216 return error::kNoError;
7217 }
7218 if (height < 0) {
7219 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
7220 return error::kNoError;
7221 }
7222 if (!validators_->texture_format.IsValid(format)) {
7223 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
7224 return error::kNoError;
7225 }
7226 if (!validators_->pixel_type.IsValid(type)) {
7227 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
7228 return error::kNoError;
7229 }
7230 if (pixels == NULL) {
7231 return error::kOutOfBounds;
7232 }
7233 DoTexSubImage2D(
7234 target, level, xoffset, yoffset, width, height, format, type, pixels);
7235 return error::kNoError;
7236}
7237
[email protected]f7a64ee2010-02-01 22:24:147238error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:197239 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:367240 GLuint index = static_cast<GLuint>(c.index);
7241 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:257242 typedef gles2::GetVertexAttribPointerv::Result Result;
7243 Result* result = GetSharedMemoryAs<Result*>(
7244 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:367245 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:147246 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:367247 }
[email protected]07d0cc82010-02-17 04:51:407248 // Check that the client initialized the result.
7249 if (result->size != 0) {
7250 return error::kInvalidArguments;
7251 }
[email protected]9438b012010-06-15 22:55:057252 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:297253 SetGLError(GL_INVALID_ENUM,
7254 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:147255 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367256 }
[email protected]3916c97e2010-02-25 03:20:507257 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:297258 SetGLError(GL_INVALID_VALUE,
7259 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:147260 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367261 }
[email protected]0bfd9882010-02-05 23:02:257262 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:087263 *result->GetData() =
[email protected]3757a372012-01-19 05:20:447264 vertex_attrib_manager_->GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:147265 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327266}
7267
[email protected]f7b85372010-02-03 01:11:377268bool GLES2DecoderImpl::GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127269 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:377270 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:127271 error::Error* error, GLint* real_location,
7272 GLuint* service_id, void** result_pointer, GLenum* result_type) {
[email protected]939e7362010-05-13 20:49:107273 DCHECK(error);
7274 DCHECK(service_id);
7275 DCHECK(result_pointer);
7276 DCHECK(result_type);
[email protected]1b0a6752012-02-22 03:44:127277 DCHECK(real_location);
[email protected]f7b85372010-02-03 01:11:377278 *error = error::kNoError;
7279 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:257280 SizedResult<GLint>* result;
7281 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7282 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
7283 if (!result) {
[email protected]f7b85372010-02-03 01:11:377284 *error = error::kOutOfBounds;
7285 return false;
7286 }
[email protected]0bfd9882010-02-05 23:02:257287 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:377288 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:257289 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:587290 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7291 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:377292 if (!info) {
[email protected]ae51d192010-04-27 00:48:037293 return false;
7294 }
7295 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:377296 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:297297 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:377298 return false;
7299 }
[email protected]ae51d192010-04-27 00:48:037300 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:367301 GLint array_index = -1;
7302 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
[email protected]1b0a6752012-02-22 03:44:127303 info->GetUniformInfoByFakeLocation(
7304 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:367305 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:377306 // No such location.
[email protected]8eee29c2010-04-29 03:38:297307 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:377308 return false;
7309 }
[email protected]43c2f1f2011-03-25 18:35:367310 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:507311 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:377312 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:297313 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:377314 return false;
7315 }
[email protected]0bfd9882010-02-05 23:02:257316 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7317 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
7318 if (!result) {
[email protected]f7b85372010-02-03 01:11:377319 *error = error::kOutOfBounds;
7320 return false;
7321 }
[email protected]0bfd9882010-02-05 23:02:257322 result->size = size;
[email protected]939e7362010-05-13 20:49:107323 *result_type = type;
[email protected]f7b85372010-02-03 01:11:377324 return true;
7325}
7326
[email protected]f7a64ee2010-02-01 22:24:147327error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:197328 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:377329 GLuint program = c.program;
[email protected]1b0a6752012-02-22 03:44:127330 GLint fake_location = program_manager()->UnswizzleLocation(c.location);
[email protected]f7b85372010-02-03 01:11:377331 GLuint service_id;
[email protected]939e7362010-05-13 20:49:107332 GLenum result_type;
[email protected]1b0a6752012-02-22 03:44:127333 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:377334 Error error;
[email protected]0bfd9882010-02-05 23:02:257335 void* result;
[email protected]f7b85372010-02-03 01:11:377336 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127337 program, fake_location, c.params_shm_id, c.params_shm_offset,
7338 &error, &real_location, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:257339 glGetUniformiv(
[email protected]1b0a6752012-02-22 03:44:127340 service_id, real_location,
[email protected]0bfd9882010-02-05 23:02:257341 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:377342 }
7343 return error;
[email protected]96449d2c2009-11-25 00:01:327344}
7345
[email protected]f7a64ee2010-02-01 22:24:147346error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:197347 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:377348 GLuint program = c.program;
[email protected]1b0a6752012-02-22 03:44:127349 GLint fake_location = program_manager()->UnswizzleLocation(c.location);
[email protected]f7b85372010-02-03 01:11:377350 GLuint service_id;
[email protected]1b0a6752012-02-22 03:44:127351 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:377352 Error error;
[email protected]0bfd9882010-02-05 23:02:257353 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:107354 Result* result;
7355 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:377356 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127357 program, fake_location, c.params_shm_id, c.params_shm_offset,
7358 &error, &real_location, &service_id,
7359 reinterpret_cast<void**>(&result), &result_type)) {
[email protected]939e7362010-05-13 20:49:107360 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
7361 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
7362 GLsizei num_values = result->GetNumResults();
7363 scoped_array<GLint> temp(new GLint[num_values]);
[email protected]1b0a6752012-02-22 03:44:127364 glGetUniformiv(service_id, real_location, temp.get());
[email protected]939e7362010-05-13 20:49:107365 GLfloat* dst = result->GetData();
7366 for (GLsizei ii = 0; ii < num_values; ++ii) {
7367 dst[ii] = (temp[ii] != 0);
7368 }
7369 } else {
[email protected]1b0a6752012-02-22 03:44:127370 glGetUniformfv(service_id, real_location, result->GetData());
[email protected]939e7362010-05-13 20:49:107371 }
[email protected]f7b85372010-02-03 01:11:377372 }
7373 return error;
[email protected]96449d2c2009-11-25 00:01:327374}
7375
[email protected]f7a64ee2010-02-01 22:24:147376error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:197377 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:257378 GLenum shader_type = static_cast<GLenum>(c.shadertype);
7379 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
7380 typedef gles2::GetShaderPrecisionFormat::Result Result;
7381 Result* result = GetSharedMemoryAs<Result*>(
7382 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7383 if (!result) {
7384 return error::kOutOfBounds;
7385 }
[email protected]07d0cc82010-02-17 04:51:407386 // Check that the client initialized the result.
7387 if (result->success != 0) {
7388 return error::kInvalidArguments;
7389 }
[email protected]9438b012010-06-15 22:55:057390 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:297391 SetGLError(GL_INVALID_ENUM,
7392 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
7393 return error::kNoError;
7394 }
[email protected]9438b012010-06-15 22:55:057395 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:297396 SetGLError(GL_INVALID_ENUM,
7397 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
7398 return error::kNoError;
7399 }
7400
7401 result->success = 1; // true
7402 switch (precision_type) {
7403 case GL_LOW_INT:
7404 case GL_MEDIUM_INT:
7405 case GL_HIGH_INT:
7406 result->min_range = -31;
7407 result->max_range = 31;
7408 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:107409 break;
[email protected]8eee29c2010-04-29 03:38:297410 case GL_LOW_FLOAT:
7411 case GL_MEDIUM_FLOAT:
7412 case GL_HIGH_FLOAT:
7413 result->min_range = -62;
7414 result->max_range = 62;
7415 result->precision = -16;
7416 break;
7417 default:
7418 NOTREACHED();
7419 break;
[email protected]0bfd9882010-02-05 23:02:257420 }
[email protected]f7a64ee2010-02-01 22:24:147421 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327422}
7423
[email protected]f7a64ee2010-02-01 22:24:147424error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:197425 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:257426 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:587427 GLuint program = static_cast<GLuint>(c.program);
7428 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7429 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:037430 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257431 return error::kNoError;
7432 }
7433 typedef gles2::GetAttachedShaders::Result Result;
7434 uint32 max_count = Result::ComputeMaxResults(result_size);
7435 Result* result = GetSharedMemoryAs<Result*>(
7436 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
7437 if (!result) {
7438 return error::kOutOfBounds;
7439 }
[email protected]07d0cc82010-02-17 04:51:407440 // Check that the client initialized the result.
7441 if (result->size != 0) {
7442 return error::kInvalidArguments;
7443 }
[email protected]0bfd9882010-02-05 23:02:257444 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:037445 glGetAttachedShaders(
7446 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:257447 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:037448 if (!shader_manager()->GetClientId(result->GetData()[ii],
7449 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:257450 NOTREACHED();
7451 return error::kGenericError;
7452 }
7453 }
7454 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:147455 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327456}
7457
[email protected]f7a64ee2010-02-01 22:24:147458error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:197459 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:257460 GLuint program = c.program;
7461 GLuint index = c.index;
7462 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:257463 typedef gles2::GetActiveUniform::Result Result;
7464 Result* result = GetSharedMemoryAs<Result*>(
7465 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7466 if (!result) {
7467 return error::kOutOfBounds;
7468 }
[email protected]07d0cc82010-02-17 04:51:407469 // Check that the client initialized the result.
7470 if (result->success != 0) {
7471 return error::kInvalidArguments;
7472 }
[email protected]6b8cf1a2010-05-06 16:13:587473 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7474 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:037475 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257476 return error::kNoError;
7477 }
7478 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
7479 info->GetUniformInfo(index);
7480 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:297481 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:257482 return error::kNoError;
7483 }
7484 result->success = 1; // true.
7485 result->size = uniform_info->size;
7486 result->type = uniform_info->type;
7487 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297488 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:147489 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327490}
7491
[email protected]f7a64ee2010-02-01 22:24:147492error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:197493 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:257494 GLuint program = c.program;
7495 GLuint index = c.index;
7496 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:257497 typedef gles2::GetActiveAttrib::Result Result;
7498 Result* result = GetSharedMemoryAs<Result*>(
7499 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7500 if (!result) {
7501 return error::kOutOfBounds;
7502 }
[email protected]07d0cc82010-02-17 04:51:407503 // Check that the client initialized the result.
7504 if (result->success != 0) {
7505 return error::kInvalidArguments;
7506 }
[email protected]6b8cf1a2010-05-06 16:13:587507 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7508 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:037509 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257510 return error::kNoError;
7511 }
7512 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
7513 info->GetAttribInfo(index);
7514 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:297515 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:257516 return error::kNoError;
7517 }
7518 result->success = 1; // true.
7519 result->size = attrib_info->size;
7520 result->type = attrib_info->type;
7521 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297522 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:147523 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327524}
7525
[email protected]b273e432010-04-12 17:23:587526error::Error GLES2DecoderImpl::HandleShaderBinary(
7527 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
7528#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:297529 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:587530 return error::kNoError;
7531#else
7532 GLsizei n = static_cast<GLsizei>(c.n);
7533 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:297534 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:587535 return error::kNoError;
7536 }
7537 GLsizei length = static_cast<GLsizei>(c.length);
7538 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:297539 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:587540 return error::kNoError;
7541 }
7542 uint32 data_size;
7543 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
7544 return error::kOutOfBounds;
7545 }
7546 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
7547 c.shaders_shm_id, c.shaders_shm_offset, data_size);
7548 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
7549 const void* binary = GetSharedMemoryAs<const void*>(
7550 c.binary_shm_id, c.binary_shm_offset, length);
7551 if (shaders == NULL || binary == NULL) {
7552 return error::kOutOfBounds;
7553 }
7554 scoped_array<GLuint> service_ids(new GLuint[n]);
7555 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:037556 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
7557 if (!info) {
[email protected]8eee29c2010-04-29 03:38:297558 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:587559 return error::kNoError;
7560 }
[email protected]ae51d192010-04-27 00:48:037561 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:587562 }
7563 // TODO(gman): call glShaderBinary
7564 return error::kNoError;
7565#endif
7566}
7567
[email protected]6217d392010-03-25 22:08:357568error::Error GLES2DecoderImpl::HandleSwapBuffers(
7569 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:497570 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7571 int this_frame_number = frame_number_++;
[email protected]da151512011-11-11 23:27:387572 // TRACE_EVENT for gpu tests:
[email protected]529c6672012-01-04 02:18:267573 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers",
7574 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
7575 "width", (is_offscreen ? offscreen_size_.width() :
7576 surface_->GetSize().width()));
[email protected]64ace852011-05-19 21:49:497577 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
7578 "offscreen", is_offscreen,
7579 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:357580 // If offscreen then don't actually SwapBuffers to the display. Just copy
7581 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:497582 if (is_offscreen) {
[email protected]1fb8c482011-08-31 01:01:537583 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
7584 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
7585 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
7586 // fix this.
7587 if (needs_mac_nvidia_driver_workaround_) {
7588 offscreen_saved_frame_buffer_->Create();
7589 glFinish();
7590 }
7591
7592 // Allocate the offscreen saved color texture.
7593 DCHECK(offscreen_saved_color_format_);
7594 offscreen_saved_color_texture_->AllocateStorage(
7595 offscreen_size_, offscreen_saved_color_format_);
[email protected]1078f912011-12-23 13:12:147596 UpdateBackbufferMemoryAccounting();
[email protected]1fb8c482011-08-31 01:01:537597
7598 offscreen_saved_frame_buffer_->AttachRenderTexture(
7599 offscreen_saved_color_texture_.get());
7600 if (offscreen_saved_frame_buffer_->CheckStatus() !=
7601 GL_FRAMEBUFFER_COMPLETE) {
7602 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
7603 << "because offscreen saved FBO was incomplete.";
7604 return error::kLostContext;
7605 }
7606
[email protected]1fb8c482011-08-31 01:01:537607 // Clear the offscreen color texture.
7608 // TODO(piman): Is this still necessary?
7609 {
7610 ScopedFrameBufferBinder binder(this,
7611 offscreen_saved_frame_buffer_->id());
7612 glClearColor(0, 0, 0, 0);
7613 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
7614 glDisable(GL_SCISSOR_TEST);
7615 glClear(GL_COLOR_BUFFER_BIT);
7616 RestoreClearState();
7617 }
7618
7619 UpdateParentTextureInfo();
7620 }
7621
[email protected]6217d392010-03-25 22:08:357622 ScopedGLErrorSuppressor suppressor(this);
7623
[email protected]34ff8b0c2010-10-01 20:06:027624 if (IsOffscreenBufferMultisampled()) {
[email protected]51411e32012-01-19 20:21:137625 // For multisampled buffers, resolve the frame buffer.
[email protected]de26b3c2011-08-03 21:54:277626 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]89d6ed02011-04-20 00:23:237627 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:487628 } else {
[email protected]9a5afa432011-07-22 18:16:397629 if (surface_->IsOffscreen()) {
[email protected]51411e32012-01-19 20:21:137630 ScopedFrameBufferBinder binder(this,
7631 offscreen_target_frame_buffer_->id());
7632
[email protected]8a61d872012-01-20 12:43:567633 if (offscreen_target_buffer_preserved_) {
7634 // Copy the target frame buffer to the saved offscreen texture.
7635 offscreen_saved_color_texture_->Copy(
7636 offscreen_saved_color_texture_->size(),
7637 offscreen_saved_color_format_);
7638 } else {
7639 // Flip the textures in the parent context via the texture manager.
7640 if (!!offscreen_saved_color_texture_info_.get())
7641 offscreen_saved_color_texture_info_->
7642 SetServiceId(offscreen_target_color_texture_->id());
7643
7644 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
7645 offscreen_target_frame_buffer_->AttachRenderTexture(
7646 offscreen_target_color_texture_.get());
7647 }
[email protected]b86b14982010-10-11 18:45:487648
[email protected]a3ded6d2010-10-19 06:44:397649 // Ensure the side effects of the copy are visible to the parent
7650 // context. There is no need to do this for ANGLE because it uses a
7651 // single D3D device for all contexts.
[email protected]b86b14982010-10-11 18:45:487652 if (!IsAngle())
7653 glFlush();
7654 }
[email protected]89d6ed02011-04-20 00:23:237655 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:397656 }
[email protected]6217d392010-03-25 22:08:357657 } else {
[email protected]64ace852011-05-19 21:49:497658 TRACE_EVENT1("gpu", "GLContext::SwapBuffers", "frame", this_frame_number);
[email protected]f62a5ab2011-05-23 20:34:157659 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:017660 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:027661 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:017662 }
[email protected]6217d392010-03-25 22:08:357663 }
7664
[email protected]89d6ed02011-04-20 00:23:237665 return error::kNoError;
[email protected]6217d392010-03-25 22:08:357666}
7667
[email protected]d4239852011-08-12 04:51:227668error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
7669 uint32 immediate_data_size, const gles2::EnableFeatureCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:187670 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287671 if (!bucket || bucket->size() == 0) {
7672 return error::kInvalidArguments;
7673 }
[email protected]d4239852011-08-12 04:51:227674 typedef gles2::EnableFeatureCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:187675 Result* result = GetSharedMemoryAs<Result*>(
7676 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7677 if (!result) {
7678 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:107679 }
[email protected]b1d2dcb2010-05-17 19:24:187680 // Check that the client initialized the result.
7681 if (*result != 0) {
7682 return error::kInvalidArguments;
7683 }
7684 std::string feature_str;
7685 if (!bucket->GetAsString(&feature_str)) {
7686 return error::kInvalidArguments;
7687 }
7688
7689 // TODO(gman): make this some kind of table to function pointer thingy.
[email protected]d4239852011-08-12 04:51:227690 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
[email protected]b1d2dcb2010-05-17 19:24:187691 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]d4239852011-08-12 04:51:227692 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
[email protected]8fbedc02010-11-18 18:43:407693 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
7694 // TODO(gman): decide how to remove the need for this const_cast.
7695 // I could make validators_ non const but that seems bad as this is the only
7696 // place it is needed. I could make some special friend class of validators
7697 // just to allow this to set them. That seems silly. I could refactor this
7698 // code to use the extension mechanism or the initialization attributes to
7699 // turn this feature on. Given that the only real point of this is to make
7700 // the conformance tests pass and given that there is lots of real work that
7701 // needs to be done it seems like refactoring for one to one of those
7702 // methods is a very low priority.
7703 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]f0d74742011-10-03 16:31:047704 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
7705 force_webgl_glsl_validation_ = true;
7706 InitializeShaderTranslator();
[email protected]b1d2dcb2010-05-17 19:24:187707 } else {
7708 return error::kNoError;
7709 }
7710
7711 *result = 1; // true.
7712 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:107713}
7714
[email protected]c2f8c8402010-12-06 18:07:247715error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
7716 uint32 immediate_data_size,
7717 const gles2::GetRequestableExtensionsCHROMIUM& c) {
7718 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]80eb6b52012-01-19 00:14:417719 FeatureInfo::Ref info(new FeatureInfo());
[email protected]e82fb792011-09-22 00:33:297720 info->Initialize(disallowed_features_, NULL);
[email protected]c2f8c8402010-12-06 18:07:247721 bucket->SetFromString(info->extensions().c_str());
7722 return error::kNoError;
7723}
7724
7725error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
7726 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
7727 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287728 if (!bucket || bucket->size() == 0) {
7729 return error::kInvalidArguments;
7730 }
[email protected]c2f8c8402010-12-06 18:07:247731 std::string feature_str;
7732 if (!bucket->GetAsString(&feature_str)) {
7733 return error::kInvalidArguments;
7734 }
7735
7736 bool std_derivatives_enabled =
7737 feature_info_->feature_flags().oes_standard_derivatives;
7738 bool webglsl_enabled =
7739 feature_info_->feature_flags().chromium_webglsl;
7740
7741 feature_info_->AddFeatures(feature_str.c_str());
7742
[email protected]f0d74742011-10-03 16:31:047743 bool initialization_required = false;
7744 if (force_webgl_glsl_validation_ && !derivatives_explicitly_enabled_) {
7745 size_t derivatives_offset = feature_str.find(kOESDerivativeExtension);
7746 if (std::string::npos != derivatives_offset) {
7747 derivatives_explicitly_enabled_ = true;
7748 initialization_required = true;
7749 }
7750 }
7751
[email protected]c2f8c8402010-12-06 18:07:247752 // If we just enabled a feature which affects the shader translator,
7753 // we may need to re-initialize it.
7754 if (std_derivatives_enabled !=
7755 feature_info_->feature_flags().oes_standard_derivatives ||
7756 webglsl_enabled !=
[email protected]f0d74742011-10-03 16:31:047757 feature_info_->feature_flags().chromium_webglsl ||
7758 initialization_required) {
[email protected]c2f8c8402010-12-06 18:07:247759 InitializeShaderTranslator();
7760 }
7761
[email protected]302ce6d2011-07-07 23:28:117762 UpdateCapabilities();
7763
[email protected]c2f8c8402010-12-06 18:07:247764 return error::kNoError;
7765}
7766
[email protected]372e0412011-06-28 16:08:567767error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
7768 uint32 immediate_data_size, const gles2::GetMultipleIntegervCHROMIUM& c) {
7769 GLuint count = c.count;
7770 uint32 pnames_size;
7771 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
7772 return error::kOutOfBounds;
7773 }
7774 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
7775 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
7776 if (pnames == NULL) {
7777 return error::kOutOfBounds;
7778 }
7779
7780 // We have to copy them since we use them twice so the client
7781 // can't change them between the time we validate them and the time we use
7782 // them.
7783 scoped_array<GLenum> enums(new GLenum[count]);
7784 memcpy(enums.get(), pnames, pnames_size);
7785
7786 // Count up the space needed for the result.
7787 uint32 num_results = 0;
7788 for (GLuint ii = 0; ii < count; ++ii) {
7789 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
7790 if (num == 0) {
7791 SetGLError(GL_INVALID_ENUM,
7792 "glGetMulitpleCHROMIUM: pname GL_INVALID_ENUM");
7793 return error::kNoError;
7794 }
7795 // Num will never be more than 4.
7796 DCHECK_LE(num, 4u);
7797 if (!SafeAdd(num_results, num, &num_results)) {
7798 return error::kOutOfBounds;
7799 }
7800 }
7801
7802 uint32 result_size = 0;
7803 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
7804 return error::kOutOfBounds;
7805 }
7806
7807 if (result_size != static_cast<uint32>(c.size)) {
7808 SetGLError(GL_INVALID_VALUE,
7809 "glGetMulitpleCHROMIUM: bad size GL_INVALID_VALUE");
7810 return error::kNoError;
7811 }
7812
7813 GLint* results = GetSharedMemoryAs<GLint*>(
7814 c.results_shm_id, c.results_shm_offset, result_size);
7815 if (results == NULL) {
7816 return error::kOutOfBounds;
7817 }
7818
7819 // Check the results have been cleared in case the context was lost.
7820 for (uint32 ii = 0; ii < num_results; ++ii) {
7821 if (results[ii]) {
7822 return error::kInvalidArguments;
7823 }
7824 }
7825
7826 // Get each result.
7827 GLint* start = results;
7828 for (GLuint ii = 0; ii < count; ++ii) {
7829 GLsizei num_written = 0;
7830 if (!GetHelper(enums[ii], results, &num_written)) {
7831 glGetIntegerv(enums[ii], results);
7832 }
7833 results += num_written;
7834 }
7835
7836 // Just to verify. Should this be a DCHECK?
7837 if (static_cast<uint32>(results - start) != num_results) {
7838 return error::kOutOfBounds;
7839 }
7840
7841 return error::kNoError;
7842}
7843
[email protected]2318d342011-07-11 22:27:427844error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
7845 uint32 immediate_data_size, const gles2::GetProgramInfoCHROMIUM& c) {
7846 GLuint program = static_cast<GLuint>(c.program);
7847 uint32 bucket_id = c.bucket_id;
7848 Bucket* bucket = CreateBucket(bucket_id);
7849 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
7850 ProgramManager::ProgramInfo* info = NULL;
[email protected]9a14ae612011-08-08 17:51:467851 info = GetProgramInfo(program);
7852 if (!info || !info->IsValid()) {
7853 return error::kNoError;
[email protected]2318d342011-07-11 22:27:427854 }
[email protected]5d4c6b22012-02-07 08:22:287855 info->GetProgramInfo(program_manager(), bucket);
[email protected]2318d342011-07-11 22:27:427856 return error::kNoError;
7857}
7858
[email protected]38d139d2011-07-14 00:38:437859error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
7860 switch (reset_status_) {
7861 case GL_NO_ERROR:
7862 // TODO(kbr): improve the precision of the error code in this case.
7863 // Consider delegating to context for error code if MakeCurrent fails.
7864 return error::kUnknown;
7865 case GL_GUILTY_CONTEXT_RESET_ARB:
7866 return error::kGuilty;
7867 case GL_INNOCENT_CONTEXT_RESET_ARB:
7868 return error::kInnocent;
7869 case GL_UNKNOWN_CONTEXT_RESET_ARB:
7870 return error::kUnknown;
7871 }
7872
7873 NOTREACHED();
7874 return error::kUnknown;
7875}
7876
7877bool GLES2DecoderImpl::WasContextLost() {
7878 if (context_->WasAllocatedUsingARBRobustness() && has_arb_robustness_) {
7879 GLenum status = glGetGraphicsResetStatusARB();
7880 if (status != GL_NO_ERROR) {
7881 // The graphics card was reset. Signal a lost context to the application.
7882 reset_status_ = status;
7883 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
7884 << " context lost via ARB_robustness. Reset status = 0x"
7885 << std::hex << status << std::dec;
7886 return true;
7887 }
7888 }
7889 return false;
7890}
7891
[email protected]b0af4f52011-09-28 22:04:427892error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
7893 uint32 immediate_data_size,
7894 const gles2::CreateStreamTextureCHROMIUM& c) {
7895 if (!feature_info_->feature_flags().chromium_stream_texture) {
7896 SetGLError(GL_INVALID_OPERATION,
7897 "glOpenStreamTextureCHROMIUM: "
7898 "not supported.");
7899 return error::kNoError;
7900 }
7901
7902 uint32 client_id = c.client_id;
7903 typedef gles2::CreateStreamTextureCHROMIUM::Result Result;
7904 Result* result = GetSharedMemoryAs<Result*>(
7905 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7906
[email protected]e5081262012-01-05 23:09:037907 if (!result)
7908 return error::kOutOfBounds;
[email protected]b0af4f52011-09-28 22:04:427909 *result = GL_ZERO;
7910 TextureManager::TextureInfo* info =
7911 texture_manager()->GetTextureInfo(client_id);
7912 if (!info) {
7913 SetGLError(GL_INVALID_VALUE,
7914 "glCreateStreamTextureCHROMIUM: "
7915 "bad texture id.");
7916 return error::kNoError;
7917 }
7918
7919 if (info->IsStreamTexture()) {
7920 SetGLError(GL_INVALID_OPERATION,
7921 "glCreateStreamTextureCHROMIUM: "
7922 "is already a stream texture.");
7923 return error::kNoError;
7924 }
7925
7926 if (info->target() && info->target() != GL_TEXTURE_EXTERNAL_OES) {
7927 SetGLError(GL_INVALID_OPERATION,
7928 "glCreateStreamTextureCHROMIUM: "
7929 "is already bound to incompatible target.");
7930 return error::kNoError;
7931 }
7932
7933 if (!stream_texture_manager_)
7934 return error::kInvalidArguments;
7935
7936 GLuint object_id = stream_texture_manager_->CreateStreamTexture(
7937 info->service_id(), client_id);
7938
7939 if (object_id) {
7940 info->SetStreamTexture(true);
7941 } else {
7942 SetGLError(GL_OUT_OF_MEMORY,
7943 "glCreateStreamTextureCHROMIUM: "
7944 "failed to create platform texture.");
7945 }
7946
7947 *result = object_id;
7948 return error::kNoError;
7949}
7950
7951error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
7952 uint32 immediate_data_size,
7953 const gles2::DestroyStreamTextureCHROMIUM& c) {
7954 GLuint client_id = c.texture;
7955 TextureManager::TextureInfo* info =
7956 texture_manager()->GetTextureInfo(client_id);
7957 if (info && info->IsStreamTexture()) {
7958 if (!stream_texture_manager_)
7959 return error::kInvalidArguments;
7960
7961 stream_texture_manager_->DestroyStreamTexture(info->service_id());
7962 info->SetStreamTexture(false);
[email protected]80eb6b52012-01-19 00:14:417963 texture_manager()->SetInfoTarget(info, 0);
[email protected]b0af4f52011-09-28 22:04:427964 } else {
7965 SetGLError(GL_INVALID_VALUE,
7966 "glDestroyStreamTextureCHROMIUM: bad texture id.");
7967 }
7968
7969 return error::kNoError;
7970}
7971
[email protected]e51bdf32011-11-23 22:21:467972#if defined(OS_MACOSX)
7973void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
7974 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
7975 texture_id);
7976 if (it != texture_to_io_surface_map_.end()) {
7977 // Found a previous IOSurface bound to this texture; release it.
7978 CFTypeRef surface = it->second;
7979 CFRelease(surface);
7980 texture_to_io_surface_map_.erase(it);
7981 }
7982}
7983#endif
7984
7985void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
7986 GLenum target, GLsizei width, GLsizei height,
7987 GLuint io_surface_id, GLuint plane) {
7988#if defined(OS_MACOSX)
7989 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
7990 SetGLError(GL_INVALID_OPERATION,
7991 "glTexImageIOSurface2DCHROMIUM: only supported on desktop GL.");
7992 return;
7993 }
7994
7995 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
7996 if (!surface_support) {
7997 SetGLError(GL_INVALID_OPERATION,
7998 "glTexImageIOSurface2DCHROMIUM: only supported on 10.6.");
7999 return;
8000 }
8001
8002 if (target != GL_TEXTURE_RECTANGLE_ARB) {
8003 // This might be supported in the future, and if we could require
8004 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
8005 // could delete a lot of code. For now, perform strict validation so we
8006 // know what's going on.
8007 SetGLError(
8008 GL_INVALID_OPERATION,
8009 "glTexImageIOSurface2DCHROMIUM: requires TEXTURE_RECTANGLE_ARB target");
8010 return;
8011 }
8012
8013 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8014 if (!info) {
8015 SetGLError(GL_INVALID_OPERATION,
8016 "glTexImageIOSurface2DCHROMIUM: no rectangle texture bound");
8017 return;
8018 }
8019 if (info == texture_manager()->GetDefaultTextureInfo(target)) {
8020 // Maybe this is conceptually valid, but disallow it to avoid accidents.
8021 SetGLError(GL_INVALID_OPERATION,
8022 "glTexImageIOSurface2DCHROMIUM: can't bind default texture");
8023 return;
8024 }
8025
8026 // Look up the new IOSurface. Note that because of asynchrony
8027 // between processes this might fail; during live resizing the
8028 // plugin process might allocate and release an IOSurface before
8029 // this process gets a chance to look it up. Hold on to any old
8030 // IOSurface in this case.
8031 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
8032 if (!surface) {
8033 SetGLError(GL_INVALID_OPERATION,
8034 "glTexImageIOSurface2DCHROMIUM: no IOSurface with the given ID");
8035 return;
8036 }
8037
8038 // Release any IOSurface previously bound to this texture.
8039 ReleaseIOSurfaceForTexture(info->service_id());
8040
8041 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
8042 texture_to_io_surface_map_.insert(
8043 std::make_pair(info->service_id(), surface));
8044
8045 CGLContextObj context =
8046 static_cast<CGLContextObj>(context_->GetHandle());
8047
8048 CGLError err = surface_support->CGLTexImageIOSurface2D(
8049 context,
8050 target,
8051 GL_RGBA,
8052 width,
8053 height,
8054 GL_BGRA,
8055 GL_UNSIGNED_INT_8_8_8_8_REV,
8056 surface,
8057 plane);
8058
8059 if (err != kCGLNoError) {
8060 SetGLError(
8061 GL_INVALID_OPERATION,
8062 "glTexImageIOSurface2DCHROMIUM: error in CGLTexImageIOSurface2D");
8063 return;
8064 }
8065
8066 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:418067 info, target, 0, GL_RGBA, width, height, 1, 0,
[email protected]e51bdf32011-11-23 22:21:468068 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
8069
8070#else
8071 SetGLError(GL_INVALID_OPERATION,
8072 "glTexImageIOSurface2DCHROMIUM: not supported.");
8073#endif
8074}
8075
[email protected]97dc7cbe2011-12-06 17:26:178076static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
8077 switch (internalformat) {
8078 case GL_RGB565:
8079 return GL_RGB;
8080 case GL_RGBA4:
8081 return GL_RGBA;
8082 case GL_RGB5_A1:
8083 return GL_RGBA;
8084 case GL_RGB8_OES:
8085 return GL_RGB;
8086 case GL_RGBA8_OES:
8087 return GL_RGBA;
8088 case GL_LUMINANCE8_ALPHA8_EXT:
8089 return GL_LUMINANCE_ALPHA;
8090 case GL_LUMINANCE8_EXT:
8091 return GL_LUMINANCE;
8092 case GL_ALPHA8_EXT:
8093 return GL_ALPHA;
8094 case GL_RGBA32F_EXT:
8095 return GL_RGBA;
8096 case GL_RGB32F_EXT:
8097 return GL_RGB;
8098 case GL_ALPHA32F_EXT:
8099 return GL_ALPHA;
8100 case GL_LUMINANCE32F_EXT:
8101 return GL_LUMINANCE;
8102 case GL_LUMINANCE_ALPHA32F_EXT:
8103 return GL_LUMINANCE_ALPHA;
8104 case GL_RGBA16F_EXT:
8105 return GL_RGBA;
8106 case GL_RGB16F_EXT:
8107 return GL_RGB;
8108 case GL_ALPHA16F_EXT:
8109 return GL_ALPHA;
8110 case GL_LUMINANCE16F_EXT:
8111 return GL_LUMINANCE;
8112 case GL_LUMINANCE_ALPHA16F_EXT:
8113 return GL_LUMINANCE_ALPHA;
8114 case GL_BGRA8_EXT:
8115 return GL_BGRA_EXT;
8116 default:
8117 return GL_NONE;
8118 }
8119}
8120
8121static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
8122 switch (internalformat) {
8123 case GL_RGB565:
8124 return GL_UNSIGNED_SHORT_5_6_5;
8125 case GL_RGBA4:
8126 return GL_UNSIGNED_SHORT_4_4_4_4;
8127 case GL_RGB5_A1:
8128 return GL_UNSIGNED_SHORT_5_5_5_1;
8129 case GL_RGB8_OES:
8130 return GL_UNSIGNED_BYTE;
8131 case GL_RGBA8_OES:
8132 return GL_UNSIGNED_BYTE;
8133 case GL_LUMINANCE8_ALPHA8_EXT:
8134 return GL_UNSIGNED_BYTE;
8135 case GL_LUMINANCE8_EXT:
8136 return GL_UNSIGNED_BYTE;
8137 case GL_ALPHA8_EXT:
8138 return GL_UNSIGNED_BYTE;
8139 case GL_RGBA32F_EXT:
8140 return GL_FLOAT;
8141 case GL_RGB32F_EXT:
8142 return GL_FLOAT;
8143 case GL_ALPHA32F_EXT:
8144 return GL_FLOAT;
8145 case GL_LUMINANCE32F_EXT:
8146 return GL_FLOAT;
8147 case GL_LUMINANCE_ALPHA32F_EXT:
8148 return GL_FLOAT;
8149 case GL_RGBA16F_EXT:
8150 return GL_HALF_FLOAT_OES;
8151 case GL_RGB16F_EXT:
8152 return GL_HALF_FLOAT_OES;
8153 case GL_ALPHA16F_EXT:
8154 return GL_HALF_FLOAT_OES;
8155 case GL_LUMINANCE16F_EXT:
8156 return GL_HALF_FLOAT_OES;
8157 case GL_LUMINANCE_ALPHA16F_EXT:
8158 return GL_HALF_FLOAT_OES;
8159 case GL_BGRA8_EXT:
8160 return GL_UNSIGNED_BYTE;
8161 default:
8162 return GL_NONE;
8163 }
8164}
8165
8166void GLES2DecoderImpl::DoTexStorage2DEXT(
8167 GLenum target,
8168 GLint levels,
8169 GLenum internal_format,
8170 GLsizei width,
8171 GLsizei height) {
[email protected]80eb6b52012-01-19 00:14:418172 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
[email protected]97dc7cbe2011-12-06 17:26:178173 TextureManager::ComputeMipMapCount(width, height, 1) < levels) {
8174 SetGLError(GL_INVALID_VALUE, "glTexStorage2DEXT: dimensions out of range");
8175 return;
8176 }
8177 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8178 if (!info) {
8179 SetGLError(GL_INVALID_OPERATION,
8180 "glTexStorage2DEXT: unknown texture for target");
8181 return;
8182 }
8183 if (info->IsAttachedToFramebuffer()) {
8184 state_dirty_ = true;
8185 }
8186 if (info->IsImmutable()) {
8187 SetGLError(GL_INVALID_OPERATION,
8188 "glTexStorage2DEXT: texture is immutable");
8189 return;
8190 }
8191 CopyRealGLErrorsToWrapper();
[email protected]f0e6a34f2012-01-04 20:53:408192 glTexStorage2DEXT(target, levels, GetTexInternalFormat(internal_format),
8193 width, height);
[email protected]97dc7cbe2011-12-06 17:26:178194 GLenum error = PeekGLError();
8195 if (error == GL_NO_ERROR) {
8196 GLenum format = ExtractFormatFromStorageFormat(internal_format);
8197 GLenum type = ExtractTypeFromStorageFormat(internal_format);
[email protected]4502e6492011-12-14 19:39:158198 GLsizei level_width = width;
8199 GLsizei level_height = height;
8200 for (int ii = 0; ii < levels; ++ii) {
8201 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:418202 info, target, 0, format, level_width, level_height, 1, 0, format,
8203 type, false);
[email protected]4502e6492011-12-14 19:39:158204 level_width = std::max(1, level_width >> 1);
8205 level_height = std::max(1, level_height >> 1);
8206 }
[email protected]97dc7cbe2011-12-06 17:26:178207 info->SetImmutable(true);
8208 }
[email protected]97dc7cbe2011-12-06 17:26:178209}
[email protected]e51bdf32011-11-23 22:21:468210
[email protected]96449d2c2009-11-25 00:01:328211// Include the auto-generated part of this file. We split this because it means
8212// we can easily edit the non-auto generated parts right here in this file
8213// instead of having to edit some template or the code generator.
8214#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
8215
8216} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:258217} // namespace gpu