blob: 7f00f02f07eed1614885483c8ec092f3070eb6bb [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(
985 GLint location, const char* function_name, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:10986
[email protected]b177ae22011-11-01 03:29:11987 // Gets the service id for any simulated backbuffer fbo.
988 GLuint GetBackbufferServiceId();
989
[email protected]b273e432010-04-12 17:23:58990 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
991 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
992
[email protected]96449d2c2009-11-25 00:01:32993 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03994 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32995
996 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03997 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32998
[email protected]3916c97e2010-02-25 03:20:50999 // Wrapper for glActiveTexture
1000 void DoActiveTexture(GLenum texture_unit);
1001
[email protected]ae51d192010-04-27 00:48:031002 // Wrapper for glAttachShader
1003 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1004
[email protected]96449d2c2009-11-25 00:01:321005 // Wrapper for glBindBuffer since we need to track the current targets.
1006 void DoBindBuffer(GLenum target, GLuint buffer);
1007
[email protected]86093972010-03-11 00:13:561008 // Wrapper for glBindFramebuffer since we need to track the current targets.
1009 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1010
1011 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1012 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1013
[email protected]a93bb842010-02-16 23:03:471014 // Wrapper for glBindTexture since we need to track the current targets.
1015 void DoBindTexture(GLenum target, GLuint texture);
1016
[email protected]8e3e0662010-08-23 18:46:301017 // Wrapper for glBlitFramebufferEXT.
1018 void DoBlitFramebufferEXT(
1019 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1020 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1021 GLbitfield mask, GLenum filter);
1022
[email protected]36cef8ce2010-03-16 07:34:451023 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:111024 void DoBufferData(
1025 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
1026
[email protected]36cef8ce2010-03-16 07:34:451027 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:111028 void DoBufferSubData(
1029 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1030
[email protected]36cef8ce2010-03-16 07:34:451031 // Wrapper for glCheckFramebufferStatus
1032 GLenum DoCheckFramebufferStatus(GLenum target);
1033
[email protected]3a03a8f2011-03-19 00:51:271034 // Wrapper for glClear
1035 void DoClear(GLbitfield mask);
1036
[email protected]3a2e7c7b2010-08-06 01:12:281037 // Wrappers for clear and mask settings functions.
1038 void DoClearColor(
1039 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
1040 void DoClearDepthf(GLclampf depth);
1041 void DoClearStencil(GLint s);
1042 void DoColorMask(
1043 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
1044 void DoDepthMask(GLboolean depth);
1045 void DoStencilMask(GLuint mask);
1046 void DoStencilMaskSeparate(GLenum face, GLuint mask);
1047
[email protected]45bf5152010-02-12 00:11:311048 // Wrapper for glCompileShader.
1049 void DoCompileShader(GLuint shader);
1050
[email protected]269200b12010-11-18 22:53:061051 // Helper for DeleteSharedIdsCHROMIUM commands.
1052 void DoDeleteSharedIdsCHROMIUM(
1053 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101054
[email protected]ae51d192010-04-27 00:48:031055 // Wrapper for glDetachShader
1056 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1057
[email protected]3a2e7c7b2010-08-06 01:12:281058 // Wrapper for glDisable
1059 void DoDisable(GLenum cap);
1060
[email protected]07f54fcc2009-12-22 02:46:301061 // Wrapper for glDisableVertexAttribArray.
1062 void DoDisableVertexAttribArray(GLuint index);
1063
[email protected]3a2e7c7b2010-08-06 01:12:281064 // Wrapper for glEnable
1065 void DoEnable(GLenum cap);
1066
[email protected]07f54fcc2009-12-22 02:46:301067 // Wrapper for glEnableVertexAttribArray.
1068 void DoEnableVertexAttribArray(GLuint index);
1069
[email protected]36cef8ce2010-03-16 07:34:451070 // Wrapper for glFramebufferRenderbufffer.
1071 void DoFramebufferRenderbuffer(
1072 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1073 GLuint renderbuffer);
1074
1075 // Wrapper for glFramebufferTexture2D.
1076 void DoFramebufferTexture2D(
1077 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1078 GLint level);
1079
[email protected]a93bb842010-02-16 23:03:471080 // Wrapper for glGenerateMipmap
1081 void DoGenerateMipmap(GLenum target);
1082
[email protected]269200b12010-11-18 22:53:061083 // Helper for GenSharedIdsCHROMIUM commands.
1084 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:101085 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1086
[email protected]b273e432010-04-12 17:23:581087 // Wrapper for DoGetBooleanv.
1088 void DoGetBooleanv(GLenum pname, GLboolean* params);
1089
1090 // Wrapper for DoGetFloatv.
1091 void DoGetFloatv(GLenum pname, GLfloat* params);
1092
[email protected]36cef8ce2010-03-16 07:34:451093 // Wrapper for glGetFramebufferAttachmentParameteriv.
1094 void DoGetFramebufferAttachmentParameteriv(
1095 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1096
[email protected]a0c3e972010-04-21 00:49:131097 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581098 void DoGetIntegerv(GLenum pname, GLint* params);
1099
[email protected]29a9eb52010-04-13 09:04:231100 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:061101 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:231102 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1103
[email protected]a0c3e972010-04-21 00:49:131104 // Wrapper for glGetProgramiv.
1105 void DoGetProgramiv(
1106 GLuint program_id, GLenum pname, GLint* params);
1107
[email protected]36cef8ce2010-03-16 07:34:451108 // Wrapper for glRenderbufferParameteriv.
1109 void DoGetRenderbufferParameteriv(
1110 GLenum target, GLenum pname, GLint* params);
1111
[email protected]ddd968b82010-03-02 00:44:291112 // Wrapper for glGetShaderiv
1113 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1114
[email protected]b1122982010-05-17 23:04:241115 // Wrappers for glGetVertexAttrib.
1116 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1117 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1118
[email protected]1958e0e2010-04-22 05:17:151119 // Wrappers for glIsXXX functions.
1120 bool DoIsBuffer(GLuint client_id);
1121 bool DoIsFramebuffer(GLuint client_id);
1122 bool DoIsProgram(GLuint client_id);
1123 bool DoIsRenderbuffer(GLuint client_id);
1124 bool DoIsShader(GLuint client_id);
1125 bool DoIsTexture(GLuint client_id);
1126
[email protected]07f54fcc2009-12-22 02:46:301127 // Wrapper for glLinkProgram
1128 void DoLinkProgram(GLuint program);
1129
[email protected]269200b12010-11-18 22:53:061130 // Helper for RegisterSharedIdsCHROMIUM.
1131 void DoRegisterSharedIdsCHROMIUM(
1132 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101133
[email protected]36cef8ce2010-03-16 07:34:451134 // Wrapper for glRenderbufferStorage.
1135 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031136 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451137
[email protected]8e3e0662010-08-23 18:46:301138 // Wrapper for glRenderbufferStorageMultisampleEXT.
1139 void DoRenderbufferStorageMultisample(
1140 GLenum target, GLsizei samples, GLenum internalformat,
1141 GLsizei width, GLsizei height);
1142
[email protected]b273e432010-04-12 17:23:581143 // Wrapper for glReleaseShaderCompiler.
1144 void DoReleaseShaderCompiler() { }
1145
[email protected]3916c97e2010-02-25 03:20:501146 // Wrappers for glTexParameter functions.
1147 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1148 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1149 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1150 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1151
1152 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1153 // spec only these 2 functions can be used to set sampler uniforms.
1154 void DoUniform1i(GLint location, GLint v0);
[email protected]939e7362010-05-13 20:49:101155 void DoUniform1iv(GLint location, GLsizei count, const GLint* value);
[email protected]43c2f1f2011-03-25 18:35:361156 void DoUniform2iv(GLint location, GLsizei count, const GLint* value);
1157 void DoUniform3iv(GLint location, GLsizei count, const GLint* value);
1158 void DoUniform4iv(GLint location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101159
1160 // Wrappers for glUniformfv because some drivers don't correctly accept
1161 // bool uniforms.
1162 void DoUniform1fv(GLint location, GLsizei count, const GLfloat* value);
1163 void DoUniform2fv(GLint location, GLsizei count, const GLfloat* value);
1164 void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value);
1165 void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501166
[email protected]43c2f1f2011-03-25 18:35:361167 void DoUniformMatrix2fv(
1168 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1169 void DoUniformMatrix3fv(
1170 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1171 void DoUniformMatrix4fv(
1172 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1173
[email protected]b1122982010-05-17 23:04:241174 // Wrappers for glVertexAttrib??
1175 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1176 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1177 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1178 void DoVertexAttrib4f(
1179 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1180 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1181 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1182 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1183 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1184
[email protected]07f54fcc2009-12-22 02:46:301185 // Wrapper for glUseProgram
1186 void DoUseProgram(GLuint program);
1187
[email protected]ae51d192010-04-27 00:48:031188 // Wrapper for glValidateProgram.
1189 void DoValidateProgram(GLuint program_client_id);
1190
[email protected]4e8a5b122010-05-08 22:00:101191 // Gets the number of values that will be returned by glGetXXX. Returns
1192 // false if pname is unknown.
1193 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1194
[email protected]96449d2c2009-11-25 00:01:321195 // Gets the GLError through our wrapper.
1196 GLenum GetGLError();
1197
[email protected]1002c2d2011-06-28 22:39:041198 // Gets the GLError and stores it in our wrapper. Effectively
1199 // this lets us peek at the error without losing it.
1200 GLenum PeekGLError();
1201
[email protected]07f54fcc2009-12-22 02:46:301202 // Copies the real GL errors to the wrapper. This is so we can
1203 // make sure there are no native GL errors before calling some GL function
1204 // so that on return we know any error generated was for that specific
1205 // command.
1206 void CopyRealGLErrorsToWrapper();
1207
[email protected]6217d392010-03-25 22:08:351208 // Clear all real GL errors. This is to prevent the client from seeing any
1209 // errors caused by GL calls that it was not responsible for issuing.
1210 void ClearRealGLErrors();
1211
[email protected]07f54fcc2009-12-22 02:46:301212 // Checks if the current program and vertex attributes are valid for drawing.
1213 bool IsDrawValid(GLuint max_vertex_accessed);
1214
[email protected]c13e1da62011-09-09 21:48:301215 // Returns true if successful, simulated will be true if attrib0 was
1216 // simulated.
1217 bool SimulateAttrib0(GLuint max_vertex_accessed, bool* simulated);
[email protected]b1122982010-05-17 23:04:241218 void RestoreStateForSimulatedAttrib0();
1219
[email protected]ef526492010-06-02 23:12:251220 // Returns true if textures were set.
1221 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501222 void RestoreStateForNonRenderableTextures();
1223
[email protected]8fbedc02010-11-18 18:43:401224 // Returns true if GL_FIXED attribs were simulated.
1225 bool SimulateFixedAttribs(GLuint max_vertex_accessed, bool* simulated);
1226 void RestoreStateForSimulatedFixedAttribs();
1227
[email protected]07f54fcc2009-12-22 02:46:301228 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501229 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301230 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501231 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1232 bound_array_buffer_ : bound_element_array_buffer_;
[email protected]a0b78dc2011-11-11 10:43:101233 return info;
[email protected]07f54fcc2009-12-22 02:46:301234 }
1235
[email protected]a93bb842010-02-16 23:03:471236 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501237 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1238 TextureUnit& unit = texture_units_[active_texture_unit_];
1239 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471240 switch (target) {
1241 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501242 info = unit.bound_texture_2d;
1243 break;
[email protected]a93bb842010-02-16 23:03:471244 case GL_TEXTURE_CUBE_MAP:
1245 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1246 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1247 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1248 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1249 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1250 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501251 info = unit.bound_texture_cube_map;
1252 break;
[email protected]61eeb33f2011-07-26 15:30:311253 case GL_TEXTURE_EXTERNAL_OES:
1254 info = unit.bound_texture_external_oes;
1255 break;
[email protected]e51bdf32011-11-23 22:21:461256 case GL_TEXTURE_RECTANGLE_ARB:
1257 info = unit.bound_texture_rectangle_arb;
1258 break;
[email protected]a93bb842010-02-16 23:03:471259 default:
1260 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501261 return NULL;
[email protected]a93bb842010-02-16 23:03:471262 }
[email protected]a0b78dc2011-11-11 10:43:101263 return info;
[email protected]a93bb842010-02-16 23:03:471264 }
1265
[email protected]61eeb33f2011-07-26 15:30:311266 GLenum GetBindTargetForSamplerType(GLenum type) {
1267 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:461268 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1269 switch (type) {
1270 case GL_SAMPLER_2D:
1271 return GL_TEXTURE_2D;
1272 case GL_SAMPLER_CUBE:
1273 return GL_TEXTURE_CUBE_MAP;
1274 case GL_SAMPLER_EXTERNAL_OES:
1275 return GL_TEXTURE_EXTERNAL_OES;
1276 case GL_SAMPLER_2D_RECT_ARB:
1277 return GL_TEXTURE_RECTANGLE_ARB;
1278 }
1279
1280 NOTREACHED();
1281 return 0;
[email protected]61eeb33f2011-07-26 15:30:311282 }
1283
[email protected]8e3e0662010-08-23 18:46:301284 // Gets the framebuffer info for a particular target.
1285 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1286 GLenum target) {
1287 FramebufferManager::FramebufferInfo* info = NULL;
1288 switch (target) {
1289 case GL_FRAMEBUFFER:
1290 case GL_DRAW_FRAMEBUFFER:
1291 info = bound_draw_framebuffer_;
1292 break;
1293 case GL_READ_FRAMEBUFFER:
1294 info = bound_read_framebuffer_;
1295 break;
1296 default:
1297 NOTREACHED();
1298 break;
1299 }
[email protected]a0b78dc2011-11-11 10:43:101300 return info;
[email protected]8e3e0662010-08-23 18:46:301301 }
1302
[email protected]0d6bfdc2011-11-02 01:32:201303 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfoForTarget(
1304 GLenum target) {
1305 RenderbufferManager::RenderbufferInfo* info = NULL;
1306 switch (target) {
1307 case GL_RENDERBUFFER:
1308 info = bound_renderbuffer_;
1309 break;
1310 default:
1311 NOTREACHED();
1312 break;
1313 }
[email protected]a0b78dc2011-11-11 10:43:101314 return info;
[email protected]0d6bfdc2011-11-02 01:32:201315 }
1316
[email protected]f7b85372010-02-03 01:11:371317 // Validates the program and location for a glGetUniform call and returns
1318 // a SizeResult setup to receive the result. Returns true if glGetUniform
1319 // should be called.
1320 bool GetUniformSetup(
1321 GLuint program, GLint location,
1322 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:101323 error::Error* error, GLuint* service_id, void** result,
1324 GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371325
[email protected]1078f912011-12-23 13:12:141326 // Computes the estimated memory used for the backbuffer and passes it to
1327 // the tracing system.
1328 void UpdateBackbufferMemoryAccounting();
1329
[email protected]38d139d2011-07-14 00:38:431330 // Returns true if the context was just lost due to e.g. GL_ARB_robustness.
1331 bool WasContextLost();
1332
[email protected]e51bdf32011-11-23 22:21:461333#if defined(OS_MACOSX)
1334 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1335#endif
1336
[email protected]96449d2c2009-11-25 00:01:321337 // Generate a member function prototype for each command in an automated and
1338 // typesafe way.
1339 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141340 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191341 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321342 const gles2::name& args); \
1343
1344 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1345
1346 #undef GLES2_CMD_OP
1347
[email protected]2f2d7042010-04-14 21:45:581348 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381349 scoped_refptr<gfx::GLSurface> surface_;
1350 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021351
[email protected]a3ded6d2010-10-19 06:44:391352 // The ContextGroup for this decoder uses to track resources.
1353 ContextGroup::Ref group_;
1354
[email protected]6217d392010-03-25 22:08:351355 // A parent decoder can access this decoders saved offscreen frame buffer.
1356 // The parent pointer is reset if the parent is destroyed.
1357 base::WeakPtr<GLES2DecoderImpl> parent_;
1358
[email protected]34ff8b0c2010-10-01 20:06:021359 // Current width and height of the offscreen frame buffer.
1360 gfx::Size offscreen_size_;
1361
[email protected]96449d2c2009-11-25 00:01:321362 // Current GL error bits.
1363 uint32 error_bits_;
1364
[email protected]96449d2c2009-11-25 00:01:321365 // Util to help with GL.
1366 GLES2Util util_;
1367
1368 // pack alignment as last set by glPixelStorei
1369 GLint pack_alignment_;
1370
1371 // unpack alignment as last set by glPixelStorei
1372 GLint unpack_alignment_;
1373
1374 // The currently bound array buffer. If this is 0 it is illegal to call
1375 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501376 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321377
1378 // The currently bound element array buffer. If this is 0 it is illegal
1379 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501380 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301381
[email protected]f39f4b3f2010-05-12 17:04:081382 // Class that manages vertex attribs.
[email protected]3757a372012-01-19 05:20:441383 scoped_ptr<VertexAttribManager> vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301384
[email protected]b1122982010-05-17 23:04:241385 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1386 GLuint attrib_0_buffer_id_;
1387
1388 // The value currently in attrib_0.
1389 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1390
[email protected]fc753442011-02-04 19:49:491391 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1392 bool attrib_0_buffer_matches_value_;
1393
[email protected]b1122982010-05-17 23:04:241394 // The size of attrib 0.
1395 GLsizei attrib_0_size_;
1396
[email protected]8fbedc02010-11-18 18:43:401397 // The buffer used to simulate GL_FIXED attribs.
1398 GLuint fixed_attrib_buffer_id_;
1399
1400 // The size of fiixed attrib buffer.
1401 GLsizei fixed_attrib_buffer_size_;
1402
[email protected]3916c97e2010-02-25 03:20:501403 // Current active texture by 0 - n index.
1404 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1405 // be 2.
1406 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301407
[email protected]3916c97e2010-02-25 03:20:501408 // Which textures are bound to texture units through glActiveTexture.
1409 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471410
[email protected]3a2e7c7b2010-08-06 01:12:281411 // state saved for clearing so we can clear render buffers and then
1412 // restore to these values.
1413 GLclampf clear_red_;
1414 GLclampf clear_green_;
1415 GLclampf clear_blue_;
1416 GLclampf clear_alpha_;
1417 GLboolean mask_red_;
1418 GLboolean mask_green_;
1419 GLboolean mask_blue_;
1420 GLboolean mask_alpha_;
1421 GLint clear_stencil_;
1422 GLuint mask_stencil_front_;
1423 GLuint mask_stencil_back_;
1424 GLclampf clear_depth_;
1425 GLboolean mask_depth_;
1426 bool enable_scissor_test_;
[email protected]297ca1c2011-06-20 23:08:461427 bool enable_depth_test_;
1428 bool enable_stencil_test_;
1429 bool state_dirty_;
[email protected]3a2e7c7b2010-08-06 01:12:281430
[email protected]1d32bc82010-01-13 22:06:461431 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501432 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301433
[email protected]8e3e0662010-08-23 18:46:301434 // The currently bound framebuffers
1435 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1436 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561437
1438 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081439 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561440
[email protected]b9363b22010-06-09 22:06:151441 // The offscreen frame buffer that the client renders to. With EGL, the
1442 // depth and stencil buffers are separate. With regular GL there is a single
1443 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1444 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351445 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1446 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021447 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151448 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1449 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021450 GLenum offscreen_target_color_format_;
1451 GLenum offscreen_target_depth_format_;
1452 GLenum offscreen_target_stencil_format_;
1453 GLsizei offscreen_target_samples_;
[email protected]8a61d872012-01-20 12:43:561454 GLboolean offscreen_target_buffer_preserved_;
[email protected]6217d392010-03-25 22:08:351455
[email protected]de26b3c2011-08-03 21:54:271456 // The copy that is saved when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021457 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351458 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]8a61d872012-01-20 12:43:561459 TextureManager::TextureInfo::Ref offscreen_saved_color_texture_info_;
[email protected]de26b3c2011-08-03 21:54:271460
1461 // The copy that is used as the destination for multi-sample resolves.
1462 scoped_ptr<FrameBuffer> offscreen_resolved_frame_buffer_;
1463 scoped_ptr<Texture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051464 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351465
[email protected]9d37f062011-11-22 01:24:521466 base::Callback<void(gfx::Size)> resize_callback_;
[email protected]22f320a2011-08-30 01:17:001467
[email protected]6b6e7ee2011-12-13 08:04:521468 MsgCallback msg_callback_;
[email protected]43f28f832010-02-03 02:28:481469
[email protected]b0af4f52011-09-28 22:04:421470 StreamTextureManager* stream_texture_manager_;
1471
[email protected]32fe9aa2011-01-21 23:47:131472 // The format of the back buffer_
1473 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461474 bool back_buffer_has_depth_;
1475 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131476
[email protected]473c01ccb2011-06-07 01:33:301477 bool teximage2d_faster_than_texsubimage2d_;
1478 bool bufferdata_faster_than_buffersubdata_;
1479
[email protected]8eee29c2010-04-29 03:38:291480 // The last error message set.
1481 std::string last_error_;
1482
[email protected]a3a93e7b2010-08-28 00:48:561483 // The current decoder error.
1484 error::Error current_decoder_error_;
1485
[email protected]b1d2dcb2010-05-17 19:24:181486 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451487 scoped_ptr<ShaderTranslator> vertex_translator_;
1488 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181489
[email protected]e82fb792011-09-22 00:33:291490 DisallowedFeatures disallowed_features_;
[email protected]c410da802011-03-14 19:17:411491
[email protected]915a59a12010-09-30 21:29:111492 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051493 const Validators* validators_;
[email protected]80eb6b52012-01-19 00:14:411494 FeatureInfo::Ref feature_info_;
[email protected]9438b012010-06-15 22:55:051495
[email protected]b493ee622011-04-13 23:52:001496 // This indicates all the following texSubImage2D calls that are part of the
1497 // failed texImage2D call should be ignored.
1498 bool tex_image_2d_failed_;
1499
[email protected]65225772011-05-12 21:10:241500 int frame_number_;
1501
[email protected]38d139d2011-07-14 00:38:431502 bool has_arb_robustness_;
1503 GLenum reset_status_;
1504
[email protected]75c023c2011-08-22 23:54:511505 bool needs_mac_nvidia_driver_workaround_;
[email protected]a2a0fe762011-09-20 00:59:121506 bool needs_glsl_built_in_function_emulation_;
[email protected]75c023c2011-08-22 23:54:511507
[email protected]f0d74742011-10-03 16:31:041508 // These flags are used to override the state of the shared feature_info_
1509 // member. Because the same FeatureInfo instance may be shared among many
1510 // contexts, the assumptions on the availablity of extensions in WebGL
1511 // contexts may be broken. These flags override the shared state to preserve
1512 // WebGL semantics.
1513 bool force_webgl_glsl_validation_;
1514 bool derivatives_explicitly_enabled_;
1515
[email protected]062c38b2012-01-18 03:25:101516 bool compile_shader_always_succeeds_;
1517
[email protected]e51bdf32011-11-23 22:21:461518#if defined(OS_MACOSX)
1519 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1520 TextureToIOSurfaceMap texture_to_io_surface_map_;
1521#endif
1522
[email protected]c826d732012-02-09 04:40:261523 typedef std::vector<GLES2DecoderImpl*> ChildList;
1524 ChildList children_;
1525
[email protected]96449d2c2009-11-25 00:01:321526 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1527};
1528
[email protected]6217d392010-03-25 22:08:351529ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1530 : decoder_(decoder) {
1531 decoder_->CopyRealGLErrorsToWrapper();
1532}
1533
1534ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1535 decoder_->ClearRealGLErrors();
1536}
1537
1538ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1539 GLuint id)
1540 : decoder_(decoder) {
1541 ScopedGLErrorSuppressor suppressor(decoder_);
1542
1543 // TODO(apatrick): Check if there are any other states that need to be reset
1544 // before binding a new texture.
1545 glActiveTexture(GL_TEXTURE0);
1546 glBindTexture(GL_TEXTURE_2D, id);
1547}
1548
1549ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1550 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301551 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351552}
1553
1554ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1555 GLuint id)
1556 : decoder_(decoder) {
1557 ScopedGLErrorSuppressor suppressor(decoder_);
1558 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1559}
1560
1561ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1562 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301563 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351564}
1565
1566ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1567 GLuint id)
1568 : decoder_(decoder) {
1569 ScopedGLErrorSuppressor suppressor(decoder_);
1570 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1571}
1572
1573ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1574 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301575 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351576}
1577
[email protected]34ff8b0c2010-10-01 20:06:021578ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271579 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521580 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021581 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1582 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]c0701082011-04-20 00:34:521583 (!decoder_->bound_read_framebuffer_.get() ||
1584 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021585 if (!resolve_and_bind_)
1586 return;
1587
1588 ScopedGLErrorSuppressor suppressor(decoder_);
1589 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1590 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271591 GLuint targetid;
1592 if (internal) {
1593 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1594 decoder_->offscreen_resolved_frame_buffer_.reset(
1595 new FrameBuffer(decoder_));
1596 decoder_->offscreen_resolved_frame_buffer_->Create();
1597 decoder_->offscreen_resolved_color_texture_.reset(new Texture(decoder_));
1598 decoder_->offscreen_resolved_color_texture_->Create();
1599
1600 DCHECK(decoder_->offscreen_saved_color_format_);
1601 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1602 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_);
[email protected]de26b3c2011-08-03 21:54:271603 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1604 decoder_->offscreen_resolved_color_texture_.get());
1605 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1606 GL_FRAMEBUFFER_COMPLETE) {
1607 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1608 << "because offscreen resolved FBO was incomplete.";
1609 return;
1610 }
1611 }
1612 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1613 } else {
1614 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1615 }
1616 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021617 const int width = decoder_->offscreen_size_.width();
1618 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181619 glDisable(GL_SCISSOR_TEST);
[email protected]57edfdad2012-02-07 04:57:151620 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021621 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1622 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1623 } else {
1624 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1625 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1626 }
[email protected]de26b3c2011-08-03 21:54:271627 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021628}
1629
1630ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1631 if (!resolve_and_bind_)
1632 return;
1633
1634 ScopedGLErrorSuppressor suppressor(decoder_);
1635 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181636 if (decoder_->enable_scissor_test_) {
1637 glEnable(GL_SCISSOR_TEST);
1638 }
[email protected]34ff8b0c2010-10-01 20:06:021639}
1640
[email protected]6217d392010-03-25 22:08:351641Texture::Texture(GLES2DecoderImpl* decoder)
1642 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141643 id_(0),
1644 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351645}
1646
1647Texture::~Texture() {
1648 // This does not destroy the render texture because that would require that
1649 // the associated GL context was current. Just check that it was explicitly
1650 // destroyed.
1651 DCHECK_EQ(id_, 0u);
1652}
1653
1654void Texture::Create() {
1655 ScopedGLErrorSuppressor suppressor(decoder_);
1656 Destroy();
1657 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581658 ScopedTexture2DBinder binder(decoder_, id_);
1659 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1660 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1661 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1662 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]62788802011-10-03 17:57:161663
1664 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1665 // never called on an offscreen context, no data will ever be uploaded to the
1666 // saved offscreen color texture (it is deferred until to when SwapBuffers
1667 // is called). My idea is that some nvidia drivers might have a bug where
1668 // deleting a texture that has never been populated might cause a
1669 // crash.
1670 glTexImage2D(
1671 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
[email protected]1078f912011-12-23 13:12:141672 estimated_size_ = 16u * 16u * 4u;
1673 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351674}
1675
[email protected]34ff8b0c2010-10-01 20:06:021676bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351677 DCHECK_NE(id_, 0u);
1678 ScopedGLErrorSuppressor suppressor(decoder_);
1679 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]6217d392010-03-25 22:08:351680
[email protected]f0e6a34f2012-01-04 20:53:401681 WrappedTexImage2D(GL_TEXTURE_2D,
1682 0, // mip level
1683 format,
1684 size.width(),
1685 size.height(),
1686 0, // border
1687 format,
1688 GL_UNSIGNED_BYTE,
1689 NULL);
[email protected]6217d392010-03-25 22:08:351690
[email protected]d37231fa2010-04-09 21:16:021691 size_ = size;
1692
[email protected]1078f912011-12-23 13:12:141693 bool success = glGetError() == GL_NO_ERROR;
1694 if (success) {
1695 uint32 image_size = 0;
1696 GLES2Util::ComputeImageDataSize(
1697 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 4, &image_size);
1698 estimated_size_ = image_size;
1699 decoder_->UpdateBackbufferMemoryAccounting();
1700 }
1701 return success;
[email protected]6217d392010-03-25 22:08:351702}
1703
[email protected]3a4d0c52011-06-29 23:11:581704void Texture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351705 DCHECK_NE(id_, 0u);
1706 ScopedGLErrorSuppressor suppressor(decoder_);
1707 ScopedTexture2DBinder binder(decoder_, id_);
1708 glCopyTexImage2D(GL_TEXTURE_2D,
1709 0, // level
[email protected]3a4d0c52011-06-29 23:11:581710 format,
[email protected]6217d392010-03-25 22:08:351711 0, 0,
1712 size.width(),
1713 size.height(),
1714 0); // border
1715}
1716
1717void Texture::Destroy() {
1718 if (id_ != 0) {
1719 ScopedGLErrorSuppressor suppressor(decoder_);
1720 glDeleteTextures(1, &id_);
1721 id_ = 0;
[email protected]1078f912011-12-23 13:12:141722 estimated_size_ = 0;
1723 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351724 }
1725}
1726
[email protected]97872062010-11-03 19:07:051727void Texture::Invalidate() {
1728 id_ = 0;
1729}
1730
[email protected]6217d392010-03-25 22:08:351731RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1732 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141733 id_(0),
1734 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351735}
1736
1737RenderBuffer::~RenderBuffer() {
1738 // This does not destroy the render buffer because that would require that
1739 // the associated GL context was current. Just check that it was explicitly
1740 // destroyed.
1741 DCHECK_EQ(id_, 0u);
1742}
1743
1744void RenderBuffer::Create() {
1745 ScopedGLErrorSuppressor suppressor(decoder_);
1746 Destroy();
1747 glGenRenderbuffersEXT(1, &id_);
1748}
1749
[email protected]34ff8b0c2010-10-01 20:06:021750bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1751 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351752 ScopedGLErrorSuppressor suppressor(decoder_);
1753 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021754 if (samples <= 1) {
1755 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1756 format,
1757 size.width(),
1758 size.height());
1759 } else {
[email protected]57edfdad2012-02-07 04:57:151760 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021761 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1762 samples,
1763 format,
1764 size.width(),
1765 size.height());
1766 } else {
1767 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1768 samples,
1769 format,
1770 size.width(),
1771 size.height());
1772 }
1773 }
[email protected]1078f912011-12-23 13:12:141774 bool success = glGetError() == GL_NO_ERROR;
1775 if (success) {
1776 estimated_size_ = size.width() * size.height() * samples *
1777 GLES2Util::RenderbufferBytesPerPixel(format);
1778 decoder_->UpdateBackbufferMemoryAccounting();
1779 }
1780 return success;
[email protected]6217d392010-03-25 22:08:351781}
1782
1783void RenderBuffer::Destroy() {
1784 if (id_ != 0) {
1785 ScopedGLErrorSuppressor suppressor(decoder_);
1786 glDeleteRenderbuffersEXT(1, &id_);
1787 id_ = 0;
[email protected]1078f912011-12-23 13:12:141788 estimated_size_ = 0;
1789 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351790 }
1791}
1792
[email protected]97872062010-11-03 19:07:051793void RenderBuffer::Invalidate() {
1794 id_ = 0;
1795}
1796
[email protected]6217d392010-03-25 22:08:351797FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1798 : decoder_(decoder),
1799 id_(0) {
1800}
1801
1802FrameBuffer::~FrameBuffer() {
1803 // This does not destroy the frame buffer because that would require that
1804 // the associated GL context was current. Just check that it was explicitly
1805 // destroyed.
1806 DCHECK_EQ(id_, 0u);
1807}
1808
1809void FrameBuffer::Create() {
1810 ScopedGLErrorSuppressor suppressor(decoder_);
1811 Destroy();
1812 glGenFramebuffersEXT(1, &id_);
1813}
1814
1815void FrameBuffer::AttachRenderTexture(Texture* texture) {
1816 DCHECK_NE(id_, 0u);
1817 ScopedGLErrorSuppressor suppressor(decoder_);
1818 ScopedFrameBufferBinder binder(decoder_, id_);
1819 GLuint attach_id = texture ? texture->id() : 0;
1820 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1821 GL_COLOR_ATTACHMENT0,
1822 GL_TEXTURE_2D,
1823 attach_id,
1824 0);
1825}
1826
[email protected]b9363b22010-06-09 22:06:151827void FrameBuffer::AttachRenderBuffer(GLenum target,
1828 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351829 DCHECK_NE(id_, 0u);
1830 ScopedGLErrorSuppressor suppressor(decoder_);
1831 ScopedFrameBufferBinder binder(decoder_, id_);
1832 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1833 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151834 target,
[email protected]6217d392010-03-25 22:08:351835 GL_RENDERBUFFER,
1836 attach_id);
1837}
1838
[email protected]6217d392010-03-25 22:08:351839void FrameBuffer::Destroy() {
1840 if (id_ != 0) {
1841 ScopedGLErrorSuppressor suppressor(decoder_);
1842 glDeleteFramebuffersEXT(1, &id_);
1843 id_ = 0;
1844 }
1845}
1846
[email protected]97872062010-11-03 19:07:051847void FrameBuffer::Invalidate() {
1848 id_ = 0;
1849}
1850
[email protected]6217d392010-03-25 22:08:351851GLenum FrameBuffer::CheckStatus() {
1852 DCHECK_NE(id_, 0u);
1853 ScopedGLErrorSuppressor suppressor(decoder_);
1854 ScopedFrameBufferBinder binder(decoder_, id_);
1855 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1856}
1857
[email protected]aa7666122011-09-02 19:45:521858GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1859 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321860}
1861
[email protected]aa7666122011-09-02 19:45:521862GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391863 : GLES2Decoder(),
[email protected]3b1ecc262011-08-03 22:49:571864 group_(group),
[email protected]96449d2c2009-11-25 00:01:321865 error_bits_(0),
[email protected]96449d2c2009-11-25 00:01:321866 pack_alignment_(4),
1867 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241868 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491869 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241870 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401871 fixed_attrib_buffer_id_(0),
1872 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501873 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281874 clear_red_(0),
1875 clear_green_(0),
1876 clear_blue_(0),
1877 clear_alpha_(0),
1878 mask_red_(true),
1879 mask_green_(true),
1880 mask_blue_(true),
1881 mask_alpha_(true),
1882 clear_stencil_(0),
1883 mask_stencil_front_(-1),
1884 mask_stencil_back_(-1),
1885 clear_depth_(1.0f),
1886 mask_depth_(true),
1887 enable_scissor_test_(false),
[email protected]297ca1c2011-06-20 23:08:461888 enable_depth_test_(false),
1889 enable_stencil_test_(false),
1890 state_dirty_(true),
[email protected]34ff8b0c2010-10-01 20:06:021891 offscreen_target_color_format_(0),
1892 offscreen_target_depth_format_(0),
1893 offscreen_target_stencil_format_(0),
1894 offscreen_target_samples_(0),
[email protected]8a61d872012-01-20 12:43:561895 offscreen_target_buffer_preserved_(true),
[email protected]97872062010-11-03 19:07:051896 offscreen_saved_color_format_(0),
[email protected]b0af4f52011-09-28 22:04:421897 stream_texture_manager_(NULL),
[email protected]32fe9aa2011-01-21 23:47:131898 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:461899 back_buffer_has_depth_(false),
1900 back_buffer_has_stencil_(false),
[email protected]473c01ccb2011-06-07 01:33:301901 teximage2d_faster_than_texsubimage2d_(true),
1902 bufferdata_faster_than_buffersubdata_(true),
[email protected]a3a93e7b2010-08-28 00:48:561903 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051904 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111905 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001906 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241907 tex_image_2d_failed_(false),
[email protected]38d139d2011-07-14 00:38:431908 frame_number_(0),
1909 has_arb_robustness_(false),
[email protected]75c023c2011-08-22 23:54:511910 reset_status_(GL_NO_ERROR),
[email protected]a2a0fe762011-09-20 00:59:121911 needs_mac_nvidia_driver_workaround_(false),
[email protected]f0d74742011-10-03 16:31:041912 needs_glsl_built_in_function_emulation_(false),
1913 force_webgl_glsl_validation_(false),
[email protected]062c38b2012-01-18 03:25:101914 derivatives_explicitly_enabled_(false),
1915 compile_shader_always_succeeds_(false) {
[email protected]3b1ecc262011-08-03 22:49:571916 DCHECK(group);
1917
[email protected]b1122982010-05-17 23:04:241918 attrib_0_value_.v[0] = 0.0f;
1919 attrib_0_value_.v[1] = 0.0f;
1920 attrib_0_value_.v[2] = 0.0f;
1921 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151922
[email protected]c2f8c8402010-12-06 18:07:241923 // The shader translator is used for WebGL even when running on EGL
1924 // because additional restrictions are needed (like only enabling
1925 // GL_OES_standard_derivatives on demand). It is used for the unit
1926 // tests because
1927 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1928 // empty string to CompileShader and this is not a valid shader.
1929 // TODO(apatrick): fix this test.
1930 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:041931 !feature_info_->feature_flags().chromium_webglsl &&
1932 !force_webgl_glsl_validation_) ||
[email protected]b9363b22010-06-09 22:06:151933 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) {
1934 use_shader_translator_ = false;
1935 }
[email protected]473c01ccb2011-06-07 01:33:301936
1937 // TODO(gman): Consider setting these based on GPU and/or driver.
1938 if (IsAngle()) {
1939 teximage2d_faster_than_texsubimage2d_ = false;
1940 bufferdata_faster_than_buffersubdata_ = false;
1941 }
[email protected]96449d2c2009-11-25 00:01:321942}
1943
[email protected]80eb6b52012-01-19 00:14:411944GLES2DecoderImpl::~GLES2DecoderImpl() {
1945}
1946
[email protected]c410da802011-03-14 19:17:411947bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:381948 const scoped_refptr<gfx::GLSurface>& surface,
1949 const scoped_refptr<gfx::GLContext>& context,
[email protected]c410da802011-03-14 19:17:411950 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:291951 const DisallowedFeatures& disallowed_features,
[email protected]c410da802011-03-14 19:17:411952 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:241953 const std::vector<int32>& attribs) {
[email protected]4bedba72010-04-20 22:08:541954 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301955 DCHECK(!context_.get());
1956
[email protected]e844ae22012-01-14 03:36:261957 if (CommandLine::ForCurrentProcess()->HasSwitch(
1958 switches::kEnableGPUDebugging)) {
1959 set_debug(true);
1960 }
1961
[email protected]062c38b2012-01-18 03:25:101962 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
1963 switches::kCompileShaderAlwaysSucceeds);
1964
[email protected]fbe20372011-06-01 01:46:381965 // Take ownership of the GLSurface. TODO(apatrick): once the parent / child
1966 // context is retired, the decoder should not take an initial surface as
1967 // an argument to this function.
1968 // Maybe create a short lived offscreen GLSurface for the purpose of
1969 // initializing the decoder's GLContext.
1970 surface_ = surface;
[email protected]f62a5ab2011-05-23 20:34:151971
[email protected]66791e382010-07-14 20:48:301972 // Take ownership of the GLContext.
[email protected]fbe20372011-06-01 01:46:381973 context_ = context;
[email protected]d37231fa2010-04-09 21:16:021974
[email protected]246a70452010-03-05 21:53:501975 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:011976 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
1977 << "MakeCurrent failed.";
[email protected]1871a092011-10-10 21:46:421978 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]246a70452010-03-05 21:53:501979 Destroy();
1980 return false;
[email protected]eb54a562010-01-20 21:55:181981 }
1982
[email protected]e82fb792011-09-22 00:33:291983 if (!group_->Initialize(disallowed_features, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:221984 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:391985 << "failed to initialize.";
[email protected]1871a092011-10-10 21:46:421986 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]a3ded6d2010-10-19 06:44:391987 Destroy();
[email protected]ae1741092010-11-17 19:16:031988 return false;
[email protected]a3ded6d2010-10-19 06:44:391989 }
1990
[email protected]246a70452010-03-05 21:53:501991 CHECK_GL_ERROR();
[email protected]e82fb792011-09-22 00:33:291992 disallowed_features_ = disallowed_features;
[email protected]246a70452010-03-05 21:53:501993
[email protected]3757a372012-01-19 05:20:441994 vertex_attrib_manager_.reset(new VertexAttribManager());
1995 vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:321996
[email protected]302ce6d2011-07-07 23:28:111997 util_.set_num_compressed_texture_formats(
1998 validators_->compressed_texture_format.GetValues().size());
1999
[email protected]1071e572011-02-09 20:00:122000 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2001 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2002 // OpenGL ES 2.0 does not have this issue.
2003 glEnableVertexAttribArray(0);
2004 }
[email protected]b1122982010-05-17 23:04:242005 glGenBuffersARB(1, &attrib_0_buffer_id_);
2006 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2007 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2008 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:402009 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:082010
[email protected]246a70452010-03-05 21:53:502011 texture_units_.reset(
2012 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:152013 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:492014 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:312015 // We want the last bind to be 2D.
2016 TextureManager::TextureInfo* info;
2017 if (feature_info_->feature_flags().oes_egl_image_external) {
2018 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_EXTERNAL_OES);
2019 texture_units_[tt].bound_texture_external_oes = info;
2020 glBindTexture(GL_TEXTURE_EXTERNAL_OES, info->service_id());
2021 }
[email protected]e51bdf32011-11-23 22:21:462022 if (feature_info_->feature_flags().arb_texture_rectangle) {
2023 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_RECTANGLE_ARB);
2024 texture_units_[tt].bound_texture_rectangle_arb = info;
2025 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, info->service_id());
2026 }
[email protected]61eeb33f2011-07-26 15:30:312027 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:492028 texture_units_[tt].bound_texture_cube_map = info;
2029 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
2030 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2031 texture_units_[tt].bound_texture_2d = info;
2032 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:152033 }
[email protected]00f893d2010-08-24 18:55:492034 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:502035 CHECK_GL_ERROR();
2036
[email protected]297ca1c2011-06-20 23:08:462037 ContextCreationAttribParser attrib_parser;
2038 if (!attrib_parser.Parse(attribs))
2039 return false;
[email protected]41c56362011-06-14 16:47:432040
[email protected]297ca1c2011-06-20 23:08:462041 // These are NOT if the back buffer has these proprorties. They are
2042 // if we want the command buffer to enforce them regardless of what
2043 // the real backbuffer is assuming the real back buffer gives us more than
2044 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2045 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2046 // can't do anything about that.
2047
2048 GLint v = 0;
2049 glGetIntegerv(GL_ALPHA_BITS, &v);
2050 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2051 // user requested RGB then RGB. If the user did not specify a preference than
2052 // use whatever we were given. Same for DEPTH and STENCIL.
2053 back_buffer_color_format_ =
2054 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2055 glGetIntegerv(GL_DEPTH_BITS, &v);
2056 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2057 glGetIntegerv(GL_STENCIL_BITS, &v);
2058 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2059
2060 if (surface_->IsOffscreen()) {
[email protected]34ff8b0c2010-10-01 20:06:022061 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:542062 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:022063 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
2064 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:432065 // max_sample_count must be initialized to a sane value. If
2066 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2067 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:022068 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2069 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2070 max_sample_count);
2071 } else {
2072 offscreen_target_samples_ = 1;
2073 }
[email protected]8a61d872012-01-20 12:43:562074 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
[email protected]34ff8b0c2010-10-01 20:06:022075
2076 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2077 const bool rgb8_supported =
2078 context_->HasExtension("GL_OES_rgb8_rgba8");
2079 // The only available default render buffer formats in GLES2 have very
2080 // little precision. Don't enable multisampling unless 8-bit render
2081 // buffer formats are available--instead fall back to 8-bit textures.
2082 if (rgb8_supported && offscreen_target_samples_ > 1) {
2083 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2084 GL_RGBA8 : GL_RGB8;
2085 } else {
2086 offscreen_target_samples_ = 1;
2087 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2088 GL_RGBA : GL_RGB;
2089 }
2090
2091 // ANGLE only supports packed depth/stencil formats, so use it if it is
2092 // available.
2093 const bool depth24_stencil8_supported =
2094 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272095 VLOG(1) << "GL_OES_packed_depth_stencil "
2096 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:002097 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2098 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022099 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2100 offscreen_target_stencil_format_ = 0;
2101 } else {
2102 // It may be the case that this depth/stencil combination is not
2103 // supported, but this will be checked later by CheckFramebufferStatus.
2104 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2105 GL_DEPTH_COMPONENT16 : 0;
2106 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2107 GL_STENCIL_INDEX8 : 0;
2108 }
2109 } else {
2110 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2111 GL_RGBA : GL_RGB;
2112
2113 // If depth is requested at all, use the packed depth stencil format if
2114 // it's available, as some desktop GL drivers don't support any non-packed
2115 // formats for depth attachments.
2116 const bool depth24_stencil8_supported =
2117 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272118 VLOG(1) << "GL_EXT_packed_depth_stencil "
2119 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:022120
[email protected]71ee3642010-10-14 18:08:002121 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2122 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022123 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2124 offscreen_target_stencil_format_ = 0;
2125 } else {
2126 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2127 GL_DEPTH_COMPONENT : 0;
2128 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2129 GL_STENCIL_INDEX : 0;
2130 }
2131 }
2132
[email protected]97872062010-11-03 19:07:052133 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2134 GL_RGBA : GL_RGB;
2135
[email protected]6217d392010-03-25 22:08:352136 // Create the target frame buffer. This is the one that the client renders
2137 // directly to.
2138 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
2139 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022140 // Due to GLES2 format limitations, either the color texture (for
2141 // non-multisampling) or the color render buffer (for multisampling) will be
2142 // attached to the offscreen frame buffer. The render buffer has more
2143 // limited formats available to it, but the texture can't do multisampling.
2144 if (IsOffscreenBufferMultisampled()) {
2145 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
2146 offscreen_target_color_render_buffer_->Create();
2147 } else {
2148 offscreen_target_color_texture_.reset(new Texture(this));
2149 offscreen_target_color_texture_->Create();
2150 }
2151 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152152 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022153 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152154 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:352155
2156 // Create the saved offscreen texture. The target frame buffer is copied
2157 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:022158 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
2159 offscreen_saved_frame_buffer_->Create();
2160 //
[email protected]6217d392010-03-25 22:08:352161 offscreen_saved_color_texture_.reset(new Texture(this));
2162 offscreen_saved_color_texture_->Create();
2163
[email protected]6217d392010-03-25 22:08:352164 // Allocate the render buffers at their initial size and check the status
2165 // of the frame buffers is okay.
[email protected]799b4b22011-08-22 17:09:592166 if (!ResizeOffscreenFrameBuffer(size)) {
[email protected]d0498742010-09-20 20:27:012167 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:352168 Destroy();
2169 return false;
2170 }
2171
2172 // Bind to the new default frame buffer (the offscreen target frame buffer).
2173 // This should now be associated with ID zero.
2174 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2175 }
2176
[email protected]295faf4b2012-01-25 23:31:412177 // Clear the backbuffer.
2178 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2179
[email protected]76a0ee102010-04-07 21:03:042180 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2181 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2182 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372183 // mailing list archives. It also implicitly enables the desktop GL
2184 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2185 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152186 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2187 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372188 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152189 }
[email protected]de17df392010-04-23 21:09:412190
[email protected]38d139d2011-07-14 00:38:432191 has_arb_robustness_ = context->HasExtension("GL_ARB_robustness");
2192
[email protected]e82fb792011-09-22 00:33:292193 if (!disallowed_features_.driver_bug_workarounds) {
[email protected]75c023c2011-08-22 23:54:512194#if defined(OS_MACOSX)
[email protected]a2a0fe762011-09-20 00:59:122195 const char* vendor_str = reinterpret_cast<const char*>(
2196 glGetString(GL_VENDOR));
2197 needs_mac_nvidia_driver_workaround_ =
2198 vendor_str && strstr(vendor_str, "NVIDIA");
2199 needs_glsl_built_in_function_emulation_ =
2200 vendor_str && (strstr(vendor_str, "ATI") || strstr(vendor_str, "AMD"));
2201#elif defined(OS_WIN)
2202 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
2203 needs_glsl_built_in_function_emulation_ = true;
[email protected]75c023c2011-08-22 23:54:512204#endif
[email protected]a2a0fe762011-09-20 00:59:122205 }
[email protected]75c023c2011-08-22 23:54:512206
[email protected]c2f8c8402010-12-06 18:07:242207 if (!InitializeShaderTranslator()) {
2208 return false;
[email protected]de17df392010-04-23 21:09:412209 }
[email protected]76a0ee102010-04-07 21:03:042210
[email protected]246a70452010-03-05 21:53:502211 return true;
[email protected]96449d2c2009-11-25 00:01:322212}
2213
[email protected]302ce6d2011-07-07 23:28:112214void GLES2DecoderImpl::UpdateCapabilities() {
2215 util_.set_num_compressed_texture_formats(
2216 validators_->compressed_texture_format.GetValues().size());
2217 util_.set_num_shader_binary_formats(
2218 validators_->shader_binary_format.GetValues().size());
2219}
2220
[email protected]c2f8c8402010-12-06 18:07:242221bool GLES2DecoderImpl::InitializeShaderTranslator() {
2222 // Re-check the state of use_shader_translator_ each time this is called.
2223 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:042224 (feature_info_->feature_flags().chromium_webglsl ||
2225 force_webgl_glsl_validation_) &&
[email protected]c2f8c8402010-12-06 18:07:242226 !use_shader_translator_) {
2227 use_shader_translator_ = true;
2228 }
2229 if (!use_shader_translator_) {
2230 return true;
2231 }
2232 ShBuiltInResources resources;
2233 ShInitBuiltInResources(&resources);
2234 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2235 resources.MaxVertexUniformVectors =
2236 group_->max_vertex_uniform_vectors();
2237 resources.MaxVaryingVectors = group_->max_varying_vectors();
2238 resources.MaxVertexTextureImageUnits =
2239 group_->max_vertex_texture_image_units();
2240 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2241 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2242 resources.MaxFragmentUniformVectors =
2243 group_->max_fragment_uniform_vectors();
2244 resources.MaxDrawBuffers = 1;
[email protected]f0d74742011-10-03 16:31:042245
2246 if (force_webgl_glsl_validation_) {
2247 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2248 } else {
2249 resources.OES_standard_derivatives =
2250 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
[email protected]e51bdf32011-11-23 22:21:462251 resources.ARB_texture_rectangle =
2252 feature_info_->feature_flags().arb_texture_rectangle ? 1 : 0;
[email protected]f0d74742011-10-03 16:31:042253 }
2254
[email protected]c2f8c8402010-12-06 18:07:242255 vertex_translator_.reset(new ShaderTranslator);
[email protected]f0d74742011-10-03 16:31:042256 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ||
2257 feature_info_->feature_flags().chromium_webglsl ?
2258 SH_WEBGL_SPEC : SH_GLES2_SPEC;
[email protected]a2a0fe762011-09-20 00:59:122259 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2260 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2261 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2262 ShaderTranslatorInterface::GlslBuiltInFunctionBehavior function_behavior =
2263 needs_glsl_built_in_function_emulation_ ?
2264 ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated :
2265 ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal;
[email protected]c2f8c8402010-12-06 18:07:242266 if (!vertex_translator_->Init(
[email protected]a2a0fe762011-09-20 00:59:122267 SH_VERTEX_SHADER, shader_spec, &resources,
2268 implementation_type, function_behavior)) {
[email protected]c2f8c8402010-12-06 18:07:242269 LOG(ERROR) << "Could not initialize vertex shader translator.";
2270 Destroy();
2271 return false;
2272 }
2273 fragment_translator_.reset(new ShaderTranslator);
2274 if (!fragment_translator_->Init(
[email protected]a2a0fe762011-09-20 00:59:122275 SH_FRAGMENT_SHADER, shader_spec, &resources,
2276 implementation_type, function_behavior)) {
[email protected]c2f8c8402010-12-06 18:07:242277 LOG(ERROR) << "Could not initialize fragment shader translator.";
2278 Destroy();
2279 return false;
2280 }
2281 return true;
2282}
2283
[email protected]ae51d192010-04-27 00:48:032284bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472285 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032286 if (GetBufferInfo(client_ids[ii])) {
2287 return false;
2288 }
2289 }
2290 scoped_array<GLuint> service_ids(new GLuint[n]);
2291 glGenBuffersARB(n, service_ids.get());
2292 for (GLsizei ii = 0; ii < n; ++ii) {
2293 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2294 }
2295 return true;
2296}
2297
2298bool GLES2DecoderImpl::GenFramebuffersHelper(
2299 GLsizei n, const GLuint* client_ids) {
2300 for (GLsizei ii = 0; ii < n; ++ii) {
2301 if (GetFramebufferInfo(client_ids[ii])) {
2302 return false;
2303 }
2304 }
2305 scoped_array<GLuint> service_ids(new GLuint[n]);
2306 glGenFramebuffersEXT(n, service_ids.get());
2307 for (GLsizei ii = 0; ii < n; ++ii) {
2308 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2309 }
2310 return true;
2311}
2312
2313bool GLES2DecoderImpl::GenRenderbuffersHelper(
2314 GLsizei n, const GLuint* client_ids) {
2315 for (GLsizei ii = 0; ii < n; ++ii) {
2316 if (GetRenderbufferInfo(client_ids[ii])) {
2317 return false;
2318 }
2319 }
2320 scoped_array<GLuint> service_ids(new GLuint[n]);
2321 glGenRenderbuffersEXT(n, service_ids.get());
2322 for (GLsizei ii = 0; ii < n; ++ii) {
2323 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2324 }
2325 return true;
2326}
2327
2328bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2329 for (GLsizei ii = 0; ii < n; ++ii) {
2330 if (GetTextureInfo(client_ids[ii])) {
2331 return false;
2332 }
2333 }
2334 scoped_array<GLuint> service_ids(new GLuint[n]);
2335 glGenTextures(n, service_ids.get());
2336 for (GLsizei ii = 0; ii < n; ++ii) {
2337 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2338 }
2339 return true;
2340}
2341
2342void GLES2DecoderImpl::DeleteBuffersHelper(
2343 GLsizei n, const GLuint* client_ids) {
2344 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102345 BufferManager::BufferInfo* buffer = GetBufferInfo(client_ids[ii]);
2346 if (buffer && !buffer->IsDeleted()) {
[email protected]3757a372012-01-19 05:20:442347 vertex_attrib_manager_->Unbind(buffer);
[email protected]a0b78dc2011-11-11 10:43:102348 if (bound_array_buffer_ == buffer) {
2349 bound_array_buffer_ = NULL;
2350 }
2351 if (bound_element_array_buffer_ == buffer) {
2352 bound_element_array_buffer_ = NULL;
2353 }
2354 GLuint service_id = buffer->service_id();
[email protected]ae51d192010-04-27 00:48:032355 glDeleteBuffersARB(1, &service_id);
2356 RemoveBufferInfo(client_ids[ii]);
2357 }
[email protected]a93bb842010-02-16 23:03:472358 }
[email protected]07f54fcc2009-12-22 02:46:302359}
2360
[email protected]ae51d192010-04-27 00:48:032361void GLES2DecoderImpl::DeleteFramebuffersHelper(
2362 GLsizei n, const GLuint* client_ids) {
[email protected]b177ae22011-11-01 03:29:112363 bool supports_seperate_framebuffer_binds =
2364 feature_info_->feature_flags().chromium_framebuffer_multisample;
2365
[email protected]a25fa872010-03-25 02:57:582366 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102367 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ae51d192010-04-27 00:48:032368 GetFramebufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102369 if (framebuffer && !framebuffer->IsDeleted()) {
2370 if (framebuffer == bound_draw_framebuffer_) {
[email protected]297ca1c2011-06-20 23:08:462371 bound_draw_framebuffer_ = NULL;
2372 state_dirty_ = true;
[email protected]b177ae22011-11-01 03:29:112373 GLenum target = supports_seperate_framebuffer_binds ?
2374 GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER;
2375 glBindFramebufferEXT(target, GetBackbufferServiceId());
2376 }
[email protected]a0b78dc2011-11-11 10:43:102377 if (framebuffer == bound_read_framebuffer_) {
[email protected]b177ae22011-11-01 03:29:112378 bound_read_framebuffer_ = NULL;
2379 GLenum target = supports_seperate_framebuffer_binds ?
2380 GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER;
2381 glBindFramebufferEXT(target, GetBackbufferServiceId());
[email protected]297ca1c2011-06-20 23:08:462382 }
[email protected]a0b78dc2011-11-11 10:43:102383 GLuint service_id = framebuffer->service_id();
[email protected]ae51d192010-04-27 00:48:032384 glDeleteFramebuffersEXT(1, &service_id);
2385 RemoveFramebufferInfo(client_ids[ii]);
2386 }
[email protected]a25fa872010-03-25 02:57:582387 }
[email protected]07f54fcc2009-12-22 02:46:302388}
2389
[email protected]ae51d192010-04-27 00:48:032390void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2391 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102392 bool supports_seperate_framebuffer_binds =
2393 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a25fa872010-03-25 02:57:582394 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102395 RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]ae51d192010-04-27 00:48:032396 GetRenderbufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102397 if (renderbuffer && !renderbuffer->IsDeleted()) {
2398 if (bound_renderbuffer_ == renderbuffer) {
2399 bound_renderbuffer_ = NULL;
2400 }
2401 // Unbind from current framebuffers.
2402 if (supports_seperate_framebuffer_binds) {
2403 if (bound_read_framebuffer_) {
2404 bound_read_framebuffer_->UnbindRenderbuffer(
2405 GL_READ_FRAMEBUFFER, renderbuffer);
2406 }
2407 if (bound_draw_framebuffer_) {
2408 bound_draw_framebuffer_->UnbindRenderbuffer(
2409 GL_DRAW_FRAMEBUFFER, renderbuffer);
2410 }
2411 } else {
2412 if (bound_draw_framebuffer_) {
2413 bound_draw_framebuffer_->UnbindRenderbuffer(
2414 GL_FRAMEBUFFER, renderbuffer);
2415 }
2416 }
[email protected]297ca1c2011-06-20 23:08:462417 state_dirty_ = true;
[email protected]a0b78dc2011-11-11 10:43:102418 GLuint service_id = renderbuffer->service_id();
[email protected]ae51d192010-04-27 00:48:032419 glDeleteRenderbuffersEXT(1, &service_id);
2420 RemoveRenderbufferInfo(client_ids[ii]);
2421 }
[email protected]a25fa872010-03-25 02:57:582422 }
[email protected]07f54fcc2009-12-22 02:46:302423}
2424
[email protected]ae51d192010-04-27 00:48:032425void GLES2DecoderImpl::DeleteTexturesHelper(
2426 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102427 bool supports_seperate_framebuffer_binds =
2428 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a93bb842010-02-16 23:03:472429 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102430 TextureManager::TextureInfo* texture = GetTextureInfo(client_ids[ii]);
2431 if (texture && !texture->IsDeleted()) {
2432 if (texture->IsAttachedToFramebuffer()) {
[email protected]297ca1c2011-06-20 23:08:462433 state_dirty_ = true;
2434 }
[email protected]a0b78dc2011-11-11 10:43:102435 // Unbind texture from texture units.
2436 for (size_t jj = 0; jj < group_->max_texture_units(); ++jj) {
2437 texture_units_[ii].Unbind(texture);
2438 }
2439 // Unbind from current framebuffers.
2440 if (supports_seperate_framebuffer_binds) {
2441 if (bound_read_framebuffer_) {
2442 bound_read_framebuffer_->UnbindTexture(GL_READ_FRAMEBUFFER, texture);
2443 }
2444 if (bound_draw_framebuffer_) {
2445 bound_draw_framebuffer_->UnbindTexture(GL_DRAW_FRAMEBUFFER, texture);
2446 }
2447 } else {
2448 if (bound_draw_framebuffer_) {
2449 bound_draw_framebuffer_->UnbindTexture(GL_FRAMEBUFFER, texture);
2450 }
2451 }
2452 GLuint service_id = texture->service_id();
2453 if (texture->IsStreamTexture() && stream_texture_manager_) {
[email protected]b0af4f52011-09-28 22:04:422454 stream_texture_manager_->DestroyStreamTexture(service_id);
2455 }
[email protected]e51bdf32011-11-23 22:21:462456#if defined(OS_MACOSX)
2457 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2458 ReleaseIOSurfaceForTexture(service_id);
2459 }
2460#endif
[email protected]5f4f2a732011-07-30 00:47:552461 glDeleteTextures(1, &service_id);
[email protected]ae51d192010-04-27 00:48:032462 RemoveTextureInfo(client_ids[ii]);
2463 }
[email protected]a93bb842010-02-16 23:03:472464 }
[email protected]07f54fcc2009-12-22 02:46:302465}
2466
[email protected]43f28f832010-02-03 02:28:482467// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322468
[email protected]eb54a562010-01-20 21:55:182469bool GLES2DecoderImpl::MakeCurrent() {
[email protected]38d139d2011-07-14 00:38:432470 bool result = context_.get() ? context_->MakeCurrent(surface_.get()) : false;
2471 if (result && WasContextLost()) {
2472 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2473 result = false;
2474 }
2475
2476 return result;
[email protected]eb54a562010-01-20 21:55:182477}
2478
[email protected]a96a6022011-11-04 00:58:122479void GLES2DecoderImpl::ReleaseCurrent() {
2480 if (context_.get())
2481 context_->ReleaseCurrent(surface_.get());
2482}
2483
[email protected]8e3e0662010-08-23 18:46:302484void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
[email protected]0d6bfdc2011-11-02 01:32:202485 RenderbufferManager::RenderbufferInfo* renderbuffer =
2486 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
[email protected]8e3e0662010-08-23 18:46:302487 glBindRenderbufferEXT(
[email protected]0d6bfdc2011-11-02 01:32:202488 GL_RENDERBUFFER, renderbuffer ? renderbuffer->service_id() : 0);
[email protected]8e3e0662010-08-23 18:46:302489}
2490
2491static void RebindCurrentFramebuffer(
2492 GLenum target,
2493 FramebufferManager::FramebufferInfo* info,
[email protected]a3783712012-01-20 22:18:242494 GLuint back_buffer_service_id) {
[email protected]8e3e0662010-08-23 18:46:302495 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462496
[email protected]a3783712012-01-20 22:18:242497 if (framebuffer_id == 0) {
2498 framebuffer_id = back_buffer_service_id;
[email protected]8e3e0662010-08-23 18:46:302499 }
[email protected]297ca1c2011-06-20 23:08:462500
[email protected]8e3e0662010-08-23 18:46:302501 glBindFramebufferEXT(target, framebuffer_id);
2502}
2503
2504void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]297ca1c2011-06-20 23:08:462505 state_dirty_ = true;
2506
[email protected]a3ded6d2010-10-19 06:44:392507 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302508 RebindCurrentFramebuffer(
2509 GL_FRAMEBUFFER,
2510 bound_draw_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242511 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302512 } else {
2513 RebindCurrentFramebuffer(
2514 GL_READ_FRAMEBUFFER_EXT,
2515 bound_read_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242516 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302517 RebindCurrentFramebuffer(
2518 GL_DRAW_FRAMEBUFFER_EXT,
2519 bound_draw_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242520 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302521 }
2522}
2523
2524void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2525 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2526 GLuint last_id;
2527 if (info.bound_texture_2d) {
2528 last_id = info.bound_texture_2d->service_id();
2529 } else {
2530 last_id = 0;
2531 }
2532
2533 glBindTexture(GL_TEXTURE_2D, last_id);
2534 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2535}
2536
[email protected]0d6bfdc2011-11-02 01:32:202537bool GLES2DecoderImpl::CheckFramebufferValid(
2538 FramebufferManager::FramebufferInfo* framebuffer,
2539 GLenum target, const char* func_name) {
[email protected]a0b78dc2011-11-11 10:43:102540 if (!framebuffer) {
[email protected]0d6bfdc2011-11-02 01:32:202541 return true;
2542 }
2543
[email protected]968351b2011-12-20 08:26:512544 if (framebuffer_manager()->IsComplete(framebuffer)) {
2545 return true;
2546 }
2547
[email protected]0d6bfdc2011-11-02 01:32:202548 GLenum completeness = framebuffer->IsPossiblyComplete();
2549 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
2550 SetGLError(
2551 GL_INVALID_FRAMEBUFFER_OPERATION,
2552 (std::string(func_name) + " framebuffer incomplete").c_str());
[email protected]3a03a8f2011-03-19 00:51:272553 return false;
2554 }
[email protected]0d6bfdc2011-11-02 01:32:202555
2556 // Are all the attachments cleared?
2557 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2558 texture_manager()->HaveUnclearedMips()) {
2559 if (!framebuffer->IsCleared()) {
2560 // Can we clear them?
2561 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2562 SetGLError(
2563 GL_INVALID_FRAMEBUFFER_OPERATION,
2564 (std::string(func_name) +
2565 " framebuffer incomplete (clear)").c_str());
2566 return false;
2567 }
2568 ClearUnclearedAttachments(target, framebuffer);
2569 }
2570 }
2571
[email protected]968351b2011-12-20 08:26:512572 if (!framebuffer_manager()->IsComplete(framebuffer)) {
2573 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2574 SetGLError(
2575 GL_INVALID_FRAMEBUFFER_OPERATION,
2576 (std::string(func_name) +
2577 " framebuffer incomplete (check)").c_str());
2578 return false;
2579 }
2580 framebuffer_manager()->MarkAsComplete(framebuffer);
2581 }
2582
[email protected]0d6bfdc2011-11-02 01:32:202583 // NOTE: At this point we don't know if the framebuffer is complete but
2584 // we DO know that everything that needs to be cleared has been cleared.
[email protected]3a03a8f2011-03-19 00:51:272585 return true;
2586}
2587
[email protected]0d6bfdc2011-11-02 01:32:202588bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
2589 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
2590 return CheckFramebufferValid(
2591 bound_draw_framebuffer_, GL_FRAMEBUFFER_EXT, func_name);
2592 }
2593 return CheckFramebufferValid(
2594 bound_draw_framebuffer_, GL_DRAW_FRAMEBUFFER_EXT, func_name) &&
2595 CheckFramebufferValid(
2596 bound_read_framebuffer_, GL_READ_FRAMEBUFFER_EXT, func_name);
2597}
2598
[email protected]8e3e0662010-08-23 18:46:302599gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
[email protected]0d6bfdc2011-11-02 01:32:202600 FramebufferManager::FramebufferInfo* framebuffer =
2601 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2602 if (framebuffer != NULL) {
[email protected]9edc6b22010-12-23 02:00:262603 const FramebufferManager::FramebufferInfo::Attachment* attachment =
[email protected]0d6bfdc2011-11-02 01:32:202604 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
[email protected]9edc6b22010-12-23 02:00:262605 if (attachment) {
2606 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502607 }
[email protected]9edc6b22010-12-23 02:00:262608 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022609 } else if (offscreen_target_frame_buffer_.get()) {
2610 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352611 } else {
[email protected]f62a5ab2011-05-23 20:34:152612 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022613 }
[email protected]246a70452010-03-05 21:53:502614}
2615
[email protected]9edc6b22010-12-23 02:00:262616GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202617 FramebufferManager::FramebufferInfo* framebuffer =
2618 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2619 if (framebuffer != NULL) {
2620 return framebuffer->GetColorAttachmentFormat();
[email protected]297ca1c2011-06-20 23:08:462621 } else if (offscreen_target_frame_buffer_.get()) {
2622 return offscreen_target_color_format_;
2623 } else {
2624 return back_buffer_color_format_;
2625 }
2626}
2627
2628GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202629 FramebufferManager::FramebufferInfo* framebuffer =
2630 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
2631 if (framebuffer != NULL) {
2632 return framebuffer->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262633 } else if (offscreen_target_frame_buffer_.get()) {
2634 return offscreen_target_color_format_;
2635 } else {
[email protected]32fe9aa2011-01-21 23:47:132636 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262637 }
2638}
2639
[email protected]9a5afa432011-07-22 18:16:392640void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]34ff8b0c2010-10-01 20:06:022641 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582642 // Update the info about the offscreen saved color texture in the parent.
2643 // The reference to the parent is a weak pointer and will become null if the
2644 // parent is later destroyed.
[email protected]262d7aa2010-12-03 22:07:292645 TextureManager* parent_texture_manager = parent_->texture_manager();
[email protected]262d7aa2010-12-03 22:07:292646 parent_texture_manager->SetLevelInfo(
[email protected]8a61d872012-01-20 12:43:562647 offscreen_saved_color_texture_info_,
[email protected]ef526492010-06-02 23:12:252648 GL_TEXTURE_2D,
2649 0, // level
2650 GL_RGBA,
[email protected]799b4b22011-08-22 17:09:592651 offscreen_size_.width(),
2652 offscreen_size_.height(),
[email protected]ef526492010-06-02 23:12:252653 1, // depth
2654 0, // border
2655 GL_RGBA,
[email protected]0d6bfdc2011-11-02 01:32:202656 GL_UNSIGNED_BYTE,
2657 true);
[email protected]262d7aa2010-12-03 22:07:292658 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562659 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042660 GL_TEXTURE_MAG_FILTER,
2661 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292662 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562663 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042664 GL_TEXTURE_MIN_FILTER,
2665 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292666 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562667 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042668 GL_TEXTURE_WRAP_S,
2669 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292670 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562671 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042672 GL_TEXTURE_WRAP_T,
2673 GL_CLAMP_TO_EDGE);
[email protected]8a61d872012-01-20 12:43:562674 } else {
2675 offscreen_saved_color_texture_info_ = NULL;
[email protected]0c8c9d22010-06-25 17:36:392676 }
[email protected]6217d392010-03-25 22:08:352677}
2678
[email protected]799b4b22011-08-22 17:09:592679void GLES2DecoderImpl::SetResizeCallback(
[email protected]9d37f062011-11-22 01:24:522680 const base::Callback<void(gfx::Size)>& callback) {
2681 resize_callback_ = callback;
[email protected]7ff86b92010-11-25 17:50:002682}
2683
[email protected]6b6e7ee2011-12-13 08:04:522684void GLES2DecoderImpl::SetMsgCallback(const MsgCallback& callback) {
2685 msg_callback_ = callback;
2686}
2687
[email protected]b0af4f52011-09-28 22:04:422688void GLES2DecoderImpl::SetStreamTextureManager(StreamTextureManager* manager) {
2689 stream_texture_manager_ = manager;
2690}
2691
[email protected]1318e922010-09-17 22:03:162692bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2693 uint32* service_texture_id) {
2694 TextureManager::TextureInfo* texture =
2695 texture_manager()->GetTextureInfo(client_texture_id);
2696 if (texture) {
2697 *service_texture_id = texture->service_id();
2698 return true;
2699 }
2700 return false;
2701}
2702
[email protected]96449d2c2009-11-25 00:01:322703void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392704 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052705
[email protected]c826d732012-02-09 04:40:262706 ChildList children = children_;
2707 for (ChildList::iterator it = children.begin(); it != children.end(); ++it)
2708 (*it)->SetParent(NULL, 0);
2709 DCHECK(children_.empty());
[email protected]3c644d82011-06-20 19:58:242710 SetParent(NULL, 0);
2711
[email protected]80eb6b52012-01-19 00:14:412712 // Unbind everything.
[email protected]3757a372012-01-19 05:20:442713 vertex_attrib_manager_.reset();
[email protected]80eb6b52012-01-19 00:14:412714 texture_units_.reset();
2715 bound_array_buffer_ = NULL;
2716 bound_element_array_buffer_ = NULL;
2717 current_program_ = NULL;
2718 bound_read_framebuffer_ = NULL;
2719 bound_draw_framebuffer_ = NULL;
2720 bound_renderbuffer_ = NULL;
2721
[email protected]eadc96792010-10-27 19:39:392722 if (have_context) {
[email protected]ca488e12010-12-13 20:06:142723 if (current_program_) {
2724 program_manager()->UnuseProgram(shader_manager(), current_program_);
2725 current_program_ = NULL;
2726 }
2727
[email protected]b1122982010-05-17 23:04:242728 if (attrib_0_buffer_id_) {
2729 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2730 }
[email protected]8fbedc02010-11-18 18:43:402731 if (fixed_attrib_buffer_id_) {
2732 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2733 }
[email protected]b1122982010-05-17 23:04:242734
[email protected]97872062010-11-03 19:07:052735 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542736 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052737 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542738 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052739 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022740 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052741 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152742 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052743 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152744 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052745 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022746 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052747 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542748 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:272749 if (offscreen_resolved_frame_buffer_.get())
2750 offscreen_resolved_frame_buffer_->Destroy();
2751 if (offscreen_resolved_color_texture_.get())
2752 offscreen_resolved_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052753 } else {
2754 if (offscreen_target_frame_buffer_.get())
2755 offscreen_target_frame_buffer_->Invalidate();
2756 if (offscreen_target_color_texture_.get())
2757 offscreen_target_color_texture_->Invalidate();
2758 if (offscreen_target_color_render_buffer_.get())
2759 offscreen_target_color_render_buffer_->Invalidate();
2760 if (offscreen_target_depth_render_buffer_.get())
2761 offscreen_target_depth_render_buffer_->Invalidate();
2762 if (offscreen_target_stencil_render_buffer_.get())
2763 offscreen_target_stencil_render_buffer_->Invalidate();
2764 if (offscreen_saved_frame_buffer_.get())
2765 offscreen_saved_frame_buffer_->Invalidate();
2766 if (offscreen_saved_color_texture_.get())
2767 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:272768 if (offscreen_resolved_frame_buffer_.get())
2769 offscreen_resolved_frame_buffer_->Invalidate();
2770 if (offscreen_resolved_color_texture_.get())
2771 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022772 }
[email protected]97872062010-11-03 19:07:052773
[email protected]1871a092011-10-10 21:46:422774 if (group_) {
2775 group_->Destroy(have_context);
2776 group_ = NULL;
2777 }
[email protected]3ae019382011-10-05 19:42:412778
[email protected]fe871662011-06-16 20:43:052779 if (context_.get()) {
2780 context_->ReleaseCurrent(NULL);
[email protected]79311e82011-09-20 00:40:502781 context_ = NULL;
[email protected]fe871662011-06-16 20:43:052782 }
[email protected]0fc35742011-04-13 17:57:542783
[email protected]97872062010-11-03 19:07:052784 offscreen_target_frame_buffer_.reset();
2785 offscreen_target_color_texture_.reset();
2786 offscreen_target_color_render_buffer_.reset();
2787 offscreen_target_depth_render_buffer_.reset();
2788 offscreen_target_stencil_render_buffer_.reset();
2789 offscreen_saved_frame_buffer_.reset();
2790 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:272791 offscreen_resolved_frame_buffer_.reset();
2792 offscreen_resolved_color_texture_.reset();
[email protected]e51bdf32011-11-23 22:21:462793
2794#if defined(OS_MACOSX)
2795 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
2796 it != texture_to_io_surface_map_.end(); ++it) {
2797 CFRelease(it->second);
2798 }
2799 texture_to_io_surface_map_.clear();
2800#endif
[email protected]96449d2c2009-11-25 00:01:322801}
2802
[email protected]3c644d82011-06-20 19:58:242803bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
2804 uint32 new_parent_texture_id) {
[email protected]9a5afa432011-07-22 18:16:392805 if (!offscreen_saved_color_texture_.get())
2806 return false;
2807
[email protected]3c644d82011-06-20 19:58:242808 // Remove the saved frame buffer mapping from the parent decoder. The
2809 // parent pointer is a weak pointer so it will be null if the parent has
2810 // already been destroyed.
2811 if (parent_) {
[email protected]c826d732012-02-09 04:40:262812 ChildList::iterator it = std::find(
2813 parent_->children_.begin(),
2814 parent_->children_.end(),
2815 this);
2816 DCHECK(it != parent_->children_.end());
2817 parent_->children_.erase(it);
[email protected]3c644d82011-06-20 19:58:242818 // First check the texture has been mapped into the parent. This might not
2819 // be the case if initialization failed midway through.
2820 GLuint service_id = offscreen_saved_color_texture_->id();
2821 GLuint client_id = 0;
2822 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
[email protected]80eb6b52012-01-19 00:14:412823 parent_->texture_manager()->RemoveTextureInfo(client_id);
[email protected]3c644d82011-06-20 19:58:242824 }
2825 }
2826
2827 GLES2DecoderImpl* new_parent_impl = static_cast<GLES2DecoderImpl*>(
2828 new_parent);
2829 if (new_parent_impl) {
[email protected]c826d732012-02-09 04:40:262830#ifndef NDEBUG
2831 ChildList::iterator it = std::find(
2832 new_parent_impl->children_.begin(),
2833 new_parent_impl->children_.end(),
2834 this);
2835 DCHECK(it == new_parent_impl->children_.end());
2836#endif
2837 new_parent_impl->children_.push_back(this);
[email protected]3c644d82011-06-20 19:58:242838 // Map the ID of the saved offscreen texture into the parent so that
2839 // it can reference it.
2840 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]98687862011-07-11 23:31:302841
2842 // Replace texture info when ID is already in use by parent.
2843 if (new_parent_impl->texture_manager()->GetTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412844 new_parent_texture_id))
[email protected]98687862011-07-11 23:31:302845 new_parent_impl->texture_manager()->RemoveTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412846 new_parent_texture_id);
[email protected]98687862011-07-11 23:31:302847
[email protected]8a61d872012-01-20 12:43:562848 offscreen_saved_color_texture_info_ =
[email protected]5f4f2a732011-07-30 00:47:552849 new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id);
[email protected]8a61d872012-01-20 12:43:562850 offscreen_saved_color_texture_info_->SetNotOwned();
2851 new_parent_impl->texture_manager()->
2852 SetInfoTarget(offscreen_saved_color_texture_info_, GL_TEXTURE_2D);
[email protected]3c644d82011-06-20 19:58:242853
2854 parent_ = new_parent_impl->AsWeakPtr();
[email protected]9a5afa432011-07-22 18:16:392855
2856 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:242857 } else {
2858 parent_.reset();
[email protected]8a61d872012-01-20 12:43:562859 offscreen_saved_color_texture_info_ = NULL;
[email protected]3c644d82011-06-20 19:58:242860 }
2861
2862 return true;
2863}
2864
[email protected]1078f912011-12-23 13:12:142865void GLES2DecoderImpl::UpdateBackbufferMemoryAccounting() {
2866 size_t total = 0;
2867 if (offscreen_target_frame_buffer_.get()) {
2868 if (offscreen_target_color_texture_.get()) {
2869 total += offscreen_target_color_texture_->estimated_size();
2870 }
2871 if (offscreen_target_color_render_buffer_.get()) {
2872 total += offscreen_target_color_render_buffer_->estimated_size();
2873 }
2874 if (offscreen_target_depth_render_buffer_.get()) {
2875 total += offscreen_target_depth_render_buffer_->estimated_size();
2876 }
2877 if (offscreen_target_stencil_render_buffer_.get()) {
2878 total += offscreen_target_stencil_render_buffer_->estimated_size();
2879 }
2880 if (offscreen_saved_color_texture_.get()) {
2881 total += offscreen_saved_color_texture_->estimated_size();
2882 }
2883 if (offscreen_resolved_color_texture_.get()) {
2884 total += offscreen_resolved_color_texture_->estimated_size();
2885 }
2886 } else {
2887 gfx::Size size = surface_->GetSize();
2888 total += size.width() * size.height() *
2889 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_);
2890 }
2891 TRACE_COUNTER_ID1(
2892 "GLES2DecoderImpl", "BackbufferMemory", this, total);
2893}
2894
[email protected]799b4b22011-08-22 17:09:592895bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2896 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
2897 if (!is_offscreen) {
2898 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
2899 << " with an onscreen framebuffer.";
2900 return false;
2901 }
2902
2903 if (offscreen_size_ == size)
2904 return true;
2905
2906 offscreen_size_ = size;
2907 int w = offscreen_size_.width();
2908 int h = offscreen_size_.height();
2909 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
2910 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2911 << "to allocate storage due to excessive dimensions.";
2912 return false;
2913 }
2914
2915 // Reallocate the offscreen target buffers.
2916 DCHECK(offscreen_target_color_format_);
2917 if (IsOffscreenBufferMultisampled()) {
2918 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2919 offscreen_size_, offscreen_target_color_format_,
2920 offscreen_target_samples_)) {
2921 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2922 << "to allocate storage for offscreen target color buffer.";
2923 return false;
2924 }
2925 } else {
2926 if (!offscreen_target_color_texture_->AllocateStorage(
2927 offscreen_size_, offscreen_target_color_format_)) {
2928 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2929 << "to allocate storage for offscreen target color texture.";
2930 return false;
2931 }
2932 }
2933 if (offscreen_target_depth_format_ &&
2934 !offscreen_target_depth_render_buffer_->AllocateStorage(
2935 offscreen_size_, offscreen_target_depth_format_,
2936 offscreen_target_samples_)) {
2937 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2938 << "to allocate storage for offscreen target depth buffer.";
2939 return false;
2940 }
2941 if (offscreen_target_stencil_format_ &&
2942 !offscreen_target_stencil_render_buffer_->AllocateStorage(
2943 offscreen_size_, offscreen_target_stencil_format_,
2944 offscreen_target_samples_)) {
2945 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2946 << "to allocate storage for offscreen target stencil buffer.";
2947 return false;
2948 }
[email protected]1078f912011-12-23 13:12:142949 UpdateBackbufferMemoryAccounting();
[email protected]799b4b22011-08-22 17:09:592950
2951 // Attach the offscreen target buffers to the target frame buffer.
2952 if (IsOffscreenBufferMultisampled()) {
2953 offscreen_target_frame_buffer_->AttachRenderBuffer(
2954 GL_COLOR_ATTACHMENT0,
2955 offscreen_target_color_render_buffer_.get());
2956 } else {
2957 offscreen_target_frame_buffer_->AttachRenderTexture(
2958 offscreen_target_color_texture_.get());
2959 }
2960 if (offscreen_target_depth_format_) {
2961 offscreen_target_frame_buffer_->AttachRenderBuffer(
2962 GL_DEPTH_ATTACHMENT,
2963 offscreen_target_depth_render_buffer_.get());
2964 }
2965 const bool packed_depth_stencil =
2966 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2967 if (packed_depth_stencil) {
2968 offscreen_target_frame_buffer_->AttachRenderBuffer(
2969 GL_STENCIL_ATTACHMENT,
2970 offscreen_target_depth_render_buffer_.get());
2971 } else if (offscreen_target_stencil_format_) {
2972 offscreen_target_frame_buffer_->AttachRenderBuffer(
2973 GL_STENCIL_ATTACHMENT,
2974 offscreen_target_stencil_render_buffer_.get());
2975 }
2976
2977 if (offscreen_target_frame_buffer_->CheckStatus() !=
2978 GL_FRAMEBUFFER_COMPLETE) {
2979 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2980 << "because offscreen FBO was incomplete.";
2981 return false;
2982 }
2983
2984 // Clear the target frame buffer.
2985 {
2986 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
2987 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2988 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
2989 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2990 glClearStencil(0);
2991 glStencilMaskSeparate(GL_FRONT, -1);
2992 glStencilMaskSeparate(GL_BACK, -1);
2993 glClearDepth(0);
2994 glDepthMask(GL_TRUE);
2995 glDisable(GL_SCISSOR_TEST);
2996 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2997 RestoreClearState();
2998 }
[email protected]d85ef76d2011-09-08 22:21:432999
3000 // Destroy the offscreen resolved framebuffers.
3001 if (offscreen_resolved_frame_buffer_.get())
3002 offscreen_resolved_frame_buffer_->Destroy();
3003 if (offscreen_resolved_color_texture_.get())
3004 offscreen_resolved_color_texture_->Destroy();
3005 offscreen_resolved_color_texture_.reset();
3006 offscreen_resolved_frame_buffer_.reset();
3007
[email protected]799b4b22011-08-22 17:09:593008 return true;
[email protected]6217d392010-03-25 22:08:353009}
3010
[email protected]799b4b22011-08-22 17:09:593011error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3012 uint32 immediate_data_size, const gles2::ResizeCHROMIUM& c) {
3013 GLuint width = static_cast<GLuint>(c.width);
3014 GLuint height = static_cast<GLuint>(c.height);
3015 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
[email protected]a0d989162011-11-22 13:15:073016#if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3017 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
[email protected]7ff86b92010-11-25 17:50:003018 // Make sure that we are done drawing to the back buffer before resizing.
3019 glFinish();
3020#endif
[email protected]799b4b22011-08-22 17:09:593021 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3022 if (is_offscreen) {
3023 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height)))
3024 return error::kLostContext;
[email protected]7ff86b92010-11-25 17:50:003025 }
[email protected]799b4b22011-08-22 17:09:593026
[email protected]9d37f062011-11-22 01:24:523027 if (!resize_callback_.is_null()) {
3028 resize_callback_.Run(gfx::Size(width, height));
[email protected]c777de52011-09-09 23:08:563029 DCHECK(context_->IsCurrent(surface_.get()));
3030 if (!context_->IsCurrent(surface_.get()))
[email protected]658f7562011-09-09 05:24:053031 return error::kLostContext;
[email protected]658f7562011-09-09 05:24:053032 }
[email protected]799b4b22011-08-22 17:09:593033
[email protected]1078f912011-12-23 13:12:143034 UpdateBackbufferMemoryAccounting();
3035
[email protected]799b4b22011-08-22 17:09:593036 return error::kNoError;
[email protected]43ecf372010-11-16 19:19:393037}
3038
[email protected]96449d2c2009-11-25 00:01:323039const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3040 if (command_id > kStartPoint && command_id < kNumCommands) {
3041 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3042 }
3043 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3044}
3045
3046// Decode command with its arguments, and call the corresponding GL function.
3047// Note: args is a pointer to the command buffer. As such, it could be changed
3048// by a (malicious) client at any time, so if validation has to happen, it
3049// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:143050error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:323051 unsigned int command,
3052 unsigned int arg_count,
3053 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:143054 error::Error result = error::kNoError;
[email protected]e844ae22012-01-14 03:36:263055 if (log_commands()) {
[email protected]4297cbe2011-11-03 18:04:003056 LOG(INFO) << "[" << this << "]" << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193057 }
[email protected]96449d2c2009-11-25 00:01:323058 unsigned int command_index = command - kStartPoint - 1;
3059 if (command_index < arraysize(g_command_info)) {
3060 const CommandInfo& info = g_command_info[command_index];
3061 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3062 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3063 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:193064 uint32 immediate_data_size =
3065 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:323066 switch (command) {
3067 #define GLES2_CMD_OP(name) \
3068 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:193069 result = Handle ## name( \
3070 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:323071 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:193072 break; \
[email protected]96449d2c2009-11-25 00:01:323073
3074 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:323075 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:383076 }
3077 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:303078 GLenum error;
3079 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]e844ae22012-01-14 03:36:263080 SetGLError(error, "GL error from driver");
3081 LOG(INFO) << "[" << this << "]"
3082 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3083 << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193084 }
[email protected]96449d2c2009-11-25 00:01:323085 }
3086 } else {
[email protected]f7a64ee2010-02-01 22:24:143087 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:323088 }
[email protected]b9849abf2009-11-25 19:13:193089 } else {
3090 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:323091 }
[email protected]a3a93e7b2010-08-28 00:48:563092 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3093 result = current_decoder_error_;
3094 current_decoder_error_ = error::kNoError;
3095 }
[email protected]b9849abf2009-11-25 19:13:193096 return result;
[email protected]96449d2c2009-11-25 00:01:323097}
3098
[email protected]ae51d192010-04-27 00:48:033099void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
3100 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:503101}
3102
[email protected]ae51d192010-04-27 00:48:033103bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3104 if (GetProgramInfo(client_id)) {
3105 return false;
3106 }
[email protected]96449d2c2009-11-25 00:01:323107 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:033108 if (service_id != 0) {
3109 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:323110 }
[email protected]ae51d192010-04-27 00:48:033111 return true;
[email protected]96449d2c2009-11-25 00:01:323112}
3113
[email protected]ae51d192010-04-27 00:48:033114bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3115 if (GetShaderInfo(client_id)) {
3116 return false;
[email protected]96449d2c2009-11-25 00:01:323117 }
[email protected]ae51d192010-04-27 00:48:033118 GLuint service_id = glCreateShader(type);
3119 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:383120 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:033121 }
3122 return true;
[email protected]96449d2c2009-11-25 00:01:323123}
3124
[email protected]3916c97e2010-02-25 03:20:503125void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:453126 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]660858b2011-07-13 23:16:143127 if (texture_index >= group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:293128 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:503129 return;
3130 }
[email protected]36cef8ce2010-03-16 07:34:453131 active_texture_unit_ = texture_index;
3132 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:503133}
3134
[email protected]051b1372010-04-12 02:42:083135void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:503136 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083137 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033138 if (client_id != 0) {
3139 info = GetBufferInfo(client_id);
3140 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353141 if (!group_->bind_generates_resource()) {
3142 SetGLError(GL_INVALID_VALUE,
3143 "glBindBuffer: id not generated by glGenBuffers");
3144 return;
3145 }
3146
[email protected]ae51d192010-04-27 00:48:033147 // It's a new id so make a buffer info for it.
3148 glGenBuffersARB(1, &service_id);
3149 CreateBufferInfo(client_id, service_id);
3150 info = GetBufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573151 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103152 group_->GetIdAllocator(id_namespaces::kBuffers);
3153 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033154 }
[email protected]051b1372010-04-12 02:42:083155 }
[email protected]ae51d192010-04-27 00:48:033156 if (info) {
[email protected]4e8a5b122010-05-08 22:00:103157 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:293158 SetGLError(GL_INVALID_OPERATION,
3159 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:473160 return;
3161 }
[email protected]ae51d192010-04-27 00:48:033162 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:473163 }
[email protected]96449d2c2009-11-25 00:01:323164 switch (target) {
3165 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503166 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323167 break;
3168 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503169 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323170 break;
3171 default:
[email protected]a93bb842010-02-16 23:03:473172 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:323173 break;
3174 }
[email protected]051b1372010-04-12 02:42:083175 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:323176}
3177
[email protected]297ca1c2011-06-20 23:08:463178bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
3179 return (GLES2Util::GetChannelsForFormat(
3180 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3181}
3182
3183bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203184 FramebufferManager::FramebufferInfo* framebuffer =
3185 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3186 if (framebuffer) {
3187 return framebuffer->HasDepthAttachment();
[email protected]297ca1c2011-06-20 23:08:463188 }
3189 if (offscreen_target_frame_buffer_.get()) {
3190 return offscreen_target_depth_format_ != 0;
3191 }
3192 return back_buffer_has_depth_;
3193}
3194
3195bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203196 FramebufferManager::FramebufferInfo* framebuffer =
3197 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3198 if (framebuffer) {
3199 return framebuffer->HasStencilAttachment();
[email protected]297ca1c2011-06-20 23:08:463200 }
3201 if (offscreen_target_frame_buffer_.get()) {
3202 return offscreen_target_stencil_format_ != 0 ||
3203 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3204 }
3205 return back_buffer_has_stencil_;
3206}
3207
3208void GLES2DecoderImpl::ApplyDirtyState() {
3209 if (state_dirty_) {
3210 glColorMask(
3211 mask_red_, mask_green_, mask_blue_,
3212 mask_alpha_ && BoundFramebufferHasColorAttachmentWithAlpha());
3213 bool have_depth = BoundFramebufferHasDepthAttachment();
3214 glDepthMask(mask_depth_ && have_depth);
3215 EnableDisable(GL_DEPTH_TEST, enable_depth_test_ && have_depth);
3216 bool have_stencil = BoundFramebufferHasStencilAttachment();
3217 glStencilMaskSeparate(GL_FRONT, have_stencil ? mask_stencil_front_ : 0);
3218 glStencilMaskSeparate(GL_BACK, have_stencil ? mask_stencil_back_ : 0);
3219 EnableDisable(GL_STENCIL_TEST, enable_stencil_test_ && have_stencil);
3220 state_dirty_ = false;
3221 }
3222}
3223
[email protected]b177ae22011-11-01 03:29:113224GLuint GLES2DecoderImpl::GetBackbufferServiceId() {
3225 return (offscreen_target_frame_buffer_.get()) ?
3226 offscreen_target_frame_buffer_->id() :
3227 surface_->GetBackingFrameBufferObject();
3228}
3229
[email protected]051b1372010-04-12 02:42:083230void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3231 FramebufferManager::FramebufferInfo* info = NULL;
3232 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033233 if (client_id != 0) {
3234 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083235 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353236 if (!group_->bind_generates_resource()) {
3237 SetGLError(GL_INVALID_VALUE,
3238 "glBindFramebuffer: id not generated by glGenFramebuffers");
3239 return;
3240 }
3241
[email protected]ae51d192010-04-27 00:48:033242 // It's a new id so make a framebuffer info for it.
3243 glGenFramebuffersEXT(1, &service_id);
3244 CreateFramebufferInfo(client_id, service_id);
3245 info = GetFramebufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573246 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103247 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3248 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033249 } else {
3250 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083251 }
[email protected]06c8b082011-01-05 18:00:363252 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083253 }
[email protected]8e3e0662010-08-23 18:46:303254
3255 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
3256 bound_draw_framebuffer_ = info;
3257 }
3258 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
3259 bound_read_framebuffer_ = info;
3260 }
[email protected]6217d392010-03-25 22:08:353261
[email protected]297ca1c2011-06-20 23:08:463262 state_dirty_ = true;
3263
[email protected]b177ae22011-11-01 03:29:113264 // If we are rendering to the backbuffer get the FBO id for any simulated
3265 // backbuffer.
3266 if (info == NULL) {
3267 service_id = GetBackbufferServiceId();
[email protected]297ca1c2011-06-20 23:08:463268 }
[email protected]6217d392010-03-25 22:08:353269
[email protected]051b1372010-04-12 02:42:083270 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563271}
3272
[email protected]051b1372010-04-12 02:42:083273void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
3274 RenderbufferManager::RenderbufferInfo* info = NULL;
3275 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033276 if (client_id != 0) {
3277 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083278 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353279 if (!group_->bind_generates_resource()) {
3280 SetGLError(
3281 GL_INVALID_VALUE,
3282 "glBindRenderbuffer: id not generated by glGenRenderbuffers");
3283 return;
3284 }
3285
[email protected]ae51d192010-04-27 00:48:033286 // It's a new id so make a renderbuffer info for it.
3287 glGenRenderbuffersEXT(1, &service_id);
3288 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:103289 info = GetRenderbufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573290 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103291 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3292 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033293 } else {
3294 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083295 }
[email protected]06c8b082011-01-05 18:00:363296 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083297 }
3298 bound_renderbuffer_ = info;
3299 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563300}
3301
[email protected]051b1372010-04-12 02:42:083302void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033303 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083304 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033305 if (client_id != 0) {
3306 info = GetTextureInfo(client_id);
3307 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353308 if (!group_->bind_generates_resource()) {
3309 SetGLError(GL_INVALID_VALUE,
3310 "glBindTexture: id not generated by glGenTextures");
3311 return;
3312 }
3313
[email protected]ae51d192010-04-27 00:48:033314 // It's a new id so make a texture info for it.
3315 glGenTextures(1, &service_id);
[email protected]80eb6b52012-01-19 00:14:413316 DCHECK_NE(0u, service_id);
[email protected]ae51d192010-04-27 00:48:033317 CreateTextureInfo(client_id, service_id);
3318 info = GetTextureInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573319 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103320 group_->GetIdAllocator(id_namespaces::kTextures);
3321 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033322 }
3323 } else {
3324 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:083325 }
[email protected]ae51d192010-04-27 00:48:033326
[email protected]1958e0e2010-04-22 05:17:153327 // Check the texture exists
3328 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:033329 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:293330 SetGLError(GL_INVALID_OPERATION,
3331 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:153332 return;
3333 }
[email protected]b0af4f52011-09-28 22:04:423334 if (info->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
3335 SetGLError(GL_INVALID_OPERATION,
3336 "glBindTexture: illegal target for stream texture.");
3337 return;
3338 }
[email protected]1958e0e2010-04-22 05:17:153339 if (info->target() == 0) {
[email protected]80eb6b52012-01-19 00:14:413340 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:473341 }
[email protected]ae51d192010-04-27 00:48:033342 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:503343 TextureUnit& unit = texture_units_[active_texture_unit_];
3344 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:473345 switch (target) {
3346 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:503347 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:473348 break;
3349 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:503350 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:473351 break;
[email protected]61eeb33f2011-07-26 15:30:313352 case GL_TEXTURE_EXTERNAL_OES:
3353 unit.bound_texture_external_oes = info;
[email protected]b0af4f52011-09-28 22:04:423354 if (info->IsStreamTexture()) {
3355 DCHECK(stream_texture_manager_);
3356 StreamTexture* stream_tex =
3357 stream_texture_manager_->LookupStreamTexture(info->service_id());
3358 if (stream_tex)
3359 stream_tex->Update();
3360 }
[email protected]61eeb33f2011-07-26 15:30:313361 break;
[email protected]e51bdf32011-11-23 22:21:463362 case GL_TEXTURE_RECTANGLE_ARB:
3363 unit.bound_texture_rectangle_arb = info;
3364 break;
[email protected]a93bb842010-02-16 23:03:473365 default:
3366 NOTREACHED(); // Validation should prevent us getting here.
3367 break;
3368 }
3369}
3370
[email protected]07f54fcc2009-12-22 02:46:303371void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443372 if (vertex_attrib_manager_->Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:123373 if (index != 0 ||
3374 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:243375 glDisableVertexAttribArray(index);
3376 }
[email protected]07f54fcc2009-12-22 02:46:303377 } else {
[email protected]8eee29c2010-04-29 03:38:293378 SetGLError(GL_INVALID_VALUE,
3379 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:303380 }
3381}
3382
3383void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443384 if (vertex_attrib_manager_->Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:303385 glEnableVertexAttribArray(index);
3386 } else {
[email protected]8eee29c2010-04-29 03:38:293387 SetGLError(GL_INVALID_VALUE,
3388 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:303389 }
3390}
3391
[email protected]a93bb842010-02-16 23:03:473392void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:503393 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]97dc7cbe2011-12-06 17:26:173394 if (!info ||
[email protected]80eb6b52012-01-19 00:14:413395 !texture_manager()->MarkMipmapsGenerated(info)) {
[email protected]8eee29c2010-04-29 03:38:293396 SetGLError(GL_INVALID_OPERATION,
3397 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:473398 return;
3399 }
[email protected]59f3ca02011-03-26 22:24:193400 // Workaround for Mac driver bug. In the large scheme of things setting
3401 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
[email protected]a8bad262011-10-21 18:28:563402 // hit so there's probably no need to make this conditional. The bug appears
3403 // to be that if the filtering mode is set to something that doesn't require
3404 // mipmaps for rendering, or is never set to something other than the default,
3405 // then glGenerateMipmap misbehaves.
3406 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
[email protected]a93bb842010-02-16 23:03:473407 glGenerateMipmapEXT(target);
[email protected]59f3ca02011-03-26 22:24:193408 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
[email protected]a93bb842010-02-16 23:03:473409}
3410
[email protected]b273e432010-04-12 17:23:583411bool GLES2DecoderImpl::GetHelper(
3412 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:583413 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:153414 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
3415 switch (pname) {
[email protected]b273e432010-04-12 17:23:583416 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
3417 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103418 if (params) {
[email protected]5094b0f2010-11-09 19:45:243419 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:103420 }
[email protected]b273e432010-04-12 17:23:583421 return true;
3422 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3423 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103424 if (params) {
[email protected]5094b0f2010-11-09 19:45:243425 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:103426 }
[email protected]b273e432010-04-12 17:23:583427 return true;
3428 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
3429 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103430 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483431 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:103432 }
[email protected]b273e432010-04-12 17:23:583433 return true;
3434 case GL_MAX_VARYING_VECTORS:
3435 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103436 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483437 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:103438 }
[email protected]b273e432010-04-12 17:23:583439 return true;
3440 case GL_MAX_VERTEX_UNIFORM_VECTORS:
3441 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103442 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483443 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:103444 }
[email protected]b273e432010-04-12 17:23:583445 return true;
[email protected]5cb735d2011-10-13 01:37:233446 }
3447 }
3448 switch (pname) {
[email protected]5094b0f2010-11-09 19:45:243449 case GL_MAX_VIEWPORT_DIMS:
3450 if (offscreen_target_frame_buffer_.get()) {
3451 *num_written = 2;
3452 if (params) {
3453 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3454 params[1] = renderbuffer_manager()->max_renderbuffer_size();
3455 }
3456 return true;
3457 }
[email protected]5cb735d2011-10-13 01:37:233458 return false;
[email protected]84afefa2011-10-19 21:45:533459 case GL_MAX_SAMPLES:
3460 *num_written = 1;
3461 if (params) {
3462 params[0] = renderbuffer_manager()->max_samples();
3463 }
3464 return true;
3465 case GL_MAX_RENDERBUFFER_SIZE:
3466 *num_written = 1;
3467 if (params) {
3468 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3469 }
3470 return true;
[email protected]5cb735d2011-10-13 01:37:233471 case GL_MAX_TEXTURE_SIZE:
3472 *num_written = 1;
3473 if (params) {
3474 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
3475 }
3476 return true;
3477 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
3478 *num_written = 1;
3479 if (params) {
3480 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
3481 }
3482 return true;
[email protected]297ca1c2011-06-20 23:08:463483 case GL_COLOR_WRITEMASK:
3484 *num_written = 4;
3485 if (params) {
3486 params[0] = mask_red_;
3487 params[1] = mask_green_;
3488 params[2] = mask_blue_;
3489 params[3] = mask_alpha_;
3490 }
3491 return true;
3492 case GL_DEPTH_WRITEMASK:
3493 *num_written = 1;
3494 if (params) {
3495 params[0] = mask_depth_;
3496 }
3497 return true;
3498 case GL_STENCIL_BACK_WRITEMASK:
3499 *num_written = 1;
3500 if (params) {
3501 params[0] = mask_stencil_back_;
3502 }
3503 return true;
3504 case GL_STENCIL_WRITEMASK:
3505 *num_written = 1;
3506 if (params) {
3507 params[0] = mask_stencil_front_;
3508 }
3509 return true;
3510 case GL_DEPTH_TEST:
3511 *num_written = 1;
3512 if (params) {
3513 params[0] = enable_depth_test_;
3514 }
3515 return true;
3516 case GL_STENCIL_TEST:
3517 *num_written = 1;
3518 if (params) {
3519 params[0] = enable_stencil_test_;
3520 }
3521 return true;
3522 case GL_ALPHA_BITS:
3523 *num_written = 1;
3524 if (params) {
3525 GLint v = 0;
3526 glGetIntegerv(GL_ALPHA_BITS, &v);
3527 params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0;
3528 }
3529 return true;
3530 case GL_DEPTH_BITS:
3531 *num_written = 1;
3532 if (params) {
3533 GLint v = 0;
3534 glGetIntegerv(GL_DEPTH_BITS, &v);
3535 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
3536 }
3537 return true;
3538 case GL_STENCIL_BITS:
3539 *num_written = 1;
3540 if (params) {
3541 GLint v = 0;
3542 glGetIntegerv(GL_STENCIL_BITS, &v);
3543 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
3544 }
3545 return true;
[email protected]656dcaad2010-05-07 17:18:373546 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113547 *num_written = validators_->compressed_texture_format.GetValues().size();
3548 if (params) {
3549 for (GLint ii = 0; ii < *num_written; ++ii) {
3550 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
3551 }
3552 }
[email protected]656dcaad2010-05-07 17:18:373553 return true;
[email protected]b273e432010-04-12 17:23:583554 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
3555 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103556 if (params) {
[email protected]302ce6d2011-07-07 23:28:113557 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103558 }
[email protected]b273e432010-04-12 17:23:583559 return true;
3560 case GL_NUM_SHADER_BINARY_FORMATS:
3561 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103562 if (params) {
[email protected]302ce6d2011-07-07 23:28:113563 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103564 }
[email protected]b273e432010-04-12 17:23:583565 return true;
3566 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113567 *num_written = validators_->shader_binary_format.GetValues().size();
3568 if (params) {
3569 for (GLint ii = 0; ii < *num_written; ++ii) {
3570 params[ii] = validators_->shader_binary_format.GetValues()[ii];
3571 }
3572 }
3573 return true;
[email protected]b273e432010-04-12 17:23:583574 case GL_SHADER_COMPILER:
3575 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103576 if (params) {
3577 *params = GL_TRUE;
3578 }
[email protected]b273e432010-04-12 17:23:583579 return true;
[email protected]6b8cf1a2010-05-06 16:13:583580 case GL_ARRAY_BUFFER_BINDING:
3581 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103582 if (params) {
3583 if (bound_array_buffer_) {
3584 GLuint client_id = 0;
3585 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
3586 &client_id);
3587 *params = client_id;
3588 } else {
3589 *params = 0;
3590 }
[email protected]6b8cf1a2010-05-06 16:13:583591 }
3592 return true;
3593 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3594 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103595 if (params) {
3596 if (bound_element_array_buffer_) {
3597 GLuint client_id = 0;
3598 buffer_manager()->GetClientId(
3599 bound_element_array_buffer_->service_id(),
3600 &client_id);
3601 *params = client_id;
3602 } else {
3603 *params = 0;
3604 }
[email protected]6b8cf1a2010-05-06 16:13:583605 }
3606 return true;
3607 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:303608 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:583609 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103610 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203611 FramebufferManager::FramebufferInfo* framebuffer =
3612 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3613 if (framebuffer) {
[email protected]4e8a5b122010-05-08 22:00:103614 GLuint client_id = 0;
3615 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203616 framebuffer->service_id(), &client_id);
[email protected]8e3e0662010-08-23 18:46:303617 *params = client_id;
3618 } else {
3619 *params = 0;
3620 }
3621 }
3622 return true;
3623 case GL_READ_FRAMEBUFFER_BINDING:
3624 *num_written = 1;
3625 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203626 FramebufferManager::FramebufferInfo* framebuffer =
3627 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
3628 if (framebuffer) {
[email protected]8e3e0662010-08-23 18:46:303629 GLuint client_id = 0;
3630 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203631 framebuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103632 *params = client_id;
3633 } else {
3634 *params = 0;
3635 }
[email protected]6b8cf1a2010-05-06 16:13:583636 }
3637 return true;
3638 case GL_RENDERBUFFER_BINDING:
3639 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103640 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203641 RenderbufferManager::RenderbufferInfo* renderbuffer =
3642 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
3643 if (renderbuffer) {
[email protected]4e8a5b122010-05-08 22:00:103644 GLuint client_id = 0;
3645 renderbuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203646 renderbuffer->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_CURRENT_PROGRAM:
3654 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103655 if (params) {
3656 if (current_program_) {
3657 GLuint client_id = 0;
3658 program_manager()->GetClientId(
3659 current_program_->service_id(), &client_id);
3660 *params = client_id;
3661 } else {
3662 *params = 0;
3663 }
[email protected]6b8cf1a2010-05-06 16:13:583664 }
3665 return true;
[email protected]4e8a5b122010-05-08 22:00:103666 case GL_TEXTURE_BINDING_2D:
3667 *num_written = 1;
3668 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583669 TextureUnit& unit = texture_units_[active_texture_unit_];
3670 if (unit.bound_texture_2d) {
3671 GLuint client_id = 0;
3672 texture_manager()->GetClientId(
3673 unit.bound_texture_2d->service_id(), &client_id);
3674 *params = client_id;
3675 } else {
3676 *params = 0;
3677 }
[email protected]6b8cf1a2010-05-06 16:13:583678 }
[email protected]4e8a5b122010-05-08 22:00:103679 return true;
3680 case GL_TEXTURE_BINDING_CUBE_MAP:
3681 *num_written = 1;
3682 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583683 TextureUnit& unit = texture_units_[active_texture_unit_];
3684 if (unit.bound_texture_cube_map) {
3685 GLuint client_id = 0;
3686 texture_manager()->GetClientId(
3687 unit.bound_texture_cube_map->service_id(), &client_id);
3688 *params = client_id;
3689 } else {
3690 *params = 0;
3691 }
[email protected]6b8cf1a2010-05-06 16:13:583692 }
[email protected]4e8a5b122010-05-08 22:00:103693 return true;
[email protected]61eeb33f2011-07-26 15:30:313694 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3695 *num_written = 1;
3696 if (params) {
3697 TextureUnit& unit = texture_units_[active_texture_unit_];
3698 if (unit.bound_texture_external_oes) {
3699 GLuint client_id = 0;
3700 texture_manager()->GetClientId(
3701 unit.bound_texture_external_oes->service_id(), &client_id);
3702 *params = client_id;
3703 } else {
3704 *params = 0;
3705 }
3706 }
3707 return true;
[email protected]e51bdf32011-11-23 22:21:463708 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
3709 *num_written = 1;
3710 if (params) {
3711 TextureUnit& unit = texture_units_[active_texture_unit_];
3712 if (unit.bound_texture_rectangle_arb) {
3713 GLuint client_id = 0;
3714 texture_manager()->GetClientId(
3715 unit.bound_texture_rectangle_arb->service_id(), &client_id);
3716 *params = client_id;
3717 } else {
3718 *params = 0;
3719 }
3720 }
3721 return true;
[email protected]b273e432010-04-12 17:23:583722 default:
[email protected]4e8a5b122010-05-08 22:00:103723 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533724 return false;
[email protected]b273e432010-04-12 17:23:583725 }
3726}
3727
[email protected]4e8a5b122010-05-08 22:00:103728bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3729 GLenum pname, GLsizei* num_values) {
3730 return GetHelper(pname, NULL, num_values);
3731}
3732
[email protected]b273e432010-04-12 17:23:583733void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3734 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103735 GLsizei num_written = 0;
3736 if (GetHelper(pname, NULL, &num_written)) {
3737 scoped_array<GLint> values(new GLint[num_written]);
3738 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583739 for (GLsizei ii = 0; ii < num_written; ++ii) {
3740 params[ii] = static_cast<GLboolean>(values[ii]);
3741 }
3742 } else {
3743 glGetBooleanv(pname, params);
3744 }
3745}
3746
3747void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3748 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103749 GLsizei num_written = 0;
3750 if (GetHelper(pname, NULL, &num_written)) {
3751 scoped_array<GLint> values(new GLint[num_written]);
3752 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583753 for (GLsizei ii = 0; ii < num_written; ++ii) {
3754 params[ii] = static_cast<GLfloat>(values[ii]);
3755 }
3756 } else {
3757 glGetFloatv(pname, params);
3758 }
3759}
3760
3761void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3762 DCHECK(params);
3763 GLsizei num_written;
3764 if (!GetHelper(pname, params, &num_written)) {
3765 glGetIntegerv(pname, params);
3766 }
3767}
3768
[email protected]a0c3e972010-04-21 00:49:133769void GLES2DecoderImpl::DoGetProgramiv(
3770 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583771 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3772 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133773 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133774 return;
3775 }
3776 info->GetProgramiv(pname, params);
3777}
3778
[email protected]258a3313f2011-10-18 20:13:573779void GLES2DecoderImpl::DoBindAttribLocation(
3780 GLuint program, GLuint index, const char* name) {
3781 if (!StringIsValidForGLES(name)) {
3782 SetGLError(GL_INVALID_VALUE, "glBindAttribLocation: Invalid character");
3783 return;
3784 }
[email protected]6b8cf1a2010-05-06 16:13:583785 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3786 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033787 if (!info) {
[email protected]258a3313f2011-10-18 20:13:573788 return;
[email protected]558847a2010-03-24 07:02:543789 }
[email protected]258a3313f2011-10-18 20:13:573790 glBindAttribLocation(info->service_id(), index, name);
3791}
3792
3793error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3794 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
3795 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543796 GLuint index = static_cast<GLuint>(c.index);
3797 uint32 name_size = c.data_size;
3798 const char* name = GetSharedMemoryAs<const char*>(
3799 c.name_shm_id, c.name_shm_offset, name_size);
3800 if (name == NULL) {
3801 return error::kOutOfBounds;
3802 }
3803 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573804 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543805 return error::kNoError;
3806}
3807
3808error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3809 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583810 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 = GetImmediateDataAs<const char*>(
3814 c, name_size, immediate_data_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::HandleBindAttribLocationBucket(
3824 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& 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 Bucket* bucket = GetBucket(c.name_bucket_id);
3828 if (!bucket || bucket->size() == 0) {
3829 return error::kInvalidArguments;
3830 }
3831 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183832 if (!bucket->GetAsString(&name_str)) {
3833 return error::kInvalidArguments;
3834 }
[email protected]258a3313f2011-10-18 20:13:573835 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543836 return error::kNoError;
3837}
3838
[email protected]f7a64ee2010-02-01 22:24:143839error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463840 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033841 GLuint client_id = c.shader;
3842 if (client_id) {
3843 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3844 if (info) {
[email protected]ca488e12010-12-13 20:06:143845 if (!info->IsDeleted()) {
3846 glDeleteShader(info->service_id());
3847 shader_manager()->MarkAsDeleted(info);
3848 }
[email protected]ae51d192010-04-27 00:48:033849 } else {
[email protected]8eee29c2010-04-29 03:38:293850 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033851 }
[email protected]96449d2c2009-11-25 00:01:323852 }
[email protected]f7a64ee2010-02-01 22:24:143853 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323854}
3855
[email protected]f7a64ee2010-02-01 22:24:143856error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463857 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033858 GLuint client_id = c.program;
3859 if (client_id) {
3860 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3861 if (info) {
[email protected]ca488e12010-12-13 20:06:143862 if (!info->IsDeleted()) {
3863 glDeleteProgram(info->service_id());
3864 program_manager()->MarkAsDeleted(shader_manager(), info);
3865 }
[email protected]ae51d192010-04-27 00:48:033866 } else {
[email protected]8eee29c2010-04-29 03:38:293867 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033868 }
[email protected]96449d2c2009-11-25 00:01:323869 }
[email protected]f7a64ee2010-02-01 22:24:143870 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323871}
3872
[email protected]269200b12010-11-18 22:53:063873void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103874 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573875 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103876 for (GLsizei ii = 0; ii < n; ++ii) {
3877 id_allocator->FreeID(ids[ii]);
3878 }
3879}
3880
[email protected]269200b12010-11-18 22:53:063881error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
3882 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103883 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3884 GLsizei n = static_cast<GLsizei>(c.n);
3885 uint32 data_size;
3886 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3887 return error::kOutOfBounds;
3888 }
3889 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3890 c.ids_shm_id, c.ids_shm_offset, data_size);
3891 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063892 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103893 return error::kNoError;
3894 }
3895 if (ids == NULL) {
3896 return error::kOutOfBounds;
3897 }
[email protected]269200b12010-11-18 22:53:063898 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103899 return error::kNoError;
3900}
3901
[email protected]269200b12010-11-18 22:53:063902void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103903 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573904 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103905 if (id_offset == 0) {
3906 for (GLsizei ii = 0; ii < n; ++ii) {
3907 ids[ii] = id_allocator->AllocateID();
3908 }
3909 } else {
3910 for (GLsizei ii = 0; ii < n; ++ii) {
3911 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
3912 id_offset = ids[ii] + 1;
3913 }
3914 }
3915}
3916
[email protected]269200b12010-11-18 22:53:063917error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
3918 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103919 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3920 GLuint id_offset = static_cast<GLuint>(c.id_offset);
3921 GLsizei n = static_cast<GLsizei>(c.n);
3922 uint32 data_size;
3923 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3924 return error::kOutOfBounds;
3925 }
3926 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3927 c.ids_shm_id, c.ids_shm_offset, data_size);
3928 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063929 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103930 return error::kNoError;
3931 }
3932 if (ids == NULL) {
3933 return error::kOutOfBounds;
3934 }
[email protected]269200b12010-11-18 22:53:063935 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:103936 return error::kNoError;
3937}
3938
[email protected]269200b12010-11-18 22:53:063939void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103940 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573941 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103942 for (GLsizei ii = 0; ii < n; ++ii) {
3943 if (!id_allocator->MarkAsUsed(ids[ii])) {
3944 for (GLsizei jj = 0; jj < ii; ++jj) {
3945 id_allocator->FreeID(ids[jj]);
3946 }
3947 SetGLError(
3948 GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:063949 "RegisterSharedIdsCHROMIUM: attempt to register "
3950 "id that already exists");
[email protected]066849e32010-05-03 19:14:103951 return;
3952 }
3953 }
3954}
3955
[email protected]269200b12010-11-18 22:53:063956error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
3957 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103958 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3959 GLsizei n = static_cast<GLsizei>(c.n);
3960 uint32 data_size;
3961 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3962 return error::kOutOfBounds;
3963 }
3964 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3965 c.ids_shm_id, c.ids_shm_offset, data_size);
3966 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063967 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103968 return error::kNoError;
3969 }
3970 if (ids == NULL) {
3971 return error::kOutOfBounds;
3972 }
[email protected]269200b12010-11-18 22:53:063973 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103974 return error::kNoError;
3975}
3976
[email protected]3a03a8f2011-03-19 00:51:273977void GLES2DecoderImpl::DoClear(GLbitfield mask) {
[email protected]0d6bfdc2011-11-02 01:32:203978 if (CheckBoundFramebuffersValid("glClear")) {
[email protected]529c6672012-01-04 02:18:263979 UNSHIPPED_TRACE_EVENT_INSTANT2("test_gpu", "DoClear", "red", clear_red_,
3980 "green", clear_green_);
[email protected]297ca1c2011-06-20 23:08:463981 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:273982 glClear(mask);
3983 }
3984}
3985
[email protected]36cef8ce2010-03-16 07:34:453986void GLES2DecoderImpl::DoFramebufferRenderbuffer(
3987 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:033988 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:303989 FramebufferManager::FramebufferInfo* framebuffer_info =
3990 GetFramebufferInfoForTarget(target);
3991 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293992 SetGLError(GL_INVALID_OPERATION,
3993 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453994 return;
3995 }
[email protected]ae51d192010-04-27 00:48:033996 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283997 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033998 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283999 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:034000 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294001 SetGLError(GL_INVALID_OPERATION,
4002 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:034003 return;
4004 }
4005 service_id = info->service_id();
4006 }
[email protected]9edc6b22010-12-23 02:00:264007 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034008 glFramebufferRenderbufferEXT(
4009 target, attachment, renderbuffertarget, service_id);
[email protected]1002c2d2011-06-28 22:39:044010 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264011 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:304012 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]3a2e7c7b2010-08-06 01:12:284013 }
[email protected]297ca1c2011-06-20 23:08:464014 if (framebuffer_info == bound_draw_framebuffer_) {
4015 state_dirty_ = true;
4016 }
[email protected]3a2e7c7b2010-08-06 01:12:284017}
4018
[email protected]297ca1c2011-06-20 23:08:464019bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
[email protected]3a2e7c7b2010-08-06 01:12:284020 switch (cap) {
4021 case GL_SCISSOR_TEST:
4022 enable_scissor_test_ = enabled;
[email protected]297ca1c2011-06-20 23:08:464023 return true;
4024 case GL_DEPTH_TEST: {
4025 if (enable_depth_test_ != enabled) {
4026 enable_depth_test_ = enabled;
4027 state_dirty_ = true;
4028 }
4029 return false;
4030 }
4031 case GL_STENCIL_TEST:
4032 if (enable_stencil_test_ != enabled) {
4033 enable_stencil_test_ = enabled;
4034 state_dirty_ = true;
4035 }
4036 return false;
[email protected]3a2e7c7b2010-08-06 01:12:284037 default:
[email protected]297ca1c2011-06-20 23:08:464038 return true;
[email protected]3a2e7c7b2010-08-06 01:12:284039 }
4040}
4041
4042void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464043 if (SetCapabilityState(cap, false)) {
4044 glDisable(cap);
4045 }
[email protected]3a2e7c7b2010-08-06 01:12:284046}
4047
4048void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464049 if (SetCapabilityState(cap, true)) {
4050 glEnable(cap);
4051 }
[email protected]3a2e7c7b2010-08-06 01:12:284052}
4053
4054void GLES2DecoderImpl::DoClearColor(
4055 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
4056 clear_red_ = red;
4057 clear_green_ = green;
4058 clear_blue_ = blue;
4059 clear_alpha_ = alpha;
4060 glClearColor(red, green, blue, alpha);
4061}
4062
4063void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
4064 clear_depth_ = depth;
4065 glClearDepth(depth);
4066}
4067
4068void GLES2DecoderImpl::DoClearStencil(GLint s) {
4069 clear_stencil_ = s;
4070 glClearStencil(s);
4071}
4072
4073void GLES2DecoderImpl::DoColorMask(
4074 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
4075 mask_red_ = red;
4076 mask_green_ = green;
4077 mask_blue_ = blue;
4078 mask_alpha_ = alpha;
[email protected]297ca1c2011-06-20 23:08:464079 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284080}
4081
4082void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
4083 mask_depth_ = depth;
[email protected]297ca1c2011-06-20 23:08:464084 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284085}
4086
4087void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
4088 mask_stencil_front_ = mask;
4089 mask_stencil_back_ = mask;
[email protected]297ca1c2011-06-20 23:08:464090 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284091}
4092
4093void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
[email protected]297ca1c2011-06-20 23:08:464094 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284095 mask_stencil_front_ = mask;
[email protected]297ca1c2011-06-20 23:08:464096 }
4097 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284098 mask_stencil_back_ = mask;
4099 }
[email protected]297ca1c2011-06-20 23:08:464100 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284101}
4102
[email protected]0d6bfdc2011-11-02 01:32:204103// Assumes framebuffer is complete.
4104void GLES2DecoderImpl::ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:304105 GLenum target, FramebufferManager::FramebufferInfo* info) {
4106 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204107 // bind this to the DRAW point, clear then bind back to READ
4108 // TODO(gman): I don't think there is any guarantee that an FBO that
4109 // is complete on the READ attachment will be complete as a DRAW
4110 // attachment.
4111 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
4112 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, info->service_id());
[email protected]8e3e0662010-08-23 18:46:304113 }
[email protected]3a2e7c7b2010-08-06 01:12:284114 GLbitfield clear_bits = 0;
4115 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:464116 glClearColor(
[email protected]0d6bfdc2011-11-02 01:32:204117 0.0f, 0.0f, 0.0f,
[email protected]297ca1c2011-06-20 23:08:464118 (GLES2Util::GetChannelsForFormat(
[email protected]0d6bfdc2011-11-02 01:32:204119 info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f : 1.0f);
[email protected]3a2e7c7b2010-08-06 01:12:284120 glColorMask(true, true, true, true);
4121 clear_bits |= GL_COLOR_BUFFER_BIT;
4122 }
4123
4124 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4125 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4126 glClearStencil(0);
4127 glStencilMask(-1);
4128 clear_bits |= GL_STENCIL_BUFFER_BIT;
4129 }
4130
4131 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4132 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4133 glClearDepth(1.0f);
4134 glDepthMask(true);
4135 clear_bits |= GL_DEPTH_BUFFER_BIT;
4136 }
4137
4138 glDisable(GL_SCISSOR_TEST);
4139 glClear(clear_bits);
4140
[email protected]968351b2011-12-20 08:26:514141 framebuffer_manager()->MarkAttachmentsAsCleared(
4142 info, renderbuffer_manager(), texture_manager());
[email protected]3a2e7c7b2010-08-06 01:12:284143
[email protected]c007aa02010-09-02 22:22:404144 RestoreClearState();
4145
4146 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204147 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, info->service_id());
[email protected]87d1a3fe2011-12-01 04:25:484148 FramebufferManager::FramebufferInfo* framebuffer =
4149 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4150 GLuint service_id =
4151 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
4152 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
[email protected]c007aa02010-09-02 22:22:404153 }
4154}
4155
4156void GLES2DecoderImpl::RestoreClearState() {
[email protected]297ca1c2011-06-20 23:08:464157 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284158 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
[email protected]3a2e7c7b2010-08-06 01:12:284159 glClearStencil(clear_stencil_);
[email protected]3a2e7c7b2010-08-06 01:12:284160 glClearDepth(clear_depth_);
[email protected]3a2e7c7b2010-08-06 01:12:284161 if (enable_scissor_test_) {
4162 glEnable(GL_SCISSOR_TEST);
4163 }
[email protected]36cef8ce2010-03-16 07:34:454164}
4165
4166GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]0d6bfdc2011-11-02 01:32:204167 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]8e3e0662010-08-23 18:46:304168 GetFramebufferInfoForTarget(target);
[email protected]0d6bfdc2011-11-02 01:32:204169 if (!framebuffer) {
[email protected]36cef8ce2010-03-16 07:34:454170 return GL_FRAMEBUFFER_COMPLETE;
4171 }
[email protected]0d6bfdc2011-11-02 01:32:204172 GLenum completeness = framebuffer->IsPossiblyComplete();
4173 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4174 return completeness;
4175 }
[email protected]36cef8ce2010-03-16 07:34:454176 return glCheckFramebufferStatusEXT(target);
4177}
4178
4179void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:034180 GLenum target, GLenum attachment, GLenum textarget,
4181 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:304182 FramebufferManager::FramebufferInfo* framebuffer_info =
4183 GetFramebufferInfoForTarget(target);
4184 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294185 SetGLError(GL_INVALID_OPERATION,
4186 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:454187 return;
4188 }
[email protected]ae51d192010-04-27 00:48:034189 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:284190 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:034191 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:284192 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:034193 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294194 SetGLError(GL_INVALID_OPERATION,
4195 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:034196 return;
4197 }
4198 service_id = info->service_id();
4199 }
[email protected]0d6bfdc2011-11-02 01:32:204200
[email protected]80eb6b52012-01-19 00:14:414201 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
[email protected]0d6bfdc2011-11-02 01:32:204202 SetGLError(GL_INVALID_VALUE,
4203 "glFramebufferTexture2D: level out of range");
4204 return;
4205 }
4206
[email protected]9edc6b22010-12-23 02:00:264207 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034208 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]1002c2d2011-06-28 22:39:044209 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264210 if (error == GL_NO_ERROR) {
4211 framebuffer_info->AttachTexture(attachment, info, textarget, level);
[email protected]3a2e7c7b2010-08-06 01:12:284212 }
[email protected]297ca1c2011-06-20 23:08:464213 if (framebuffer_info == bound_draw_framebuffer_) {
4214 state_dirty_ = true;
4215 }
[email protected]36cef8ce2010-03-16 07:34:454216}
4217
4218void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4219 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:304220 FramebufferManager::FramebufferInfo* framebuffer_info =
4221 GetFramebufferInfoForTarget(target);
4222 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294223 SetGLError(GL_INVALID_OPERATION,
4224 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454225 return;
4226 }
4227 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:574228 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4229 GLint type = 0;
4230 GLuint client_id = 0;
4231 glGetFramebufferAttachmentParameterivEXT(
4232 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
4233 switch (type) {
4234 case GL_RENDERBUFFER: {
4235 renderbuffer_manager()->GetClientId(*params, &client_id);
4236 break;
4237 }
4238 case GL_TEXTURE: {
4239 texture_manager()->GetClientId(*params, &client_id);
4240 break;
4241 }
4242 default:
4243 break;
4244 }
4245 *params = client_id;
4246 }
[email protected]36cef8ce2010-03-16 07:34:454247}
4248
4249void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4250 GLenum target, GLenum pname, GLint* params) {
[email protected]0d6bfdc2011-11-02 01:32:204251 RenderbufferManager::RenderbufferInfo* renderbuffer =
4252 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4253 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294254 SetGLError(GL_INVALID_OPERATION,
4255 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454256 return;
4257 }
[email protected]3a03a8f2011-03-19 00:51:274258 switch (pname) {
4259 case GL_RENDERBUFFER_INTERNAL_FORMAT:
[email protected]0d6bfdc2011-11-02 01:32:204260 *params = renderbuffer->internal_format();
[email protected]3a03a8f2011-03-19 00:51:274261 break;
4262 case GL_RENDERBUFFER_WIDTH:
[email protected]0d6bfdc2011-11-02 01:32:204263 *params = renderbuffer->width();
[email protected]3a03a8f2011-03-19 00:51:274264 break;
4265 case GL_RENDERBUFFER_HEIGHT:
[email protected]0d6bfdc2011-11-02 01:32:204266 *params = renderbuffer->height();
[email protected]3a03a8f2011-03-19 00:51:274267 break;
4268 default:
4269 glGetRenderbufferParameterivEXT(target, pname, params);
4270 break;
[email protected]b71f52c2010-06-18 22:20:204271 }
[email protected]36cef8ce2010-03-16 07:34:454272}
4273
[email protected]8e3e0662010-08-23 18:46:304274void GLES2DecoderImpl::DoBlitFramebufferEXT(
4275 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
4276 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
4277 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:394278 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304279 SetGLError(GL_INVALID_OPERATION,
4280 "glBlitFramebufferEXT: function not available");
4281 }
[email protected]5094b0f2010-11-09 19:45:244282 if (IsAngle()) {
4283 glBlitFramebufferANGLE(
4284 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4285 } else {
4286 glBlitFramebufferEXT(
4287 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4288 }
[email protected]529c6672012-01-04 02:18:264289 UNSHIPPED_TRACE_EVENT_INSTANT1("test_gpu", "DoBlit", "width", srcX1 - srcX0);
[email protected]8e3e0662010-08-23 18:46:304290}
4291
4292void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
4293 GLenum target, GLsizei samples, GLenum internalformat,
4294 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:394295 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304296 SetGLError(GL_INVALID_OPERATION,
4297 "glRenderbufferStorageMultisampleEXT: function not available");
4298 return;
4299 }
[email protected]8e3e0662010-08-23 18:46:304300
[email protected]0d6bfdc2011-11-02 01:32:204301 RenderbufferManager::RenderbufferInfo* renderbuffer =
4302 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4303 if (!renderbuffer) {
4304 SetGLError(GL_INVALID_OPERATION,
4305 "glGetRenderbufferStorageMultisample: no renderbuffer bound");
4306 return;
4307 }
4308
[email protected]84afefa2011-10-19 21:45:534309 if (samples > renderbuffer_manager()->max_samples()) {
4310 SetGLError(GL_INVALID_VALUE,
4311 "glGetRenderbufferStorageMultisample: samples too large");
4312 return;
4313 }
4314
4315 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4316 height > renderbuffer_manager()->max_renderbuffer_size()) {
4317 SetGLError(GL_INVALID_VALUE,
4318 "glGetRenderbufferStorageMultisample: size too large");
4319 return;
4320 }
4321
[email protected]9edc6b22010-12-23 02:00:264322 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:304323 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264324 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:304325 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264326 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:304327 break;
4328 case GL_RGBA4:
4329 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264330 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:304331 break;
4332 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264333 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:304334 break;
4335 }
4336 }
4337
[email protected]9edc6b22010-12-23 02:00:264338 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:084339 if (IsAngle()) {
4340 glRenderbufferStorageMultisampleANGLE(
4341 target, samples, impl_format, width, height);
4342 } else {
4343 glRenderbufferStorageMultisampleEXT(
4344 target, samples, impl_format, width, height);
4345 }
[email protected]1002c2d2011-06-28 22:39:044346 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264347 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514348 // TODO(gman): If renderbuffers tracked which framebuffers they were
4349 // attached to we could just mark those framebuffers as not complete.
4350 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204351 renderbuffer_manager()->SetInfo(
4352 renderbuffer, samples, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264353 }
[email protected]8e3e0662010-08-23 18:46:304354}
4355
[email protected]36cef8ce2010-03-16 07:34:454356void GLES2DecoderImpl::DoRenderbufferStorage(
4357 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]0d6bfdc2011-11-02 01:32:204358 RenderbufferManager::RenderbufferInfo* renderbuffer =
4359 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4360 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294361 SetGLError(GL_INVALID_OPERATION,
4362 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454363 return;
4364 }
[email protected]876f6fee2010-08-02 23:10:324365
[email protected]84afefa2011-10-19 21:45:534366 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4367 height > renderbuffer_manager()->max_renderbuffer_size()) {
4368 SetGLError(GL_INVALID_VALUE,
4369 "glGetRenderbufferStorage: size too large");
4370 return;
4371 }
4372
[email protected]9edc6b22010-12-23 02:00:264373 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:324374 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264375 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:324376 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264377 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:324378 break;
4379 case GL_RGBA4:
4380 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264381 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:324382 break;
4383 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264384 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:324385 break;
4386 }
[email protected]b71f52c2010-06-18 22:20:204387 }
[email protected]876f6fee2010-08-02 23:10:324388
[email protected]9edc6b22010-12-23 02:00:264389 CopyRealGLErrorsToWrapper();
4390 glRenderbufferStorageEXT(target, impl_format, width, height);
[email protected]1002c2d2011-06-28 22:39:044391 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264392 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514393 // TODO(gman): If tetxures tracked which framebuffers they were attached to
4394 // we could just mark those framebuffers as not complete.
4395 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204396 renderbuffer_manager()->SetInfo(
4397 renderbuffer, 0, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264398 }
[email protected]36cef8ce2010-03-16 07:34:454399}
4400
[email protected]07f54fcc2009-12-22 02:46:304401void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]0c8fabf2011-06-14 19:35:224402 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]6b8cf1a2010-05-06 16:13:584403 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4404 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:474405 if (!info) {
[email protected]a93bb842010-02-16 23:03:474406 return;
4407 }
[email protected]05afda12011-01-20 00:17:344408
[email protected]d685a682011-04-29 16:19:574409 info->Link();
[email protected]07f54fcc2009-12-22 02:46:304410};
4411
[email protected]3916c97e2010-02-25 03:20:504412void GLES2DecoderImpl::DoTexParameterf(
4413 GLenum target, GLenum pname, GLfloat param) {
4414 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:304415 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294416 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244417 return;
[email protected]07f54fcc2009-12-22 02:46:304418 }
[email protected]cbb22e42011-05-12 23:36:244419
4420 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414421 info, pname, static_cast<GLint>(param))) {
[email protected]cbb22e42011-05-12 23:36:244422 SetGLError(GL_INVALID_ENUM, "glTexParameterf: param GL_INVALID_ENUM");
4423 return;
4424 }
4425 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:304426}
4427
[email protected]3916c97e2010-02-25 03:20:504428void GLES2DecoderImpl::DoTexParameteri(
4429 GLenum target, GLenum pname, GLint param) {
4430 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4431 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294432 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244433 return;
[email protected]3916c97e2010-02-25 03:20:504434 }
[email protected]cbb22e42011-05-12 23:36:244435
[email protected]80eb6b52012-01-19 00:14:414436 if (!texture_manager()->SetParameter(info, pname, param)) {
[email protected]cbb22e42011-05-12 23:36:244437 SetGLError(GL_INVALID_ENUM, "glTexParameteri: param GL_INVALID_ENUM");
4438 return;
4439 }
4440 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:504441}
4442
4443void GLES2DecoderImpl::DoTexParameterfv(
4444 GLenum target, GLenum pname, const GLfloat* params) {
4445 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4446 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294447 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: 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
4451 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414452 info, pname, static_cast<GLint>(params[0]))) {
[email protected]cbb22e42011-05-12 23:36:244453 SetGLError(GL_INVALID_ENUM, "glTexParameterfv: param GL_INVALID_ENUM");
4454 return;
4455 }
4456 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504457}
4458
4459void GLES2DecoderImpl::DoTexParameteriv(
4460 GLenum target, GLenum pname, const GLint* params) {
4461 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4462 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294463 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244464 return;
[email protected]3916c97e2010-02-25 03:20:504465 }
[email protected]cbb22e42011-05-12 23:36:244466
[email protected]80eb6b52012-01-19 00:14:414467 if (!texture_manager()->SetParameter(info, pname, *params)) {
[email protected]cbb22e42011-05-12 23:36:244468 SetGLError(GL_INVALID_ENUM, "glTexParameteriv: param GL_INVALID_ENUM");
4469 return;
4470 }
4471 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504472}
4473
[email protected]939e7362010-05-13 20:49:104474bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:144475 if (!current_program_) {
[email protected]939e7362010-05-13 20:49:104476 // The program does not exist.
4477 SetGLError(GL_INVALID_OPERATION,
4478 (std::string(function_name) + ": no program in use").c_str());
4479 return false;
4480 }
[email protected]ca488e12010-12-13 20:06:144481 if (!current_program_->InUse()) {
[email protected]939e7362010-05-13 20:49:104482 SetGLError(GL_INVALID_OPERATION,
4483 (std::string(function_name) + ": program not linked").c_str());
4484 return false;
4485 }
4486 return true;
4487}
4488
4489bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
4490 GLint location, const char* function_name) {
4491 if (!CheckCurrentProgram(function_name)) {
4492 return false;
4493 }
4494 return location != -1;
4495}
4496
[email protected]43c2f1f2011-03-25 18:35:364497bool GLES2DecoderImpl::PrepForSetUniformByLocation(
4498 GLint location, const char* function_name, GLenum* type, GLsizei* count) {
4499 DCHECK(type);
4500 DCHECK(count);
[email protected]939e7362010-05-13 20:49:104501 if (!CheckCurrentProgramForUniform(location, function_name)) {
4502 return false;
4503 }
[email protected]43c2f1f2011-03-25 18:35:364504 GLint array_index = -1;
4505 const ProgramManager::ProgramInfo::UniformInfo* info =
4506 current_program_->GetUniformInfoByLocation(location, &array_index);
4507 if (!info) {
[email protected]939e7362010-05-13 20:49:104508 SetGLError(GL_INVALID_OPERATION,
[email protected]43c2f1f2011-03-25 18:35:364509 (std::string(function_name) + ": unknown location").c_str());
[email protected]939e7362010-05-13 20:49:104510 return false;
4511 }
[email protected]43c2f1f2011-03-25 18:35:364512 if (*count > 1 && !info->is_array) {
4513 SetGLError(
4514 GL_INVALID_OPERATION,
4515 (std::string(function_name) + ": count > 1 for non-array").c_str());
4516 return false;
4517 }
4518 *count = std::min(info->size - array_index, *count);
4519 if (*count <= 0) {
4520 return false;
4521 }
4522 *type = info->type;
[email protected]939e7362010-05-13 20:49:104523 return true;
4524}
4525
[email protected]939e7362010-05-13 20:49:104526void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
4527 if (!CheckCurrentProgramForUniform(location, "glUniform1i")) {
[email protected]3916c97e2010-02-25 03:20:504528 return;
4529 }
4530 current_program_->SetSamplers(location, 1, &v0);
4531 glUniform1i(location, v0);
4532}
4533
4534void GLES2DecoderImpl::DoUniform1iv(
4535 GLint location, GLsizei count, const GLint *value) {
[email protected]939e7362010-05-13 20:49:104536 if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) {
[email protected]3916c97e2010-02-25 03:20:504537 return;
4538 }
[email protected]43c2f1f2011-03-25 18:35:364539 GLenum type = 0;
4540 if (!PrepForSetUniformByLocation(location, "glUniform1iv", &type, &count)) {
4541 return;
4542 }
[email protected]61eeb33f2011-07-26 15:30:314543 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
4544 type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]43c2f1f2011-03-25 18:35:364545 current_program_->SetSamplers(location, count, value);
4546 }
[email protected]3916c97e2010-02-25 03:20:504547 glUniform1iv(location, count, value);
4548}
4549
[email protected]939e7362010-05-13 20:49:104550void GLES2DecoderImpl::DoUniform1fv(
4551 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364552 GLenum type = 0;
4553 if (!PrepForSetUniformByLocation(location, "glUniform1fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104554 return;
4555 }
4556 if (type == GL_BOOL) {
4557 scoped_array<GLint> temp(new GLint[count]);
4558 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:534559 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104560 }
4561 DoUniform1iv(location, count, temp.get());
4562 } else {
4563 glUniform1fv(location, count, value);
4564 }
4565}
4566
4567void GLES2DecoderImpl::DoUniform2fv(
4568 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364569 GLenum type = 0;
4570 if (!PrepForSetUniformByLocation(location, "glUniform2fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104571 return;
4572 }
4573 if (type == GL_BOOL_VEC2) {
4574 GLsizei num_values = count * 2;
4575 scoped_array<GLint> temp(new GLint[num_values]);
4576 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534577 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104578 }
4579 glUniform2iv(location, count, temp.get());
4580 } else {
4581 glUniform2fv(location, count, value);
4582 }
4583}
4584
4585void GLES2DecoderImpl::DoUniform3fv(
4586 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364587 GLenum type = 0;
4588 if (!PrepForSetUniformByLocation(location, "glUniform3fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104589 return;
4590 }
4591 if (type == GL_BOOL_VEC3) {
4592 GLsizei num_values = count * 3;
4593 scoped_array<GLint> temp(new GLint[num_values]);
4594 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534595 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104596 }
4597 glUniform3iv(location, count, temp.get());
4598 } else {
4599 glUniform3fv(location, count, value);
4600 }
4601}
4602
4603void GLES2DecoderImpl::DoUniform4fv(
4604 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364605 GLenum type = 0;
4606 if (!PrepForSetUniformByLocation(location, "glUniform4fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104607 return;
4608 }
4609 if (type == GL_BOOL_VEC4) {
4610 GLsizei num_values = count * 4;
4611 scoped_array<GLint> temp(new GLint[num_values]);
4612 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534613 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104614 }
4615 glUniform4iv(location, count, temp.get());
4616 } else {
4617 glUniform4fv(location, count, value);
4618 }
4619}
4620
[email protected]43c2f1f2011-03-25 18:35:364621void GLES2DecoderImpl::DoUniform2iv(
4622 GLint location, GLsizei count, const GLint* value) {
4623 GLenum type = 0;
4624 if (!PrepForSetUniformByLocation(location, "glUniform2iv", &type, &count)) {
4625 return;
4626 }
4627 glUniform2iv(location, count, value);
4628}
4629
4630void GLES2DecoderImpl::DoUniform3iv(
4631 GLint location, GLsizei count, const GLint* value) {
4632 GLenum type = 0;
4633 if (!PrepForSetUniformByLocation(location, "glUniform3iv", &type, &count)) {
4634 return;
4635 }
4636 glUniform3iv(location, count, value);
4637}
4638
4639void GLES2DecoderImpl::DoUniform4iv(
4640 GLint location, GLsizei count, const GLint* value) {
4641 GLenum type = 0;
4642 if (!PrepForSetUniformByLocation(location, "glUniform4iv", &type, &count)) {
4643 return;
4644 }
4645 glUniform4iv(location, count, value);
4646}
4647
4648void GLES2DecoderImpl::DoUniformMatrix2fv(
4649 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4650 GLenum type = 0;
4651 if (!PrepForSetUniformByLocation(
4652 location, "glUniformMatrix2fv", &type, &count)) {
4653 return;
4654 }
[email protected]e5081262012-01-05 23:09:034655 glUniformMatrix2fv(location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364656}
4657
4658void GLES2DecoderImpl::DoUniformMatrix3fv(
4659 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4660 GLenum type = 0;
4661 if (!PrepForSetUniformByLocation(
4662 location, "glUniformMatrix3fv", &type, &count)) {
4663 return;
4664 }
[email protected]e5081262012-01-05 23:09:034665 glUniformMatrix3fv(location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364666}
4667
4668void GLES2DecoderImpl::DoUniformMatrix4fv(
4669 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4670 GLenum type = 0;
4671 if (!PrepForSetUniformByLocation(
4672 location, "glUniformMatrix4fv", &type, &count)) {
4673 return;
4674 }
[email protected]e5081262012-01-05 23:09:034675 glUniformMatrix4fv(location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364676}
4677
[email protected]3916c97e2010-02-25 03:20:504678void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:034679 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:504680 ProgramManager::ProgramInfo* info = NULL;
4681 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:584682 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:504683 if (!info) {
[email protected]ae51d192010-04-27 00:48:034684 return;
4685 }
4686 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:504687 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:294688 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:504689 return;
4690 }
[email protected]ae51d192010-04-27 00:48:034691 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:504692 }
[email protected]ca488e12010-12-13 20:06:144693 if (current_program_) {
4694 program_manager()->UnuseProgram(shader_manager(), current_program_);
4695 }
[email protected]3916c97e2010-02-25 03:20:504696 current_program_ = info;
[email protected]ca488e12010-12-13 20:06:144697 if (current_program_) {
4698 program_manager()->UseProgram(current_program_);
4699 }
[email protected]ae51d192010-04-27 00:48:034700 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:504701}
4702
[email protected]96449d2c2009-11-25 00:01:324703GLenum GLES2DecoderImpl::GetGLError() {
4704 // Check the GL error first, then our wrapped error.
4705 GLenum error = glGetError();
4706 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:374707 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:324708 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:294709 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:324710 break;
4711 }
4712 }
4713 }
4714
4715 if (error != GL_NO_ERROR) {
4716 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:294717 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324718 }
4719 return error;
4720}
4721
[email protected]1002c2d2011-06-28 22:39:044722GLenum GLES2DecoderImpl::PeekGLError() {
4723 GLenum error = glGetError();
4724 if (error != GL_NO_ERROR) {
4725 SetGLError(error, "");
4726 }
4727 return error;
4728}
4729
[email protected]8eee29c2010-04-29 03:38:294730void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
4731 if (msg) {
4732 last_error_ = msg;
[email protected]b5d647c2012-02-10 01:41:324733 // LOG this unless logging is turned off as any chromium code that generates
4734 // these errors probably has a bug.
4735 if (log_synthesized_gl_errors()) {
4736 LOG(ERROR) << last_error_;
4737 }
[email protected]6b6e7ee2011-12-13 08:04:524738 if (!msg_callback_.is_null()) {
4739 msg_callback_.Run(0, GLES2Util::GetStringEnum(error) + " : " + msg);
4740 }
[email protected]8eee29c2010-04-29 03:38:294741 }
[email protected]ddd968b82010-03-02 00:44:294742 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324743}
4744
[email protected]07f54fcc2009-12-22 02:46:304745void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
4746 GLenum error;
4747 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294748 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:304749 }
4750}
4751
[email protected]6217d392010-03-25 22:08:354752void GLES2DecoderImpl::ClearRealGLErrors() {
4753 GLenum error;
4754 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]3ed14d112011-12-13 22:05:514755 if (error != GL_OUT_OF_MEMORY) {
4756 // GL_OUT_OF_MEMORY can legally happen on lost device.
4757 NOTREACHED() << "GL error " << error << " was unhandled.";
4758 }
[email protected]6217d392010-03-25 22:08:354759 }
4760}
4761
[email protected]ef526492010-06-02 23:12:254762bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:504763 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:254764 // Only check if there are some unrenderable textures.
4765 if (!texture_manager()->HaveUnrenderableTextures()) {
4766 return false;
4767 }
4768 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:504769 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4770 current_program_->sampler_indices();
4771 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4772 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4773 current_program_->GetUniformInfo(sampler_indices[ii]);
4774 DCHECK(uniform_info);
4775 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4776 GLuint texture_unit_index = uniform_info->texture_units[jj];
4777 if (texture_unit_index < group_->max_texture_units()) {
4778 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4779 TextureManager::TextureInfo* texture_info =
[email protected]61eeb33f2011-07-26 15:30:314780 texture_unit.GetInfoForSamplerType(uniform_info->type);
[email protected]80eb6b52012-01-19 00:14:414781 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]ef526492010-06-02 23:12:254782 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:504783 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4784 glBindTexture(
[email protected]61eeb33f2011-07-26 15:30:314785 GetBindTargetForSamplerType(uniform_info->type),
[email protected]00f893d2010-08-24 18:55:494786 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:504787 }
4788 }
4789 // else: should this be an error?
4790 }
4791 }
[email protected]ef526492010-06-02 23:12:254792 return textures_set;
[email protected]3916c97e2010-02-25 03:20:504793}
4794
4795void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
4796 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:504797 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4798 current_program_->sampler_indices();
4799 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4800 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4801 current_program_->GetUniformInfo(sampler_indices[ii]);
4802 DCHECK(uniform_info);
4803 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4804 GLuint texture_unit_index = uniform_info->texture_units[jj];
4805 if (texture_unit_index < group_->max_texture_units()) {
4806 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4807 TextureManager::TextureInfo* texture_info =
4808 uniform_info->type == GL_SAMPLER_2D ?
4809 texture_unit.bound_texture_2d :
4810 texture_unit.bound_texture_cube_map;
[email protected]80eb6b52012-01-19 00:14:414811 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]3916c97e2010-02-25 03:20:504812 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4813 // Get the texture info that was previously bound here.
4814 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
4815 texture_unit.bound_texture_2d :
4816 texture_unit.bound_texture_cube_map;
4817 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:034818 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:504819 }
4820 }
4821 }
4822 }
4823 // Set the active texture back to whatever the user had it as.
4824 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:304825}
4826
[email protected]0d6bfdc2011-11-02 01:32:204827bool GLES2DecoderImpl::ClearUnclearedTextures() {
4828 // Only check if there are some uncleared textures.
4829 if (!texture_manager()->HaveUnsafeTextures()) {
4830 return true;
4831 }
4832
4833 // 1: Check all textures we are about to render with.
4834 if (current_program_) {
4835 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4836 current_program_->sampler_indices();
4837 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4838 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4839 current_program_->GetUniformInfo(sampler_indices[ii]);
4840 DCHECK(uniform_info);
4841 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4842 GLuint texture_unit_index = uniform_info->texture_units[jj];
4843 if (texture_unit_index < group_->max_texture_units()) {
4844 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4845 TextureManager::TextureInfo* texture_info =
4846 texture_unit.GetInfoForSamplerType(uniform_info->type);
4847 if (texture_info && !texture_info->SafeToRenderFrom()) {
4848 if (!texture_manager()->ClearRenderableLevels(this, texture_info)) {
4849 return false;
4850 }
4851 }
4852 }
4853 }
4854 }
4855 }
4856 return true;
4857}
4858
[email protected]07f54fcc2009-12-22 02:46:304859bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]689fa1c52010-06-09 18:35:034860 // NOTE: We specifically do not check current_program->IsValid() because
4861 // it could never be invalid since glUseProgram would have failed. While
4862 // glLinkProgram could later mark the program as invalid the previous
4863 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:144864 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:504865 // The program does not exist.
4866 // But GL says no ERROR.
4867 return false;
4868 }
[email protected]f39f4b3f2010-05-12 17:04:084869 // Validate all attribs currently enabled. If they are used by the current
4870 // program then check that they have enough elements to handle the draw call.
4871 // If they are not used by the current program check that they have a buffer
4872 // assigned.
4873 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:444874 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]f39f4b3f2010-05-12 17:04:084875 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:404876 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:084877 const VertexAttribManager::VertexAttribInfo* info = *it;
4878 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4879 current_program_->GetAttribInfoByLocation(info->index());
4880 if (attrib_info) {
4881 // This attrib is used in the current program.
4882 if (!info->CanAccess(max_vertex_accessed)) {
4883 SetGLError(GL_INVALID_OPERATION,
4884 "glDrawXXX: attempt to access out of range vertices");
4885 return false;
4886 }
4887 } else {
4888 // This attrib is not used in the current program.
[email protected]a0b78dc2011-11-11 10:43:104889 if (!info->buffer()) {
[email protected]f39f4b3f2010-05-12 17:04:084890 SetGLError(
4891 GL_INVALID_OPERATION,
4892 "glDrawXXX: attempt to render with no buffer attached to enabled "
4893 "attrib");
4894 return false;
4895 }
[email protected]1d32bc82010-01-13 22:06:464896 }
[email protected]07f54fcc2009-12-22 02:46:304897 }
[email protected]3916c97e2010-02-25 03:20:504898 return true;
[email protected]b1122982010-05-17 23:04:244899}
4900
[email protected]c13e1da62011-09-09 21:48:304901bool GLES2DecoderImpl::SimulateAttrib0(
4902 GLuint max_vertex_accessed, bool* simulated) {
4903 DCHECK(simulated);
4904 *simulated = false;
4905
[email protected]876f6fee2010-08-02 23:10:324906 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
[email protected]c13e1da62011-09-09 21:48:304907 return true;
[email protected]876f6fee2010-08-02 23:10:324908
[email protected]b1122982010-05-17 23:04:244909 const VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:444910 vertex_attrib_manager_->GetVertexAttribInfo(0);
[email protected]b1122982010-05-17 23:04:244911 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:494912 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
4913 if (info->enabled() && attrib_0_used) {
[email protected]c13e1da62011-09-09 21:48:304914 return true;
[email protected]b1122982010-05-17 23:04:244915 }
4916
[email protected]b1122982010-05-17 23:04:244917 // Make a buffer with a single repeated vec4 value enough to
4918 // simulate the constant value that is supposed to be here.
4919 // This is required to emulate GLES2 on GL.
[email protected]c13e1da62011-09-09 21:48:304920 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
4921
4922 GLuint num_vertices = max_vertex_accessed + 1;
4923 GLuint size_needed = 0;
4924
4925 if (num_vertices == 0 ||
4926 !SafeMultiply(num_vertices, static_cast<GLuint>(sizeof(Vec4)),
4927 &size_needed) ||
4928 size_needed > 0x7FFFFFFFU) {
4929 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
4930 return false;
4931 }
4932
4933 CopyRealGLErrorsToWrapper();
4934 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
4935
4936 if (static_cast<GLsizei>(size_needed) > attrib_0_size_) {
[email protected]fc753442011-02-04 19:49:494937 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:304938 GLenum error = glGetError();
4939 if (error != GL_NO_ERROR) {
4940 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
4941 return false;
4942 }
[email protected]fc753442011-02-04 19:49:494943 attrib_0_buffer_matches_value_ = false;
4944 }
4945 if (attrib_0_used &&
4946 (!attrib_0_buffer_matches_value_ ||
4947 (info->value().v[0] != attrib_0_value_.v[0] ||
4948 info->value().v[1] != attrib_0_value_.v[1] ||
4949 info->value().v[2] != attrib_0_value_.v[2] ||
4950 info->value().v[3] != attrib_0_value_.v[3]))) {
4951 std::vector<Vec4> temp(num_vertices, info->value());
4952 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
4953 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:244954 attrib_0_value_ = info->value();
4955 attrib_0_size_ = size_needed;
4956 }
4957
4958 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4959
[email protected]c13e1da62011-09-09 21:48:304960 *simulated = true;
[email protected]b1122982010-05-17 23:04:244961 return true;
[email protected]b1122982010-05-17 23:04:244962}
4963
4964void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
4965 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 const void* ptr = reinterpret_cast<const void*>(info->offset());
4968 BufferManager::BufferInfo* buffer_info = info->buffer();
4969 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
4970 glVertexAttribPointer(
4971 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
4972 ptr);
4973 glBindBuffer(GL_ARRAY_BUFFER,
4974 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4975}
[email protected]07f54fcc2009-12-22 02:46:304976
[email protected]8fbedc02010-11-18 18:43:404977bool GLES2DecoderImpl::SimulateFixedAttribs(
4978 GLuint max_vertex_accessed, bool* simulated) {
4979 DCHECK(simulated);
4980 *simulated = false;
4981 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4982 return true;
4983
[email protected]3757a372012-01-19 05:20:444984 if (!vertex_attrib_manager_->HaveFixedAttribs()) {
[email protected]8fbedc02010-11-18 18:43:404985 return true;
4986 }
4987
4988 // NOTE: we could be smart and try to check if a buffer is used
4989 // twice in 2 different attribs, find the overlapping parts and therefore
4990 // duplicate the minimum amount of data but this whole code path is not meant
4991 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
4992 // tests so we just add to the buffer attrib used.
4993
4994 // Compute the number of elements needed.
[email protected]c13e1da62011-09-09 21:48:304995 GLuint num_vertices = max_vertex_accessed + 1;
4996 if (num_vertices == 0) {
4997 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
4998 return false;
4999 }
5000
5001 GLuint elements_needed = 0;
[email protected]8fbedc02010-11-18 18:43:405002 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:445003 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]8fbedc02010-11-18 18:43:405004 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5005 infos.begin(); it != infos.end(); ++it) {
5006 const VertexAttribManager::VertexAttribInfo* info = *it;
5007 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5008 current_program_->GetAttribInfoByLocation(info->index());
5009 if (attrib_info &&
5010 info->CanAccess(max_vertex_accessed) &&
5011 info->type() == GL_FIXED) {
[email protected]c13e1da62011-09-09 21:48:305012 GLuint elements_used = 0;
5013 if (!SafeMultiply(num_vertices,
5014 static_cast<GLuint>(info->size()), &elements_used) ||
[email protected]8fbedc02010-11-18 18:43:405015 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
5016 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5017 return false;
5018 }
5019 }
5020 }
5021
[email protected]c13e1da62011-09-09 21:48:305022 const GLuint kSizeOfFloat = sizeof(float); // NOLINT
5023 GLuint size_needed = 0;
5024 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed) ||
5025 size_needed > 0x7FFFFFFFU) {
[email protected]8fbedc02010-11-18 18:43:405026 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5027 return false;
5028 }
5029
[email protected]c13e1da62011-09-09 21:48:305030 CopyRealGLErrorsToWrapper();
[email protected]8fbedc02010-11-18 18:43:405031
5032 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
[email protected]c13e1da62011-09-09 21:48:305033 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
[email protected]8fbedc02010-11-18 18:43:405034 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305035 GLenum error = glGetError();
5036 if (error != GL_NO_ERROR) {
5037 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5038 return false;
5039 }
[email protected]8fbedc02010-11-18 18:43:405040 }
5041
5042 // Copy the elements and convert to float
5043 GLintptr offset = 0;
5044 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5045 infos.begin(); it != infos.end(); ++it) {
5046 const VertexAttribManager::VertexAttribInfo* info = *it;
5047 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5048 current_program_->GetAttribInfoByLocation(info->index());
5049 if (attrib_info &&
5050 info->CanAccess(max_vertex_accessed) &&
5051 info->type() == GL_FIXED) {
5052 int num_elements = info->size() * kSizeOfFloat;
5053 int size = num_elements * num_vertices;
5054 scoped_array<float> data(new float[size]);
5055 const int32* src = reinterpret_cast<const int32 *>(
5056 info->buffer()->GetRange(info->offset(), size));
5057 const int32* end = src + num_elements;
5058 float* dst = data.get();
5059 while (src != end) {
5060 *dst++ = static_cast<float>(*src++) / 65536.0f;
5061 }
5062 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
5063 glVertexAttribPointer(
5064 info->index(), info->size(), GL_FLOAT, false, 0,
5065 reinterpret_cast<GLvoid*>(offset));
5066 offset += size;
5067 }
5068 }
5069 *simulated = true;
5070 return true;
5071}
5072
5073void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
5074 // There's no need to call glVertexAttribPointer because we shadow all the
5075 // settings and passing GL_FIXED to it will not work.
5076 glBindBuffer(GL_ARRAY_BUFFER,
5077 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
5078}
5079
[email protected]38d139d2011-07-14 00:38:435080error::Error GLES2DecoderImpl::HandleDrawArrays(
5081 uint32 immediate_data_size, const gles2::DrawArrays& c) {
5082 GLenum mode = static_cast<GLenum>(c.mode);
5083 GLint first = static_cast<GLint>(c.first);
5084 GLsizei count = static_cast<GLsizei>(c.count);
5085 if (!validators_->draw_mode.IsValid(mode)) {
5086 SetGLError(GL_INVALID_ENUM, "glDrawArrays: mode GL_INVALID_ENUM");
5087 return error::kNoError;
5088 }
5089 if (count < 0) {
5090 SetGLError(GL_INVALID_VALUE, "glDrawArrays: count < 0");
5091 return error::kNoError;
5092 }
[email protected]0d6bfdc2011-11-02 01:32:205093 if (!CheckBoundFramebuffersValid("glDrawArrays")) {
[email protected]38d139d2011-07-14 00:38:435094 return error::kNoError;
5095 }
5096 // We have to check this here because the prototype for glDrawArrays
5097 // is GLint not GLsizei.
5098 if (first < 0) {
5099 SetGLError(GL_INVALID_VALUE, "glDrawArrays: first < 0");
5100 return error::kNoError;
5101 }
5102
5103 if (count == 0) {
5104 return error::kNoError;
5105 }
5106
5107 GLuint max_vertex_accessed = first + count - 1;
5108 if (IsDrawValid(max_vertex_accessed)) {
[email protected]0d6bfdc2011-11-02 01:32:205109 if (!ClearUnclearedTextures()) {
5110 SetGLError(GL_INVALID_VALUE, "glDrawArrays: out of memory");
5111 return error::kNoError;
5112 }
[email protected]c13e1da62011-09-09 21:48:305113 bool simulated_attrib_0 = false;
5114 if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
5115 return error::kNoError;
5116 }
[email protected]38d139d2011-07-14 00:38:435117 bool simulated_fixed_attribs = false;
5118 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
5119 bool textures_set = SetBlackTextureForNonRenderableTextures();
5120 ApplyDirtyState();
5121 glDrawArrays(mode, first, count);
5122 if (textures_set) {
5123 RestoreStateForNonRenderableTextures();
5124 }
5125 if (simulated_fixed_attribs) {
5126 RestoreStateForSimulatedFixedAttribs();
5127 }
5128 }
5129 if (simulated_attrib_0) {
5130 RestoreStateForSimulatedAttrib0();
5131 }
5132 if (WasContextLost()) {
5133 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawArrays.";
5134 return error::kLostContext;
5135 }
5136 }
5137 return error::kNoError;
5138}
5139
[email protected]f7a64ee2010-02-01 22:24:145140error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:195141 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]a0b78dc2011-11-11 10:43:105142 if (!bound_element_array_buffer_) {
[email protected]8eee29c2010-04-29 03:38:295143 SetGLError(GL_INVALID_OPERATION,
5144 "glDrawElements: No element array buffer bound");
5145 return error::kNoError;
5146 }
5147
5148 GLenum mode = c.mode;
5149 GLsizei count = c.count;
5150 GLenum type = c.type;
5151 int32 offset = c.index_offset;
5152 if (count < 0) {
5153 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
5154 return error::kNoError;
5155 }
5156 if (offset < 0) {
5157 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
5158 return error::kNoError;
5159 }
[email protected]9438b012010-06-15 22:55:055160 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:295161 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
5162 return error::kNoError;
5163 }
[email protected]9438b012010-06-15 22:55:055164 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295165 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
5166 return error::kNoError;
5167 }
5168
[email protected]0d6bfdc2011-11-02 01:32:205169 if (!CheckBoundFramebuffersValid("glDrawElements")) {
[email protected]3a03a8f2011-03-19 00:51:275170 return error::kNoError;
5171 }
5172
[email protected]6c788fb72010-08-26 02:16:315173 if (count == 0) {
5174 return error::kNoError;
5175 }
5176
[email protected]8eee29c2010-04-29 03:38:295177 GLuint max_vertex_accessed;
5178 if (!bound_element_array_buffer_->GetMaxValueForRange(
5179 offset, count, type, &max_vertex_accessed)) {
5180 SetGLError(GL_INVALID_OPERATION,
5181 "glDrawElements: range out of bounds for buffer");
5182 return error::kNoError;
5183 }
5184
5185 if (IsDrawValid(max_vertex_accessed)) {
[email protected]0d6bfdc2011-11-02 01:32:205186 if (!ClearUnclearedTextures()) {
5187 SetGLError(GL_INVALID_VALUE, "glDrawElements: out of memory");
5188 return error::kNoError;
5189 }
[email protected]c13e1da62011-09-09 21:48:305190 bool simulated_attrib_0 = false;
5191 if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
5192 return error::kNoError;
5193 }
[email protected]8fbedc02010-11-18 18:43:405194 bool simulated_fixed_attribs = false;
5195 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
5196 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:465197 ApplyDirtyState();
[email protected]8fbedc02010-11-18 18:43:405198 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
5199 glDrawElements(mode, count, type, indices);
5200 if (textures_set) {
5201 RestoreStateForNonRenderableTextures();
5202 }
5203 if (simulated_fixed_attribs) {
5204 RestoreStateForSimulatedFixedAttribs();
5205 }
[email protected]ba3176a2009-12-16 18:19:465206 }
[email protected]b1122982010-05-17 23:04:245207 if (simulated_attrib_0) {
5208 RestoreStateForSimulatedAttrib0();
5209 }
[email protected]38d139d2011-07-14 00:38:435210 if (WasContextLost()) {
5211 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawElements.";
5212 return error::kLostContext;
5213 }
[email protected]96449d2c2009-11-25 00:01:325214 }
[email protected]f7a64ee2010-02-01 22:24:145215 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325216}
5217
[email protected]269200b12010-11-18 22:53:065218GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:235219 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
5220 GLuint max_vertex_accessed = 0;
5221 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:295222 if (!info) {
[email protected]ae51d192010-04-27 00:48:035223 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:295224 SetGLError(GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:065225 "GetMaxValueInBufferCHROMIUM: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:235226 } else {
5227 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:035228 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:065229 SetGLError(
5230 GL_INVALID_OPERATION,
5231 "GetMaxValueInBufferCHROMIUM: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:235232 }
5233 }
5234 return max_vertex_accessed;
5235}
5236
[email protected]96449d2c2009-11-25 00:01:325237// Calls glShaderSource for the various versions of the ShaderSource command.
5238// Assumes that data / data_size points to a piece of memory that is in range
5239// of whatever context it came from (shared memory, immediate memory, bucket
5240// memory.)
[email protected]45bf5152010-02-12 00:11:315241error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035242 GLuint client_id, const char* data, uint32 data_size) {
[email protected]258a3313f2011-10-18 20:13:575243 std::string str(data, data + data_size);
[email protected]6b8cf1a2010-05-06 16:13:585244 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5245 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:315246 if (!info) {
[email protected]45bf5152010-02-12 00:11:315247 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325248 }
[email protected]45bf5152010-02-12 00:11:315249 // Note: We don't actually call glShaderSource here. We wait until
5250 // the call to glCompileShader.
[email protected]258a3313f2011-10-18 20:13:575251 info->UpdateSource(str.c_str());
[email protected]f7a64ee2010-02-01 22:24:145252 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325253}
5254
[email protected]f7a64ee2010-02-01 22:24:145255error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:195256 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:325257 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315258 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:325259 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:465260 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145261 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325262 }
[email protected]ae51d192010-04-27 00:48:035263 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:325264}
5265
[email protected]f7a64ee2010-02-01 22:24:145266error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:195267 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:325268 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315269 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:305270 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465271 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145272 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325273 }
[email protected]ae51d192010-04-27 00:48:035274 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:315275}
5276
[email protected]558847a2010-03-24 07:02:545277error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
5278 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:545279 Bucket* bucket = GetBucket(c.data_bucket_id);
5280 if (!bucket || bucket->size() == 0) {
5281 return error::kInvalidArguments;
5282 }
5283 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035284 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:545285 bucket->size() - 1);
5286}
5287
[email protected]ae51d192010-04-27 00:48:035288void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]0c8fabf2011-06-14 19:35:225289 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]6b8cf1a2010-05-06 16:13:585290 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5291 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:315292 if (!info) {
[email protected]45bf5152010-02-12 00:11:315293 return;
5294 }
[email protected]de17df392010-04-23 21:09:415295 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
5296 // glShaderSource and then glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:525297 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:345298 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:185299 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:345300 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:455301 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:235302
[email protected]a550584e2010-09-17 18:01:455303 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:345304 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:185305 return;
5306 }
[email protected]a550584e2010-09-17 18:01:455307 shader_src = translator->translated_shader();
[email protected]93297702011-11-05 05:09:465308 if (!feature_info_->feature_flags().angle_translated_shader_source)
[email protected]d6a53e42011-10-05 00:09:365309 info->UpdateTranslatedSource(shader_src);
[email protected]de17df392010-04-23 21:09:415310 }
[email protected]de17df392010-04-23 21:09:415311
[email protected]ae51d192010-04-27 00:48:035312 glShaderSource(info->service_id(), 1, &shader_src, NULL);
5313 glCompileShader(info->service_id());
[email protected]93297702011-11-05 05:09:465314 if (feature_info_->feature_flags().angle_translated_shader_source) {
[email protected]d6a53e42011-10-05 00:09:365315 GLint max_len = 0;
5316 glGetShaderiv(info->service_id(),
5317 GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
5318 &max_len);
5319 scoped_array<char> temp(new char[max_len]);
5320 GLint len = 0;
5321 glGetTranslatedShaderSourceANGLE(
5322 info->service_id(), max_len, &len, temp.get());
5323 DCHECK(max_len == 0 || len < max_len);
5324 DCHECK(len == 0 || temp[len] == '\0');
5325 info->UpdateTranslatedSource(temp.get());
5326 }
5327
[email protected]e5186162010-06-14 18:54:415328 GLint status = GL_FALSE;
5329 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
5330 if (status) {
[email protected]f57bb282010-11-12 00:51:345331 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:415332 } else {
[email protected]d9977d42010-09-01 20:27:025333 // We cannot reach here if we are using the shader translator.
5334 // All invalid shaders must be rejected by the translator.
5335 // All translated shaders must compile.
5336 LOG_IF(ERROR, use_shader_translator_)
5337 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:335338 GLint max_len = 0;
5339 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
5340 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:415341 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:335342 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
5343 DCHECK(max_len == 0 || len < max_len);
[email protected]d6a53e42011-10-05 00:09:365344 DCHECK(len == 0 || temp[len] == '\0');
[email protected]df6cf1ad2011-01-29 01:20:525345 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
[email protected]e5186162010-06-14 18:54:415346 }
[email protected]45bf5152010-02-12 00:11:315347};
5348
[email protected]ddd968b82010-03-02 00:44:295349void GLES2DecoderImpl::DoGetShaderiv(
5350 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:585351 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5352 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:295353 if (!info) {
[email protected]ddd968b82010-03-02 00:44:295354 return;
5355 }
[email protected]8f1ccdac2010-05-19 21:01:485356 switch (pname) {
5357 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525358 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:485359 return;
5360 case GL_COMPILE_STATUS:
[email protected]062c38b2012-01-18 03:25:105361 *params = compile_shader_always_succeeds_ ? true : info->IsValid();
[email protected]e5186162010-06-14 18:54:415362 return;
[email protected]8f1ccdac2010-05-19 21:01:485363 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525364 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:415365 return;
[email protected]d6a53e42011-10-05 00:09:365366 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5367 *params = info->translated_source() ?
5368 info->translated_source()->size() + 1 : 0;
5369 return;
[email protected]8f1ccdac2010-05-19 21:01:485370 default:
5371 break;
[email protected]ddd968b82010-03-02 00:44:295372 }
[email protected]8f1ccdac2010-05-19 21:01:485373 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:295374}
5375
[email protected]ae51d192010-04-27 00:48:035376error::Error GLES2DecoderImpl::HandleGetShaderSource(
5377 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
5378 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:035379 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5380 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:585381 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5382 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:525383 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:295384 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:295385 return error::kNoError;
5386 }
[email protected]df6cf1ad2011-01-29 01:20:525387 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:035388 return error::kNoError;
5389}
5390
[email protected]d6a53e42011-10-05 00:09:365391error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
5392 uint32 immediate_data_size,
5393 const gles2::GetTranslatedShaderSourceANGLE& c) {
5394 GLuint shader = c.shader;
5395
5396 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5397 Bucket* bucket = CreateBucket(bucket_id);
5398 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5399 shader, "glTranslatedGetShaderSourceANGLE");
5400 if (!info) {
5401 bucket->SetSize(0);
5402 return error::kNoError;
5403 }
5404
5405 bucket->SetFromString(info->translated_source() ?
5406 info->translated_source()->c_str() : NULL);
5407 return error::kNoError;
5408}
5409
[email protected]ae51d192010-04-27 00:48:035410error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
5411 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
5412 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:585413 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5414 Bucket* bucket = CreateBucket(bucket_id);
5415 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5416 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525417 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465418 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035419 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:315420 }
[email protected]df6cf1ad2011-01-29 01:20:525421 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035422 return error::kNoError;
5423}
5424
5425error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
5426 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
5427 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:585428 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5429 Bucket* bucket = CreateBucket(bucket_id);
5430 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5431 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525432 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465433 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035434 return error::kNoError;
5435 }
[email protected]df6cf1ad2011-01-29 01:20:525436 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035437 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325438}
5439
[email protected]1958e0e2010-04-22 05:17:155440bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105441 const BufferManager::BufferInfo* buffer = GetBufferInfo(client_id);
5442 return buffer && buffer->IsValid() && !buffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155443}
5444
5445bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105446 const FramebufferManager::FramebufferInfo* framebuffer =
[email protected]06c8b082011-01-05 18:00:365447 GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105448 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155449}
5450
5451bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365452 // IsProgram is true for programs as soon as they are created, until they are
5453 // deleted and no longer in use.
[email protected]a0b78dc2011-11-11 10:43:105454 const ProgramManager::ProgramInfo* program = GetProgramInfo(client_id);
5455 return program != NULL && !program->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155456}
5457
5458bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105459 const RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]06c8b082011-01-05 18:00:365460 GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105461 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155462}
5463
5464bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365465 // IsShader is true for shaders as soon as they are created, until they
5466 // are deleted and not attached to any programs.
[email protected]a0b78dc2011-11-11 10:43:105467 const ShaderManager::ShaderInfo* shader = GetShaderInfo(client_id);
5468 return shader != NULL && !shader->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155469}
5470
5471bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105472 const TextureManager::TextureInfo* texture = GetTextureInfo(client_id);
5473 return texture && texture->IsValid() && !texture->IsDeleted();
[email protected]ae51d192010-04-27 00:48:035474}
5475
5476void GLES2DecoderImpl::DoAttachShader(
5477 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585478 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5479 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035480 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035481 return;
[email protected]1958e0e2010-04-22 05:17:155482 }
[email protected]6b8cf1a2010-05-06 16:13:585483 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5484 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035485 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035486 return;
5487 }
[email protected]ca488e12010-12-13 20:06:145488 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:315489 SetGLError(GL_INVALID_OPERATION,
5490 "glAttachShader: can not attach more than"
5491 " one shader of the same type.");
5492 return;
5493 }
[email protected]ae51d192010-04-27 00:48:035494 glAttachShader(program_info->service_id(), shader_info->service_id());
5495}
5496
5497void GLES2DecoderImpl::DoDetachShader(
5498 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585499 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5500 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035501 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035502 return;
5503 }
[email protected]6b8cf1a2010-05-06 16:13:585504 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5505 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035506 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035507 return;
5508 }
[email protected]9a0ccd42011-03-16 23:58:225509 if (!program_info->DetachShader(shader_manager(), shader_info)) {
5510 SetGLError(GL_INVALID_OPERATION,
5511 "glDetachShader: shader not attached to program");
5512 return;
5513 }
[email protected]ae51d192010-04-27 00:48:035514 glDetachShader(program_info->service_id(), shader_info->service_id());
5515}
5516
5517void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585518 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5519 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:035520 if (!info) {
[email protected]ae51d192010-04-27 00:48:035521 return;
5522 }
[email protected]d685a682011-04-29 16:19:575523 info->Validate();
[email protected]1958e0e2010-04-22 05:17:155524}
5525
[email protected]b1122982010-05-17 23:04:245526void GLES2DecoderImpl::DoGetVertexAttribfv(
5527 GLuint index, GLenum pname, GLfloat* params) {
5528 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445529 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245530 if (!info) {
5531 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
5532 return;
5533 }
5534 switch (pname) {
5535 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5536 BufferManager::BufferInfo* buffer = info->buffer();
5537 if (buffer && !buffer->IsDeleted()) {
5538 GLuint client_id;
5539 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5540 *params = static_cast<GLfloat>(client_id);
5541 }
5542 break;
5543 }
5544 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5545 *params = static_cast<GLfloat>(info->enabled());
5546 break;
5547 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5548 *params = static_cast<GLfloat>(info->size());
5549 break;
5550 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5551 *params = static_cast<GLfloat>(info->gl_stride());
5552 break;
5553 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5554 *params = static_cast<GLfloat>(info->type());
5555 break;
5556 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5557 *params = static_cast<GLfloat>(info->normalized());
5558 break;
5559 case GL_CURRENT_VERTEX_ATTRIB:
5560 params[0] = info->value().v[0];
5561 params[1] = info->value().v[1];
5562 params[2] = info->value().v[2];
5563 params[3] = info->value().v[3];
5564 break;
5565 default:
5566 NOTREACHED();
5567 break;
5568 }
5569}
5570
5571void GLES2DecoderImpl::DoGetVertexAttribiv(
5572 GLuint index, GLenum pname, GLint* params) {
5573 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445574 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245575 if (!info) {
5576 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
5577 return;
5578 }
5579 switch (pname) {
5580 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5581 BufferManager::BufferInfo* buffer = info->buffer();
5582 if (buffer && !buffer->IsDeleted()) {
5583 GLuint client_id;
5584 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5585 *params = client_id;
5586 }
5587 break;
5588 }
5589 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5590 *params = info->enabled();
5591 break;
5592 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5593 *params = info->size();
5594 break;
5595 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5596 *params = info->gl_stride();
5597 break;
5598 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5599 *params = info->type();
5600 break;
5601 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5602 *params = static_cast<GLint>(info->normalized());
5603 break;
5604 case GL_CURRENT_VERTEX_ATTRIB:
5605 params[0] = static_cast<GLint>(info->value().v[0]);
5606 params[1] = static_cast<GLint>(info->value().v[1]);
5607 params[2] = static_cast<GLint>(info->value().v[2]);
5608 params[3] = static_cast<GLint>(info->value().v[3]);
5609 break;
5610 default:
5611 NOTREACHED();
5612 break;
5613 }
5614}
5615
5616void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
5617 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445618 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245619 if (!info) {
5620 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
5621 return;
5622 }
5623 VertexAttribManager::VertexAttribInfo::Vec4 value;
5624 value.v[0] = v0;
5625 value.v[1] = 0.0f;
5626 value.v[2] = 0.0f;
5627 value.v[3] = 1.0f;
5628 info->set_value(value);
5629 glVertexAttrib1f(index, v0);
5630}
5631
5632void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
5633 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445634 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245635 if (!info) {
5636 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
5637 return;
5638 }
5639 VertexAttribManager::VertexAttribInfo::Vec4 value;
5640 value.v[0] = v0;
5641 value.v[1] = v1;
5642 value.v[2] = 0.0f;
5643 value.v[3] = 1.0f;
5644 info->set_value(value);
5645 glVertexAttrib2f(index, v0, v1);
5646}
5647
5648void GLES2DecoderImpl::DoVertexAttrib3f(
5649 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
5650 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445651 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245652 if (!info) {
5653 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
5654 return;
5655 }
5656 VertexAttribManager::VertexAttribInfo::Vec4 value;
5657 value.v[0] = v0;
5658 value.v[1] = v1;
5659 value.v[2] = v2;
5660 value.v[3] = 1.0f;
5661 info->set_value(value);
5662 glVertexAttrib3f(index, v0, v1, v2);
5663}
5664
5665void GLES2DecoderImpl::DoVertexAttrib4f(
5666 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
5667 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445668 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245669 if (!info) {
5670 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
5671 return;
5672 }
5673 VertexAttribManager::VertexAttribInfo::Vec4 value;
5674 value.v[0] = v0;
5675 value.v[1] = v1;
5676 value.v[2] = v2;
5677 value.v[3] = v3;
5678 info->set_value(value);
5679 glVertexAttrib4f(index, v0, v1, v2, v3);
5680}
5681
5682void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
5683 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445684 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245685 if (!info) {
5686 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
5687 return;
5688 }
5689 VertexAttribManager::VertexAttribInfo::Vec4 value;
5690 value.v[0] = v[0];
5691 value.v[1] = 0.0f;
5692 value.v[2] = 0.0f;
5693 value.v[3] = 1.0f;
5694 info->set_value(value);
5695 glVertexAttrib1fv(index, v);
5696}
5697
5698void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
5699 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445700 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245701 if (!info) {
5702 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
5703 return;
5704 }
5705 VertexAttribManager::VertexAttribInfo::Vec4 value;
5706 value.v[0] = v[0];
5707 value.v[1] = v[1];
5708 value.v[2] = 0.0f;
5709 value.v[3] = 1.0f;
5710 info->set_value(value);
5711 glVertexAttrib2fv(index, v);
5712}
5713
5714void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
5715 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445716 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245717 if (!info) {
5718 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
5719 return;
5720 }
5721 VertexAttribManager::VertexAttribInfo::Vec4 value;
5722 value.v[0] = v[0];
5723 value.v[1] = v[1];
5724 value.v[2] = v[2];
5725 value.v[3] = 1.0f;
5726 info->set_value(value);
5727 glVertexAttrib3fv(index, v);
5728}
5729
5730void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
5731 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445732 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245733 if (!info) {
5734 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
5735 return;
5736 }
5737 VertexAttribManager::VertexAttribInfo::Vec4 value;
5738 value.v[0] = v[0];
5739 value.v[1] = v[1];
5740 value.v[2] = v[2];
5741 value.v[3] = v[3];
5742 info->set_value(value);
5743 glVertexAttrib4fv(index, v);
5744}
5745
[email protected]f7a64ee2010-02-01 22:24:145746error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:195747 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:295748 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
5749 SetGLError(GL_INVALID_VALUE,
5750 "glVertexAttribPointer: no array buffer bound");
5751 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325752 }
[email protected]8eee29c2010-04-29 03:38:295753
5754 GLuint indx = c.indx;
5755 GLint size = c.size;
5756 GLenum type = c.type;
5757 GLboolean normalized = c.normalized;
5758 GLsizei stride = c.stride;
5759 GLsizei offset = c.offset;
5760 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:055761 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295762 SetGLError(GL_INVALID_ENUM,
5763 "glVertexAttribPointer: type GL_INVALID_ENUM");
5764 return error::kNoError;
5765 }
[email protected]9438b012010-06-15 22:55:055766 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:315767 SetGLError(GL_INVALID_VALUE,
[email protected]8eee29c2010-04-29 03:38:295768 "glVertexAttribPointer: size GL_INVALID_VALUE");
5769 return error::kNoError;
5770 }
5771 if (indx >= group_->max_vertex_attribs()) {
5772 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
5773 return error::kNoError;
5774 }
5775 if (stride < 0) {
5776 SetGLError(GL_INVALID_VALUE,
5777 "glVertexAttribPointer: stride < 0");
5778 return error::kNoError;
5779 }
5780 if (stride > 255) {
5781 SetGLError(GL_INVALID_VALUE,
5782 "glVertexAttribPointer: stride > 255");
5783 return error::kNoError;
5784 }
5785 if (offset < 0) {
5786 SetGLError(GL_INVALID_VALUE,
5787 "glVertexAttribPointer: offset < 0");
5788 return error::kNoError;
5789 }
5790 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:315791 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:295792 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:315793 SetGLError(GL_INVALID_OPERATION,
5794 "glVertexAttribPointer: offset not valid for type");
5795 return error::kNoError;
5796 }
5797 if (stride % component_size > 0) {
5798 SetGLError(GL_INVALID_OPERATION,
[email protected]8eee29c2010-04-29 03:38:295799 "glVertexAttribPointer: stride not valid for type");
5800 return error::kNoError;
5801 }
[email protected]3757a372012-01-19 05:20:445802 vertex_attrib_manager_->SetAttribInfo(
[email protected]8fbedc02010-11-18 18:43:405803 indx,
[email protected]8eee29c2010-04-29 03:38:295804 bound_array_buffer_,
5805 size,
5806 type,
[email protected]b1122982010-05-17 23:04:245807 normalized,
5808 stride,
5809 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:295810 offset);
[email protected]8fbedc02010-11-18 18:43:405811 if (type != GL_FIXED) {
5812 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
5813 }
[email protected]f7a64ee2010-02-01 22:24:145814 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325815}
5816
[email protected]f7a64ee2010-02-01 22:24:145817error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:195818 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:315819 GLint x = c.x;
5820 GLint y = c.y;
5821 GLsizei width = c.width;
5822 GLsizei height = c.height;
5823 GLenum format = c.format;
5824 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:565825 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:295826 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:565827 return error::kNoError;
5828 }
[email protected]a51788e2010-02-24 21:54:255829 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:185830 uint32 pixels_size;
5831 if (!GLES2Util::ComputeImageDataSize(
5832 width, height, format, type, pack_alignment_, &pixels_size)) {
5833 return error::kOutOfBounds;
5834 }
[email protected]612d2f82009-12-08 20:49:315835 void* pixels = GetSharedMemoryAs<void*>(
5836 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:255837 Result* result = GetSharedMemoryAs<Result*>(
5838 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5839 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:145840 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465841 }
[email protected]a51788e2010-02-24 21:54:255842
[email protected]9438b012010-06-15 22:55:055843 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295844 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
5845 return error::kNoError;
5846 }
[email protected]9438b012010-06-15 22:55:055847 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295848 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125849 return error::kNoError;
5850 }
[email protected]57f223832010-03-19 01:57:565851 if (width == 0 || height == 0) {
5852 return error::kNoError;
5853 }
5854
[email protected]57f223832010-03-19 01:57:565855 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:305856 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:565857
5858 GLint max_x;
5859 GLint max_y;
5860 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:295861 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:145862 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:315863 }
[email protected]57f223832010-03-19 01:57:565864
[email protected]0d6bfdc2011-11-02 01:32:205865 if (!CheckBoundFramebuffersValid("glReadPixels")) {
5866 return error::kNoError;
5867 }
5868
[email protected]a0b78dc2011-11-11 10:43:105869 CopyRealGLErrorsToWrapper();
5870
5871 ScopedResolvedFrameBufferBinder binder(this, false, true);
5872
[email protected]d37231fa2010-04-09 21:16:025873 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:565874 // The user requested an out of range area. Get the results 1 line
5875 // at a time.
5876 uint32 temp_size;
5877 if (!GLES2Util::ComputeImageDataSize(
5878 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295879 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565880 return error::kNoError;
5881 }
5882 GLsizei unpadded_row_size = temp_size;
5883 if (!GLES2Util::ComputeImageDataSize(
5884 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295885 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565886 return error::kNoError;
5887 }
5888 GLsizei padded_row_size = temp_size - unpadded_row_size;
5889 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:295890 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565891 return error::kNoError;
5892 }
5893
5894 GLint dest_x_offset = std::max(-x, 0);
5895 uint32 dest_row_offset;
5896 if (!GLES2Util::ComputeImageDataSize(
5897 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:295898 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565899 return error::kNoError;
5900 }
5901
5902 // Copy each row into the larger dest rect.
5903 int8* dst = static_cast<int8*>(pixels);
5904 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:025905 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:565906 GLint read_width = read_end_x - read_x;
5907 for (GLint yy = 0; yy < height; ++yy) {
5908 GLint ry = y + yy;
5909
5910 // Clear the row.
5911 memset(dst, 0, unpadded_row_size);
5912
5913 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:025914 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:565915 glReadPixels(
5916 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
5917 }
5918 dst += padded_row_size;
5919 }
5920 } else {
5921 glReadPixels(x, y, width, height, format, type, pixels);
5922 }
[email protected]1002c2d2011-06-28 22:39:045923 GLenum error = PeekGLError();
[email protected]a51788e2010-02-24 21:54:255924 if (error == GL_NO_ERROR) {
5925 *result = true;
[email protected]4848b9f82011-03-10 18:37:565926
5927 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5928 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5929 if ((channels_exist & 0x0008) == 0) {
5930 // Set the alpha to 255 because some drivers are buggy in this regard.
5931 uint32 temp_size;
5932 if (!GLES2Util::ComputeImageDataSize(
5933 width, 1, format, type, pack_alignment_, &temp_size)) {
5934 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5935 return error::kNoError;
5936 }
5937 GLsizei unpadded_row_size = temp_size;
5938 if (!GLES2Util::ComputeImageDataSize(
5939 width, 2, format, type, pack_alignment_, &temp_size)) {
5940 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5941 return error::kNoError;
5942 }
5943 GLsizei padded_row_size = temp_size - unpadded_row_size;
5944 if (padded_row_size < 0 || unpadded_row_size < 0) {
5945 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5946 return error::kNoError;
5947 }
5948 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
5949 // of this implementation.
5950 if (type != GL_UNSIGNED_BYTE) {
5951 SetGLError(GL_INVALID_OPERATION, "unsupported readPixel format");
5952 return error::kNoError;
5953 }
5954 switch (format) {
5955 case GL_RGBA:
[email protected]297ca1c2011-06-20 23:08:465956 case GL_BGRA_EXT:
[email protected]4848b9f82011-03-10 18:37:565957 case GL_ALPHA: {
5958 int offset = (format == GL_ALPHA) ? 0 : 3;
5959 int step = (format == GL_ALPHA) ? 1 : 4;
5960 uint8* dst = static_cast<uint8*>(pixels) + offset;
5961 for (GLint yy = 0; yy < height; ++yy) {
5962 uint8* end = dst + unpadded_row_size;
5963 for (uint8* d = dst; d < end; d += step) {
5964 *d = 255;
5965 }
5966 dst += padded_row_size;
5967 }
5968 break;
5969 }
5970 default:
5971 break;
5972 }
5973 }
[email protected]a51788e2010-02-24 21:54:255974 }
[email protected]4848b9f82011-03-10 18:37:565975
[email protected]f7a64ee2010-02-01 22:24:145976 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325977}
5978
[email protected]f7a64ee2010-02-01 22:24:145979error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:195980 uint32 immediate_data_size, const gles2::PixelStorei& c) {
5981 GLenum pname = c.pname;
5982 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:055983 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:295984 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125985 return error::kNoError;
5986 }
[email protected]222471d2011-11-30 18:06:395987 switch (pname) {
5988 case GL_PACK_ALIGNMENT:
5989 case GL_UNPACK_ALIGNMENT:
5990 if (!validators_->pixel_store_alignment.IsValid(param)) {
5991 SetGLError(GL_INVALID_VALUE,
5992 "glPixelSTore: param GL_INVALID_VALUE");
5993 return error::kNoError;
5994 }
5995 default:
5996 break;
[email protected]b9849abf2009-11-25 19:13:195997 }
5998 glPixelStorei(pname, param);
5999 switch (pname) {
6000 case GL_PACK_ALIGNMENT:
6001 pack_alignment_ = param;
6002 break;
[email protected]222471d2011-11-30 18:06:396003 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
6004 break;
[email protected]b9849abf2009-11-25 19:13:196005 case GL_UNPACK_ALIGNMENT:
6006 unpack_alignment_ = param;
6007 break;
6008 default:
6009 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:376010 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:196011 break;
6012 }
[email protected]f7a64ee2010-02-01 22:24:146013 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196014}
6015
[email protected]1c75a3702011-11-11 14:15:286016error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
6017 uint32 immediate_data_size, const gles2::PostSubBufferCHROMIUM& c) {
6018 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
[email protected]aa258822011-11-22 13:52:256019 if (!context_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
[email protected]1c75a3702011-11-11 14:15:286020 SetGLError(GL_INVALID_OPERATION,
6021 "glPostSubBufferCHROMIUM: command not supported by surface");
6022 return error::kNoError;
6023 }
6024 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height))
6025 return error::kNoError;
6026 else
6027 return error::kLostContext;
6028}
6029
[email protected]558847a2010-03-24 07:02:546030error::Error GLES2DecoderImpl::GetAttribLocationHelper(
6031 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6032 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576033 if (!StringIsValidForGLES(name_str.c_str())) {
6034 SetGLError(GL_INVALID_VALUE, "glGetAttribLocation: Invalid character");
6035 return error::kNoError;
6036 }
[email protected]6b8cf1a2010-05-06 16:13:586037 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6038 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:036039 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146040 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196041 }
[email protected]ae51d192010-04-27 00:48:036042 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:296043 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:256044 return error::kNoError;
6045 }
[email protected]b9849abf2009-11-25 19:13:196046 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546047 location_shm_id, location_shm_offset, sizeof(GLint));
6048 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146049 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196050 }
[email protected]558847a2010-03-24 07:02:546051 // Require the client to init this incase the context is lost and we are no
6052 // longer executing commands.
6053 if (*location != -1) {
6054 return error::kGenericError;
6055 }
[email protected]0bfd9882010-02-05 23:02:256056 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:146057 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196058}
6059
[email protected]558847a2010-03-24 07:02:546060error::Error GLES2DecoderImpl::HandleGetAttribLocation(
6061 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
6062 uint32 name_size = c.data_size;
6063 const char* name = GetSharedMemoryAs<const char*>(
6064 c.name_shm_id, c.name_shm_offset, name_size);
6065 if (!name) {
6066 return error::kOutOfBounds;
6067 }
6068 String name_str(name, name_size);
6069 return GetAttribLocationHelper(
6070 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6071}
6072
[email protected]f7a64ee2010-02-01 22:24:146073error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196074 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:546075 uint32 name_size = c.data_size;
6076 const char* name = GetImmediateDataAs<const char*>(
6077 c, name_size, immediate_data_size);
6078 if (!name) {
6079 return error::kOutOfBounds;
6080 }
6081 String name_str(name, name_size);
6082 return GetAttribLocationHelper(
6083 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6084}
6085
6086error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
6087 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
6088 Bucket* bucket = GetBucket(c.name_bucket_id);
6089 if (!bucket) {
6090 return error::kInvalidArguments;
6091 }
6092 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186093 if (!bucket->GetAsString(&name_str)) {
6094 return error::kInvalidArguments;
6095 }
[email protected]558847a2010-03-24 07:02:546096 return GetAttribLocationHelper(
6097 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6098}
6099
6100error::Error GLES2DecoderImpl::GetUniformLocationHelper(
6101 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6102 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576103 if (!StringIsValidForGLES(name_str.c_str())) {
6104 SetGLError(GL_INVALID_VALUE, "glGetUniformLocation: Invalid character");
6105 return error::kNoError;
6106 }
[email protected]6b8cf1a2010-05-06 16:13:586107 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6108 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:036109 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146110 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196111 }
[email protected]ae51d192010-04-27 00:48:036112 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:296113 SetGLError(GL_INVALID_OPERATION,
6114 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:256115 return error::kNoError;
6116 }
[email protected]b9849abf2009-11-25 19:13:196117 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546118 location_shm_id, location_shm_offset, sizeof(GLint));
6119 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146120 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196121 }
[email protected]558847a2010-03-24 07:02:546122 // Require the client to init this incase the context is lost an we are no
6123 // longer executing commands.
6124 if (*location != -1) {
6125 return error::kGenericError;
6126 }
[email protected]5d4c6b22012-02-07 08:22:286127 *location = program_manager()->SwizzleLocation(
6128 info->GetUniformLocation(name_str));
[email protected]f7a64ee2010-02-01 22:24:146129 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196130}
6131
[email protected]f7a64ee2010-02-01 22:24:146132error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:196133 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:196134 uint32 name_size = c.data_size;
6135 const char* name = GetSharedMemoryAs<const char*>(
6136 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:546137 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146138 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196139 }
6140 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546141 return GetUniformLocationHelper(
6142 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196143}
6144
[email protected]f7a64ee2010-02-01 22:24:146145error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196146 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:196147 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:306148 const char* name = GetImmediateDataAs<const char*>(
6149 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:546150 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146151 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196152 }
6153 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546154 return GetUniformLocationHelper(
6155 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6156}
6157
6158error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
6159 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
6160 Bucket* bucket = GetBucket(c.name_bucket_id);
6161 if (!bucket) {
6162 return error::kInvalidArguments;
6163 }
6164 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186165 if (!bucket->GetAsString(&name_str)) {
6166 return error::kInvalidArguments;
6167 }
[email protected]558847a2010-03-24 07:02:546168 return GetUniformLocationHelper(
6169 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196170}
6171
[email protected]ddd968b82010-03-02 00:44:296172error::Error GLES2DecoderImpl::HandleGetString(
6173 uint32 immediate_data_size, const gles2::GetString& c) {
6174 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:056175 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:296176 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:296177 return error::kNoError;
6178 }
[email protected]1958e0e2010-04-22 05:17:156179 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
6180 const char* str = NULL;
[email protected]f0d74742011-10-03 16:31:046181 std::string extensions;
[email protected]1958e0e2010-04-22 05:17:156182 switch (name) {
6183 case GL_VERSION:
6184 str = "OpenGL ES 2.0 Chromium";
6185 break;
6186 case GL_SHADING_LANGUAGE_VERSION:
6187 str = "OpenGL ES GLSL ES 1.0 Chromium";
6188 break;
6189 case GL_EXTENSIONS:
[email protected]f0d74742011-10-03 16:31:046190 {
6191 // For WebGL contexts, strip out the OES derivatives extension if it has
6192 // not been enabled.
6193 if (force_webgl_glsl_validation_ &&
6194 !derivatives_explicitly_enabled_) {
6195 extensions = feature_info_->extensions();
6196 size_t offset = extensions.find(kOESDerivativeExtension);
6197 if (std::string::npos != offset) {
6198 extensions.replace(offset,
6199 offset + arraysize(kOESDerivativeExtension),
6200 std::string());
6201 }
6202 str = extensions.c_str();
6203 } else {
6204 str = feature_info_->extensions().c_str();
6205 }
[email protected]f0d74742011-10-03 16:31:046206 }
[email protected]1958e0e2010-04-22 05:17:156207 break;
6208 default:
6209 str = gl_str;
6210 break;
6211 }
[email protected]ddd968b82010-03-02 00:44:296212 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:156213 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:296214 return error::kNoError;
6215}
6216
[email protected]0c86dbf2010-03-05 08:14:116217void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:156218 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:056219 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296220 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
6221 return;
6222 }
[email protected]9438b012010-06-15 22:55:056223 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:296224 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:116225 return;
[email protected]3b6ec202010-03-05 05:16:236226 }
6227 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:296228 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:286229 return;
[email protected]3b6ec202010-03-05 05:16:236230 }
6231 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
6232 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296233 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:286234 return;
[email protected]3b6ec202010-03-05 05:16:236235 }
6236 // Clear the buffer to 0 if no initial data was passed in.
6237 scoped_array<int8> zero;
6238 if (!data) {
6239 zero.reset(new int8[size]);
6240 memset(zero.get(), 0, size);
6241 data = zero.get();
6242 }
[email protected]473c01ccb2011-06-07 01:33:306243
6244 if (!bufferdata_faster_than_buffersubdata_ &&
6245 size == info->size() && usage == info->usage()) {
6246 glBufferSubData(target, 0, size, data);
6247 info->SetRange(0, size, data);
6248 return;
6249 }
6250
[email protected]3b6ec202010-03-05 05:16:236251 CopyRealGLErrorsToWrapper();
6252 glBufferData(target, size, data, usage);
[email protected]1002c2d2011-06-28 22:39:046253 GLenum error = PeekGLError();
6254 if (error == GL_NO_ERROR) {
[email protected]473c01ccb2011-06-07 01:33:306255 buffer_manager()->SetInfo(info, size, usage);
[email protected]0c86dbf2010-03-05 08:14:116256 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:236257 }
[email protected]0c86dbf2010-03-05 08:14:116258}
6259
6260error::Error GLES2DecoderImpl::HandleBufferData(
6261 uint32 immediate_data_size, const gles2::BufferData& c) {
6262 GLenum target = static_cast<GLenum>(c.target);
6263 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
6264 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6265 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6266 GLenum usage = static_cast<GLenum>(c.usage);
6267 const void* data = NULL;
6268 if (data_shm_id != 0 || data_shm_offset != 0) {
6269 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
6270 if (!data) {
6271 return error::kOutOfBounds;
6272 }
6273 }
6274 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:146275 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196276}
6277
[email protected]f7a64ee2010-02-01 22:24:146278error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:196279 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
6280 GLenum target = static_cast<GLenum>(c.target);
6281 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:306282 const void* data = GetImmediateDataAs<const void*>(
6283 c, size, immediate_data_size);
6284 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146285 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:306286 }
[email protected]b9849abf2009-11-25 19:13:196287 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:116288 DoBufferData(target, size, data, usage);
6289 return error::kNoError;
6290}
6291
6292void GLES2DecoderImpl::DoBufferSubData(
6293 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:506294 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476295 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296296 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:286297 return;
[email protected]a93bb842010-02-16 23:03:476298 }
[email protected]0c86dbf2010-03-05 08:14:116299 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:296300 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]473c01ccb2011-06-07 01:33:306301 return;
[email protected]07f54fcc2009-12-22 02:46:306302 }
[email protected]473c01ccb2011-06-07 01:33:306303 if (bufferdata_faster_than_buffersubdata_ &&
6304 offset == 0 && size == info->size()) {
6305 glBufferData(target, size, data, info->usage());
6306 return;
6307 }
6308 glBufferSubData(target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:196309}
6310
[email protected]0d6bfdc2011-11-02 01:32:206311bool GLES2DecoderImpl::ClearLevel(
6312 unsigned service_id,
6313 unsigned bind_target,
6314 unsigned target,
6315 int level,
6316 unsigned format,
6317 unsigned type,
6318 int width,
[email protected]4502e6492011-12-14 19:39:156319 int height,
6320 bool is_texture_immutable) {
[email protected]0d6bfdc2011-11-02 01:32:206321 // Assumes the size has already been checked.
6322 uint32 pixels_size = 0;
6323 if (!GLES2Util::ComputeImageDataSize(
6324 width, height, format, type, unpack_alignment_, &pixels_size)) {
6325 return false;
6326 }
6327 scoped_array<char> zero(new char[pixels_size]);
6328 memset(zero.get(), 0, pixels_size);
6329 glBindTexture(bind_target, service_id);
[email protected]4502e6492011-12-14 19:39:156330 if (is_texture_immutable) {
6331 glTexSubImage2D(
6332 target, level, 0, 0, width, height, format, type, zero.get());
6333 } else {
6334 WrappedTexImage2D(
6335 target, level, format, width, height, 0, format, type, zero.get());
6336 }
[email protected]0d6bfdc2011-11-02 01:32:206337 TextureManager::TextureInfo* info = GetTextureInfoForTarget(bind_target);
6338 glBindTexture(bind_target, info ? info->service_id() : 0);
6339 return true;
6340}
6341
[email protected]a93bb842010-02-16 23:03:476342error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
6343 GLenum target,
6344 GLint level,
6345 GLenum internal_format,
6346 GLsizei width,
6347 GLsizei height,
6348 GLint border,
6349 GLsizei image_size,
6350 const void* data) {
[email protected]a93bb842010-02-16 23:03:476351 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:056352 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296353 SetGLError(GL_INVALID_ENUM,
6354 "glCompressedTexImage2D: target GL_INVALID_ENUM");
6355 return error::kNoError;
6356 }
[email protected]9438b012010-06-15 22:55:056357 if (!validators_->compressed_texture_format.IsValid(
6358 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296359 SetGLError(GL_INVALID_ENUM,
6360 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:476361 return error::kNoError;
6362 }
[email protected]80eb6b52012-01-19 00:14:416363 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476364 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296365 SetGLError(GL_INVALID_VALUE,
6366 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476367 return error::kNoError;
6368 }
[email protected]3916c97e2010-02-25 03:20:506369 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476370 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296371 SetGLError(GL_INVALID_VALUE,
6372 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:476373 return error::kNoError;
6374 }
[email protected]97dc7cbe2011-12-06 17:26:176375 if (info->IsImmutable()) {
6376 SetGLError(GL_INVALID_OPERATION,
6377 "glCompressedTexImage2D: texture is immutable");
6378 return error::kNoError;
6379 }
[email protected]968351b2011-12-20 08:26:516380
6381 if (info->IsAttachedToFramebuffer()) {
6382 state_dirty_ = true;
6383 // TODO(gman): If textures tracked which framebuffers they were attached to
6384 // we could just mark those framebuffers as not complete.
6385 framebuffer_manager()->IncFramebufferStateChangeCount();
6386 }
6387
[email protected]a93bb842010-02-16 23:03:476388 scoped_array<int8> zero;
6389 if (!data) {
6390 zero.reset(new int8[image_size]);
6391 memset(zero.get(), 0, image_size);
6392 data = zero.get();
6393 }
[email protected]cadde4a2010-07-31 17:10:436394 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:476395 glCompressedTexImage2D(
6396 target, level, internal_format, width, height, border, image_size, data);
[email protected]1002c2d2011-06-28 22:39:046397 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436398 if (error == GL_NO_ERROR) {
6399 texture_manager()->SetLevelInfo(
[email protected]0d6bfdc2011-11-02 01:32:206400 info, target, level, internal_format, width, height, 1, border, 0, 0,
6401 true);
[email protected]cadde4a2010-07-31 17:10:436402 }
[email protected]a93bb842010-02-16 23:03:476403 return error::kNoError;
6404}
6405
[email protected]f7a64ee2010-02-01 22:24:146406error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196407 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
6408 GLenum target = static_cast<GLenum>(c.target);
6409 GLint level = static_cast<GLint>(c.level);
6410 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6411 GLsizei width = static_cast<GLsizei>(c.width);
6412 GLsizei height = static_cast<GLsizei>(c.height);
6413 GLint border = static_cast<GLint>(c.border);
6414 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
6415 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6416 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6417 const void* data = NULL;
6418 if (data_shm_id != 0 || data_shm_offset != 0) {
6419 data = GetSharedMemoryAs<const void*>(
6420 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:466421 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146422 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196423 }
6424 }
[email protected]a93bb842010-02-16 23:03:476425 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196426 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:196427}
6428
[email protected]f7a64ee2010-02-01 22:24:146429error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:196430 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
6431 GLenum target = static_cast<GLenum>(c.target);
6432 GLint level = static_cast<GLint>(c.level);
6433 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6434 GLsizei width = static_cast<GLsizei>(c.width);
6435 GLsizei height = static_cast<GLsizei>(c.height);
6436 GLint border = static_cast<GLint>(c.border);
6437 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:306438 const void* data = GetImmediateDataAs<const void*>(
6439 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466440 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146441 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466442 }
[email protected]a93bb842010-02-16 23:03:476443 return DoCompressedTexImage2D(
6444 target, level, internal_format, width, height, border, image_size, data);
6445}
6446
[email protected]b6140d02010-05-17 14:47:166447error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
6448 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
6449 GLenum target = static_cast<GLenum>(c.target);
6450 GLint level = static_cast<GLint>(c.level);
6451 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6452 GLsizei width = static_cast<GLsizei>(c.width);
6453 GLsizei height = static_cast<GLsizei>(c.height);
6454 GLint border = static_cast<GLint>(c.border);
6455 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:286456 if (!bucket) {
6457 return error::kInvalidArguments;
6458 }
6459 uint32 data_size = bucket->size();
6460 GLsizei imageSize = data_size;
6461 const void* data = bucket->GetData(0, data_size);
6462 if (!data) {
6463 return error::kInvalidArguments;
6464 }
[email protected]b6140d02010-05-17 14:47:166465 return DoCompressedTexImage2D(
6466 target, level, internal_format, width, height, border,
[email protected]12f93d82011-10-17 21:16:286467 imageSize, data);
[email protected]b6140d02010-05-17 14:47:166468}
6469
6470error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
6471 uint32 immediate_data_size,
6472 const gles2::CompressedTexSubImage2DBucket& c) {
6473 GLenum target = static_cast<GLenum>(c.target);
6474 GLint level = static_cast<GLint>(c.level);
6475 GLint xoffset = static_cast<GLint>(c.xoffset);
6476 GLint yoffset = static_cast<GLint>(c.yoffset);
6477 GLsizei width = static_cast<GLsizei>(c.width);
6478 GLsizei height = static_cast<GLsizei>(c.height);
6479 GLenum format = static_cast<GLenum>(c.format);
6480 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:286481 if (!bucket) {
6482 return error::kInvalidArguments;
6483 }
[email protected]b6140d02010-05-17 14:47:166484 uint32 data_size = bucket->size();
6485 GLsizei imageSize = data_size;
6486 const void* data = bucket->GetData(0, data_size);
[email protected]12f93d82011-10-17 21:16:286487 if (!data) {
6488 return error::kInvalidArguments;
6489 }
[email protected]9438b012010-06-15 22:55:056490 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:166491 SetGLError(
6492 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
6493 return error::kNoError;
6494 }
[email protected]9438b012010-06-15 22:55:056495 if (!validators_->compressed_texture_format.IsValid(format)) {
6496 SetGLError(GL_INVALID_ENUM,
6497 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
6498 return error::kNoError;
6499 }
[email protected]b6140d02010-05-17 14:47:166500 if (width < 0) {
6501 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
6502 return error::kNoError;
6503 }
6504 if (height < 0) {
6505 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
6506 return error::kNoError;
6507 }
6508 if (imageSize < 0) {
6509 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
6510 return error::kNoError;
6511 }
[email protected]cadde4a2010-07-31 17:10:436512 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:166513 target, level, xoffset, yoffset, width, height, format, imageSize, data);
6514 return error::kNoError;
6515}
6516
[email protected]a93bb842010-02-16 23:03:476517error::Error GLES2DecoderImpl::DoTexImage2D(
6518 GLenum target,
6519 GLint level,
6520 GLenum internal_format,
6521 GLsizei width,
6522 GLsizei height,
6523 GLint border,
6524 GLenum format,
6525 GLenum type,
6526 const void* pixels,
6527 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:056528 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296529 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
6530 return error::kNoError;
6531 }
[email protected]9438b012010-06-15 22:55:056532 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296533 SetGLError(GL_INVALID_ENUM,
6534 "glTexImage2D: internal_format GL_INVALID_ENUM");
6535 return error::kNoError;
6536 }
[email protected]9438b012010-06-15 22:55:056537 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:296538 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
6539 return error::kNoError;
6540 }
[email protected]9438b012010-06-15 22:55:056541 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:296542 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:146543 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196544 }
[email protected]7b92c412010-07-20 17:48:256545 if (format != internal_format) {
6546 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
6547 return error::kNoError;
6548 }
[email protected]80eb6b52012-01-19 00:14:416549 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476550 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296551 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476552 return error::kNoError;
6553 }
[email protected]3916c97e2010-02-25 03:20:506554 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476555 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296556 SetGLError(GL_INVALID_OPERATION,
6557 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:476558 return error::kNoError;
6559 }
[email protected]0226c112011-07-22 03:25:076560
[email protected]97dc7cbe2011-12-06 17:26:176561 if (info->IsImmutable()) {
6562 SetGLError(GL_INVALID_OPERATION,
6563 "glTexImage2D: texture is immutable");
6564 return error::kNoError;
6565 }
6566
[email protected]0226c112011-07-22 03:25:076567 GLsizei tex_width = 0;
6568 GLsizei tex_height = 0;
6569 GLenum tex_type = 0;
6570 GLenum tex_format = 0;
6571 bool level_is_same =
6572 info->GetLevelSize(target, level, &tex_width, &tex_height) &&
6573 info->GetLevelType(target, level, &tex_type, &tex_format) &&
6574 width == tex_width && height == tex_height &&
6575 type == tex_type && format == tex_format;
6576
6577 if (level_is_same && !pixels) {
[email protected]1bed6222011-12-21 11:21:396578 // Just set the level info but mark the texture as uncleared.
6579 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416580 info,
[email protected]1bed6222011-12-21 11:21:396581 target, level, internal_format, width, height, 1, border, format, type,
6582 false);
[email protected]ea72ed222011-08-17 18:58:436583 tex_image_2d_failed_ = false;
[email protected]0226c112011-07-22 03:25:076584 return error::kNoError;
6585 }
6586
[email protected]297ca1c2011-06-20 23:08:466587 if (info->IsAttachedToFramebuffer()) {
6588 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:516589 // TODO(gman): If textures tracked which framebuffers they were attached to
6590 // we could just mark those framebuffers as not complete.
6591 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:466592 }
6593
[email protected]1bed6222011-12-21 11:21:396594 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same && pixels) {
[email protected]0226c112011-07-22 03:25:076595 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
[email protected]57edfdad2012-02-07 04:57:156596 texture_manager()->SetLevelCleared(info, target, level);
[email protected]0226c112011-07-22 03:25:076597 tex_image_2d_failed_ = false;
6598 return error::kNoError;
[email protected]7488d962010-07-16 02:41:586599 }
[email protected]876f6fee2010-08-02 23:10:326600
[email protected]cadde4a2010-07-31 17:10:436601 CopyRealGLErrorsToWrapper();
[email protected]473c01ccb2011-06-07 01:33:306602 WrappedTexImage2D(
6603 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476604 pixels);
[email protected]1002c2d2011-06-28 22:39:046605 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436606 if (error == GL_NO_ERROR) {
[email protected]0d6bfdc2011-11-02 01:32:206607 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416608 info,
[email protected]0d6bfdc2011-11-02 01:32:206609 target, level, internal_format, width, height, 1, border, format, type,
6610 pixels != NULL);
[email protected]b493ee622011-04-13 23:52:006611 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:436612 }
[email protected]f7a64ee2010-02-01 22:24:146613 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196614}
6615
[email protected]f7a64ee2010-02-01 22:24:146616error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196617 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]366ae242011-05-10 02:23:586618 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:006619 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:196620 GLenum target = static_cast<GLenum>(c.target);
6621 GLint level = static_cast<GLint>(c.level);
6622 GLint internal_format = static_cast<GLint>(c.internalformat);
6623 GLsizei width = static_cast<GLsizei>(c.width);
6624 GLsizei height = static_cast<GLsizei>(c.height);
6625 GLint border = static_cast<GLint>(c.border);
6626 GLenum format = static_cast<GLenum>(c.format);
6627 GLenum type = static_cast<GLenum>(c.type);
6628 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
6629 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:186630 uint32 pixels_size;
6631 if (!GLES2Util::ComputeImageDataSize(
6632 width, height, format, type, unpack_alignment_, &pixels_size)) {
6633 return error::kOutOfBounds;
6634 }
[email protected]b9849abf2009-11-25 19:13:196635 const void* pixels = NULL;
6636 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
6637 pixels = GetSharedMemoryAs<const void*>(
6638 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:466639 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146640 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196641 }
6642 }
[email protected]a93bb842010-02-16 23:03:476643 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196644 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476645 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:196646}
6647
[email protected]f7a64ee2010-02-01 22:24:146648error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:196649 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
6650 GLenum target = static_cast<GLenum>(c.target);
6651 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:466652 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:196653 GLsizei width = static_cast<GLsizei>(c.width);
6654 GLsizei height = static_cast<GLsizei>(c.height);
6655 GLint border = static_cast<GLint>(c.border);
6656 GLenum format = static_cast<GLenum>(c.format);
6657 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:186658 uint32 size;
6659 if (!GLES2Util::ComputeImageDataSize(
6660 width, height, format, type, unpack_alignment_, &size)) {
6661 return error::kOutOfBounds;
6662 }
[email protected]07f54fcc2009-12-22 02:46:306663 const void* pixels = GetImmediateDataAs<const void*>(
6664 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466665 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146666 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466667 }
[email protected]a93bb842010-02-16 23:03:476668 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:466669 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476670 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:146671 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326672}
6673
[email protected]cadde4a2010-07-31 17:10:436674void GLES2DecoderImpl::DoCompressedTexSubImage2D(
6675 GLenum target,
6676 GLint level,
6677 GLint xoffset,
6678 GLint yoffset,
6679 GLsizei width,
6680 GLsizei height,
6681 GLenum format,
6682 GLsizei image_size,
6683 const void * data) {
6684 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6685 if (!info) {
6686 SetGLError(GL_INVALID_OPERATION,
6687 "glCompressedTexSubImage2D: unknown texture for target");
6688 return;
6689 }
6690 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:526691 GLenum internal_format = 0;
6692 if (!info->GetLevelType(target, level, &type, &internal_format)) {
6693 SetGLError(
6694 GL_INVALID_OPERATION,
[email protected]4502e6492011-12-14 19:39:156695 "glCompressedTexSubImage2D: level does not exist.");
[email protected]df6cf1ad2011-01-29 01:20:526696 return;
6697 }
6698 if (internal_format != format) {
6699 SetGLError(
6700 GL_INVALID_OPERATION,
[email protected]4502e6492011-12-14 19:39:156701 "glCompressedTexSubImage2D: format does not match internal format.");
[email protected]df6cf1ad2011-01-29 01:20:526702 return;
6703 }
6704 if (!info->ValidForTexture(
6705 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:436706 SetGLError(GL_INVALID_VALUE,
[email protected]4502e6492011-12-14 19:39:156707 "glCompressedTexSubImage2D: bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:436708 return;
6709 }
[email protected]0d6bfdc2011-11-02 01:32:206710 // Note: There is no need to deal with texture cleared tracking here
6711 // because the validation above means you can only get here if the level
6712 // is already a matching compressed format and in that case
6713 // CompressedTexImage2D already cleared the texture.
[email protected]cadde4a2010-07-31 17:10:436714 glCompressedTexSubImage2D(
6715 target, level, xoffset, yoffset, width, height, format, image_size, data);
6716}
6717
[email protected]6e288612010-12-21 20:45:036718static void Clip(
6719 GLint start, GLint range, GLint sourceRange,
6720 GLint* out_start, GLint* out_range) {
6721 DCHECK(out_start);
6722 DCHECK(out_range);
6723 if (start < 0) {
6724 range += start;
6725 start = 0;
6726 }
6727 GLint end = start + range;
6728 if (end > sourceRange) {
6729 range -= end - sourceRange;
6730 }
6731 *out_start = start;
6732 *out_range = range;
6733}
6734
[email protected]cadde4a2010-07-31 17:10:436735void GLES2DecoderImpl::DoCopyTexImage2D(
6736 GLenum target,
6737 GLint level,
6738 GLenum internal_format,
6739 GLint x,
6740 GLint y,
6741 GLsizei width,
6742 GLsizei height,
6743 GLint border) {
6744 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6745 if (!info) {
6746 SetGLError(GL_INVALID_OPERATION,
6747 "glCopyTexImage2D: unknown texture for target");
6748 return;
6749 }
[email protected]97dc7cbe2011-12-06 17:26:176750 if (info->IsImmutable()) {
6751 SetGLError(GL_INVALID_OPERATION,
6752 "glCopyTexImage2D: texture is immutable");
6753 }
[email protected]80eb6b52012-01-19 00:14:416754 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:186755 border != 0) {
6756 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
6757 return;
6758 }
6759
[email protected]9edc6b22010-12-23 02:00:266760 // Check we have compatible formats.
6761 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6762 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6763 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
6764
6765 if ((channels_needed & channels_exist) != channels_needed) {
6766 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
6767 return;
6768 }
6769
[email protected]a0b78dc2011-11-11 10:43:106770 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
6771 return;
6772 }
6773
[email protected]cadde4a2010-07-31 17:10:436774 CopyRealGLErrorsToWrapper();
[email protected]de26b3c2011-08-03 21:54:276775 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:036776 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:266777
[email protected]297ca1c2011-06-20 23:08:466778 if (info->IsAttachedToFramebuffer()) {
6779 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:516780 // TODO(gman): If textures tracked which framebuffers they were attached to
6781 // we could just mark those framebuffers as not complete.
6782 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:466783 }
6784
[email protected]9edc6b22010-12-23 02:00:266785 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:036786 GLint copyX = 0;
6787 GLint copyY = 0;
6788 GLint copyWidth = 0;
6789 GLint copyHeight = 0;
6790 Clip(x, width, size.width(), &copyX, &copyWidth);
6791 Clip(y, height, size.height(), &copyY, &copyHeight);
6792
6793 if (copyX != x ||
6794 copyY != y ||
6795 copyWidth != width ||
6796 copyHeight != height) {
6797 // some part was clipped so clear the texture.
[email protected]0d6bfdc2011-11-02 01:32:206798 if (!ClearLevel(
6799 info->service_id(), info->target(),
[email protected]4502e6492011-12-14 19:39:156800 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
6801 info->IsImmutable())) {
[email protected]0d6bfdc2011-11-02 01:32:206802 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexImage2D: dimensions too big");
[email protected]6e288612010-12-21 20:45:036803 return;
6804 }
[email protected]6e288612010-12-21 20:45:036805 if (copyHeight > 0 && copyWidth > 0) {
6806 GLint dx = copyX - x;
6807 GLint dy = copyY - y;
6808 GLint destX = dx;
6809 GLint destY = dy;
6810 glCopyTexSubImage2D(target, level,
6811 destX, destY, copyX, copyY,
6812 copyWidth, copyHeight);
6813 }
6814 } else {
6815 glCopyTexImage2D(target, level, internal_format,
6816 copyX, copyY, copyWidth, copyHeight, border);
6817 }
[email protected]1002c2d2011-06-28 22:39:046818 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436819 if (error == GL_NO_ERROR) {
6820 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416821 info, target, level, internal_format, width, height, 1,
[email protected]0d6bfdc2011-11-02 01:32:206822 border, internal_format, GL_UNSIGNED_BYTE, true);
[email protected]cadde4a2010-07-31 17:10:436823 }
6824}
6825
6826void GLES2DecoderImpl::DoCopyTexSubImage2D(
6827 GLenum target,
6828 GLint level,
6829 GLint xoffset,
6830 GLint yoffset,
6831 GLint x,
6832 GLint y,
6833 GLsizei width,
6834 GLsizei height) {
6835 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6836 if (!info) {
6837 SetGLError(GL_INVALID_OPERATION,
6838 "glCopyTexSubImage2D: unknown texture for target");
6839 return;
6840 }
6841 GLenum type = 0;
6842 GLenum format = 0;
6843 if (!info->GetLevelType(target, level, &type, &format) ||
6844 !info->ValidForTexture(
6845 target, level, xoffset, yoffset, width, height, format, type)) {
6846 SetGLError(GL_INVALID_VALUE,
6847 "glCopyTexSubImage2D: bad dimensions.");
6848 return;
6849 }
[email protected]9edc6b22010-12-23 02:00:266850
6851 // Check we have compatible formats.
6852 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6853 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6854 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
6855
6856 if ((channels_needed & channels_exist) != channels_needed) {
6857 SetGLError(
6858 GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
6859 return;
6860 }
6861
[email protected]a0b78dc2011-11-11 10:43:106862 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
6863 return;
6864 }
6865
[email protected]de26b3c2011-08-03 21:54:276866 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:036867 gfx::Size size = GetBoundReadFrameBufferSize();
6868 GLint copyX = 0;
6869 GLint copyY = 0;
6870 GLint copyWidth = 0;
6871 GLint copyHeight = 0;
6872 Clip(x, width, size.width(), &copyX, &copyWidth);
6873 Clip(y, height, size.height(), &copyY, &copyHeight);
[email protected]0d6bfdc2011-11-02 01:32:206874
6875 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
6876 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D: dimensions too big");
6877 return;
6878 }
6879
[email protected]6e288612010-12-21 20:45:036880 if (copyX != x ||
6881 copyY != y ||
6882 copyWidth != width ||
6883 copyHeight != height) {
[email protected]0d6bfdc2011-11-02 01:32:206884 // some part was clipped so clear the sub rect.
[email protected]6e288612010-12-21 20:45:036885 uint32 pixels_size = 0;
6886 if (!GLES2Util::ComputeImageDataSize(
6887 width, height, format, type, unpack_alignment_, &pixels_size)) {
6888 SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large");
6889 return;
6890 }
6891 scoped_array<char> zero(new char[pixels_size]);
6892 memset(zero.get(), 0, pixels_size);
6893 glTexSubImage2D(
6894 target, level, xoffset, yoffset, width, height,
6895 format, type, zero.get());
6896 }
[email protected]0d6bfdc2011-11-02 01:32:206897
[email protected]6e288612010-12-21 20:45:036898 if (copyHeight > 0 && copyWidth > 0) {
6899 GLint dx = copyX - x;
6900 GLint dy = copyY - y;
6901 GLint destX = xoffset + dx;
6902 GLint destY = yoffset + dy;
6903 glCopyTexSubImage2D(target, level,
6904 destX, destY, copyX, copyY,
6905 copyWidth, copyHeight);
6906 }
[email protected]cadde4a2010-07-31 17:10:436907}
6908
6909void GLES2DecoderImpl::DoTexSubImage2D(
6910 GLenum target,
6911 GLint level,
6912 GLint xoffset,
6913 GLint yoffset,
6914 GLsizei width,
6915 GLsizei height,
6916 GLenum format,
6917 GLenum type,
6918 const void * data) {
6919 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6920 if (!info) {
6921 SetGLError(GL_INVALID_OPERATION,
6922 "glTexSubImage2D: unknown texture for target");
6923 return;
6924 }
[email protected]df6cf1ad2011-01-29 01:20:526925 GLenum current_type = 0;
6926 GLenum internal_format = 0;
6927 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
6928 SetGLError(
6929 GL_INVALID_OPERATION,
6930 "glTexSubImage2D: level does not exist.");
6931 return;
6932 }
6933 if (format != internal_format) {
6934 SetGLError(GL_INVALID_OPERATION,
6935 "glTexSubImage2D: format does not match internal format.");
6936 return;
6937 }
6938 if (type != current_type) {
6939 SetGLError(GL_INVALID_OPERATION,
6940 "glTexSubImage2D: type does not match type of texture.");
6941 return;
6942 }
6943
[email protected]cadde4a2010-07-31 17:10:436944 if (!info->ValidForTexture(
6945 target, level, xoffset, yoffset, width, height, format, type)) {
6946 SetGLError(GL_INVALID_VALUE,
6947 "glTexSubImage2D: bad dimensions.");
6948 return;
6949 }
[email protected]473c01ccb2011-06-07 01:33:306950
[email protected]4502e6492011-12-14 19:39:156951 GLsizei tex_width = 0;
6952 GLsizei tex_height = 0;
6953 bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height);
6954 DCHECK(ok);
6955 if (xoffset != 0 || yoffset != 0 ||
6956 width != tex_width || height != tex_height) {
6957 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
6958 SetGLError(GL_OUT_OF_MEMORY, "glTexSubImage2D: dimensions too big");
[email protected]473c01ccb2011-06-07 01:33:306959 return;
6960 }
[email protected]4502e6492011-12-14 19:39:156961 glTexSubImage2D(
6962 target, level, xoffset, yoffset, width, height, format, type, data);
[email protected]0d6bfdc2011-11-02 01:32:206963 return;
6964 }
[email protected]4502e6492011-12-14 19:39:156965
6966 if (teximage2d_faster_than_texsubimage2d_ && !info->IsImmutable()) {
6967 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
6968 // same as internal_foramt. If that changes we'll need to look them up.
6969 WrappedTexImage2D(
6970 target, level, format, width, height, 0, format, type, data);
6971 } else {
6972 glTexSubImage2D(
6973 target, level, xoffset, yoffset, width, height, format, type, data);
6974 }
6975 texture_manager()->SetLevelCleared(info, target, level);
[email protected]cadde4a2010-07-31 17:10:436976}
6977
[email protected]b493ee622011-04-13 23:52:006978error::Error GLES2DecoderImpl::HandleTexSubImage2D(
6979 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]366ae242011-05-10 02:23:586980 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:006981 GLboolean internal = static_cast<GLboolean>(c.internal);
6982 if (internal == GL_TRUE && tex_image_2d_failed_)
6983 return error::kNoError;
6984
6985 GLenum target = static_cast<GLenum>(c.target);
6986 GLint level = static_cast<GLint>(c.level);
6987 GLint xoffset = static_cast<GLint>(c.xoffset);
6988 GLint yoffset = static_cast<GLint>(c.yoffset);
6989 GLsizei width = static_cast<GLsizei>(c.width);
6990 GLsizei height = static_cast<GLsizei>(c.height);
6991 GLenum format = static_cast<GLenum>(c.format);
6992 GLenum type = static_cast<GLenum>(c.type);
6993 uint32 data_size;
6994 if (!GLES2Util::ComputeImageDataSize(
6995 width, height, format, type, unpack_alignment_, &data_size)) {
6996 return error::kOutOfBounds;
6997 }
6998 const void* pixels = GetSharedMemoryAs<const void*>(
6999 c.pixels_shm_id, c.pixels_shm_offset, data_size);
7000 if (!validators_->texture_target.IsValid(target)) {
7001 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
7002 return error::kNoError;
7003 }
7004 if (width < 0) {
7005 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
7006 return error::kNoError;
7007 }
7008 if (height < 0) {
7009 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
7010 return error::kNoError;
7011 }
7012 if (!validators_->texture_format.IsValid(format)) {
7013 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
7014 return error::kNoError;
7015 }
7016 if (!validators_->pixel_type.IsValid(type)) {
7017 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
7018 return error::kNoError;
7019 }
7020 if (pixels == NULL) {
7021 return error::kOutOfBounds;
7022 }
7023 DoTexSubImage2D(
7024 target, level, xoffset, yoffset, width, height, format, type, pixels);
7025 return error::kNoError;
7026}
7027
7028error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
7029 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
7030 GLboolean internal = static_cast<GLboolean>(c.internal);
7031 if (internal == GL_TRUE && tex_image_2d_failed_)
7032 return error::kNoError;
7033
7034 GLenum target = static_cast<GLenum>(c.target);
7035 GLint level = static_cast<GLint>(c.level);
7036 GLint xoffset = static_cast<GLint>(c.xoffset);
7037 GLint yoffset = static_cast<GLint>(c.yoffset);
7038 GLsizei width = static_cast<GLsizei>(c.width);
7039 GLsizei height = static_cast<GLsizei>(c.height);
7040 GLenum format = static_cast<GLenum>(c.format);
7041 GLenum type = static_cast<GLenum>(c.type);
7042 uint32 data_size;
7043 if (!GLES2Util::ComputeImageDataSize(
7044 width, height, format, type, unpack_alignment_, &data_size)) {
7045 return error::kOutOfBounds;
7046 }
7047 const void* pixels = GetImmediateDataAs<const void*>(
7048 c, data_size, immediate_data_size);
7049 if (!validators_->texture_target.IsValid(target)) {
7050 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
7051 return error::kNoError;
7052 }
7053 if (width < 0) {
7054 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
7055 return error::kNoError;
7056 }
7057 if (height < 0) {
7058 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
7059 return error::kNoError;
7060 }
7061 if (!validators_->texture_format.IsValid(format)) {
7062 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
7063 return error::kNoError;
7064 }
7065 if (!validators_->pixel_type.IsValid(type)) {
7066 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
7067 return error::kNoError;
7068 }
7069 if (pixels == NULL) {
7070 return error::kOutOfBounds;
7071 }
7072 DoTexSubImage2D(
7073 target, level, xoffset, yoffset, width, height, format, type, pixels);
7074 return error::kNoError;
7075}
7076
[email protected]f7a64ee2010-02-01 22:24:147077error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:197078 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:367079 GLuint index = static_cast<GLuint>(c.index);
7080 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:257081 typedef gles2::GetVertexAttribPointerv::Result Result;
7082 Result* result = GetSharedMemoryAs<Result*>(
7083 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:367084 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:147085 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:367086 }
[email protected]07d0cc82010-02-17 04:51:407087 // Check that the client initialized the result.
7088 if (result->size != 0) {
7089 return error::kInvalidArguments;
7090 }
[email protected]9438b012010-06-15 22:55:057091 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:297092 SetGLError(GL_INVALID_ENUM,
7093 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:147094 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367095 }
[email protected]3916c97e2010-02-25 03:20:507096 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:297097 SetGLError(GL_INVALID_VALUE,
7098 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:147099 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367100 }
[email protected]0bfd9882010-02-05 23:02:257101 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:087102 *result->GetData() =
[email protected]3757a372012-01-19 05:20:447103 vertex_attrib_manager_->GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:147104 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327105}
7106
[email protected]f7b85372010-02-03 01:11:377107bool GLES2DecoderImpl::GetUniformSetup(
7108 GLuint program, GLint location,
7109 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:107110 error::Error* error, GLuint* service_id, void** result_pointer,
7111 GLenum* result_type) {
7112 DCHECK(error);
7113 DCHECK(service_id);
7114 DCHECK(result_pointer);
7115 DCHECK(result_type);
[email protected]f7b85372010-02-03 01:11:377116 *error = error::kNoError;
7117 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:257118 SizedResult<GLint>* result;
7119 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7120 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
7121 if (!result) {
[email protected]f7b85372010-02-03 01:11:377122 *error = error::kOutOfBounds;
7123 return false;
7124 }
[email protected]0bfd9882010-02-05 23:02:257125 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:377126 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:257127 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:587128 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7129 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:377130 if (!info) {
[email protected]ae51d192010-04-27 00:48:037131 return false;
7132 }
7133 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:377134 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:297135 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:377136 return false;
7137 }
[email protected]ae51d192010-04-27 00:48:037138 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:367139 GLint array_index = -1;
7140 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
7141 info->GetUniformInfoByLocation(location, &array_index);
7142 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:377143 // No such location.
[email protected]8eee29c2010-04-29 03:38:297144 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:377145 return false;
7146 }
[email protected]43c2f1f2011-03-25 18:35:367147 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:507148 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:377149 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:297150 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:377151 return false;
7152 }
[email protected]0bfd9882010-02-05 23:02:257153 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7154 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
7155 if (!result) {
[email protected]f7b85372010-02-03 01:11:377156 *error = error::kOutOfBounds;
7157 return false;
7158 }
[email protected]0bfd9882010-02-05 23:02:257159 result->size = size;
[email protected]939e7362010-05-13 20:49:107160 *result_type = type;
[email protected]f7b85372010-02-03 01:11:377161 return true;
7162}
7163
[email protected]f7a64ee2010-02-01 22:24:147164error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:197165 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:377166 GLuint program = c.program;
[email protected]5d4c6b22012-02-07 08:22:287167 GLint location = program_manager()->UnswizzleLocation(c.location);
[email protected]f7b85372010-02-03 01:11:377168 GLuint service_id;
[email protected]939e7362010-05-13 20:49:107169 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:377170 Error error;
[email protected]0bfd9882010-02-05 23:02:257171 void* result;
[email protected]f7b85372010-02-03 01:11:377172 if (GetUniformSetup(
7173 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:107174 &error, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:257175 glGetUniformiv(
7176 service_id, location,
7177 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:377178 }
7179 return error;
[email protected]96449d2c2009-11-25 00:01:327180}
7181
[email protected]f7a64ee2010-02-01 22:24:147182error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:197183 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:377184 GLuint program = c.program;
[email protected]5d4c6b22012-02-07 08:22:287185 GLint location = program_manager()->UnswizzleLocation(c.location);
[email protected]f7b85372010-02-03 01:11:377186 GLuint service_id;
7187 Error error;
[email protected]0bfd9882010-02-05 23:02:257188 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:107189 Result* result;
7190 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:377191 if (GetUniformSetup(
7192 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:107193 &error, &service_id, reinterpret_cast<void**>(&result), &result_type)) {
7194 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
7195 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
7196 GLsizei num_values = result->GetNumResults();
7197 scoped_array<GLint> temp(new GLint[num_values]);
7198 glGetUniformiv(service_id, location, temp.get());
7199 GLfloat* dst = result->GetData();
7200 for (GLsizei ii = 0; ii < num_values; ++ii) {
7201 dst[ii] = (temp[ii] != 0);
7202 }
7203 } else {
7204 glGetUniformfv(service_id, location, result->GetData());
7205 }
[email protected]f7b85372010-02-03 01:11:377206 }
7207 return error;
[email protected]96449d2c2009-11-25 00:01:327208}
7209
[email protected]f7a64ee2010-02-01 22:24:147210error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:197211 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:257212 GLenum shader_type = static_cast<GLenum>(c.shadertype);
7213 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
7214 typedef gles2::GetShaderPrecisionFormat::Result Result;
7215 Result* result = GetSharedMemoryAs<Result*>(
7216 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7217 if (!result) {
7218 return error::kOutOfBounds;
7219 }
[email protected]07d0cc82010-02-17 04:51:407220 // Check that the client initialized the result.
7221 if (result->success != 0) {
7222 return error::kInvalidArguments;
7223 }
[email protected]9438b012010-06-15 22:55:057224 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:297225 SetGLError(GL_INVALID_ENUM,
7226 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
7227 return error::kNoError;
7228 }
[email protected]9438b012010-06-15 22:55:057229 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:297230 SetGLError(GL_INVALID_ENUM,
7231 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
7232 return error::kNoError;
7233 }
7234
7235 result->success = 1; // true
7236 switch (precision_type) {
7237 case GL_LOW_INT:
7238 case GL_MEDIUM_INT:
7239 case GL_HIGH_INT:
7240 result->min_range = -31;
7241 result->max_range = 31;
7242 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:107243 break;
[email protected]8eee29c2010-04-29 03:38:297244 case GL_LOW_FLOAT:
7245 case GL_MEDIUM_FLOAT:
7246 case GL_HIGH_FLOAT:
7247 result->min_range = -62;
7248 result->max_range = 62;
7249 result->precision = -16;
7250 break;
7251 default:
7252 NOTREACHED();
7253 break;
[email protected]0bfd9882010-02-05 23:02:257254 }
[email protected]f7a64ee2010-02-01 22:24:147255 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327256}
7257
[email protected]f7a64ee2010-02-01 22:24:147258error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:197259 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:257260 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:587261 GLuint program = static_cast<GLuint>(c.program);
7262 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7263 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:037264 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257265 return error::kNoError;
7266 }
7267 typedef gles2::GetAttachedShaders::Result Result;
7268 uint32 max_count = Result::ComputeMaxResults(result_size);
7269 Result* result = GetSharedMemoryAs<Result*>(
7270 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
7271 if (!result) {
7272 return error::kOutOfBounds;
7273 }
[email protected]07d0cc82010-02-17 04:51:407274 // Check that the client initialized the result.
7275 if (result->size != 0) {
7276 return error::kInvalidArguments;
7277 }
[email protected]0bfd9882010-02-05 23:02:257278 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:037279 glGetAttachedShaders(
7280 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:257281 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:037282 if (!shader_manager()->GetClientId(result->GetData()[ii],
7283 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:257284 NOTREACHED();
7285 return error::kGenericError;
7286 }
7287 }
7288 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:147289 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327290}
7291
[email protected]f7a64ee2010-02-01 22:24:147292error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:197293 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:257294 GLuint program = c.program;
7295 GLuint index = c.index;
7296 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:257297 typedef gles2::GetActiveUniform::Result Result;
7298 Result* result = GetSharedMemoryAs<Result*>(
7299 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7300 if (!result) {
7301 return error::kOutOfBounds;
7302 }
[email protected]07d0cc82010-02-17 04:51:407303 // Check that the client initialized the result.
7304 if (result->success != 0) {
7305 return error::kInvalidArguments;
7306 }
[email protected]6b8cf1a2010-05-06 16:13:587307 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7308 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:037309 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257310 return error::kNoError;
7311 }
7312 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
7313 info->GetUniformInfo(index);
7314 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:297315 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:257316 return error::kNoError;
7317 }
7318 result->success = 1; // true.
7319 result->size = uniform_info->size;
7320 result->type = uniform_info->type;
7321 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297322 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:147323 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327324}
7325
[email protected]f7a64ee2010-02-01 22:24:147326error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:197327 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:257328 GLuint program = c.program;
7329 GLuint index = c.index;
7330 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:257331 typedef gles2::GetActiveAttrib::Result Result;
7332 Result* result = GetSharedMemoryAs<Result*>(
7333 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7334 if (!result) {
7335 return error::kOutOfBounds;
7336 }
[email protected]07d0cc82010-02-17 04:51:407337 // Check that the client initialized the result.
7338 if (result->success != 0) {
7339 return error::kInvalidArguments;
7340 }
[email protected]6b8cf1a2010-05-06 16:13:587341 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7342 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:037343 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257344 return error::kNoError;
7345 }
7346 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
7347 info->GetAttribInfo(index);
7348 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:297349 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:257350 return error::kNoError;
7351 }
7352 result->success = 1; // true.
7353 result->size = attrib_info->size;
7354 result->type = attrib_info->type;
7355 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297356 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:147357 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327358}
7359
[email protected]b273e432010-04-12 17:23:587360error::Error GLES2DecoderImpl::HandleShaderBinary(
7361 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
7362#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:297363 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:587364 return error::kNoError;
7365#else
7366 GLsizei n = static_cast<GLsizei>(c.n);
7367 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:297368 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:587369 return error::kNoError;
7370 }
7371 GLsizei length = static_cast<GLsizei>(c.length);
7372 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:297373 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:587374 return error::kNoError;
7375 }
7376 uint32 data_size;
7377 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
7378 return error::kOutOfBounds;
7379 }
7380 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
7381 c.shaders_shm_id, c.shaders_shm_offset, data_size);
7382 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
7383 const void* binary = GetSharedMemoryAs<const void*>(
7384 c.binary_shm_id, c.binary_shm_offset, length);
7385 if (shaders == NULL || binary == NULL) {
7386 return error::kOutOfBounds;
7387 }
7388 scoped_array<GLuint> service_ids(new GLuint[n]);
7389 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:037390 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
7391 if (!info) {
[email protected]8eee29c2010-04-29 03:38:297392 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:587393 return error::kNoError;
7394 }
[email protected]ae51d192010-04-27 00:48:037395 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:587396 }
7397 // TODO(gman): call glShaderBinary
7398 return error::kNoError;
7399#endif
7400}
7401
[email protected]6217d392010-03-25 22:08:357402error::Error GLES2DecoderImpl::HandleSwapBuffers(
7403 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:497404 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7405 int this_frame_number = frame_number_++;
[email protected]da151512011-11-11 23:27:387406 // TRACE_EVENT for gpu tests:
[email protected]529c6672012-01-04 02:18:267407 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers",
7408 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
7409 "width", (is_offscreen ? offscreen_size_.width() :
7410 surface_->GetSize().width()));
[email protected]64ace852011-05-19 21:49:497411 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
7412 "offscreen", is_offscreen,
7413 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:357414 // If offscreen then don't actually SwapBuffers to the display. Just copy
7415 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:497416 if (is_offscreen) {
[email protected]1fb8c482011-08-31 01:01:537417 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
7418 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
7419 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
7420 // fix this.
7421 if (needs_mac_nvidia_driver_workaround_) {
7422 offscreen_saved_frame_buffer_->Create();
7423 glFinish();
7424 }
7425
7426 // Allocate the offscreen saved color texture.
7427 DCHECK(offscreen_saved_color_format_);
7428 offscreen_saved_color_texture_->AllocateStorage(
7429 offscreen_size_, offscreen_saved_color_format_);
[email protected]1078f912011-12-23 13:12:147430 UpdateBackbufferMemoryAccounting();
[email protected]1fb8c482011-08-31 01:01:537431
7432 offscreen_saved_frame_buffer_->AttachRenderTexture(
7433 offscreen_saved_color_texture_.get());
7434 if (offscreen_saved_frame_buffer_->CheckStatus() !=
7435 GL_FRAMEBUFFER_COMPLETE) {
7436 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
7437 << "because offscreen saved FBO was incomplete.";
7438 return error::kLostContext;
7439 }
7440
[email protected]1fb8c482011-08-31 01:01:537441 // Clear the offscreen color texture.
7442 // TODO(piman): Is this still necessary?
7443 {
7444 ScopedFrameBufferBinder binder(this,
7445 offscreen_saved_frame_buffer_->id());
7446 glClearColor(0, 0, 0, 0);
7447 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
7448 glDisable(GL_SCISSOR_TEST);
7449 glClear(GL_COLOR_BUFFER_BIT);
7450 RestoreClearState();
7451 }
7452
7453 UpdateParentTextureInfo();
7454 }
7455
[email protected]6217d392010-03-25 22:08:357456 ScopedGLErrorSuppressor suppressor(this);
7457
[email protected]34ff8b0c2010-10-01 20:06:027458 if (IsOffscreenBufferMultisampled()) {
[email protected]51411e32012-01-19 20:21:137459 // For multisampled buffers, resolve the frame buffer.
[email protected]de26b3c2011-08-03 21:54:277460 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]89d6ed02011-04-20 00:23:237461 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:487462 } else {
[email protected]9a5afa432011-07-22 18:16:397463 if (surface_->IsOffscreen()) {
[email protected]51411e32012-01-19 20:21:137464 ScopedFrameBufferBinder binder(this,
7465 offscreen_target_frame_buffer_->id());
7466
[email protected]8a61d872012-01-20 12:43:567467 if (offscreen_target_buffer_preserved_) {
7468 // Copy the target frame buffer to the saved offscreen texture.
7469 offscreen_saved_color_texture_->Copy(
7470 offscreen_saved_color_texture_->size(),
7471 offscreen_saved_color_format_);
7472 } else {
7473 // Flip the textures in the parent context via the texture manager.
7474 if (!!offscreen_saved_color_texture_info_.get())
7475 offscreen_saved_color_texture_info_->
7476 SetServiceId(offscreen_target_color_texture_->id());
7477
7478 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
7479 offscreen_target_frame_buffer_->AttachRenderTexture(
7480 offscreen_target_color_texture_.get());
7481 }
[email protected]b86b14982010-10-11 18:45:487482
[email protected]a3ded6d2010-10-19 06:44:397483 // Ensure the side effects of the copy are visible to the parent
7484 // context. There is no need to do this for ANGLE because it uses a
7485 // single D3D device for all contexts.
[email protected]b86b14982010-10-11 18:45:487486 if (!IsAngle())
7487 glFlush();
7488 }
[email protected]89d6ed02011-04-20 00:23:237489 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:397490 }
[email protected]6217d392010-03-25 22:08:357491 } else {
[email protected]64ace852011-05-19 21:49:497492 TRACE_EVENT1("gpu", "GLContext::SwapBuffers", "frame", this_frame_number);
[email protected]f62a5ab2011-05-23 20:34:157493 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:017494 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:027495 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:017496 }
[email protected]6217d392010-03-25 22:08:357497 }
7498
[email protected]89d6ed02011-04-20 00:23:237499 return error::kNoError;
[email protected]6217d392010-03-25 22:08:357500}
7501
[email protected]d4239852011-08-12 04:51:227502error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
7503 uint32 immediate_data_size, const gles2::EnableFeatureCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:187504 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287505 if (!bucket || bucket->size() == 0) {
7506 return error::kInvalidArguments;
7507 }
[email protected]d4239852011-08-12 04:51:227508 typedef gles2::EnableFeatureCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:187509 Result* result = GetSharedMemoryAs<Result*>(
7510 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7511 if (!result) {
7512 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:107513 }
[email protected]b1d2dcb2010-05-17 19:24:187514 // Check that the client initialized the result.
7515 if (*result != 0) {
7516 return error::kInvalidArguments;
7517 }
7518 std::string feature_str;
7519 if (!bucket->GetAsString(&feature_str)) {
7520 return error::kInvalidArguments;
7521 }
7522
7523 // TODO(gman): make this some kind of table to function pointer thingy.
[email protected]d4239852011-08-12 04:51:227524 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
[email protected]b1d2dcb2010-05-17 19:24:187525 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]d4239852011-08-12 04:51:227526 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
[email protected]8fbedc02010-11-18 18:43:407527 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
7528 // TODO(gman): decide how to remove the need for this const_cast.
7529 // I could make validators_ non const but that seems bad as this is the only
7530 // place it is needed. I could make some special friend class of validators
7531 // just to allow this to set them. That seems silly. I could refactor this
7532 // code to use the extension mechanism or the initialization attributes to
7533 // turn this feature on. Given that the only real point of this is to make
7534 // the conformance tests pass and given that there is lots of real work that
7535 // needs to be done it seems like refactoring for one to one of those
7536 // methods is a very low priority.
7537 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]f0d74742011-10-03 16:31:047538 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
7539 force_webgl_glsl_validation_ = true;
7540 InitializeShaderTranslator();
[email protected]b1d2dcb2010-05-17 19:24:187541 } else {
7542 return error::kNoError;
7543 }
7544
7545 *result = 1; // true.
7546 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:107547}
7548
[email protected]c2f8c8402010-12-06 18:07:247549error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
7550 uint32 immediate_data_size,
7551 const gles2::GetRequestableExtensionsCHROMIUM& c) {
7552 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]80eb6b52012-01-19 00:14:417553 FeatureInfo::Ref info(new FeatureInfo());
[email protected]e82fb792011-09-22 00:33:297554 info->Initialize(disallowed_features_, NULL);
[email protected]c2f8c8402010-12-06 18:07:247555 bucket->SetFromString(info->extensions().c_str());
7556 return error::kNoError;
7557}
7558
7559error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
7560 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
7561 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287562 if (!bucket || bucket->size() == 0) {
7563 return error::kInvalidArguments;
7564 }
[email protected]c2f8c8402010-12-06 18:07:247565 std::string feature_str;
7566 if (!bucket->GetAsString(&feature_str)) {
7567 return error::kInvalidArguments;
7568 }
7569
7570 bool std_derivatives_enabled =
7571 feature_info_->feature_flags().oes_standard_derivatives;
7572 bool webglsl_enabled =
7573 feature_info_->feature_flags().chromium_webglsl;
7574
7575 feature_info_->AddFeatures(feature_str.c_str());
7576
[email protected]f0d74742011-10-03 16:31:047577 bool initialization_required = false;
7578 if (force_webgl_glsl_validation_ && !derivatives_explicitly_enabled_) {
7579 size_t derivatives_offset = feature_str.find(kOESDerivativeExtension);
7580 if (std::string::npos != derivatives_offset) {
7581 derivatives_explicitly_enabled_ = true;
7582 initialization_required = true;
7583 }
7584 }
7585
[email protected]c2f8c8402010-12-06 18:07:247586 // If we just enabled a feature which affects the shader translator,
7587 // we may need to re-initialize it.
7588 if (std_derivatives_enabled !=
7589 feature_info_->feature_flags().oes_standard_derivatives ||
7590 webglsl_enabled !=
[email protected]f0d74742011-10-03 16:31:047591 feature_info_->feature_flags().chromium_webglsl ||
7592 initialization_required) {
[email protected]c2f8c8402010-12-06 18:07:247593 InitializeShaderTranslator();
7594 }
7595
[email protected]302ce6d2011-07-07 23:28:117596 UpdateCapabilities();
7597
[email protected]c2f8c8402010-12-06 18:07:247598 return error::kNoError;
7599}
7600
[email protected]372e0412011-06-28 16:08:567601error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
7602 uint32 immediate_data_size, const gles2::GetMultipleIntegervCHROMIUM& c) {
7603 GLuint count = c.count;
7604 uint32 pnames_size;
7605 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
7606 return error::kOutOfBounds;
7607 }
7608 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
7609 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
7610 if (pnames == NULL) {
7611 return error::kOutOfBounds;
7612 }
7613
7614 // We have to copy them since we use them twice so the client
7615 // can't change them between the time we validate them and the time we use
7616 // them.
7617 scoped_array<GLenum> enums(new GLenum[count]);
7618 memcpy(enums.get(), pnames, pnames_size);
7619
7620 // Count up the space needed for the result.
7621 uint32 num_results = 0;
7622 for (GLuint ii = 0; ii < count; ++ii) {
7623 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
7624 if (num == 0) {
7625 SetGLError(GL_INVALID_ENUM,
7626 "glGetMulitpleCHROMIUM: pname GL_INVALID_ENUM");
7627 return error::kNoError;
7628 }
7629 // Num will never be more than 4.
7630 DCHECK_LE(num, 4u);
7631 if (!SafeAdd(num_results, num, &num_results)) {
7632 return error::kOutOfBounds;
7633 }
7634 }
7635
7636 uint32 result_size = 0;
7637 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
7638 return error::kOutOfBounds;
7639 }
7640
7641 if (result_size != static_cast<uint32>(c.size)) {
7642 SetGLError(GL_INVALID_VALUE,
7643 "glGetMulitpleCHROMIUM: bad size GL_INVALID_VALUE");
7644 return error::kNoError;
7645 }
7646
7647 GLint* results = GetSharedMemoryAs<GLint*>(
7648 c.results_shm_id, c.results_shm_offset, result_size);
7649 if (results == NULL) {
7650 return error::kOutOfBounds;
7651 }
7652
7653 // Check the results have been cleared in case the context was lost.
7654 for (uint32 ii = 0; ii < num_results; ++ii) {
7655 if (results[ii]) {
7656 return error::kInvalidArguments;
7657 }
7658 }
7659
7660 // Get each result.
7661 GLint* start = results;
7662 for (GLuint ii = 0; ii < count; ++ii) {
7663 GLsizei num_written = 0;
7664 if (!GetHelper(enums[ii], results, &num_written)) {
7665 glGetIntegerv(enums[ii], results);
7666 }
7667 results += num_written;
7668 }
7669
7670 // Just to verify. Should this be a DCHECK?
7671 if (static_cast<uint32>(results - start) != num_results) {
7672 return error::kOutOfBounds;
7673 }
7674
7675 return error::kNoError;
7676}
7677
[email protected]2318d342011-07-11 22:27:427678error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
7679 uint32 immediate_data_size, const gles2::GetProgramInfoCHROMIUM& c) {
7680 GLuint program = static_cast<GLuint>(c.program);
7681 uint32 bucket_id = c.bucket_id;
7682 Bucket* bucket = CreateBucket(bucket_id);
7683 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
7684 ProgramManager::ProgramInfo* info = NULL;
[email protected]9a14ae612011-08-08 17:51:467685 info = GetProgramInfo(program);
7686 if (!info || !info->IsValid()) {
7687 return error::kNoError;
[email protected]2318d342011-07-11 22:27:427688 }
[email protected]5d4c6b22012-02-07 08:22:287689 info->GetProgramInfo(program_manager(), bucket);
[email protected]2318d342011-07-11 22:27:427690 return error::kNoError;
7691}
7692
[email protected]38d139d2011-07-14 00:38:437693error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
7694 switch (reset_status_) {
7695 case GL_NO_ERROR:
7696 // TODO(kbr): improve the precision of the error code in this case.
7697 // Consider delegating to context for error code if MakeCurrent fails.
7698 return error::kUnknown;
7699 case GL_GUILTY_CONTEXT_RESET_ARB:
7700 return error::kGuilty;
7701 case GL_INNOCENT_CONTEXT_RESET_ARB:
7702 return error::kInnocent;
7703 case GL_UNKNOWN_CONTEXT_RESET_ARB:
7704 return error::kUnknown;
7705 }
7706
7707 NOTREACHED();
7708 return error::kUnknown;
7709}
7710
7711bool GLES2DecoderImpl::WasContextLost() {
7712 if (context_->WasAllocatedUsingARBRobustness() && has_arb_robustness_) {
7713 GLenum status = glGetGraphicsResetStatusARB();
7714 if (status != GL_NO_ERROR) {
7715 // The graphics card was reset. Signal a lost context to the application.
7716 reset_status_ = status;
7717 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
7718 << " context lost via ARB_robustness. Reset status = 0x"
7719 << std::hex << status << std::dec;
7720 return true;
7721 }
7722 }
7723 return false;
7724}
7725
[email protected]b0af4f52011-09-28 22:04:427726error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
7727 uint32 immediate_data_size,
7728 const gles2::CreateStreamTextureCHROMIUM& c) {
7729 if (!feature_info_->feature_flags().chromium_stream_texture) {
7730 SetGLError(GL_INVALID_OPERATION,
7731 "glOpenStreamTextureCHROMIUM: "
7732 "not supported.");
7733 return error::kNoError;
7734 }
7735
7736 uint32 client_id = c.client_id;
7737 typedef gles2::CreateStreamTextureCHROMIUM::Result Result;
7738 Result* result = GetSharedMemoryAs<Result*>(
7739 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7740
[email protected]e5081262012-01-05 23:09:037741 if (!result)
7742 return error::kOutOfBounds;
[email protected]b0af4f52011-09-28 22:04:427743 *result = GL_ZERO;
7744 TextureManager::TextureInfo* info =
7745 texture_manager()->GetTextureInfo(client_id);
7746 if (!info) {
7747 SetGLError(GL_INVALID_VALUE,
7748 "glCreateStreamTextureCHROMIUM: "
7749 "bad texture id.");
7750 return error::kNoError;
7751 }
7752
7753 if (info->IsStreamTexture()) {
7754 SetGLError(GL_INVALID_OPERATION,
7755 "glCreateStreamTextureCHROMIUM: "
7756 "is already a stream texture.");
7757 return error::kNoError;
7758 }
7759
7760 if (info->target() && info->target() != GL_TEXTURE_EXTERNAL_OES) {
7761 SetGLError(GL_INVALID_OPERATION,
7762 "glCreateStreamTextureCHROMIUM: "
7763 "is already bound to incompatible target.");
7764 return error::kNoError;
7765 }
7766
7767 if (!stream_texture_manager_)
7768 return error::kInvalidArguments;
7769
7770 GLuint object_id = stream_texture_manager_->CreateStreamTexture(
7771 info->service_id(), client_id);
7772
7773 if (object_id) {
7774 info->SetStreamTexture(true);
7775 } else {
7776 SetGLError(GL_OUT_OF_MEMORY,
7777 "glCreateStreamTextureCHROMIUM: "
7778 "failed to create platform texture.");
7779 }
7780
7781 *result = object_id;
7782 return error::kNoError;
7783}
7784
7785error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
7786 uint32 immediate_data_size,
7787 const gles2::DestroyStreamTextureCHROMIUM& c) {
7788 GLuint client_id = c.texture;
7789 TextureManager::TextureInfo* info =
7790 texture_manager()->GetTextureInfo(client_id);
7791 if (info && info->IsStreamTexture()) {
7792 if (!stream_texture_manager_)
7793 return error::kInvalidArguments;
7794
7795 stream_texture_manager_->DestroyStreamTexture(info->service_id());
7796 info->SetStreamTexture(false);
[email protected]80eb6b52012-01-19 00:14:417797 texture_manager()->SetInfoTarget(info, 0);
[email protected]b0af4f52011-09-28 22:04:427798 } else {
7799 SetGLError(GL_INVALID_VALUE,
7800 "glDestroyStreamTextureCHROMIUM: bad texture id.");
7801 }
7802
7803 return error::kNoError;
7804}
7805
[email protected]e51bdf32011-11-23 22:21:467806#if defined(OS_MACOSX)
7807void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
7808 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
7809 texture_id);
7810 if (it != texture_to_io_surface_map_.end()) {
7811 // Found a previous IOSurface bound to this texture; release it.
7812 CFTypeRef surface = it->second;
7813 CFRelease(surface);
7814 texture_to_io_surface_map_.erase(it);
7815 }
7816}
7817#endif
7818
7819void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
7820 GLenum target, GLsizei width, GLsizei height,
7821 GLuint io_surface_id, GLuint plane) {
7822#if defined(OS_MACOSX)
7823 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
7824 SetGLError(GL_INVALID_OPERATION,
7825 "glTexImageIOSurface2DCHROMIUM: only supported on desktop GL.");
7826 return;
7827 }
7828
7829 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
7830 if (!surface_support) {
7831 SetGLError(GL_INVALID_OPERATION,
7832 "glTexImageIOSurface2DCHROMIUM: only supported on 10.6.");
7833 return;
7834 }
7835
7836 if (target != GL_TEXTURE_RECTANGLE_ARB) {
7837 // This might be supported in the future, and if we could require
7838 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
7839 // could delete a lot of code. For now, perform strict validation so we
7840 // know what's going on.
7841 SetGLError(
7842 GL_INVALID_OPERATION,
7843 "glTexImageIOSurface2DCHROMIUM: requires TEXTURE_RECTANGLE_ARB target");
7844 return;
7845 }
7846
7847 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7848 if (!info) {
7849 SetGLError(GL_INVALID_OPERATION,
7850 "glTexImageIOSurface2DCHROMIUM: no rectangle texture bound");
7851 return;
7852 }
7853 if (info == texture_manager()->GetDefaultTextureInfo(target)) {
7854 // Maybe this is conceptually valid, but disallow it to avoid accidents.
7855 SetGLError(GL_INVALID_OPERATION,
7856 "glTexImageIOSurface2DCHROMIUM: can't bind default texture");
7857 return;
7858 }
7859
7860 // Look up the new IOSurface. Note that because of asynchrony
7861 // between processes this might fail; during live resizing the
7862 // plugin process might allocate and release an IOSurface before
7863 // this process gets a chance to look it up. Hold on to any old
7864 // IOSurface in this case.
7865 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
7866 if (!surface) {
7867 SetGLError(GL_INVALID_OPERATION,
7868 "glTexImageIOSurface2DCHROMIUM: no IOSurface with the given ID");
7869 return;
7870 }
7871
7872 // Release any IOSurface previously bound to this texture.
7873 ReleaseIOSurfaceForTexture(info->service_id());
7874
7875 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
7876 texture_to_io_surface_map_.insert(
7877 std::make_pair(info->service_id(), surface));
7878
7879 CGLContextObj context =
7880 static_cast<CGLContextObj>(context_->GetHandle());
7881
7882 CGLError err = surface_support->CGLTexImageIOSurface2D(
7883 context,
7884 target,
7885 GL_RGBA,
7886 width,
7887 height,
7888 GL_BGRA,
7889 GL_UNSIGNED_INT_8_8_8_8_REV,
7890 surface,
7891 plane);
7892
7893 if (err != kCGLNoError) {
7894 SetGLError(
7895 GL_INVALID_OPERATION,
7896 "glTexImageIOSurface2DCHROMIUM: error in CGLTexImageIOSurface2D");
7897 return;
7898 }
7899
7900 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:417901 info, target, 0, GL_RGBA, width, height, 1, 0,
[email protected]e51bdf32011-11-23 22:21:467902 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
7903
7904#else
7905 SetGLError(GL_INVALID_OPERATION,
7906 "glTexImageIOSurface2DCHROMIUM: not supported.");
7907#endif
7908}
7909
[email protected]97dc7cbe2011-12-06 17:26:177910static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
7911 switch (internalformat) {
7912 case GL_RGB565:
7913 return GL_RGB;
7914 case GL_RGBA4:
7915 return GL_RGBA;
7916 case GL_RGB5_A1:
7917 return GL_RGBA;
7918 case GL_RGB8_OES:
7919 return GL_RGB;
7920 case GL_RGBA8_OES:
7921 return GL_RGBA;
7922 case GL_LUMINANCE8_ALPHA8_EXT:
7923 return GL_LUMINANCE_ALPHA;
7924 case GL_LUMINANCE8_EXT:
7925 return GL_LUMINANCE;
7926 case GL_ALPHA8_EXT:
7927 return GL_ALPHA;
7928 case GL_RGBA32F_EXT:
7929 return GL_RGBA;
7930 case GL_RGB32F_EXT:
7931 return GL_RGB;
7932 case GL_ALPHA32F_EXT:
7933 return GL_ALPHA;
7934 case GL_LUMINANCE32F_EXT:
7935 return GL_LUMINANCE;
7936 case GL_LUMINANCE_ALPHA32F_EXT:
7937 return GL_LUMINANCE_ALPHA;
7938 case GL_RGBA16F_EXT:
7939 return GL_RGBA;
7940 case GL_RGB16F_EXT:
7941 return GL_RGB;
7942 case GL_ALPHA16F_EXT:
7943 return GL_ALPHA;
7944 case GL_LUMINANCE16F_EXT:
7945 return GL_LUMINANCE;
7946 case GL_LUMINANCE_ALPHA16F_EXT:
7947 return GL_LUMINANCE_ALPHA;
7948 case GL_BGRA8_EXT:
7949 return GL_BGRA_EXT;
7950 default:
7951 return GL_NONE;
7952 }
7953}
7954
7955static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
7956 switch (internalformat) {
7957 case GL_RGB565:
7958 return GL_UNSIGNED_SHORT_5_6_5;
7959 case GL_RGBA4:
7960 return GL_UNSIGNED_SHORT_4_4_4_4;
7961 case GL_RGB5_A1:
7962 return GL_UNSIGNED_SHORT_5_5_5_1;
7963 case GL_RGB8_OES:
7964 return GL_UNSIGNED_BYTE;
7965 case GL_RGBA8_OES:
7966 return GL_UNSIGNED_BYTE;
7967 case GL_LUMINANCE8_ALPHA8_EXT:
7968 return GL_UNSIGNED_BYTE;
7969 case GL_LUMINANCE8_EXT:
7970 return GL_UNSIGNED_BYTE;
7971 case GL_ALPHA8_EXT:
7972 return GL_UNSIGNED_BYTE;
7973 case GL_RGBA32F_EXT:
7974 return GL_FLOAT;
7975 case GL_RGB32F_EXT:
7976 return GL_FLOAT;
7977 case GL_ALPHA32F_EXT:
7978 return GL_FLOAT;
7979 case GL_LUMINANCE32F_EXT:
7980 return GL_FLOAT;
7981 case GL_LUMINANCE_ALPHA32F_EXT:
7982 return GL_FLOAT;
7983 case GL_RGBA16F_EXT:
7984 return GL_HALF_FLOAT_OES;
7985 case GL_RGB16F_EXT:
7986 return GL_HALF_FLOAT_OES;
7987 case GL_ALPHA16F_EXT:
7988 return GL_HALF_FLOAT_OES;
7989 case GL_LUMINANCE16F_EXT:
7990 return GL_HALF_FLOAT_OES;
7991 case GL_LUMINANCE_ALPHA16F_EXT:
7992 return GL_HALF_FLOAT_OES;
7993 case GL_BGRA8_EXT:
7994 return GL_UNSIGNED_BYTE;
7995 default:
7996 return GL_NONE;
7997 }
7998}
7999
8000void GLES2DecoderImpl::DoTexStorage2DEXT(
8001 GLenum target,
8002 GLint levels,
8003 GLenum internal_format,
8004 GLsizei width,
8005 GLsizei height) {
[email protected]80eb6b52012-01-19 00:14:418006 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
[email protected]97dc7cbe2011-12-06 17:26:178007 TextureManager::ComputeMipMapCount(width, height, 1) < levels) {
8008 SetGLError(GL_INVALID_VALUE, "glTexStorage2DEXT: dimensions out of range");
8009 return;
8010 }
8011 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8012 if (!info) {
8013 SetGLError(GL_INVALID_OPERATION,
8014 "glTexStorage2DEXT: unknown texture for target");
8015 return;
8016 }
8017 if (info->IsAttachedToFramebuffer()) {
8018 state_dirty_ = true;
8019 }
8020 if (info->IsImmutable()) {
8021 SetGLError(GL_INVALID_OPERATION,
8022 "glTexStorage2DEXT: texture is immutable");
8023 return;
8024 }
8025 CopyRealGLErrorsToWrapper();
[email protected]f0e6a34f2012-01-04 20:53:408026 glTexStorage2DEXT(target, levels, GetTexInternalFormat(internal_format),
8027 width, height);
[email protected]97dc7cbe2011-12-06 17:26:178028 GLenum error = PeekGLError();
8029 if (error == GL_NO_ERROR) {
8030 GLenum format = ExtractFormatFromStorageFormat(internal_format);
8031 GLenum type = ExtractTypeFromStorageFormat(internal_format);
[email protected]4502e6492011-12-14 19:39:158032 GLsizei level_width = width;
8033 GLsizei level_height = height;
8034 for (int ii = 0; ii < levels; ++ii) {
8035 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:418036 info, target, 0, format, level_width, level_height, 1, 0, format,
8037 type, false);
[email protected]4502e6492011-12-14 19:39:158038 level_width = std::max(1, level_width >> 1);
8039 level_height = std::max(1, level_height >> 1);
8040 }
[email protected]97dc7cbe2011-12-06 17:26:178041 info->SetImmutable(true);
8042 }
[email protected]97dc7cbe2011-12-06 17:26:178043}
[email protected]e51bdf32011-11-23 22:21:468044
[email protected]96449d2c2009-11-25 00:01:328045// Include the auto-generated part of this file. We split this because it means
8046// we can easily edit the non-auto generated parts right here in this file
8047// instead of having to edit some template or the code generator.
8048#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
8049
8050} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:258051} // namespace gpu