blob: 26c80f20f131a7315bd8ab6d504ab44329779c1f [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]882ba1e22012-03-08 19:02:5339#include "gpu/command_buffer/service/query_manager.h"
[email protected]a25fa872010-03-25 02:57:5840#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4741#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4542#include "gpu/command_buffer/service/shader_translator.h"
[email protected]b0af4f52011-09-28 22:04:4243#include "gpu/command_buffer/service/stream_texture.h"
44#include "gpu/command_buffer/service/stream_texture_manager.h"
[email protected]a93bb842010-02-16 23:03:4745#include "gpu/command_buffer/service/texture_manager.h"
[email protected]d8ea9772011-07-11 18:11:4346#include "gpu/command_buffer/service/vertex_attrib_manager.h"
[email protected]5ae0b282011-03-28 19:24:4947#include "ui/gfx/gl/gl_context.h"
48#include "ui/gfx/gl/gl_implementation.h"
[email protected]f62a5ab2011-05-23 20:34:1549#include "ui/gfx/gl/gl_surface.h"
[email protected]e51bdf32011-11-23 22:21:4650#if defined(OS_MACOSX)
51#include "ui/gfx/surface/io_surface_support_mac.h"
52#endif
[email protected]de17df392010-04-23 21:09:4153
[email protected]6217d392010-03-25 22:08:3554#if !defined(GL_DEPTH24_STENCIL8)
55#define GL_DEPTH24_STENCIL8 0x88F0
56#endif
57
[email protected]a7a27ace2009-12-12 00:11:2558namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3259namespace gles2 {
60
[email protected]f0d74742011-10-03 16:31:0461namespace {
62static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
63}
64
[email protected]6217d392010-03-25 22:08:3565class GLES2DecoderImpl;
66
[email protected]07f54fcc2009-12-22 02:46:3067// Check that certain assumptions the code makes are true. There are places in
68// the code where shared memory is passed direclty to GL. Example, glUniformiv,
69// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
70// a few others) are 32bits. If they are not 32bits the code will have to change
71// to call those GL functions with service side memory and then copy the results
72// to shared memory, converting the sizes.
73COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
74 GLint_not_same_size_as_uint32);
75COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
76 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3777COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
78 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3079
[email protected]43f28f832010-02-03 02:28:4880// TODO(kbr): the use of this anonymous namespace core dumps the
81// linker on Mac OS X 10.6 when the symbol ordering file is used
82// namespace {
[email protected]96449d2c2009-11-25 00:01:3283
84// Returns the address of the first byte after a struct.
85template <typename T>
86const void* AddressAfterStruct(const T& pod) {
87 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
88}
89
[email protected]07f54fcc2009-12-22 02:46:3090// Returns the address of the frst byte after the struct or NULL if size >
91// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3292template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3093RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
94 uint32 size,
95 uint32 immediate_data_size) {
96 return (size <= immediate_data_size) ?
97 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
98 NULL;
[email protected]96449d2c2009-11-25 00:01:3299}
100
[email protected]07f54fcc2009-12-22 02:46:30101// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:18102bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:32103 GLuint count,
104 size_t size,
[email protected]a76b0052010-03-05 00:33:18105 unsigned int elements_per_unit,
106 uint32* dst) {
107 uint32 value;
108 if (!SafeMultiplyUint32(count, size, &value)) {
109 return false;
110 }
111 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
112 return false;
113 }
114 *dst = value;
115 return true;
[email protected]96449d2c2009-11-25 00:01:32116}
117
118// A struct to hold info about each command.
119struct CommandInfo {
120 int arg_flags; // How to handle the arguments for this command
121 int arg_count; // How many arguments are expected for this command.
122};
123
124// A table of CommandInfo for all the commands.
125const CommandInfo g_command_info[] = {
126 #define GLES2_CMD_OP(name) { \
127 name::kArgFlags, \
128 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
129
130 GLES2_COMMAND_LIST(GLES2_CMD_OP)
131
132 #undef GLES2_CMD_OP
133};
134
[email protected]258a3313f2011-10-18 20:13:57135// Return true if a character belongs to the ASCII subset as defined in
136// GLSL ES 1.0 spec section 3.1.
137static bool CharacterIsValidForGLES(unsigned char c) {
138 // Printing characters are valid except " $ ` @ \ ' DEL.
139 if (c >= 32 && c <= 126 &&
140 c != '"' &&
141 c != '$' &&
142 c != '`' &&
143 c != '@' &&
144 c != '\\' &&
145 c != '\'') {
146 return true;
147 }
148 // Horizontal tab, line feed, vertical tab, form feed, carriage return
149 // are also valid.
150 if (c >= 9 && c <= 13) {
151 return true;
152 }
153
154 return false;
155}
156
157static bool StringIsValidForGLES(const char* str) {
158 for (; *str; ++str) {
159 if (!CharacterIsValidForGLES(*str)) {
160 return false;
161 }
162 }
163 return true;
164}
165
[email protected]f0e6a34f2012-01-04 20:53:40166static inline GLenum GetTexInternalFormat(GLenum internal_format) {
167 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
168 if (internal_format == GL_BGRA_EXT || internal_format == GL_BGRA8_EXT)
169 return GL_RGBA8;
170 }
171 return internal_format;
172}
173
[email protected]297ca1c2011-06-20 23:08:46174static void WrappedTexImage2D(
[email protected]473c01ccb2011-06-07 01:33:30175 GLenum target,
176 GLint level,
177 GLenum internal_format,
178 GLsizei width,
179 GLsizei height,
180 GLint border,
181 GLenum format,
182 GLenum type,
183 const void* pixels) {
[email protected]f0e6a34f2012-01-04 20:53:40184 GLenum gl_internal_format = GetTexInternalFormat(internal_format);
[email protected]473c01ccb2011-06-07 01:33:30185 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]f0e6a34f2012-01-04 20:53:40186 if (type == GL_FLOAT) {
[email protected]58b75f92012-03-20 21:15:43187 switch (format) {
188 case GL_RGBA:
189 gl_internal_format = GL_RGBA32F_ARB;
190 break;
191 case GL_RGB:
192 gl_internal_format = GL_RGB32F_ARB;
193 break;
194 case GL_LUMINANCE_ALPHA:
195 gl_internal_format = GL_LUMINANCE_ALPHA32F_ARB;
196 break;
197 case GL_LUMINANCE:
198 gl_internal_format = GL_LUMINANCE32F_ARB;
199 break;
200 case GL_ALPHA:
201 gl_internal_format = GL_ALPHA32F_ARB;
202 break;
203 default:
204 NOTREACHED();
205 break;
[email protected]473c01ccb2011-06-07 01:33:30206 }
207 } else if (type == GL_HALF_FLOAT_OES) {
[email protected]58b75f92012-03-20 21:15:43208 switch (format) {
209 case GL_RGBA:
210 gl_internal_format = GL_RGBA16F_ARB;
211 break;
212 case GL_RGB:
213 gl_internal_format = GL_RGB16F_ARB;
214 break;
215 case GL_LUMINANCE_ALPHA:
216 gl_internal_format = GL_LUMINANCE_ALPHA16F_ARB;
217 break;
218 case GL_LUMINANCE:
219 gl_internal_format = GL_LUMINANCE16F_ARB;
220 break;
221 case GL_ALPHA:
222 gl_internal_format = GL_ALPHA16F_ARB;
223 break;
224 default:
225 NOTREACHED();
226 break;
[email protected]473c01ccb2011-06-07 01:33:30227 }
228 }
229 }
230 glTexImage2D(
231 target, level, gl_internal_format, width, height, border, format, type,
232 pixels);
233}
234
[email protected]297ca1c2011-06-20 23:08:46235// Wrapper for glEnable/glDisable that doesn't suck.
236static void EnableDisable(GLenum pname, bool enable) {
237 if (enable) {
238 glEnable(pname);
239 } else {
240 glDisable(pname);
241 }
242}
243
[email protected]6217d392010-03-25 22:08:35244// This class prevents any GL errors that occur when it is in scope from
245// being reported to the client.
246class ScopedGLErrorSuppressor {
247 public:
248 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
249 ~ScopedGLErrorSuppressor();
250 private:
251 GLES2DecoderImpl* decoder_;
252 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
253};
254
255// Temporarily changes a decoder's bound 2D texture and restore it when this
256// object goes out of scope. Also temporarily switches to using active texture
257// unit zero in case the client has changed that to something invalid.
258class ScopedTexture2DBinder {
259 public:
260 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
261 ~ScopedTexture2DBinder();
262
263 private:
264 GLES2DecoderImpl* decoder_;
265 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
266};
267
268// Temporarily changes a decoder's bound render buffer and restore it when this
269// object goes out of scope.
270class ScopedRenderBufferBinder {
271 public:
272 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
273 ~ScopedRenderBufferBinder();
274
275 private:
276 GLES2DecoderImpl* decoder_;
277 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
278};
279
280// Temporarily changes a decoder's bound frame buffer and restore it when this
281// object goes out of scope.
282class ScopedFrameBufferBinder {
283 public:
284 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
285 ~ScopedFrameBufferBinder();
286
287 private:
288 GLES2DecoderImpl* decoder_;
289 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
290};
291
[email protected]34ff8b0c2010-10-01 20:06:02292// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52293// the multisampled offscreen render buffer if that buffer is multisampled, and,
[email protected]de26b3c2011-08-03 21:54:27294// if it is bound or enforce_internal_framebuffer is true. If internal is
295// true, the resolved framebuffer is not visible to the parent.
[email protected]34ff8b0c2010-10-01 20:06:02296class ScopedResolvedFrameBufferBinder {
297 public:
[email protected]e7e38032011-07-26 17:25:25298 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
[email protected]de26b3c2011-08-03 21:54:27299 bool enforce_internal_framebuffer,
300 bool internal);
[email protected]34ff8b0c2010-10-01 20:06:02301 ~ScopedResolvedFrameBufferBinder();
302
303 private:
304 GLES2DecoderImpl* decoder_;
305 bool resolve_and_bind_;
306 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
307};
308
[email protected]6217d392010-03-25 22:08:35309// Encapsulates an OpenGL texture.
310class Texture {
311 public:
312 explicit Texture(GLES2DecoderImpl* decoder);
313 ~Texture();
314
315 // Create a new render texture.
316 void Create();
317
318 // Set the initial size and format of a render texture or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02319 bool AllocateStorage(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35320
321 // Copy the contents of the currently bound frame buffer.
[email protected]3a4d0c52011-06-29 23:11:58322 void Copy(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35323
324 // Destroy the render texture. This must be explicitly called before
325 // destroying this object.
326 void Destroy();
327
[email protected]97872062010-11-03 19:07:05328 // Invalidate the texture. This can be used when a context is lost and it is
329 // not possible to make it current in order to free the resource.
330 void Invalidate();
331
[email protected]6217d392010-03-25 22:08:35332 GLuint id() const {
333 return id_;
334 }
335
[email protected]d37231fa2010-04-09 21:16:02336 gfx::Size size() const {
337 return size_;
338 }
339
[email protected]1078f912011-12-23 13:12:14340 size_t estimated_size() const {
341 return estimated_size_;
342 }
343
[email protected]6217d392010-03-25 22:08:35344 private:
345 GLES2DecoderImpl* decoder_;
346 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02347 gfx::Size size_;
[email protected]1078f912011-12-23 13:12:14348 size_t estimated_size_;
[email protected]6217d392010-03-25 22:08:35349 DISALLOW_COPY_AND_ASSIGN(Texture);
350};
351
352// Encapsulates an OpenGL render buffer of any format.
353class RenderBuffer {
354 public:
355 explicit RenderBuffer(GLES2DecoderImpl* decoder);
356 ~RenderBuffer();
357
358 // Create a new render buffer.
359 void Create();
360
361 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02362 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35363
364 // Destroy the render buffer. This must be explicitly called before destroying
365 // this object.
366 void Destroy();
367
[email protected]97872062010-11-03 19:07:05368 // Invalidate the render buffer. This can be used when a context is lost and
369 // it is not possible to make it current in order to free the resource.
370 void Invalidate();
371
[email protected]6217d392010-03-25 22:08:35372 GLuint id() const {
373 return id_;
374 }
375
[email protected]1078f912011-12-23 13:12:14376 size_t estimated_size() const {
377 return estimated_size_;
378 }
379
[email protected]6217d392010-03-25 22:08:35380 private:
381 GLES2DecoderImpl* decoder_;
382 GLuint id_;
[email protected]1078f912011-12-23 13:12:14383 size_t estimated_size_;
[email protected]6217d392010-03-25 22:08:35384 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
385};
386
387// Encapsulates an OpenGL frame buffer.
388class FrameBuffer {
389 public:
390 explicit FrameBuffer(GLES2DecoderImpl* decoder);
391 ~FrameBuffer();
392
393 // Create a new frame buffer.
394 void Create();
395
396 // Attach a color render buffer to a frame buffer.
397 void AttachRenderTexture(Texture* texture);
398
[email protected]b9363b22010-06-09 22:06:15399 // Attach a render buffer to a frame buffer. Note that this unbinds any
400 // currently bound frame buffer.
401 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35402
[email protected]6217d392010-03-25 22:08:35403 // Destroy the frame buffer. This must be explicitly called before destroying
404 // this object.
405 void Destroy();
406
[email protected]97872062010-11-03 19:07:05407 // Invalidate the frame buffer. This can be used when a context is lost and it
408 // is not possible to make it current in order to free the resource.
409 void Invalidate();
410
[email protected]6217d392010-03-25 22:08:35411 // See glCheckFramebufferStatusEXT.
412 GLenum CheckStatus();
413
414 GLuint id() const {
415 return id_;
416 }
417
418 private:
419 GLES2DecoderImpl* decoder_;
420 GLuint id_;
421 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
422};
[email protected]34ff8b0c2010-10-01 20:06:02423
424class ContextCreationAttribParser {
425 public:
426 ContextCreationAttribParser();
427 bool Parse(const std::vector<int32>& attribs);
428
429 // -1 if invalid or unspecified.
430 int32 alpha_size_;
431 int32 blue_size_;
432 int32 green_size_;
433 int32 red_size_;
434 int32 depth_size_;
435 int32 stencil_size_;
436 int32 samples_;
437 int32 sample_buffers_;
[email protected]8a61d872012-01-20 12:43:56438 bool buffer_preserved_;
[email protected]34ff8b0c2010-10-01 20:06:02439};
440
441ContextCreationAttribParser::ContextCreationAttribParser()
442 : alpha_size_(-1),
443 blue_size_(-1),
444 green_size_(-1),
445 red_size_(-1),
446 depth_size_(-1),
447 stencil_size_(-1),
448 samples_(-1),
[email protected]8a61d872012-01-20 12:43:56449 sample_buffers_(-1),
450 buffer_preserved_(true) {
[email protected]34ff8b0c2010-10-01 20:06:02451}
452
453bool ContextCreationAttribParser::Parse(const std::vector<int32>& attribs) {
454 // From <EGL/egl.h>.
455 const int32 EGL_ALPHA_SIZE = 0x3021;
456 const int32 EGL_BLUE_SIZE = 0x3022;
457 const int32 EGL_GREEN_SIZE = 0x3023;
458 const int32 EGL_RED_SIZE = 0x3024;
459 const int32 EGL_DEPTH_SIZE = 0x3025;
460 const int32 EGL_STENCIL_SIZE = 0x3026;
461 const int32 EGL_SAMPLES = 0x3031;
462 const int32 EGL_SAMPLE_BUFFERS = 0x3032;
463 const int32 EGL_NONE = 0x3038;
[email protected]8a61d872012-01-20 12:43:56464 const int32 EGL_SWAP_BEHAVIOR = 0x3093;
465 const int32 EGL_BUFFER_PRESERVED = 0x3094;
[email protected]34ff8b0c2010-10-01 20:06:02466
467 for (size_t i = 0; i < attribs.size(); i += 2) {
468 const int32 attrib = attribs[i];
469 if (i + 1 >= attribs.size()) {
470 if (attrib == EGL_NONE)
471 return true;
472
473 DLOG(ERROR) << "Missing value after context creation attribute: "
474 << attrib;
475 return false;
476 }
477
478 const int32 value = attribs[i+1];
479 switch (attrib) {
480 case EGL_ALPHA_SIZE:
481 alpha_size_ = value;
482 break;
483 case EGL_BLUE_SIZE:
484 blue_size_ = value;
485 break;
486 case EGL_GREEN_SIZE:
487 green_size_ = value;
488 break;
489 case EGL_RED_SIZE:
490 red_size_ = value;
491 break;
492 case EGL_DEPTH_SIZE:
493 depth_size_ = value;
494 break;
495 case EGL_STENCIL_SIZE:
496 stencil_size_ = value;
497 break;
498 case EGL_SAMPLES:
499 samples_ = value;
500 break;
501 case EGL_SAMPLE_BUFFERS:
502 sample_buffers_ = value;
503 break;
[email protected]8a61d872012-01-20 12:43:56504 case EGL_SWAP_BEHAVIOR:
505 buffer_preserved_ = value == EGL_BUFFER_PRESERVED;
506 break;
[email protected]34ff8b0c2010-10-01 20:06:02507 case EGL_NONE:
508 // Terminate list, even if more attributes.
509 return true;
510 default:
511 DLOG(ERROR) << "Invalid context creation attribute: " << attrib;
512 return false;
513 }
514 }
515
516 return true;
517}
518
[email protected]43f28f832010-02-03 02:28:48519// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32520
[email protected]ddb1e5a2010-12-13 20:10:45521bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
522 uint32* service_texture_id) {
523 return false;
524}
525
[email protected]a3ded6d2010-10-19 06:44:39526GLES2Decoder::GLES2Decoder()
[email protected]e844ae22012-01-14 03:36:26527 : debug_(false),
[email protected]b5d647c2012-02-10 01:41:32528 log_commands_(false),
529 log_synthesized_gl_errors_(true) {
[email protected]96449d2c2009-11-25 00:01:32530}
531
[email protected]3916c97e2010-02-25 03:20:50532GLES2Decoder::~GLES2Decoder() {
533}
534
[email protected]57edfdad2012-02-07 04:57:15535bool GLES2Decoder::testing_force_is_angle_;
536
537void GLES2Decoder::set_testing_force_is_angle(bool force) {
538 testing_force_is_angle_ = force;
539}
540
541bool GLES2Decoder::IsAngle() {
542#if defined(OS_WIN)
543 return testing_force_is_angle_ ||
544 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
545#else
546 return testing_force_is_angle_;
547#endif
548}
549
[email protected]f39f4b3f2010-05-12 17:04:08550// This class implements GLES2Decoder so we don't have to expose all the GLES2
551// cmd stuff to outside this class.
552class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
553 public GLES2Decoder {
554 public:
[email protected]aa7666122011-09-02 19:45:52555 explicit GLES2DecoderImpl(ContextGroup* group);
[email protected]80eb6b52012-01-19 00:14:41556 ~GLES2DecoderImpl();
[email protected]f39f4b3f2010-05-12 17:04:08557
[email protected]96449d2c2009-11-25 00:01:32558 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14559 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50560 unsigned int arg_count,
561 const void* args);
[email protected]96449d2c2009-11-25 00:01:32562
563 // Overridden from AsyncAPIInterface.
564 virtual const char* GetCommandName(unsigned int command_id) const;
565
566 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38567 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
568 const scoped_refptr<gfx::GLContext>& context,
[email protected]6217d392010-03-25 22:08:35569 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:29570 const DisallowedFeatures& disallowed_features,
[email protected]a3ded6d2010-10-19 06:44:39571 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:24572 const std::vector<int32>& attribs);
[email protected]96449d2c2009-11-25 00:01:32573 virtual void Destroy();
[email protected]3c644d82011-06-20 19:58:24574 virtual bool SetParent(GLES2Decoder* parent_decoder,
575 uint32 parent_texture_id);
[email protected]799b4b22011-08-22 17:09:59576 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]9a5afa432011-07-22 18:16:39577 void UpdateParentTextureInfo();
[email protected]eb54a562010-01-20 21:55:18578 virtual bool MakeCurrent();
[email protected]a96a6022011-11-04 00:58:12579 virtual void ReleaseCurrent();
[email protected]56ac89b2010-03-17 21:16:55580 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30581 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]f62a5ab2011-05-23 20:34:15582 virtual gfx::GLSurface* GetGLSurface() { return surface_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39583 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]882ba1e22012-03-08 19:02:53584 virtual QueryManager* GetQueryManager() { return query_manager_.get(); }
[email protected]22e3f552012-03-13 01:54:19585 virtual bool ProcessPendingQueries();
[email protected]43f28f832010-02-03 02:28:48586
[email protected]0d6bfdc2011-11-02 01:32:20587 virtual void SetGLError(GLenum error, const char* msg);
[email protected]9d37f062011-11-22 01:24:52588 virtual void SetResizeCallback(
589 const base::Callback<void(gfx::Size)>& callback);
[email protected]22f320a2011-08-30 01:17:00590
[email protected]6b6e7ee2011-12-13 08:04:52591 virtual void SetMsgCallback(const MsgCallback& callback);
[email protected]22f320a2011-08-30 01:17:00592
[email protected]b0af4f52011-09-28 22:04:42593 virtual void SetStreamTextureManager(StreamTextureManager* manager);
[email protected]1318e922010-09-17 22:03:16594 virtual bool GetServiceTextureId(uint32 client_texture_id,
595 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48596
[email protected]8e3e0662010-08-23 18:46:30597 // Restores the current state to the user's settings.
598 void RestoreCurrentFramebufferBindings();
599 void RestoreCurrentRenderbufferBindings();
600 void RestoreCurrentTexture2DBindings();
601
[email protected]297ca1c2011-06-20 23:08:46602 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
603 void ApplyDirtyState();
604
605 // These check the state of the currently bound framebuffer or the
606 // backbuffer if no framebuffer is bound.
607 bool BoundFramebufferHasColorAttachmentWithAlpha();
608 bool BoundFramebufferHasDepthAttachment();
609 bool BoundFramebufferHasStencilAttachment();
610
[email protected]38d139d2011-07-14 00:38:43611 virtual error::ContextLostReason GetContextLostReason();
612
[email protected]96449d2c2009-11-25 00:01:32613 private:
[email protected]6217d392010-03-25 22:08:35614 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02615 friend class ScopedResolvedFrameBufferBinder;
[email protected]1078f912011-12-23 13:12:14616 friend class Texture;
[email protected]6217d392010-03-25 22:08:35617 friend class RenderBuffer;
618 friend class FrameBuffer;
619
[email protected]3916c97e2010-02-25 03:20:50620 // State associated with each texture unit.
621 struct TextureUnit {
622 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
623
624 // The last target that was bound to this texture unit.
625 GLenum bind_target;
626
627 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
628 TextureManager::TextureInfo::Ref bound_texture_2d;
629
630 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
631 // glBindTexture
632 TextureManager::TextureInfo::Ref bound_texture_cube_map;
[email protected]61eeb33f2011-07-26 15:30:31633
634 // texture currently bound to this unit's GL_TEXTURE_EXTERNAL_OES with
635 // glBindTexture
636 TextureManager::TextureInfo::Ref bound_texture_external_oes;
637
[email protected]e51bdf32011-11-23 22:21:46638 // texture currently bound to this unit's GL_TEXTURE_RECTANGLE_ARB with
639 // glBindTexture
640 TextureManager::TextureInfo::Ref bound_texture_rectangle_arb;
641
[email protected]61eeb33f2011-07-26 15:30:31642 TextureManager::TextureInfo::Ref GetInfoForSamplerType(GLenum type) {
643 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:46644 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
645 switch (type) {
646 case GL_SAMPLER_2D:
647 return bound_texture_2d;
648 case GL_SAMPLER_CUBE:
649 return bound_texture_cube_map;
650 case GL_SAMPLER_EXTERNAL_OES:
651 return bound_texture_external_oes;
652 case GL_SAMPLER_2D_RECT_ARB:
653 return bound_texture_rectangle_arb;
654 }
655
656 NOTREACHED();
657 return NULL;
[email protected]61eeb33f2011-07-26 15:30:31658 }
[email protected]a0b78dc2011-11-11 10:43:10659
660 void Unbind(TextureManager::TextureInfo* texture) {
661 if (bound_texture_2d == texture) {
662 bound_texture_2d = NULL;
663 }
664 if (bound_texture_cube_map == texture) {
665 bound_texture_cube_map = NULL;
666 }
667 if (bound_texture_external_oes == texture) {
668 bound_texture_external_oes = NULL;
669 }
670 }
[email protected]3916c97e2010-02-25 03:20:50671 };
672
[email protected]c2f8c8402010-12-06 18:07:24673 // Initialize or re-initialize the shader translator.
674 bool InitializeShaderTranslator();
675
[email protected]302ce6d2011-07-07 23:28:11676 void UpdateCapabilities();
677
[email protected]ae51d192010-04-27 00:48:03678 // Helpers for the glGen and glDelete functions.
679 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
680 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
681 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
682 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
683 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
684 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
685 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
686 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]882ba1e22012-03-08 19:02:53687 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
688 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47689
[email protected]3916c97e2010-02-25 03:20:50690 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50691 BufferManager* buffer_manager() {
692 return group_->buffer_manager();
693 }
694
[email protected]a25fa872010-03-25 02:57:58695 RenderbufferManager* renderbuffer_manager() {
696 return group_->renderbuffer_manager();
697 }
698
699 FramebufferManager* framebuffer_manager() {
700 return group_->framebuffer_manager();
701 }
702
[email protected]3916c97e2010-02-25 03:20:50703 ProgramManager* program_manager() {
704 return group_->program_manager();
705 }
706
707 ShaderManager* shader_manager() {
708 return group_->shader_manager();
709 }
710
711 TextureManager* texture_manager() {
712 return group_->texture_manager();
713 }
714
[email protected]34ff8b0c2010-10-01 20:06:02715 bool IsOffscreenBufferMultisampled() const {
716 return offscreen_target_samples_ > 1;
717 }
718
[email protected]a93bb842010-02-16 23:03:47719 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03720 TextureManager::TextureInfo* CreateTextureInfo(
721 GLuint client_id, GLuint service_id) {
[email protected]80eb6b52012-01-19 00:14:41722 return texture_manager()->CreateTextureInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47723 }
724
725 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03726 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50727 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03728 texture_manager()->GetTextureInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10729 return info;
[email protected]a93bb842010-02-16 23:03:47730 }
731
732 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03733 void RemoveTextureInfo(GLuint client_id) {
[email protected]80eb6b52012-01-19 00:14:41734 texture_manager()->RemoveTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50735 }
[email protected]a93bb842010-02-16 23:03:47736
[email protected]d37231fa2010-04-09 21:16:02737 // Get the size (in pixels) of the currently bound frame buffer (either FBO
738 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30739 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02740
[email protected]9edc6b22010-12-23 02:00:26741 // Get the format of the currently bound frame buffer (either FBO or regular
742 // back buffer)
743 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46744 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26745
[email protected]a93bb842010-02-16 23:03:47746 // Wrapper for CompressedTexImage2D commands.
747 error::Error DoCompressedTexImage2D(
748 GLenum target,
749 GLint level,
750 GLenum internal_format,
751 GLsizei width,
752 GLsizei height,
753 GLint border,
754 GLsizei image_size,
755 const void* data);
756
[email protected]cadde4a2010-07-31 17:10:43757 // Wrapper for CompressedTexSubImage2D.
758 void DoCompressedTexSubImage2D(
759 GLenum target,
760 GLint level,
761 GLint xoffset,
762 GLint yoffset,
763 GLsizei width,
764 GLsizei height,
765 GLenum format,
766 GLsizei imageSize,
767 const void * data);
768
769 // Wrapper for CopyTexImage2D.
770 void DoCopyTexImage2D(
771 GLenum target,
772 GLint level,
773 GLenum internal_format,
774 GLint x,
775 GLint y,
776 GLsizei width,
777 GLsizei height,
778 GLint border);
779
780 // Wrapper for CopyTexSubImage2D.
781 void DoCopyTexSubImage2D(
782 GLenum target,
783 GLint level,
784 GLint xoffset,
785 GLint yoffset,
786 GLint x,
787 GLint y,
788 GLsizei width,
789 GLsizei height);
790
[email protected]a93bb842010-02-16 23:03:47791 // Wrapper for TexImage2D commands.
792 error::Error DoTexImage2D(
793 GLenum target,
794 GLint level,
795 GLenum internal_format,
796 GLsizei width,
797 GLsizei height,
798 GLint border,
799 GLenum format,
800 GLenum type,
801 const void* pixels,
802 uint32 pixels_size);
803
[email protected]cadde4a2010-07-31 17:10:43804 // Wrapper for TexSubImage2D.
805 void DoTexSubImage2D(
806 GLenum target,
807 GLint level,
808 GLint xoffset,
809 GLint yoffset,
810 GLsizei width,
811 GLsizei height,
812 GLenum format,
813 GLenum type,
814 const void * data);
815
[email protected]e51bdf32011-11-23 22:21:46816 // Wrapper for TexImageIOSurface2DCHROMIUM.
817 void DoTexImageIOSurface2DCHROMIUM(
818 GLenum target,
819 GLsizei width,
820 GLsizei height,
821 GLuint io_surface_id,
822 GLuint plane);
823
[email protected]97dc7cbe2011-12-06 17:26:17824 // Wrapper for TexStorage2DEXT.
825 void DoTexStorage2DEXT(
826 GLenum target,
827 GLint levels,
828 GLenum internal_format,
829 GLsizei width,
830 GLsizei height);
831
[email protected]a93bb842010-02-16 23:03:47832 // Creates a ProgramInfo for the given program.
[email protected]d685a682011-04-29 16:19:57833 ProgramManager::ProgramInfo* CreateProgramInfo(
834 GLuint client_id, GLuint service_id) {
835 return program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47836 }
837
[email protected]07f54fcc2009-12-22 02:46:30838 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03839 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14840 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46841 }
[email protected]07f54fcc2009-12-22 02:46:30842
[email protected]6b8cf1a2010-05-06 16:13:58843 // Gets the program info for the given program. If it's not a program
844 // generates a GL error. Returns NULL if not program.
845 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
846 GLuint client_id, const char* function_name) {
847 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
848 if (!info) {
849 if (GetShaderInfo(client_id)) {
850 SetGLError(GL_INVALID_OPERATION,
851 (std::string(function_name) +
852 ": shader passed for program").c_str());
853 } else {
854 SetGLError(GL_INVALID_VALUE,
855 (std::string(function_name) + ": unknown program").c_str());
856 }
857 }
858 return info;
859 }
860
861
[email protected]45bf5152010-02-12 00:11:31862 // Creates a ShaderInfo for the given shader.
[email protected]d685a682011-04-29 16:19:57863 ShaderManager::ShaderInfo* CreateShaderInfo(
864 GLuint client_id,
865 GLuint service_id,
866 GLenum shader_type) {
867 return shader_manager()->CreateShaderInfo(
868 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31869 }
870
871 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03872 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14873 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31874 }
875
[email protected]6b8cf1a2010-05-06 16:13:58876 // Gets the shader info for the given shader. If it's not a shader generates a
877 // GL error. Returns NULL if not shader.
878 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
879 GLuint client_id, const char* function_name) {
880 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
881 if (!info) {
882 if (GetProgramInfo(client_id)) {
883 SetGLError(
884 GL_INVALID_OPERATION,
885 (std::string(function_name) +
886 ": program passed for shader").c_str());
887 } else {
888 SetGLError(GL_INVALID_VALUE,
889 (std::string(function_name) + ": unknown shader").c_str());
890 }
891 }
892 return info;
893 }
894
[email protected]a93bb842010-02-16 23:03:47895 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03896 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
897 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47898 }
899
[email protected]07f54fcc2009-12-22 02:46:30900 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03901 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
902 BufferManager::BufferInfo* info =
903 buffer_manager()->GetBufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10904 return info;
[email protected]1d32bc82010-01-13 22:06:46905 }
[email protected]07f54fcc2009-12-22 02:46:30906
[email protected]a93bb842010-02-16 23:03:47907 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
908 // on glDeleteBuffers so we can make sure the user does not try to render
909 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03910 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47911
[email protected]a25fa872010-03-25 02:57:58912 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03913 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
914 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58915 }
916
917 // Gets the framebuffer info for the given framebuffer.
918 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03919 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58920 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03921 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10922 return info;
[email protected]a25fa872010-03-25 02:57:58923 }
924
925 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03926 void RemoveFramebufferInfo(GLuint client_id) {
927 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58928 }
929
930 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03931 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
932 return renderbuffer_manager()->CreateRenderbufferInfo(
933 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58934 }
935
936 // Gets the renderbuffer info for the given renderbuffer.
937 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03938 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58939 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03940 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10941 return info;
[email protected]a25fa872010-03-25 02:57:58942 }
943
944 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03945 void RemoveRenderbufferInfo(GLuint client_id) {
946 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58947 }
948
[email protected]258a3313f2011-10-18 20:13:57949 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
950
[email protected]558847a2010-03-24 07:02:54951 error::Error GetAttribLocationHelper(
952 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
953 const std::string& name_str);
954
955 error::Error GetUniformLocationHelper(
956 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
957 const std::string& name_str);
958
[email protected]3916c97e2010-02-25 03:20:50959 // Helper for glShaderSource.
960 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03961 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30962
[email protected]0d6bfdc2011-11-02 01:32:20963 // Clear any textures used by the current program.
964 bool ClearUnclearedTextures();
965
966 // Clear any uncleared level in texture.
967 // Returns false if there was a generated GL error.
968 bool ClearTexture(TextureManager::TextureInfo* info);
969
970 // Clears any uncleared attachments attached to the given frame buffer.
971 // Returns false if there was a generated GL error.
972 void ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:30973 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28974
[email protected]0d6bfdc2011-11-02 01:32:20975 // overridden from GLES2Decoder
976 virtual bool ClearLevel(
977 unsigned service_id,
978 unsigned bind_target,
979 unsigned target,
980 int level,
981 unsigned format,
982 unsigned type,
983 int width,
[email protected]4502e6492011-12-14 19:39:15984 int height,
985 bool is_texture_immutable);
[email protected]0d6bfdc2011-11-02 01:32:20986
[email protected]c007aa02010-09-02 22:22:40987 // Restore all GL state that affects clearing.
988 void RestoreClearState();
989
[email protected]3a2e7c7b2010-08-06 01:12:28990 // Remembers the state of some capabilities.
[email protected]297ca1c2011-06-20 23:08:46991 // Returns: true if glEnable/glDisable should actually be called.
992 bool SetCapabilityState(GLenum cap, bool enabled);
[email protected]3a2e7c7b2010-08-06 01:12:28993
[email protected]0d6bfdc2011-11-02 01:32:20994 // Check that the currently bound framebuffers are valid.
995 // Generates GL error if not.
996 bool CheckBoundFramebuffersValid(const char* func_name);
997
998 // Check if a framebuffer meets our requirements.
999 bool CheckFramebufferValid(
1000 FramebufferManager::FramebufferInfo* framebuffer,
1001 GLenum target,
1002 const char* func_name);
[email protected]3a03a8f2011-03-19 00:51:271003
[email protected]939e7362010-05-13 20:49:101004 // Checks if the current program exists and is valid. If not generates the
1005 // appropriate GL error. Returns true if the current program is in a usable
1006 // state.
1007 bool CheckCurrentProgram(const char* function_name);
1008
1009 // Checks if the current program exists and is valid and that location is not
1010 // -1. If the current program is not valid generates the appropriate GL
1011 // error. Returns true if the current program is in a usable state and
1012 // location is not -1.
1013 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1014
1015 // Gets the type of a uniform for a location in the current program. Sets GL
1016 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:361017 // program is valid and the location exists. Adjusts count so it
1018 // does not overflow the uniform.
1019 bool PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:121020 GLint fake_location, const char* function_name,
1021 GLint* real_location, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:101022
[email protected]b177ae22011-11-01 03:29:111023 // Gets the service id for any simulated backbuffer fbo.
1024 GLuint GetBackbufferServiceId();
1025
[email protected]b273e432010-04-12 17:23:581026 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1027 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1028
[email protected]96449d2c2009-11-25 00:01:321029 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:031030 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:321031
1032 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:031033 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:321034
[email protected]3916c97e2010-02-25 03:20:501035 // Wrapper for glActiveTexture
1036 void DoActiveTexture(GLenum texture_unit);
1037
[email protected]ae51d192010-04-27 00:48:031038 // Wrapper for glAttachShader
1039 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1040
[email protected]96449d2c2009-11-25 00:01:321041 // Wrapper for glBindBuffer since we need to track the current targets.
1042 void DoBindBuffer(GLenum target, GLuint buffer);
1043
[email protected]86093972010-03-11 00:13:561044 // Wrapper for glBindFramebuffer since we need to track the current targets.
1045 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1046
1047 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1048 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1049
[email protected]a93bb842010-02-16 23:03:471050 // Wrapper for glBindTexture since we need to track the current targets.
1051 void DoBindTexture(GLenum target, GLuint texture);
1052
[email protected]8e3e0662010-08-23 18:46:301053 // Wrapper for glBlitFramebufferEXT.
1054 void DoBlitFramebufferEXT(
1055 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1056 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1057 GLbitfield mask, GLenum filter);
1058
[email protected]36cef8ce2010-03-16 07:34:451059 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:111060 void DoBufferData(
1061 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
1062
[email protected]36cef8ce2010-03-16 07:34:451063 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:111064 void DoBufferSubData(
1065 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1066
[email protected]36cef8ce2010-03-16 07:34:451067 // Wrapper for glCheckFramebufferStatus
1068 GLenum DoCheckFramebufferStatus(GLenum target);
1069
[email protected]3a03a8f2011-03-19 00:51:271070 // Wrapper for glClear
1071 void DoClear(GLbitfield mask);
1072
[email protected]3a2e7c7b2010-08-06 01:12:281073 // Wrappers for clear and mask settings functions.
1074 void DoClearColor(
1075 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
1076 void DoClearDepthf(GLclampf depth);
1077 void DoClearStencil(GLint s);
1078 void DoColorMask(
1079 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
1080 void DoDepthMask(GLboolean depth);
1081 void DoStencilMask(GLuint mask);
1082 void DoStencilMaskSeparate(GLenum face, GLuint mask);
1083
[email protected]45bf5152010-02-12 00:11:311084 // Wrapper for glCompileShader.
1085 void DoCompileShader(GLuint shader);
1086
[email protected]269200b12010-11-18 22:53:061087 // Helper for DeleteSharedIdsCHROMIUM commands.
1088 void DoDeleteSharedIdsCHROMIUM(
1089 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101090
[email protected]ae51d192010-04-27 00:48:031091 // Wrapper for glDetachShader
1092 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1093
[email protected]3a2e7c7b2010-08-06 01:12:281094 // Wrapper for glDisable
1095 void DoDisable(GLenum cap);
1096
[email protected]07f54fcc2009-12-22 02:46:301097 // Wrapper for glDisableVertexAttribArray.
1098 void DoDisableVertexAttribArray(GLuint index);
1099
[email protected]3a2e7c7b2010-08-06 01:12:281100 // Wrapper for glEnable
1101 void DoEnable(GLenum cap);
1102
[email protected]07f54fcc2009-12-22 02:46:301103 // Wrapper for glEnableVertexAttribArray.
1104 void DoEnableVertexAttribArray(GLuint index);
1105
[email protected]882ba1e22012-03-08 19:02:531106 // Wrapper for glFinish.
1107 void DoFinish();
1108
1109 // Wrapper for glFlush.
1110 void DoFlush();
1111
[email protected]36cef8ce2010-03-16 07:34:451112 // Wrapper for glFramebufferRenderbufffer.
1113 void DoFramebufferRenderbuffer(
1114 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1115 GLuint renderbuffer);
1116
1117 // Wrapper for glFramebufferTexture2D.
1118 void DoFramebufferTexture2D(
1119 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1120 GLint level);
1121
[email protected]a93bb842010-02-16 23:03:471122 // Wrapper for glGenerateMipmap
1123 void DoGenerateMipmap(GLenum target);
1124
[email protected]269200b12010-11-18 22:53:061125 // Helper for GenSharedIdsCHROMIUM commands.
1126 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:101127 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1128
[email protected]b273e432010-04-12 17:23:581129 // Wrapper for DoGetBooleanv.
1130 void DoGetBooleanv(GLenum pname, GLboolean* params);
1131
1132 // Wrapper for DoGetFloatv.
1133 void DoGetFloatv(GLenum pname, GLfloat* params);
1134
[email protected]36cef8ce2010-03-16 07:34:451135 // Wrapper for glGetFramebufferAttachmentParameteriv.
1136 void DoGetFramebufferAttachmentParameteriv(
1137 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1138
[email protected]a0c3e972010-04-21 00:49:131139 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581140 void DoGetIntegerv(GLenum pname, GLint* params);
1141
[email protected]29a9eb52010-04-13 09:04:231142 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:061143 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:231144 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1145
[email protected]a0c3e972010-04-21 00:49:131146 // Wrapper for glGetProgramiv.
1147 void DoGetProgramiv(
1148 GLuint program_id, GLenum pname, GLint* params);
1149
[email protected]36cef8ce2010-03-16 07:34:451150 // Wrapper for glRenderbufferParameteriv.
1151 void DoGetRenderbufferParameteriv(
1152 GLenum target, GLenum pname, GLint* params);
1153
[email protected]ddd968b82010-03-02 00:44:291154 // Wrapper for glGetShaderiv
1155 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1156
[email protected]b1122982010-05-17 23:04:241157 // Wrappers for glGetVertexAttrib.
1158 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1159 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1160
[email protected]1958e0e2010-04-22 05:17:151161 // Wrappers for glIsXXX functions.
1162 bool DoIsBuffer(GLuint client_id);
1163 bool DoIsFramebuffer(GLuint client_id);
1164 bool DoIsProgram(GLuint client_id);
1165 bool DoIsRenderbuffer(GLuint client_id);
1166 bool DoIsShader(GLuint client_id);
1167 bool DoIsTexture(GLuint client_id);
1168
[email protected]07f54fcc2009-12-22 02:46:301169 // Wrapper for glLinkProgram
1170 void DoLinkProgram(GLuint program);
1171
[email protected]269200b12010-11-18 22:53:061172 // Helper for RegisterSharedIdsCHROMIUM.
1173 void DoRegisterSharedIdsCHROMIUM(
1174 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101175
[email protected]36cef8ce2010-03-16 07:34:451176 // Wrapper for glRenderbufferStorage.
1177 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031178 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451179
[email protected]8e3e0662010-08-23 18:46:301180 // Wrapper for glRenderbufferStorageMultisampleEXT.
1181 void DoRenderbufferStorageMultisample(
1182 GLenum target, GLsizei samples, GLenum internalformat,
1183 GLsizei width, GLsizei height);
1184
[email protected]b273e432010-04-12 17:23:581185 // Wrapper for glReleaseShaderCompiler.
1186 void DoReleaseShaderCompiler() { }
1187
[email protected]3916c97e2010-02-25 03:20:501188 // Wrappers for glTexParameter functions.
1189 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1190 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1191 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1192 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1193
1194 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1195 // spec only these 2 functions can be used to set sampler uniforms.
[email protected]1b0a6752012-02-22 03:44:121196 void DoUniform1i(GLint fake_location, GLint v0);
1197 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1198 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1199 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1200 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101201
1202 // Wrappers for glUniformfv because some drivers don't correctly accept
1203 // bool uniforms.
[email protected]1b0a6752012-02-22 03:44:121204 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1205 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1206 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1207 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501208
[email protected]43c2f1f2011-03-25 18:35:361209 void DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:121210 GLint fake_location, GLsizei count, GLboolean transpose,
1211 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361212 void DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:121213 GLint fake_location, GLsizei count, GLboolean transpose,
1214 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361215 void DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:121216 GLint fake_location, GLsizei count, GLboolean transpose,
1217 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361218
[email protected]b1122982010-05-17 23:04:241219 // Wrappers for glVertexAttrib??
1220 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1221 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1222 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1223 void DoVertexAttrib4f(
1224 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1225 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1226 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1227 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1228 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1229
[email protected]07f54fcc2009-12-22 02:46:301230 // Wrapper for glUseProgram
1231 void DoUseProgram(GLuint program);
1232
[email protected]ae51d192010-04-27 00:48:031233 // Wrapper for glValidateProgram.
1234 void DoValidateProgram(GLuint program_client_id);
1235
[email protected]4e8a5b122010-05-08 22:00:101236 // Gets the number of values that will be returned by glGetXXX. Returns
1237 // false if pname is unknown.
1238 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1239
[email protected]96449d2c2009-11-25 00:01:321240 // Gets the GLError through our wrapper.
1241 GLenum GetGLError();
1242
[email protected]1002c2d2011-06-28 22:39:041243 // Gets the GLError and stores it in our wrapper. Effectively
1244 // this lets us peek at the error without losing it.
1245 GLenum PeekGLError();
1246
[email protected]07f54fcc2009-12-22 02:46:301247 // Copies the real GL errors to the wrapper. This is so we can
1248 // make sure there are no native GL errors before calling some GL function
1249 // so that on return we know any error generated was for that specific
1250 // command.
1251 void CopyRealGLErrorsToWrapper();
1252
[email protected]6217d392010-03-25 22:08:351253 // Clear all real GL errors. This is to prevent the client from seeing any
1254 // errors caused by GL calls that it was not responsible for issuing.
1255 void ClearRealGLErrors();
1256
[email protected]07f54fcc2009-12-22 02:46:301257 // Checks if the current program and vertex attributes are valid for drawing.
[email protected]c6aef902012-02-14 03:31:421258 bool IsDrawValid(GLuint max_vertex_accessed, GLsizei primcount);
[email protected]07f54fcc2009-12-22 02:46:301259
[email protected]c13e1da62011-09-09 21:48:301260 // Returns true if successful, simulated will be true if attrib0 was
1261 // simulated.
[email protected]c6aef902012-02-14 03:31:421262 bool SimulateAttrib0(
1263 GLuint max_vertex_accessed, bool* simulated);
[email protected]b1122982010-05-17 23:04:241264 void RestoreStateForSimulatedAttrib0();
1265
[email protected]ef526492010-06-02 23:12:251266 // Returns true if textures were set.
1267 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501268 void RestoreStateForNonRenderableTextures();
1269
[email protected]8fbedc02010-11-18 18:43:401270 // Returns true if GL_FIXED attribs were simulated.
[email protected]c6aef902012-02-14 03:31:421271 bool SimulateFixedAttribs(
1272 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
[email protected]8fbedc02010-11-18 18:43:401273 void RestoreStateForSimulatedFixedAttribs();
1274
[email protected]c6aef902012-02-14 03:31:421275 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1276 // cases (primcount is 0 for non-instanced).
1277 error::Error DoDrawArrays(
1278 bool instanced, GLenum mode, GLint first, GLsizei count,
1279 GLsizei primcount);
1280 error::Error DoDrawElements(
1281 bool instanced, GLenum mode, GLsizei count, GLenum type,
1282 int32 offset, GLsizei primcount);
1283
[email protected]07f54fcc2009-12-22 02:46:301284 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501285 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301286 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501287 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1288 bound_array_buffer_ : bound_element_array_buffer_;
[email protected]a0b78dc2011-11-11 10:43:101289 return info;
[email protected]07f54fcc2009-12-22 02:46:301290 }
1291
[email protected]a93bb842010-02-16 23:03:471292 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501293 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1294 TextureUnit& unit = texture_units_[active_texture_unit_];
1295 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471296 switch (target) {
1297 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501298 info = unit.bound_texture_2d;
1299 break;
[email protected]a93bb842010-02-16 23:03:471300 case GL_TEXTURE_CUBE_MAP:
1301 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1302 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1303 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1304 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1305 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1306 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501307 info = unit.bound_texture_cube_map;
1308 break;
[email protected]61eeb33f2011-07-26 15:30:311309 case GL_TEXTURE_EXTERNAL_OES:
1310 info = unit.bound_texture_external_oes;
1311 break;
[email protected]e51bdf32011-11-23 22:21:461312 case GL_TEXTURE_RECTANGLE_ARB:
1313 info = unit.bound_texture_rectangle_arb;
1314 break;
[email protected]a93bb842010-02-16 23:03:471315 default:
1316 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501317 return NULL;
[email protected]a93bb842010-02-16 23:03:471318 }
[email protected]a0b78dc2011-11-11 10:43:101319 return info;
[email protected]a93bb842010-02-16 23:03:471320 }
1321
[email protected]61eeb33f2011-07-26 15:30:311322 GLenum GetBindTargetForSamplerType(GLenum type) {
1323 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:461324 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1325 switch (type) {
1326 case GL_SAMPLER_2D:
1327 return GL_TEXTURE_2D;
1328 case GL_SAMPLER_CUBE:
1329 return GL_TEXTURE_CUBE_MAP;
1330 case GL_SAMPLER_EXTERNAL_OES:
1331 return GL_TEXTURE_EXTERNAL_OES;
1332 case GL_SAMPLER_2D_RECT_ARB:
1333 return GL_TEXTURE_RECTANGLE_ARB;
1334 }
1335
1336 NOTREACHED();
1337 return 0;
[email protected]61eeb33f2011-07-26 15:30:311338 }
1339
[email protected]8e3e0662010-08-23 18:46:301340 // Gets the framebuffer info for a particular target.
1341 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1342 GLenum target) {
1343 FramebufferManager::FramebufferInfo* info = NULL;
1344 switch (target) {
1345 case GL_FRAMEBUFFER:
1346 case GL_DRAW_FRAMEBUFFER:
1347 info = bound_draw_framebuffer_;
1348 break;
1349 case GL_READ_FRAMEBUFFER:
1350 info = bound_read_framebuffer_;
1351 break;
1352 default:
1353 NOTREACHED();
1354 break;
1355 }
[email protected]a0b78dc2011-11-11 10:43:101356 return info;
[email protected]8e3e0662010-08-23 18:46:301357 }
1358
[email protected]0d6bfdc2011-11-02 01:32:201359 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfoForTarget(
1360 GLenum target) {
1361 RenderbufferManager::RenderbufferInfo* info = NULL;
1362 switch (target) {
1363 case GL_RENDERBUFFER:
1364 info = bound_renderbuffer_;
1365 break;
1366 default:
1367 NOTREACHED();
1368 break;
1369 }
[email protected]a0b78dc2011-11-11 10:43:101370 return info;
[email protected]0d6bfdc2011-11-02 01:32:201371 }
1372
[email protected]f7b85372010-02-03 01:11:371373 // Validates the program and location for a glGetUniform call and returns
1374 // a SizeResult setup to receive the result. Returns true if glGetUniform
1375 // should be called.
1376 bool GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:121377 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:371378 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:121379 error::Error* error, GLint* real_location, GLuint* service_id,
1380 void** result, GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371381
[email protected]1078f912011-12-23 13:12:141382 // Computes the estimated memory used for the backbuffer and passes it to
1383 // the tracing system.
1384 void UpdateBackbufferMemoryAccounting();
1385
[email protected]38d139d2011-07-14 00:38:431386 // Returns true if the context was just lost due to e.g. GL_ARB_robustness.
1387 bool WasContextLost();
1388
[email protected]e51bdf32011-11-23 22:21:461389#if defined(OS_MACOSX)
1390 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1391#endif
1392
[email protected]96449d2c2009-11-25 00:01:321393 // Generate a member function prototype for each command in an automated and
1394 // typesafe way.
1395 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141396 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191397 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321398 const gles2::name& args); \
1399
1400 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1401
1402 #undef GLES2_CMD_OP
1403
[email protected]2f2d7042010-04-14 21:45:581404 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381405 scoped_refptr<gfx::GLSurface> surface_;
1406 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021407
[email protected]a3ded6d2010-10-19 06:44:391408 // The ContextGroup for this decoder uses to track resources.
1409 ContextGroup::Ref group_;
1410
[email protected]6217d392010-03-25 22:08:351411 // A parent decoder can access this decoders saved offscreen frame buffer.
1412 // The parent pointer is reset if the parent is destroyed.
1413 base::WeakPtr<GLES2DecoderImpl> parent_;
1414
[email protected]34ff8b0c2010-10-01 20:06:021415 // Current width and height of the offscreen frame buffer.
1416 gfx::Size offscreen_size_;
1417
[email protected]96449d2c2009-11-25 00:01:321418 // Current GL error bits.
1419 uint32 error_bits_;
1420
[email protected]96449d2c2009-11-25 00:01:321421 // Util to help with GL.
1422 GLES2Util util_;
1423
1424 // pack alignment as last set by glPixelStorei
1425 GLint pack_alignment_;
1426
1427 // unpack alignment as last set by glPixelStorei
1428 GLint unpack_alignment_;
1429
1430 // The currently bound array buffer. If this is 0 it is illegal to call
1431 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501432 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321433
1434 // The currently bound element array buffer. If this is 0 it is illegal
1435 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501436 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301437
[email protected]f39f4b3f2010-05-12 17:04:081438 // Class that manages vertex attribs.
[email protected]3757a372012-01-19 05:20:441439 scoped_ptr<VertexAttribManager> vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301440
[email protected]b1122982010-05-17 23:04:241441 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1442 GLuint attrib_0_buffer_id_;
1443
1444 // The value currently in attrib_0.
1445 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1446
[email protected]fc753442011-02-04 19:49:491447 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1448 bool attrib_0_buffer_matches_value_;
1449
[email protected]b1122982010-05-17 23:04:241450 // The size of attrib 0.
1451 GLsizei attrib_0_size_;
1452
[email protected]8fbedc02010-11-18 18:43:401453 // The buffer used to simulate GL_FIXED attribs.
1454 GLuint fixed_attrib_buffer_id_;
1455
1456 // The size of fiixed attrib buffer.
1457 GLsizei fixed_attrib_buffer_size_;
1458
[email protected]3916c97e2010-02-25 03:20:501459 // Current active texture by 0 - n index.
1460 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1461 // be 2.
1462 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301463
[email protected]3916c97e2010-02-25 03:20:501464 // Which textures are bound to texture units through glActiveTexture.
1465 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471466
[email protected]3a2e7c7b2010-08-06 01:12:281467 // state saved for clearing so we can clear render buffers and then
1468 // restore to these values.
1469 GLclampf clear_red_;
1470 GLclampf clear_green_;
1471 GLclampf clear_blue_;
1472 GLclampf clear_alpha_;
1473 GLboolean mask_red_;
1474 GLboolean mask_green_;
1475 GLboolean mask_blue_;
1476 GLboolean mask_alpha_;
1477 GLint clear_stencil_;
1478 GLuint mask_stencil_front_;
1479 GLuint mask_stencil_back_;
1480 GLclampf clear_depth_;
1481 GLboolean mask_depth_;
1482 bool enable_scissor_test_;
[email protected]297ca1c2011-06-20 23:08:461483 bool enable_depth_test_;
1484 bool enable_stencil_test_;
1485 bool state_dirty_;
[email protected]3a2e7c7b2010-08-06 01:12:281486
[email protected]1d32bc82010-01-13 22:06:461487 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501488 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301489
[email protected]8e3e0662010-08-23 18:46:301490 // The currently bound framebuffers
1491 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1492 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561493
1494 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081495 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561496
[email protected]b9363b22010-06-09 22:06:151497 // The offscreen frame buffer that the client renders to. With EGL, the
1498 // depth and stencil buffers are separate. With regular GL there is a single
1499 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1500 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351501 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1502 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021503 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151504 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1505 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021506 GLenum offscreen_target_color_format_;
1507 GLenum offscreen_target_depth_format_;
1508 GLenum offscreen_target_stencil_format_;
1509 GLsizei offscreen_target_samples_;
[email protected]8a61d872012-01-20 12:43:561510 GLboolean offscreen_target_buffer_preserved_;
[email protected]6217d392010-03-25 22:08:351511
[email protected]de26b3c2011-08-03 21:54:271512 // The copy that is saved when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021513 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351514 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]8a61d872012-01-20 12:43:561515 TextureManager::TextureInfo::Ref offscreen_saved_color_texture_info_;
[email protected]de26b3c2011-08-03 21:54:271516
1517 // The copy that is used as the destination for multi-sample resolves.
1518 scoped_ptr<FrameBuffer> offscreen_resolved_frame_buffer_;
1519 scoped_ptr<Texture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051520 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351521
[email protected]882ba1e22012-03-08 19:02:531522 scoped_ptr<QueryManager> query_manager_;
1523 QueryManager::Query::Ref current_query_;
1524
[email protected]9d37f062011-11-22 01:24:521525 base::Callback<void(gfx::Size)> resize_callback_;
[email protected]22f320a2011-08-30 01:17:001526
[email protected]6b6e7ee2011-12-13 08:04:521527 MsgCallback msg_callback_;
[email protected]43f28f832010-02-03 02:28:481528
[email protected]b0af4f52011-09-28 22:04:421529 StreamTextureManager* stream_texture_manager_;
1530
[email protected]32fe9aa2011-01-21 23:47:131531 // The format of the back buffer_
1532 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461533 bool back_buffer_has_depth_;
1534 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131535
[email protected]473c01ccb2011-06-07 01:33:301536 bool teximage2d_faster_than_texsubimage2d_;
1537 bool bufferdata_faster_than_buffersubdata_;
1538
[email protected]8eee29c2010-04-29 03:38:291539 // The last error message set.
1540 std::string last_error_;
1541
[email protected]a3a93e7b2010-08-28 00:48:561542 // The current decoder error.
1543 error::Error current_decoder_error_;
1544
[email protected]b1d2dcb2010-05-17 19:24:181545 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451546 scoped_ptr<ShaderTranslator> vertex_translator_;
1547 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181548
[email protected]e82fb792011-09-22 00:33:291549 DisallowedFeatures disallowed_features_;
[email protected]c410da802011-03-14 19:17:411550
[email protected]915a59a12010-09-30 21:29:111551 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051552 const Validators* validators_;
[email protected]80eb6b52012-01-19 00:14:411553 FeatureInfo::Ref feature_info_;
[email protected]9438b012010-06-15 22:55:051554
[email protected]b493ee622011-04-13 23:52:001555 // This indicates all the following texSubImage2D calls that are part of the
1556 // failed texImage2D call should be ignored.
1557 bool tex_image_2d_failed_;
1558
[email protected]65225772011-05-12 21:10:241559 int frame_number_;
1560
[email protected]38d139d2011-07-14 00:38:431561 bool has_arb_robustness_;
1562 GLenum reset_status_;
1563
[email protected]75c023c2011-08-22 23:54:511564 bool needs_mac_nvidia_driver_workaround_;
[email protected]a2a0fe762011-09-20 00:59:121565 bool needs_glsl_built_in_function_emulation_;
[email protected]75c023c2011-08-22 23:54:511566
[email protected]f0d74742011-10-03 16:31:041567 // These flags are used to override the state of the shared feature_info_
1568 // member. Because the same FeatureInfo instance may be shared among many
1569 // contexts, the assumptions on the availablity of extensions in WebGL
1570 // contexts may be broken. These flags override the shared state to preserve
1571 // WebGL semantics.
1572 bool force_webgl_glsl_validation_;
1573 bool derivatives_explicitly_enabled_;
1574
[email protected]062c38b2012-01-18 03:25:101575 bool compile_shader_always_succeeds_;
1576
[email protected]e51bdf32011-11-23 22:21:461577#if defined(OS_MACOSX)
1578 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1579 TextureToIOSurfaceMap texture_to_io_surface_map_;
1580#endif
1581
[email protected]c826d732012-02-09 04:40:261582 typedef std::vector<GLES2DecoderImpl*> ChildList;
1583 ChildList children_;
1584
[email protected]96449d2c2009-11-25 00:01:321585 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1586};
1587
[email protected]6217d392010-03-25 22:08:351588ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1589 : decoder_(decoder) {
1590 decoder_->CopyRealGLErrorsToWrapper();
1591}
1592
1593ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1594 decoder_->ClearRealGLErrors();
1595}
1596
1597ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1598 GLuint id)
1599 : decoder_(decoder) {
1600 ScopedGLErrorSuppressor suppressor(decoder_);
1601
1602 // TODO(apatrick): Check if there are any other states that need to be reset
1603 // before binding a new texture.
1604 glActiveTexture(GL_TEXTURE0);
1605 glBindTexture(GL_TEXTURE_2D, id);
1606}
1607
1608ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1609 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301610 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351611}
1612
1613ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1614 GLuint id)
1615 : decoder_(decoder) {
1616 ScopedGLErrorSuppressor suppressor(decoder_);
1617 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1618}
1619
1620ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1621 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301622 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351623}
1624
1625ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1626 GLuint id)
1627 : decoder_(decoder) {
1628 ScopedGLErrorSuppressor suppressor(decoder_);
1629 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1630}
1631
1632ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1633 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301634 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351635}
1636
[email protected]34ff8b0c2010-10-01 20:06:021637ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271638 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521639 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021640 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1641 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]c0701082011-04-20 00:34:521642 (!decoder_->bound_read_framebuffer_.get() ||
1643 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021644 if (!resolve_and_bind_)
1645 return;
1646
1647 ScopedGLErrorSuppressor suppressor(decoder_);
1648 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1649 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271650 GLuint targetid;
1651 if (internal) {
1652 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1653 decoder_->offscreen_resolved_frame_buffer_.reset(
1654 new FrameBuffer(decoder_));
1655 decoder_->offscreen_resolved_frame_buffer_->Create();
1656 decoder_->offscreen_resolved_color_texture_.reset(new Texture(decoder_));
1657 decoder_->offscreen_resolved_color_texture_->Create();
1658
1659 DCHECK(decoder_->offscreen_saved_color_format_);
1660 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1661 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_);
[email protected]de26b3c2011-08-03 21:54:271662 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1663 decoder_->offscreen_resolved_color_texture_.get());
1664 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1665 GL_FRAMEBUFFER_COMPLETE) {
1666 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1667 << "because offscreen resolved FBO was incomplete.";
1668 return;
1669 }
1670 }
1671 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1672 } else {
1673 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1674 }
1675 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021676 const int width = decoder_->offscreen_size_.width();
1677 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181678 glDisable(GL_SCISSOR_TEST);
[email protected]57edfdad2012-02-07 04:57:151679 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021680 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1681 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1682 } else {
1683 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1684 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1685 }
[email protected]de26b3c2011-08-03 21:54:271686 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021687}
1688
1689ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1690 if (!resolve_and_bind_)
1691 return;
1692
1693 ScopedGLErrorSuppressor suppressor(decoder_);
1694 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181695 if (decoder_->enable_scissor_test_) {
1696 glEnable(GL_SCISSOR_TEST);
1697 }
[email protected]34ff8b0c2010-10-01 20:06:021698}
1699
[email protected]6217d392010-03-25 22:08:351700Texture::Texture(GLES2DecoderImpl* decoder)
1701 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141702 id_(0),
1703 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351704}
1705
1706Texture::~Texture() {
1707 // This does not destroy the render texture because that would require that
1708 // the associated GL context was current. Just check that it was explicitly
1709 // destroyed.
1710 DCHECK_EQ(id_, 0u);
1711}
1712
1713void Texture::Create() {
1714 ScopedGLErrorSuppressor suppressor(decoder_);
1715 Destroy();
1716 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581717 ScopedTexture2DBinder binder(decoder_, id_);
1718 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1719 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1720 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1721 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]62788802011-10-03 17:57:161722
1723 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1724 // never called on an offscreen context, no data will ever be uploaded to the
1725 // saved offscreen color texture (it is deferred until to when SwapBuffers
1726 // is called). My idea is that some nvidia drivers might have a bug where
1727 // deleting a texture that has never been populated might cause a
1728 // crash.
1729 glTexImage2D(
1730 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
[email protected]1078f912011-12-23 13:12:141731 estimated_size_ = 16u * 16u * 4u;
1732 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351733}
1734
[email protected]34ff8b0c2010-10-01 20:06:021735bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351736 DCHECK_NE(id_, 0u);
1737 ScopedGLErrorSuppressor suppressor(decoder_);
1738 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]6217d392010-03-25 22:08:351739
[email protected]f0e6a34f2012-01-04 20:53:401740 WrappedTexImage2D(GL_TEXTURE_2D,
1741 0, // mip level
1742 format,
1743 size.width(),
1744 size.height(),
1745 0, // border
1746 format,
1747 GL_UNSIGNED_BYTE,
1748 NULL);
[email protected]6217d392010-03-25 22:08:351749
[email protected]d37231fa2010-04-09 21:16:021750 size_ = size;
1751
[email protected]1078f912011-12-23 13:12:141752 bool success = glGetError() == GL_NO_ERROR;
1753 if (success) {
1754 uint32 image_size = 0;
1755 GLES2Util::ComputeImageDataSize(
1756 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 4, &image_size);
1757 estimated_size_ = image_size;
1758 decoder_->UpdateBackbufferMemoryAccounting();
1759 }
1760 return success;
[email protected]6217d392010-03-25 22:08:351761}
1762
[email protected]3a4d0c52011-06-29 23:11:581763void Texture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351764 DCHECK_NE(id_, 0u);
1765 ScopedGLErrorSuppressor suppressor(decoder_);
1766 ScopedTexture2DBinder binder(decoder_, id_);
1767 glCopyTexImage2D(GL_TEXTURE_2D,
1768 0, // level
[email protected]3a4d0c52011-06-29 23:11:581769 format,
[email protected]6217d392010-03-25 22:08:351770 0, 0,
1771 size.width(),
1772 size.height(),
1773 0); // border
1774}
1775
1776void Texture::Destroy() {
1777 if (id_ != 0) {
1778 ScopedGLErrorSuppressor suppressor(decoder_);
1779 glDeleteTextures(1, &id_);
1780 id_ = 0;
[email protected]1078f912011-12-23 13:12:141781 estimated_size_ = 0;
1782 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351783 }
1784}
1785
[email protected]97872062010-11-03 19:07:051786void Texture::Invalidate() {
1787 id_ = 0;
1788}
1789
[email protected]6217d392010-03-25 22:08:351790RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1791 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141792 id_(0),
1793 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351794}
1795
1796RenderBuffer::~RenderBuffer() {
1797 // This does not destroy the render buffer because that would require that
1798 // the associated GL context was current. Just check that it was explicitly
1799 // destroyed.
1800 DCHECK_EQ(id_, 0u);
1801}
1802
1803void RenderBuffer::Create() {
1804 ScopedGLErrorSuppressor suppressor(decoder_);
1805 Destroy();
1806 glGenRenderbuffersEXT(1, &id_);
1807}
1808
[email protected]34ff8b0c2010-10-01 20:06:021809bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1810 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351811 ScopedGLErrorSuppressor suppressor(decoder_);
1812 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021813 if (samples <= 1) {
1814 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1815 format,
1816 size.width(),
1817 size.height());
1818 } else {
[email protected]57edfdad2012-02-07 04:57:151819 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021820 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1821 samples,
1822 format,
1823 size.width(),
1824 size.height());
1825 } else {
1826 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1827 samples,
1828 format,
1829 size.width(),
1830 size.height());
1831 }
1832 }
[email protected]1078f912011-12-23 13:12:141833 bool success = glGetError() == GL_NO_ERROR;
1834 if (success) {
1835 estimated_size_ = size.width() * size.height() * samples *
1836 GLES2Util::RenderbufferBytesPerPixel(format);
1837 decoder_->UpdateBackbufferMemoryAccounting();
1838 }
1839 return success;
[email protected]6217d392010-03-25 22:08:351840}
1841
1842void RenderBuffer::Destroy() {
1843 if (id_ != 0) {
1844 ScopedGLErrorSuppressor suppressor(decoder_);
1845 glDeleteRenderbuffersEXT(1, &id_);
1846 id_ = 0;
[email protected]1078f912011-12-23 13:12:141847 estimated_size_ = 0;
1848 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351849 }
1850}
1851
[email protected]97872062010-11-03 19:07:051852void RenderBuffer::Invalidate() {
1853 id_ = 0;
1854}
1855
[email protected]6217d392010-03-25 22:08:351856FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1857 : decoder_(decoder),
1858 id_(0) {
1859}
1860
1861FrameBuffer::~FrameBuffer() {
1862 // This does not destroy the frame buffer because that would require that
1863 // the associated GL context was current. Just check that it was explicitly
1864 // destroyed.
1865 DCHECK_EQ(id_, 0u);
1866}
1867
1868void FrameBuffer::Create() {
1869 ScopedGLErrorSuppressor suppressor(decoder_);
1870 Destroy();
1871 glGenFramebuffersEXT(1, &id_);
1872}
1873
1874void FrameBuffer::AttachRenderTexture(Texture* texture) {
1875 DCHECK_NE(id_, 0u);
1876 ScopedGLErrorSuppressor suppressor(decoder_);
1877 ScopedFrameBufferBinder binder(decoder_, id_);
1878 GLuint attach_id = texture ? texture->id() : 0;
1879 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1880 GL_COLOR_ATTACHMENT0,
1881 GL_TEXTURE_2D,
1882 attach_id,
1883 0);
1884}
1885
[email protected]b9363b22010-06-09 22:06:151886void FrameBuffer::AttachRenderBuffer(GLenum target,
1887 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351888 DCHECK_NE(id_, 0u);
1889 ScopedGLErrorSuppressor suppressor(decoder_);
1890 ScopedFrameBufferBinder binder(decoder_, id_);
1891 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1892 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151893 target,
[email protected]6217d392010-03-25 22:08:351894 GL_RENDERBUFFER,
1895 attach_id);
1896}
1897
[email protected]6217d392010-03-25 22:08:351898void FrameBuffer::Destroy() {
1899 if (id_ != 0) {
1900 ScopedGLErrorSuppressor suppressor(decoder_);
1901 glDeleteFramebuffersEXT(1, &id_);
1902 id_ = 0;
1903 }
1904}
1905
[email protected]97872062010-11-03 19:07:051906void FrameBuffer::Invalidate() {
1907 id_ = 0;
1908}
1909
[email protected]6217d392010-03-25 22:08:351910GLenum FrameBuffer::CheckStatus() {
1911 DCHECK_NE(id_, 0u);
1912 ScopedGLErrorSuppressor suppressor(decoder_);
1913 ScopedFrameBufferBinder binder(decoder_, id_);
1914 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1915}
1916
[email protected]aa7666122011-09-02 19:45:521917GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1918 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321919}
1920
[email protected]aa7666122011-09-02 19:45:521921GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391922 : GLES2Decoder(),
[email protected]3b1ecc262011-08-03 22:49:571923 group_(group),
[email protected]96449d2c2009-11-25 00:01:321924 error_bits_(0),
[email protected]96449d2c2009-11-25 00:01:321925 pack_alignment_(4),
1926 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241927 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491928 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241929 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401930 fixed_attrib_buffer_id_(0),
1931 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501932 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281933 clear_red_(0),
1934 clear_green_(0),
1935 clear_blue_(0),
1936 clear_alpha_(0),
1937 mask_red_(true),
1938 mask_green_(true),
1939 mask_blue_(true),
1940 mask_alpha_(true),
1941 clear_stencil_(0),
1942 mask_stencil_front_(-1),
1943 mask_stencil_back_(-1),
1944 clear_depth_(1.0f),
1945 mask_depth_(true),
1946 enable_scissor_test_(false),
[email protected]297ca1c2011-06-20 23:08:461947 enable_depth_test_(false),
1948 enable_stencil_test_(false),
1949 state_dirty_(true),
[email protected]34ff8b0c2010-10-01 20:06:021950 offscreen_target_color_format_(0),
1951 offscreen_target_depth_format_(0),
1952 offscreen_target_stencil_format_(0),
1953 offscreen_target_samples_(0),
[email protected]8a61d872012-01-20 12:43:561954 offscreen_target_buffer_preserved_(true),
[email protected]97872062010-11-03 19:07:051955 offscreen_saved_color_format_(0),
[email protected]b0af4f52011-09-28 22:04:421956 stream_texture_manager_(NULL),
[email protected]32fe9aa2011-01-21 23:47:131957 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:461958 back_buffer_has_depth_(false),
1959 back_buffer_has_stencil_(false),
[email protected]473c01ccb2011-06-07 01:33:301960 teximage2d_faster_than_texsubimage2d_(true),
1961 bufferdata_faster_than_buffersubdata_(true),
[email protected]a3a93e7b2010-08-28 00:48:561962 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051963 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111964 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001965 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241966 tex_image_2d_failed_(false),
[email protected]38d139d2011-07-14 00:38:431967 frame_number_(0),
1968 has_arb_robustness_(false),
[email protected]75c023c2011-08-22 23:54:511969 reset_status_(GL_NO_ERROR),
[email protected]a2a0fe762011-09-20 00:59:121970 needs_mac_nvidia_driver_workaround_(false),
[email protected]f0d74742011-10-03 16:31:041971 needs_glsl_built_in_function_emulation_(false),
1972 force_webgl_glsl_validation_(false),
[email protected]062c38b2012-01-18 03:25:101973 derivatives_explicitly_enabled_(false),
1974 compile_shader_always_succeeds_(false) {
[email protected]3b1ecc262011-08-03 22:49:571975 DCHECK(group);
1976
[email protected]b1122982010-05-17 23:04:241977 attrib_0_value_.v[0] = 0.0f;
1978 attrib_0_value_.v[1] = 0.0f;
1979 attrib_0_value_.v[2] = 0.0f;
1980 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151981
[email protected]c2f8c8402010-12-06 18:07:241982 // The shader translator is used for WebGL even when running on EGL
1983 // because additional restrictions are needed (like only enabling
1984 // GL_OES_standard_derivatives on demand). It is used for the unit
1985 // tests because
1986 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1987 // empty string to CompileShader and this is not a valid shader.
1988 // TODO(apatrick): fix this test.
1989 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:041990 !feature_info_->feature_flags().chromium_webglsl &&
1991 !force_webgl_glsl_validation_) ||
[email protected]39ba4f02012-03-26 01:16:001992 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
1993 CommandLine::ForCurrentProcess()->HasSwitch(
1994 switches::kDisableGLSLTranslator)) {
[email protected]b9363b22010-06-09 22:06:151995 use_shader_translator_ = false;
1996 }
[email protected]473c01ccb2011-06-07 01:33:301997
1998 // TODO(gman): Consider setting these based on GPU and/or driver.
1999 if (IsAngle()) {
2000 teximage2d_faster_than_texsubimage2d_ = false;
2001 bufferdata_faster_than_buffersubdata_ = false;
2002 }
[email protected]96449d2c2009-11-25 00:01:322003}
2004
[email protected]80eb6b52012-01-19 00:14:412005GLES2DecoderImpl::~GLES2DecoderImpl() {
2006}
2007
[email protected]c410da802011-03-14 19:17:412008bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:382009 const scoped_refptr<gfx::GLSurface>& surface,
2010 const scoped_refptr<gfx::GLContext>& context,
[email protected]c410da802011-03-14 19:17:412011 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:292012 const DisallowedFeatures& disallowed_features,
[email protected]c410da802011-03-14 19:17:412013 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:242014 const std::vector<int32>& attribs) {
[email protected]4bedba72010-04-20 22:08:542015 DCHECK(context);
[email protected]66791e382010-07-14 20:48:302016 DCHECK(!context_.get());
2017
[email protected]e844ae22012-01-14 03:36:262018 if (CommandLine::ForCurrentProcess()->HasSwitch(
2019 switches::kEnableGPUDebugging)) {
2020 set_debug(true);
2021 }
2022
[email protected]39ba4f02012-03-26 01:16:002023 if (CommandLine::ForCurrentProcess()->HasSwitch(
2024 switches::kEnableGPUCommandLogging)) {
2025 set_log_commands(true);
2026 }
2027
[email protected]062c38b2012-01-18 03:25:102028 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2029 switches::kCompileShaderAlwaysSucceeds);
2030
[email protected]fbe20372011-06-01 01:46:382031 // Take ownership of the GLSurface. TODO(apatrick): once the parent / child
2032 // context is retired, the decoder should not take an initial surface as
2033 // an argument to this function.
2034 // Maybe create a short lived offscreen GLSurface for the purpose of
2035 // initializing the decoder's GLContext.
2036 surface_ = surface;
[email protected]f62a5ab2011-05-23 20:34:152037
[email protected]66791e382010-07-14 20:48:302038 // Take ownership of the GLContext.
[email protected]fbe20372011-06-01 01:46:382039 context_ = context;
[email protected]d37231fa2010-04-09 21:16:022040
[email protected]246a70452010-03-05 21:53:502041 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:012042 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
2043 << "MakeCurrent failed.";
[email protected]1871a092011-10-10 21:46:422044 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]246a70452010-03-05 21:53:502045 Destroy();
2046 return false;
[email protected]eb54a562010-01-20 21:55:182047 }
2048
[email protected]e82fb792011-09-22 00:33:292049 if (!group_->Initialize(disallowed_features, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:222050 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:392051 << "failed to initialize.";
[email protected]1871a092011-10-10 21:46:422052 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]a3ded6d2010-10-19 06:44:392053 Destroy();
[email protected]ae1741092010-11-17 19:16:032054 return false;
[email protected]a3ded6d2010-10-19 06:44:392055 }
2056
[email protected]246a70452010-03-05 21:53:502057 CHECK_GL_ERROR();
[email protected]e82fb792011-09-22 00:33:292058 disallowed_features_ = disallowed_features;
[email protected]246a70452010-03-05 21:53:502059
[email protected]3757a372012-01-19 05:20:442060 vertex_attrib_manager_.reset(new VertexAttribManager());
2061 vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:322062
[email protected]c45f1972012-03-14 07:27:362063 query_manager_.reset(new QueryManager(this, feature_info_->feature_flags(
2064 ).use_arb_occlusion_query2_for_occlusion_query_boolean));
[email protected]882ba1e22012-03-08 19:02:532065
[email protected]302ce6d2011-07-07 23:28:112066 util_.set_num_compressed_texture_formats(
2067 validators_->compressed_texture_format.GetValues().size());
2068
[email protected]1071e572011-02-09 20:00:122069 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2070 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2071 // OpenGL ES 2.0 does not have this issue.
2072 glEnableVertexAttribArray(0);
2073 }
[email protected]b1122982010-05-17 23:04:242074 glGenBuffersARB(1, &attrib_0_buffer_id_);
2075 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2076 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2077 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:402078 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:082079
[email protected]246a70452010-03-05 21:53:502080 texture_units_.reset(
2081 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:152082 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:492083 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:312084 // We want the last bind to be 2D.
2085 TextureManager::TextureInfo* info;
2086 if (feature_info_->feature_flags().oes_egl_image_external) {
2087 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_EXTERNAL_OES);
2088 texture_units_[tt].bound_texture_external_oes = info;
2089 glBindTexture(GL_TEXTURE_EXTERNAL_OES, info->service_id());
2090 }
[email protected]e51bdf32011-11-23 22:21:462091 if (feature_info_->feature_flags().arb_texture_rectangle) {
2092 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_RECTANGLE_ARB);
2093 texture_units_[tt].bound_texture_rectangle_arb = info;
2094 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, info->service_id());
2095 }
[email protected]61eeb33f2011-07-26 15:30:312096 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:492097 texture_units_[tt].bound_texture_cube_map = info;
2098 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
2099 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2100 texture_units_[tt].bound_texture_2d = info;
2101 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:152102 }
[email protected]00f893d2010-08-24 18:55:492103 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:502104 CHECK_GL_ERROR();
2105
[email protected]297ca1c2011-06-20 23:08:462106 ContextCreationAttribParser attrib_parser;
2107 if (!attrib_parser.Parse(attribs))
2108 return false;
[email protected]41c56362011-06-14 16:47:432109
[email protected]297ca1c2011-06-20 23:08:462110 // These are NOT if the back buffer has these proprorties. They are
2111 // if we want the command buffer to enforce them regardless of what
2112 // the real backbuffer is assuming the real back buffer gives us more than
2113 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2114 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2115 // can't do anything about that.
2116
2117 GLint v = 0;
2118 glGetIntegerv(GL_ALPHA_BITS, &v);
2119 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2120 // user requested RGB then RGB. If the user did not specify a preference than
2121 // use whatever we were given. Same for DEPTH and STENCIL.
2122 back_buffer_color_format_ =
2123 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2124 glGetIntegerv(GL_DEPTH_BITS, &v);
2125 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2126 glGetIntegerv(GL_STENCIL_BITS, &v);
2127 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2128
2129 if (surface_->IsOffscreen()) {
[email protected]34ff8b0c2010-10-01 20:06:022130 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:542131 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:022132 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
2133 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:432134 // max_sample_count must be initialized to a sane value. If
2135 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2136 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:022137 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2138 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2139 max_sample_count);
2140 } else {
2141 offscreen_target_samples_ = 1;
2142 }
[email protected]8a61d872012-01-20 12:43:562143 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
[email protected]34ff8b0c2010-10-01 20:06:022144
2145 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2146 const bool rgb8_supported =
2147 context_->HasExtension("GL_OES_rgb8_rgba8");
2148 // The only available default render buffer formats in GLES2 have very
2149 // little precision. Don't enable multisampling unless 8-bit render
2150 // buffer formats are available--instead fall back to 8-bit textures.
2151 if (rgb8_supported && offscreen_target_samples_ > 1) {
2152 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2153 GL_RGBA8 : GL_RGB8;
2154 } else {
2155 offscreen_target_samples_ = 1;
2156 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2157 GL_RGBA : GL_RGB;
2158 }
2159
2160 // ANGLE only supports packed depth/stencil formats, so use it if it is
2161 // available.
2162 const bool depth24_stencil8_supported =
2163 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272164 VLOG(1) << "GL_OES_packed_depth_stencil "
2165 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:002166 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2167 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022168 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2169 offscreen_target_stencil_format_ = 0;
2170 } else {
2171 // It may be the case that this depth/stencil combination is not
2172 // supported, but this will be checked later by CheckFramebufferStatus.
2173 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2174 GL_DEPTH_COMPONENT16 : 0;
2175 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2176 GL_STENCIL_INDEX8 : 0;
2177 }
2178 } else {
2179 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2180 GL_RGBA : GL_RGB;
2181
2182 // If depth is requested at all, use the packed depth stencil format if
2183 // it's available, as some desktop GL drivers don't support any non-packed
2184 // formats for depth attachments.
2185 const bool depth24_stencil8_supported =
2186 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272187 VLOG(1) << "GL_EXT_packed_depth_stencil "
2188 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:022189
[email protected]71ee3642010-10-14 18:08:002190 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2191 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022192 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2193 offscreen_target_stencil_format_ = 0;
2194 } else {
2195 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2196 GL_DEPTH_COMPONENT : 0;
2197 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2198 GL_STENCIL_INDEX : 0;
2199 }
2200 }
2201
[email protected]97872062010-11-03 19:07:052202 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2203 GL_RGBA : GL_RGB;
2204
[email protected]6217d392010-03-25 22:08:352205 // Create the target frame buffer. This is the one that the client renders
2206 // directly to.
2207 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
2208 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022209 // Due to GLES2 format limitations, either the color texture (for
2210 // non-multisampling) or the color render buffer (for multisampling) will be
2211 // attached to the offscreen frame buffer. The render buffer has more
2212 // limited formats available to it, but the texture can't do multisampling.
2213 if (IsOffscreenBufferMultisampled()) {
2214 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
2215 offscreen_target_color_render_buffer_->Create();
2216 } else {
2217 offscreen_target_color_texture_.reset(new Texture(this));
2218 offscreen_target_color_texture_->Create();
2219 }
2220 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152221 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022222 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152223 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:352224
2225 // Create the saved offscreen texture. The target frame buffer is copied
2226 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:022227 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
2228 offscreen_saved_frame_buffer_->Create();
2229 //
[email protected]6217d392010-03-25 22:08:352230 offscreen_saved_color_texture_.reset(new Texture(this));
2231 offscreen_saved_color_texture_->Create();
2232
[email protected]6217d392010-03-25 22:08:352233 // Allocate the render buffers at their initial size and check the status
2234 // of the frame buffers is okay.
[email protected]799b4b22011-08-22 17:09:592235 if (!ResizeOffscreenFrameBuffer(size)) {
[email protected]d0498742010-09-20 20:27:012236 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:352237 Destroy();
2238 return false;
2239 }
2240
2241 // Bind to the new default frame buffer (the offscreen target frame buffer).
2242 // This should now be associated with ID zero.
2243 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2244 }
2245
[email protected]295faf4b2012-01-25 23:31:412246 // Clear the backbuffer.
2247 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2248
[email protected]76a0ee102010-04-07 21:03:042249 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2250 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2251 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372252 // mailing list archives. It also implicitly enables the desktop GL
2253 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2254 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152255 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2256 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372257 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152258 }
[email protected]de17df392010-04-23 21:09:412259
[email protected]38d139d2011-07-14 00:38:432260 has_arb_robustness_ = context->HasExtension("GL_ARB_robustness");
2261
[email protected]e82fb792011-09-22 00:33:292262 if (!disallowed_features_.driver_bug_workarounds) {
[email protected]75c023c2011-08-22 23:54:512263#if defined(OS_MACOSX)
[email protected]a2a0fe762011-09-20 00:59:122264 const char* vendor_str = reinterpret_cast<const char*>(
2265 glGetString(GL_VENDOR));
2266 needs_mac_nvidia_driver_workaround_ =
2267 vendor_str && strstr(vendor_str, "NVIDIA");
2268 needs_glsl_built_in_function_emulation_ =
2269 vendor_str && (strstr(vendor_str, "ATI") || strstr(vendor_str, "AMD"));
2270#elif defined(OS_WIN)
2271 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
2272 needs_glsl_built_in_function_emulation_ = true;
[email protected]75c023c2011-08-22 23:54:512273#endif
[email protected]a2a0fe762011-09-20 00:59:122274 }
[email protected]75c023c2011-08-22 23:54:512275
[email protected]c2f8c8402010-12-06 18:07:242276 if (!InitializeShaderTranslator()) {
2277 return false;
[email protected]de17df392010-04-23 21:09:412278 }
[email protected]76a0ee102010-04-07 21:03:042279
[email protected]246a70452010-03-05 21:53:502280 return true;
[email protected]96449d2c2009-11-25 00:01:322281}
2282
[email protected]302ce6d2011-07-07 23:28:112283void GLES2DecoderImpl::UpdateCapabilities() {
2284 util_.set_num_compressed_texture_formats(
2285 validators_->compressed_texture_format.GetValues().size());
2286 util_.set_num_shader_binary_formats(
2287 validators_->shader_binary_format.GetValues().size());
2288}
2289
[email protected]c2f8c8402010-12-06 18:07:242290bool GLES2DecoderImpl::InitializeShaderTranslator() {
2291 // Re-check the state of use_shader_translator_ each time this is called.
2292 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:042293 (feature_info_->feature_flags().chromium_webglsl ||
2294 force_webgl_glsl_validation_) &&
[email protected]c2f8c8402010-12-06 18:07:242295 !use_shader_translator_) {
2296 use_shader_translator_ = true;
2297 }
2298 if (!use_shader_translator_) {
2299 return true;
2300 }
2301 ShBuiltInResources resources;
2302 ShInitBuiltInResources(&resources);
2303 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2304 resources.MaxVertexUniformVectors =
2305 group_->max_vertex_uniform_vectors();
2306 resources.MaxVaryingVectors = group_->max_varying_vectors();
2307 resources.MaxVertexTextureImageUnits =
2308 group_->max_vertex_texture_image_units();
2309 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2310 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2311 resources.MaxFragmentUniformVectors =
2312 group_->max_fragment_uniform_vectors();
2313 resources.MaxDrawBuffers = 1;
[email protected]f0d74742011-10-03 16:31:042314
2315 if (force_webgl_glsl_validation_) {
2316 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2317 } else {
2318 resources.OES_standard_derivatives =
2319 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
[email protected]e51bdf32011-11-23 22:21:462320 resources.ARB_texture_rectangle =
2321 feature_info_->feature_flags().arb_texture_rectangle ? 1 : 0;
[email protected]f0d74742011-10-03 16:31:042322 }
2323
[email protected]c2f8c8402010-12-06 18:07:242324 vertex_translator_.reset(new ShaderTranslator);
[email protected]f0d74742011-10-03 16:31:042325 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ||
2326 feature_info_->feature_flags().chromium_webglsl ?
2327 SH_WEBGL_SPEC : SH_GLES2_SPEC;
[email protected]a2a0fe762011-09-20 00:59:122328 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2329 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2330 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2331 ShaderTranslatorInterface::GlslBuiltInFunctionBehavior function_behavior =
2332 needs_glsl_built_in_function_emulation_ ?
2333 ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated :
2334 ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal;
[email protected]c2f8c8402010-12-06 18:07:242335 if (!vertex_translator_->Init(
[email protected]a2a0fe762011-09-20 00:59:122336 SH_VERTEX_SHADER, shader_spec, &resources,
2337 implementation_type, function_behavior)) {
[email protected]c2f8c8402010-12-06 18:07:242338 LOG(ERROR) << "Could not initialize vertex shader translator.";
2339 Destroy();
2340 return false;
2341 }
2342 fragment_translator_.reset(new ShaderTranslator);
2343 if (!fragment_translator_->Init(
[email protected]a2a0fe762011-09-20 00:59:122344 SH_FRAGMENT_SHADER, shader_spec, &resources,
2345 implementation_type, function_behavior)) {
[email protected]c2f8c8402010-12-06 18:07:242346 LOG(ERROR) << "Could not initialize fragment shader translator.";
2347 Destroy();
2348 return false;
2349 }
2350 return true;
2351}
2352
[email protected]ae51d192010-04-27 00:48:032353bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472354 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032355 if (GetBufferInfo(client_ids[ii])) {
2356 return false;
2357 }
2358 }
2359 scoped_array<GLuint> service_ids(new GLuint[n]);
2360 glGenBuffersARB(n, service_ids.get());
2361 for (GLsizei ii = 0; ii < n; ++ii) {
2362 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2363 }
2364 return true;
2365}
2366
2367bool GLES2DecoderImpl::GenFramebuffersHelper(
2368 GLsizei n, const GLuint* client_ids) {
2369 for (GLsizei ii = 0; ii < n; ++ii) {
2370 if (GetFramebufferInfo(client_ids[ii])) {
2371 return false;
2372 }
2373 }
2374 scoped_array<GLuint> service_ids(new GLuint[n]);
2375 glGenFramebuffersEXT(n, service_ids.get());
2376 for (GLsizei ii = 0; ii < n; ++ii) {
2377 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2378 }
2379 return true;
2380}
2381
2382bool GLES2DecoderImpl::GenRenderbuffersHelper(
2383 GLsizei n, const GLuint* client_ids) {
2384 for (GLsizei ii = 0; ii < n; ++ii) {
2385 if (GetRenderbufferInfo(client_ids[ii])) {
2386 return false;
2387 }
2388 }
2389 scoped_array<GLuint> service_ids(new GLuint[n]);
2390 glGenRenderbuffersEXT(n, service_ids.get());
2391 for (GLsizei ii = 0; ii < n; ++ii) {
2392 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2393 }
2394 return true;
2395}
2396
2397bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2398 for (GLsizei ii = 0; ii < n; ++ii) {
2399 if (GetTextureInfo(client_ids[ii])) {
2400 return false;
2401 }
2402 }
2403 scoped_array<GLuint> service_ids(new GLuint[n]);
2404 glGenTextures(n, service_ids.get());
2405 for (GLsizei ii = 0; ii < n; ++ii) {
2406 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2407 }
2408 return true;
2409}
2410
2411void GLES2DecoderImpl::DeleteBuffersHelper(
2412 GLsizei n, const GLuint* client_ids) {
2413 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102414 BufferManager::BufferInfo* buffer = GetBufferInfo(client_ids[ii]);
2415 if (buffer && !buffer->IsDeleted()) {
[email protected]3757a372012-01-19 05:20:442416 vertex_attrib_manager_->Unbind(buffer);
[email protected]a0b78dc2011-11-11 10:43:102417 if (bound_array_buffer_ == buffer) {
2418 bound_array_buffer_ = NULL;
2419 }
2420 if (bound_element_array_buffer_ == buffer) {
2421 bound_element_array_buffer_ = NULL;
2422 }
2423 GLuint service_id = buffer->service_id();
[email protected]ae51d192010-04-27 00:48:032424 glDeleteBuffersARB(1, &service_id);
2425 RemoveBufferInfo(client_ids[ii]);
2426 }
[email protected]a93bb842010-02-16 23:03:472427 }
[email protected]07f54fcc2009-12-22 02:46:302428}
2429
[email protected]ae51d192010-04-27 00:48:032430void GLES2DecoderImpl::DeleteFramebuffersHelper(
2431 GLsizei n, const GLuint* client_ids) {
[email protected]b177ae22011-11-01 03:29:112432 bool supports_seperate_framebuffer_binds =
2433 feature_info_->feature_flags().chromium_framebuffer_multisample;
2434
[email protected]a25fa872010-03-25 02:57:582435 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102436 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ae51d192010-04-27 00:48:032437 GetFramebufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102438 if (framebuffer && !framebuffer->IsDeleted()) {
2439 if (framebuffer == bound_draw_framebuffer_) {
[email protected]297ca1c2011-06-20 23:08:462440 bound_draw_framebuffer_ = NULL;
2441 state_dirty_ = true;
[email protected]b177ae22011-11-01 03:29:112442 GLenum target = supports_seperate_framebuffer_binds ?
2443 GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER;
2444 glBindFramebufferEXT(target, GetBackbufferServiceId());
2445 }
[email protected]a0b78dc2011-11-11 10:43:102446 if (framebuffer == bound_read_framebuffer_) {
[email protected]b177ae22011-11-01 03:29:112447 bound_read_framebuffer_ = NULL;
2448 GLenum target = supports_seperate_framebuffer_binds ?
2449 GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER;
2450 glBindFramebufferEXT(target, GetBackbufferServiceId());
[email protected]297ca1c2011-06-20 23:08:462451 }
[email protected]a0b78dc2011-11-11 10:43:102452 GLuint service_id = framebuffer->service_id();
[email protected]ae51d192010-04-27 00:48:032453 glDeleteFramebuffersEXT(1, &service_id);
2454 RemoveFramebufferInfo(client_ids[ii]);
2455 }
[email protected]a25fa872010-03-25 02:57:582456 }
[email protected]07f54fcc2009-12-22 02:46:302457}
2458
[email protected]ae51d192010-04-27 00:48:032459void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2460 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102461 bool supports_seperate_framebuffer_binds =
2462 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a25fa872010-03-25 02:57:582463 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102464 RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]ae51d192010-04-27 00:48:032465 GetRenderbufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102466 if (renderbuffer && !renderbuffer->IsDeleted()) {
2467 if (bound_renderbuffer_ == renderbuffer) {
2468 bound_renderbuffer_ = NULL;
2469 }
2470 // Unbind from current framebuffers.
2471 if (supports_seperate_framebuffer_binds) {
2472 if (bound_read_framebuffer_) {
2473 bound_read_framebuffer_->UnbindRenderbuffer(
2474 GL_READ_FRAMEBUFFER, renderbuffer);
2475 }
2476 if (bound_draw_framebuffer_) {
2477 bound_draw_framebuffer_->UnbindRenderbuffer(
2478 GL_DRAW_FRAMEBUFFER, renderbuffer);
2479 }
2480 } else {
2481 if (bound_draw_framebuffer_) {
2482 bound_draw_framebuffer_->UnbindRenderbuffer(
2483 GL_FRAMEBUFFER, renderbuffer);
2484 }
2485 }
[email protected]297ca1c2011-06-20 23:08:462486 state_dirty_ = true;
[email protected]a0b78dc2011-11-11 10:43:102487 GLuint service_id = renderbuffer->service_id();
[email protected]ae51d192010-04-27 00:48:032488 glDeleteRenderbuffersEXT(1, &service_id);
2489 RemoveRenderbufferInfo(client_ids[ii]);
2490 }
[email protected]a25fa872010-03-25 02:57:582491 }
[email protected]07f54fcc2009-12-22 02:46:302492}
2493
[email protected]ae51d192010-04-27 00:48:032494void GLES2DecoderImpl::DeleteTexturesHelper(
2495 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102496 bool supports_seperate_framebuffer_binds =
2497 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a93bb842010-02-16 23:03:472498 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102499 TextureManager::TextureInfo* texture = GetTextureInfo(client_ids[ii]);
2500 if (texture && !texture->IsDeleted()) {
2501 if (texture->IsAttachedToFramebuffer()) {
[email protected]297ca1c2011-06-20 23:08:462502 state_dirty_ = true;
2503 }
[email protected]a0b78dc2011-11-11 10:43:102504 // Unbind texture from texture units.
2505 for (size_t jj = 0; jj < group_->max_texture_units(); ++jj) {
2506 texture_units_[ii].Unbind(texture);
2507 }
2508 // Unbind from current framebuffers.
2509 if (supports_seperate_framebuffer_binds) {
2510 if (bound_read_framebuffer_) {
2511 bound_read_framebuffer_->UnbindTexture(GL_READ_FRAMEBUFFER, texture);
2512 }
2513 if (bound_draw_framebuffer_) {
2514 bound_draw_framebuffer_->UnbindTexture(GL_DRAW_FRAMEBUFFER, texture);
2515 }
2516 } else {
2517 if (bound_draw_framebuffer_) {
2518 bound_draw_framebuffer_->UnbindTexture(GL_FRAMEBUFFER, texture);
2519 }
2520 }
2521 GLuint service_id = texture->service_id();
2522 if (texture->IsStreamTexture() && stream_texture_manager_) {
[email protected]b0af4f52011-09-28 22:04:422523 stream_texture_manager_->DestroyStreamTexture(service_id);
2524 }
[email protected]e51bdf32011-11-23 22:21:462525#if defined(OS_MACOSX)
2526 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2527 ReleaseIOSurfaceForTexture(service_id);
2528 }
2529#endif
[email protected]5f4f2a732011-07-30 00:47:552530 glDeleteTextures(1, &service_id);
[email protected]ae51d192010-04-27 00:48:032531 RemoveTextureInfo(client_ids[ii]);
2532 }
[email protected]a93bb842010-02-16 23:03:472533 }
[email protected]07f54fcc2009-12-22 02:46:302534}
2535
[email protected]43f28f832010-02-03 02:28:482536// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322537
[email protected]eb54a562010-01-20 21:55:182538bool GLES2DecoderImpl::MakeCurrent() {
[email protected]38d139d2011-07-14 00:38:432539 bool result = context_.get() ? context_->MakeCurrent(surface_.get()) : false;
2540 if (result && WasContextLost()) {
2541 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2542 result = false;
2543 }
2544
2545 return result;
[email protected]eb54a562010-01-20 21:55:182546}
2547
[email protected]a96a6022011-11-04 00:58:122548void GLES2DecoderImpl::ReleaseCurrent() {
2549 if (context_.get())
2550 context_->ReleaseCurrent(surface_.get());
2551}
2552
[email protected]8e3e0662010-08-23 18:46:302553void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
[email protected]0d6bfdc2011-11-02 01:32:202554 RenderbufferManager::RenderbufferInfo* renderbuffer =
2555 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
[email protected]8e3e0662010-08-23 18:46:302556 glBindRenderbufferEXT(
[email protected]0d6bfdc2011-11-02 01:32:202557 GL_RENDERBUFFER, renderbuffer ? renderbuffer->service_id() : 0);
[email protected]8e3e0662010-08-23 18:46:302558}
2559
2560static void RebindCurrentFramebuffer(
2561 GLenum target,
2562 FramebufferManager::FramebufferInfo* info,
[email protected]a3783712012-01-20 22:18:242563 GLuint back_buffer_service_id) {
[email protected]8e3e0662010-08-23 18:46:302564 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462565
[email protected]a3783712012-01-20 22:18:242566 if (framebuffer_id == 0) {
2567 framebuffer_id = back_buffer_service_id;
[email protected]8e3e0662010-08-23 18:46:302568 }
[email protected]297ca1c2011-06-20 23:08:462569
[email protected]8e3e0662010-08-23 18:46:302570 glBindFramebufferEXT(target, framebuffer_id);
2571}
2572
2573void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]297ca1c2011-06-20 23:08:462574 state_dirty_ = true;
2575
[email protected]a3ded6d2010-10-19 06:44:392576 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302577 RebindCurrentFramebuffer(
2578 GL_FRAMEBUFFER,
2579 bound_draw_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242580 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302581 } else {
2582 RebindCurrentFramebuffer(
2583 GL_READ_FRAMEBUFFER_EXT,
2584 bound_read_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242585 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302586 RebindCurrentFramebuffer(
2587 GL_DRAW_FRAMEBUFFER_EXT,
2588 bound_draw_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242589 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302590 }
2591}
2592
2593void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2594 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2595 GLuint last_id;
2596 if (info.bound_texture_2d) {
2597 last_id = info.bound_texture_2d->service_id();
2598 } else {
2599 last_id = 0;
2600 }
2601
2602 glBindTexture(GL_TEXTURE_2D, last_id);
2603 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2604}
2605
[email protected]0d6bfdc2011-11-02 01:32:202606bool GLES2DecoderImpl::CheckFramebufferValid(
2607 FramebufferManager::FramebufferInfo* framebuffer,
2608 GLenum target, const char* func_name) {
[email protected]a0b78dc2011-11-11 10:43:102609 if (!framebuffer) {
[email protected]0d6bfdc2011-11-02 01:32:202610 return true;
2611 }
2612
[email protected]968351b2011-12-20 08:26:512613 if (framebuffer_manager()->IsComplete(framebuffer)) {
2614 return true;
2615 }
2616
[email protected]0d6bfdc2011-11-02 01:32:202617 GLenum completeness = framebuffer->IsPossiblyComplete();
2618 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
2619 SetGLError(
2620 GL_INVALID_FRAMEBUFFER_OPERATION,
2621 (std::string(func_name) + " framebuffer incomplete").c_str());
[email protected]3a03a8f2011-03-19 00:51:272622 return false;
2623 }
[email protected]0d6bfdc2011-11-02 01:32:202624
2625 // Are all the attachments cleared?
2626 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2627 texture_manager()->HaveUnclearedMips()) {
2628 if (!framebuffer->IsCleared()) {
2629 // Can we clear them?
2630 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2631 SetGLError(
2632 GL_INVALID_FRAMEBUFFER_OPERATION,
2633 (std::string(func_name) +
2634 " framebuffer incomplete (clear)").c_str());
2635 return false;
2636 }
2637 ClearUnclearedAttachments(target, framebuffer);
2638 }
2639 }
2640
[email protected]968351b2011-12-20 08:26:512641 if (!framebuffer_manager()->IsComplete(framebuffer)) {
2642 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2643 SetGLError(
2644 GL_INVALID_FRAMEBUFFER_OPERATION,
2645 (std::string(func_name) +
2646 " framebuffer incomplete (check)").c_str());
2647 return false;
2648 }
2649 framebuffer_manager()->MarkAsComplete(framebuffer);
2650 }
2651
[email protected]0d6bfdc2011-11-02 01:32:202652 // NOTE: At this point we don't know if the framebuffer is complete but
2653 // we DO know that everything that needs to be cleared has been cleared.
[email protected]3a03a8f2011-03-19 00:51:272654 return true;
2655}
2656
[email protected]0d6bfdc2011-11-02 01:32:202657bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
2658 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
2659 return CheckFramebufferValid(
2660 bound_draw_framebuffer_, GL_FRAMEBUFFER_EXT, func_name);
2661 }
2662 return CheckFramebufferValid(
2663 bound_draw_framebuffer_, GL_DRAW_FRAMEBUFFER_EXT, func_name) &&
2664 CheckFramebufferValid(
2665 bound_read_framebuffer_, GL_READ_FRAMEBUFFER_EXT, func_name);
2666}
2667
[email protected]8e3e0662010-08-23 18:46:302668gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
[email protected]0d6bfdc2011-11-02 01:32:202669 FramebufferManager::FramebufferInfo* framebuffer =
2670 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2671 if (framebuffer != NULL) {
[email protected]9edc6b22010-12-23 02:00:262672 const FramebufferManager::FramebufferInfo::Attachment* attachment =
[email protected]0d6bfdc2011-11-02 01:32:202673 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
[email protected]9edc6b22010-12-23 02:00:262674 if (attachment) {
2675 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502676 }
[email protected]9edc6b22010-12-23 02:00:262677 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022678 } else if (offscreen_target_frame_buffer_.get()) {
2679 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352680 } else {
[email protected]f62a5ab2011-05-23 20:34:152681 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022682 }
[email protected]246a70452010-03-05 21:53:502683}
2684
[email protected]9edc6b22010-12-23 02:00:262685GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202686 FramebufferManager::FramebufferInfo* framebuffer =
2687 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2688 if (framebuffer != NULL) {
2689 return framebuffer->GetColorAttachmentFormat();
[email protected]297ca1c2011-06-20 23:08:462690 } else if (offscreen_target_frame_buffer_.get()) {
2691 return offscreen_target_color_format_;
2692 } else {
2693 return back_buffer_color_format_;
2694 }
2695}
2696
2697GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202698 FramebufferManager::FramebufferInfo* framebuffer =
2699 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
2700 if (framebuffer != NULL) {
2701 return framebuffer->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262702 } else if (offscreen_target_frame_buffer_.get()) {
2703 return offscreen_target_color_format_;
2704 } else {
[email protected]32fe9aa2011-01-21 23:47:132705 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262706 }
2707}
2708
[email protected]9a5afa432011-07-22 18:16:392709void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]34ff8b0c2010-10-01 20:06:022710 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582711 // Update the info about the offscreen saved color texture in the parent.
2712 // The reference to the parent is a weak pointer and will become null if the
2713 // parent is later destroyed.
[email protected]262d7aa2010-12-03 22:07:292714 TextureManager* parent_texture_manager = parent_->texture_manager();
[email protected]262d7aa2010-12-03 22:07:292715 parent_texture_manager->SetLevelInfo(
[email protected]8a61d872012-01-20 12:43:562716 offscreen_saved_color_texture_info_,
[email protected]ef526492010-06-02 23:12:252717 GL_TEXTURE_2D,
2718 0, // level
2719 GL_RGBA,
[email protected]799b4b22011-08-22 17:09:592720 offscreen_size_.width(),
2721 offscreen_size_.height(),
[email protected]ef526492010-06-02 23:12:252722 1, // depth
2723 0, // border
2724 GL_RGBA,
[email protected]0d6bfdc2011-11-02 01:32:202725 GL_UNSIGNED_BYTE,
2726 true);
[email protected]262d7aa2010-12-03 22:07:292727 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562728 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042729 GL_TEXTURE_MAG_FILTER,
2730 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292731 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562732 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042733 GL_TEXTURE_MIN_FILTER,
2734 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292735 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562736 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042737 GL_TEXTURE_WRAP_S,
2738 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292739 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562740 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042741 GL_TEXTURE_WRAP_T,
2742 GL_CLAMP_TO_EDGE);
[email protected]8a61d872012-01-20 12:43:562743 } else {
2744 offscreen_saved_color_texture_info_ = NULL;
[email protected]0c8c9d22010-06-25 17:36:392745 }
[email protected]6217d392010-03-25 22:08:352746}
2747
[email protected]799b4b22011-08-22 17:09:592748void GLES2DecoderImpl::SetResizeCallback(
[email protected]9d37f062011-11-22 01:24:522749 const base::Callback<void(gfx::Size)>& callback) {
2750 resize_callback_ = callback;
[email protected]7ff86b92010-11-25 17:50:002751}
2752
[email protected]6b6e7ee2011-12-13 08:04:522753void GLES2DecoderImpl::SetMsgCallback(const MsgCallback& callback) {
2754 msg_callback_ = callback;
2755}
2756
[email protected]b0af4f52011-09-28 22:04:422757void GLES2DecoderImpl::SetStreamTextureManager(StreamTextureManager* manager) {
2758 stream_texture_manager_ = manager;
2759}
2760
[email protected]1318e922010-09-17 22:03:162761bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2762 uint32* service_texture_id) {
2763 TextureManager::TextureInfo* texture =
2764 texture_manager()->GetTextureInfo(client_texture_id);
2765 if (texture) {
2766 *service_texture_id = texture->service_id();
2767 return true;
2768 }
2769 return false;
2770}
2771
[email protected]96449d2c2009-11-25 00:01:322772void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392773 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052774
[email protected]c826d732012-02-09 04:40:262775 ChildList children = children_;
2776 for (ChildList::iterator it = children.begin(); it != children.end(); ++it)
2777 (*it)->SetParent(NULL, 0);
2778 DCHECK(children_.empty());
[email protected]3c644d82011-06-20 19:58:242779 SetParent(NULL, 0);
2780
[email protected]80eb6b52012-01-19 00:14:412781 // Unbind everything.
[email protected]3757a372012-01-19 05:20:442782 vertex_attrib_manager_.reset();
[email protected]80eb6b52012-01-19 00:14:412783 texture_units_.reset();
2784 bound_array_buffer_ = NULL;
2785 bound_element_array_buffer_ = NULL;
[email protected]882ba1e22012-03-08 19:02:532786 current_query_ = NULL;
[email protected]80eb6b52012-01-19 00:14:412787 current_program_ = NULL;
2788 bound_read_framebuffer_ = NULL;
2789 bound_draw_framebuffer_ = NULL;
2790 bound_renderbuffer_ = NULL;
2791
[email protected]eadc96792010-10-27 19:39:392792 if (have_context) {
[email protected]ca488e12010-12-13 20:06:142793 if (current_program_) {
2794 program_manager()->UnuseProgram(shader_manager(), current_program_);
2795 current_program_ = NULL;
2796 }
2797
[email protected]b1122982010-05-17 23:04:242798 if (attrib_0_buffer_id_) {
2799 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2800 }
[email protected]8fbedc02010-11-18 18:43:402801 if (fixed_attrib_buffer_id_) {
2802 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2803 }
[email protected]b1122982010-05-17 23:04:242804
[email protected]97872062010-11-03 19:07:052805 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542806 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052807 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542808 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052809 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022810 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052811 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152812 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052813 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152814 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052815 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022816 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052817 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542818 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:272819 if (offscreen_resolved_frame_buffer_.get())
2820 offscreen_resolved_frame_buffer_->Destroy();
2821 if (offscreen_resolved_color_texture_.get())
2822 offscreen_resolved_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052823 } else {
2824 if (offscreen_target_frame_buffer_.get())
2825 offscreen_target_frame_buffer_->Invalidate();
2826 if (offscreen_target_color_texture_.get())
2827 offscreen_target_color_texture_->Invalidate();
2828 if (offscreen_target_color_render_buffer_.get())
2829 offscreen_target_color_render_buffer_->Invalidate();
2830 if (offscreen_target_depth_render_buffer_.get())
2831 offscreen_target_depth_render_buffer_->Invalidate();
2832 if (offscreen_target_stencil_render_buffer_.get())
2833 offscreen_target_stencil_render_buffer_->Invalidate();
2834 if (offscreen_saved_frame_buffer_.get())
2835 offscreen_saved_frame_buffer_->Invalidate();
2836 if (offscreen_saved_color_texture_.get())
2837 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:272838 if (offscreen_resolved_frame_buffer_.get())
2839 offscreen_resolved_frame_buffer_->Invalidate();
2840 if (offscreen_resolved_color_texture_.get())
2841 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022842 }
[email protected]97872062010-11-03 19:07:052843
[email protected]882ba1e22012-03-08 19:02:532844 if (query_manager_.get()) {
2845 query_manager_->Destroy(have_context);
2846 query_manager_.reset();
2847 }
2848
[email protected]1871a092011-10-10 21:46:422849 if (group_) {
2850 group_->Destroy(have_context);
2851 group_ = NULL;
2852 }
[email protected]3ae019382011-10-05 19:42:412853
[email protected]fe871662011-06-16 20:43:052854 if (context_.get()) {
2855 context_->ReleaseCurrent(NULL);
[email protected]79311e82011-09-20 00:40:502856 context_ = NULL;
[email protected]fe871662011-06-16 20:43:052857 }
[email protected]0fc35742011-04-13 17:57:542858
[email protected]97872062010-11-03 19:07:052859 offscreen_target_frame_buffer_.reset();
2860 offscreen_target_color_texture_.reset();
2861 offscreen_target_color_render_buffer_.reset();
2862 offscreen_target_depth_render_buffer_.reset();
2863 offscreen_target_stencil_render_buffer_.reset();
2864 offscreen_saved_frame_buffer_.reset();
2865 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:272866 offscreen_resolved_frame_buffer_.reset();
2867 offscreen_resolved_color_texture_.reset();
[email protected]e51bdf32011-11-23 22:21:462868
2869#if defined(OS_MACOSX)
2870 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
2871 it != texture_to_io_surface_map_.end(); ++it) {
2872 CFRelease(it->second);
2873 }
2874 texture_to_io_surface_map_.clear();
2875#endif
[email protected]96449d2c2009-11-25 00:01:322876}
2877
[email protected]3c644d82011-06-20 19:58:242878bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
2879 uint32 new_parent_texture_id) {
[email protected]9a5afa432011-07-22 18:16:392880 if (!offscreen_saved_color_texture_.get())
2881 return false;
2882
[email protected]3c644d82011-06-20 19:58:242883 // Remove the saved frame buffer mapping from the parent decoder. The
2884 // parent pointer is a weak pointer so it will be null if the parent has
2885 // already been destroyed.
2886 if (parent_) {
[email protected]c826d732012-02-09 04:40:262887 ChildList::iterator it = std::find(
2888 parent_->children_.begin(),
2889 parent_->children_.end(),
2890 this);
2891 DCHECK(it != parent_->children_.end());
2892 parent_->children_.erase(it);
[email protected]3c644d82011-06-20 19:58:242893 // First check the texture has been mapped into the parent. This might not
2894 // be the case if initialization failed midway through.
2895 GLuint service_id = offscreen_saved_color_texture_->id();
2896 GLuint client_id = 0;
2897 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
[email protected]80eb6b52012-01-19 00:14:412898 parent_->texture_manager()->RemoveTextureInfo(client_id);
[email protected]3c644d82011-06-20 19:58:242899 }
2900 }
2901
2902 GLES2DecoderImpl* new_parent_impl = static_cast<GLES2DecoderImpl*>(
2903 new_parent);
2904 if (new_parent_impl) {
[email protected]c826d732012-02-09 04:40:262905#ifndef NDEBUG
2906 ChildList::iterator it = std::find(
2907 new_parent_impl->children_.begin(),
2908 new_parent_impl->children_.end(),
2909 this);
2910 DCHECK(it == new_parent_impl->children_.end());
2911#endif
2912 new_parent_impl->children_.push_back(this);
[email protected]3c644d82011-06-20 19:58:242913 // Map the ID of the saved offscreen texture into the parent so that
2914 // it can reference it.
2915 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]98687862011-07-11 23:31:302916
2917 // Replace texture info when ID is already in use by parent.
2918 if (new_parent_impl->texture_manager()->GetTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412919 new_parent_texture_id))
[email protected]98687862011-07-11 23:31:302920 new_parent_impl->texture_manager()->RemoveTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412921 new_parent_texture_id);
[email protected]98687862011-07-11 23:31:302922
[email protected]8a61d872012-01-20 12:43:562923 offscreen_saved_color_texture_info_ =
[email protected]5f4f2a732011-07-30 00:47:552924 new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id);
[email protected]8a61d872012-01-20 12:43:562925 offscreen_saved_color_texture_info_->SetNotOwned();
2926 new_parent_impl->texture_manager()->
2927 SetInfoTarget(offscreen_saved_color_texture_info_, GL_TEXTURE_2D);
[email protected]3c644d82011-06-20 19:58:242928
2929 parent_ = new_parent_impl->AsWeakPtr();
[email protected]9a5afa432011-07-22 18:16:392930
2931 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:242932 } else {
2933 parent_.reset();
[email protected]8a61d872012-01-20 12:43:562934 offscreen_saved_color_texture_info_ = NULL;
[email protected]3c644d82011-06-20 19:58:242935 }
2936
2937 return true;
2938}
2939
[email protected]1078f912011-12-23 13:12:142940void GLES2DecoderImpl::UpdateBackbufferMemoryAccounting() {
2941 size_t total = 0;
2942 if (offscreen_target_frame_buffer_.get()) {
2943 if (offscreen_target_color_texture_.get()) {
2944 total += offscreen_target_color_texture_->estimated_size();
2945 }
2946 if (offscreen_target_color_render_buffer_.get()) {
2947 total += offscreen_target_color_render_buffer_->estimated_size();
2948 }
2949 if (offscreen_target_depth_render_buffer_.get()) {
2950 total += offscreen_target_depth_render_buffer_->estimated_size();
2951 }
2952 if (offscreen_target_stencil_render_buffer_.get()) {
2953 total += offscreen_target_stencil_render_buffer_->estimated_size();
2954 }
2955 if (offscreen_saved_color_texture_.get()) {
2956 total += offscreen_saved_color_texture_->estimated_size();
2957 }
2958 if (offscreen_resolved_color_texture_.get()) {
2959 total += offscreen_resolved_color_texture_->estimated_size();
2960 }
2961 } else {
2962 gfx::Size size = surface_->GetSize();
2963 total += size.width() * size.height() *
2964 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_);
2965 }
2966 TRACE_COUNTER_ID1(
2967 "GLES2DecoderImpl", "BackbufferMemory", this, total);
2968}
2969
[email protected]799b4b22011-08-22 17:09:592970bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2971 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
2972 if (!is_offscreen) {
2973 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
2974 << " with an onscreen framebuffer.";
2975 return false;
2976 }
2977
2978 if (offscreen_size_ == size)
2979 return true;
2980
2981 offscreen_size_ = size;
2982 int w = offscreen_size_.width();
2983 int h = offscreen_size_.height();
2984 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
2985 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2986 << "to allocate storage due to excessive dimensions.";
2987 return false;
2988 }
2989
2990 // Reallocate the offscreen target buffers.
2991 DCHECK(offscreen_target_color_format_);
2992 if (IsOffscreenBufferMultisampled()) {
2993 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2994 offscreen_size_, offscreen_target_color_format_,
2995 offscreen_target_samples_)) {
2996 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2997 << "to allocate storage for offscreen target color buffer.";
2998 return false;
2999 }
3000 } else {
3001 if (!offscreen_target_color_texture_->AllocateStorage(
3002 offscreen_size_, offscreen_target_color_format_)) {
3003 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3004 << "to allocate storage for offscreen target color texture.";
3005 return false;
3006 }
3007 }
3008 if (offscreen_target_depth_format_ &&
3009 !offscreen_target_depth_render_buffer_->AllocateStorage(
3010 offscreen_size_, offscreen_target_depth_format_,
3011 offscreen_target_samples_)) {
3012 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3013 << "to allocate storage for offscreen target depth buffer.";
3014 return false;
3015 }
3016 if (offscreen_target_stencil_format_ &&
3017 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3018 offscreen_size_, offscreen_target_stencil_format_,
3019 offscreen_target_samples_)) {
3020 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3021 << "to allocate storage for offscreen target stencil buffer.";
3022 return false;
3023 }
[email protected]1078f912011-12-23 13:12:143024 UpdateBackbufferMemoryAccounting();
[email protected]799b4b22011-08-22 17:09:593025
3026 // Attach the offscreen target buffers to the target frame buffer.
3027 if (IsOffscreenBufferMultisampled()) {
3028 offscreen_target_frame_buffer_->AttachRenderBuffer(
3029 GL_COLOR_ATTACHMENT0,
3030 offscreen_target_color_render_buffer_.get());
3031 } else {
3032 offscreen_target_frame_buffer_->AttachRenderTexture(
3033 offscreen_target_color_texture_.get());
3034 }
3035 if (offscreen_target_depth_format_) {
3036 offscreen_target_frame_buffer_->AttachRenderBuffer(
3037 GL_DEPTH_ATTACHMENT,
3038 offscreen_target_depth_render_buffer_.get());
3039 }
3040 const bool packed_depth_stencil =
3041 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3042 if (packed_depth_stencil) {
3043 offscreen_target_frame_buffer_->AttachRenderBuffer(
3044 GL_STENCIL_ATTACHMENT,
3045 offscreen_target_depth_render_buffer_.get());
3046 } else if (offscreen_target_stencil_format_) {
3047 offscreen_target_frame_buffer_->AttachRenderBuffer(
3048 GL_STENCIL_ATTACHMENT,
3049 offscreen_target_stencil_render_buffer_.get());
3050 }
3051
3052 if (offscreen_target_frame_buffer_->CheckStatus() !=
3053 GL_FRAMEBUFFER_COMPLETE) {
3054 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3055 << "because offscreen FBO was incomplete.";
3056 return false;
3057 }
3058
3059 // Clear the target frame buffer.
3060 {
3061 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3062 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3063 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3064 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3065 glClearStencil(0);
3066 glStencilMaskSeparate(GL_FRONT, -1);
3067 glStencilMaskSeparate(GL_BACK, -1);
3068 glClearDepth(0);
3069 glDepthMask(GL_TRUE);
3070 glDisable(GL_SCISSOR_TEST);
3071 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3072 RestoreClearState();
3073 }
[email protected]d85ef76d2011-09-08 22:21:433074
3075 // Destroy the offscreen resolved framebuffers.
3076 if (offscreen_resolved_frame_buffer_.get())
3077 offscreen_resolved_frame_buffer_->Destroy();
3078 if (offscreen_resolved_color_texture_.get())
3079 offscreen_resolved_color_texture_->Destroy();
3080 offscreen_resolved_color_texture_.reset();
3081 offscreen_resolved_frame_buffer_.reset();
3082
[email protected]799b4b22011-08-22 17:09:593083 return true;
[email protected]6217d392010-03-25 22:08:353084}
3085
[email protected]799b4b22011-08-22 17:09:593086error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3087 uint32 immediate_data_size, const gles2::ResizeCHROMIUM& c) {
3088 GLuint width = static_cast<GLuint>(c.width);
3089 GLuint height = static_cast<GLuint>(c.height);
3090 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
[email protected]a0d989162011-11-22 13:15:073091#if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3092 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
[email protected]7ff86b92010-11-25 17:50:003093 // Make sure that we are done drawing to the back buffer before resizing.
3094 glFinish();
3095#endif
[email protected]799b4b22011-08-22 17:09:593096 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3097 if (is_offscreen) {
3098 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height)))
3099 return error::kLostContext;
[email protected]7ff86b92010-11-25 17:50:003100 }
[email protected]799b4b22011-08-22 17:09:593101
[email protected]9d37f062011-11-22 01:24:523102 if (!resize_callback_.is_null()) {
3103 resize_callback_.Run(gfx::Size(width, height));
[email protected]c777de52011-09-09 23:08:563104 DCHECK(context_->IsCurrent(surface_.get()));
3105 if (!context_->IsCurrent(surface_.get()))
[email protected]658f7562011-09-09 05:24:053106 return error::kLostContext;
[email protected]658f7562011-09-09 05:24:053107 }
[email protected]799b4b22011-08-22 17:09:593108
[email protected]1078f912011-12-23 13:12:143109 UpdateBackbufferMemoryAccounting();
3110
[email protected]799b4b22011-08-22 17:09:593111 return error::kNoError;
[email protected]43ecf372010-11-16 19:19:393112}
3113
[email protected]96449d2c2009-11-25 00:01:323114const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3115 if (command_id > kStartPoint && command_id < kNumCommands) {
3116 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3117 }
3118 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3119}
3120
3121// Decode command with its arguments, and call the corresponding GL function.
3122// Note: args is a pointer to the command buffer. As such, it could be changed
3123// by a (malicious) client at any time, so if validation has to happen, it
3124// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:143125error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:323126 unsigned int command,
3127 unsigned int arg_count,
3128 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:143129 error::Error result = error::kNoError;
[email protected]e844ae22012-01-14 03:36:263130 if (log_commands()) {
[email protected]39ba4f02012-03-26 01:16:003131 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3132 // LOG(INFO), tried VLOG(1), no luck.
3133 LOG(ERROR) << "[" << this << "]" << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193134 }
[email protected]96449d2c2009-11-25 00:01:323135 unsigned int command_index = command - kStartPoint - 1;
3136 if (command_index < arraysize(g_command_info)) {
3137 const CommandInfo& info = g_command_info[command_index];
3138 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3139 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3140 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:193141 uint32 immediate_data_size =
3142 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:323143 switch (command) {
3144 #define GLES2_CMD_OP(name) \
3145 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:193146 result = Handle ## name( \
3147 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:323148 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:193149 break; \
[email protected]96449d2c2009-11-25 00:01:323150
3151 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:323152 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:383153 }
3154 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:303155 GLenum error;
3156 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]39ba4f02012-03-26 01:16:003157 LOG(ERROR) << "[" << this << "] "
3158 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3159 << GetCommandName(command);
[email protected]e844ae22012-01-14 03:36:263160 SetGLError(error, "GL error from driver");
[email protected]b9849abf2009-11-25 19:13:193161 }
[email protected]96449d2c2009-11-25 00:01:323162 }
3163 } else {
[email protected]f7a64ee2010-02-01 22:24:143164 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:323165 }
[email protected]b9849abf2009-11-25 19:13:193166 } else {
3167 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:323168 }
[email protected]a3a93e7b2010-08-28 00:48:563169 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3170 result = current_decoder_error_;
3171 current_decoder_error_ = error::kNoError;
3172 }
[email protected]b9849abf2009-11-25 19:13:193173 return result;
[email protected]96449d2c2009-11-25 00:01:323174}
3175
[email protected]ae51d192010-04-27 00:48:033176void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
3177 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:503178}
3179
[email protected]ae51d192010-04-27 00:48:033180bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3181 if (GetProgramInfo(client_id)) {
3182 return false;
3183 }
[email protected]96449d2c2009-11-25 00:01:323184 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:033185 if (service_id != 0) {
3186 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:323187 }
[email protected]ae51d192010-04-27 00:48:033188 return true;
[email protected]96449d2c2009-11-25 00:01:323189}
3190
[email protected]ae51d192010-04-27 00:48:033191bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3192 if (GetShaderInfo(client_id)) {
3193 return false;
[email protected]96449d2c2009-11-25 00:01:323194 }
[email protected]ae51d192010-04-27 00:48:033195 GLuint service_id = glCreateShader(type);
3196 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:383197 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:033198 }
3199 return true;
[email protected]96449d2c2009-11-25 00:01:323200}
3201
[email protected]882ba1e22012-03-08 19:02:533202void GLES2DecoderImpl::DoFinish() {
3203 glFinish();
[email protected]22e3f552012-03-13 01:54:193204 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533205}
3206
3207void GLES2DecoderImpl::DoFlush() {
3208 glFlush();
[email protected]22e3f552012-03-13 01:54:193209 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533210}
3211
[email protected]3916c97e2010-02-25 03:20:503212void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:453213 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]660858b2011-07-13 23:16:143214 if (texture_index >= group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:293215 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:503216 return;
3217 }
[email protected]36cef8ce2010-03-16 07:34:453218 active_texture_unit_ = texture_index;
3219 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:503220}
3221
[email protected]051b1372010-04-12 02:42:083222void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:503223 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083224 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033225 if (client_id != 0) {
3226 info = GetBufferInfo(client_id);
3227 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353228 if (!group_->bind_generates_resource()) {
3229 SetGLError(GL_INVALID_VALUE,
3230 "glBindBuffer: id not generated by glGenBuffers");
3231 return;
3232 }
3233
[email protected]ae51d192010-04-27 00:48:033234 // It's a new id so make a buffer info for it.
3235 glGenBuffersARB(1, &service_id);
3236 CreateBufferInfo(client_id, service_id);
3237 info = GetBufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573238 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103239 group_->GetIdAllocator(id_namespaces::kBuffers);
3240 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033241 }
[email protected]051b1372010-04-12 02:42:083242 }
[email protected]ae51d192010-04-27 00:48:033243 if (info) {
[email protected]4e8a5b122010-05-08 22:00:103244 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:293245 SetGLError(GL_INVALID_OPERATION,
3246 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:473247 return;
3248 }
[email protected]ae51d192010-04-27 00:48:033249 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:473250 }
[email protected]96449d2c2009-11-25 00:01:323251 switch (target) {
3252 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503253 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323254 break;
3255 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503256 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323257 break;
3258 default:
[email protected]a93bb842010-02-16 23:03:473259 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:323260 break;
3261 }
[email protected]051b1372010-04-12 02:42:083262 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:323263}
3264
[email protected]297ca1c2011-06-20 23:08:463265bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
3266 return (GLES2Util::GetChannelsForFormat(
3267 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3268}
3269
3270bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203271 FramebufferManager::FramebufferInfo* framebuffer =
3272 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3273 if (framebuffer) {
3274 return framebuffer->HasDepthAttachment();
[email protected]297ca1c2011-06-20 23:08:463275 }
3276 if (offscreen_target_frame_buffer_.get()) {
3277 return offscreen_target_depth_format_ != 0;
3278 }
3279 return back_buffer_has_depth_;
3280}
3281
3282bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203283 FramebufferManager::FramebufferInfo* framebuffer =
3284 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3285 if (framebuffer) {
3286 return framebuffer->HasStencilAttachment();
[email protected]297ca1c2011-06-20 23:08:463287 }
3288 if (offscreen_target_frame_buffer_.get()) {
3289 return offscreen_target_stencil_format_ != 0 ||
3290 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3291 }
3292 return back_buffer_has_stencil_;
3293}
3294
3295void GLES2DecoderImpl::ApplyDirtyState() {
3296 if (state_dirty_) {
3297 glColorMask(
3298 mask_red_, mask_green_, mask_blue_,
3299 mask_alpha_ && BoundFramebufferHasColorAttachmentWithAlpha());
3300 bool have_depth = BoundFramebufferHasDepthAttachment();
3301 glDepthMask(mask_depth_ && have_depth);
3302 EnableDisable(GL_DEPTH_TEST, enable_depth_test_ && have_depth);
3303 bool have_stencil = BoundFramebufferHasStencilAttachment();
3304 glStencilMaskSeparate(GL_FRONT, have_stencil ? mask_stencil_front_ : 0);
3305 glStencilMaskSeparate(GL_BACK, have_stencil ? mask_stencil_back_ : 0);
3306 EnableDisable(GL_STENCIL_TEST, enable_stencil_test_ && have_stencil);
3307 state_dirty_ = false;
3308 }
3309}
3310
[email protected]b177ae22011-11-01 03:29:113311GLuint GLES2DecoderImpl::GetBackbufferServiceId() {
3312 return (offscreen_target_frame_buffer_.get()) ?
3313 offscreen_target_frame_buffer_->id() :
3314 surface_->GetBackingFrameBufferObject();
3315}
3316
[email protected]051b1372010-04-12 02:42:083317void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3318 FramebufferManager::FramebufferInfo* info = NULL;
3319 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033320 if (client_id != 0) {
3321 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083322 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353323 if (!group_->bind_generates_resource()) {
3324 SetGLError(GL_INVALID_VALUE,
3325 "glBindFramebuffer: id not generated by glGenFramebuffers");
3326 return;
3327 }
3328
[email protected]ae51d192010-04-27 00:48:033329 // It's a new id so make a framebuffer info for it.
3330 glGenFramebuffersEXT(1, &service_id);
3331 CreateFramebufferInfo(client_id, service_id);
3332 info = GetFramebufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573333 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103334 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3335 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033336 } else {
3337 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083338 }
[email protected]06c8b082011-01-05 18:00:363339 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083340 }
[email protected]8e3e0662010-08-23 18:46:303341
3342 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
3343 bound_draw_framebuffer_ = info;
3344 }
3345 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
3346 bound_read_framebuffer_ = info;
3347 }
[email protected]6217d392010-03-25 22:08:353348
[email protected]297ca1c2011-06-20 23:08:463349 state_dirty_ = true;
3350
[email protected]b177ae22011-11-01 03:29:113351 // If we are rendering to the backbuffer get the FBO id for any simulated
3352 // backbuffer.
3353 if (info == NULL) {
3354 service_id = GetBackbufferServiceId();
[email protected]297ca1c2011-06-20 23:08:463355 }
[email protected]6217d392010-03-25 22:08:353356
[email protected]051b1372010-04-12 02:42:083357 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563358}
3359
[email protected]051b1372010-04-12 02:42:083360void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
3361 RenderbufferManager::RenderbufferInfo* info = NULL;
3362 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033363 if (client_id != 0) {
3364 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083365 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353366 if (!group_->bind_generates_resource()) {
3367 SetGLError(
3368 GL_INVALID_VALUE,
3369 "glBindRenderbuffer: id not generated by glGenRenderbuffers");
3370 return;
3371 }
3372
[email protected]ae51d192010-04-27 00:48:033373 // It's a new id so make a renderbuffer info for it.
3374 glGenRenderbuffersEXT(1, &service_id);
3375 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:103376 info = GetRenderbufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573377 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103378 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3379 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033380 } else {
3381 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083382 }
[email protected]06c8b082011-01-05 18:00:363383 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083384 }
3385 bound_renderbuffer_ = info;
3386 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563387}
3388
[email protected]051b1372010-04-12 02:42:083389void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033390 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083391 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033392 if (client_id != 0) {
3393 info = GetTextureInfo(client_id);
3394 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353395 if (!group_->bind_generates_resource()) {
3396 SetGLError(GL_INVALID_VALUE,
3397 "glBindTexture: id not generated by glGenTextures");
3398 return;
3399 }
3400
[email protected]ae51d192010-04-27 00:48:033401 // It's a new id so make a texture info for it.
3402 glGenTextures(1, &service_id);
[email protected]80eb6b52012-01-19 00:14:413403 DCHECK_NE(0u, service_id);
[email protected]ae51d192010-04-27 00:48:033404 CreateTextureInfo(client_id, service_id);
3405 info = GetTextureInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573406 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103407 group_->GetIdAllocator(id_namespaces::kTextures);
3408 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033409 }
3410 } else {
3411 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:083412 }
[email protected]ae51d192010-04-27 00:48:033413
[email protected]1958e0e2010-04-22 05:17:153414 // Check the texture exists
3415 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:033416 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:293417 SetGLError(GL_INVALID_OPERATION,
3418 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:153419 return;
3420 }
[email protected]b0af4f52011-09-28 22:04:423421 if (info->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
3422 SetGLError(GL_INVALID_OPERATION,
3423 "glBindTexture: illegal target for stream texture.");
3424 return;
3425 }
[email protected]1958e0e2010-04-22 05:17:153426 if (info->target() == 0) {
[email protected]80eb6b52012-01-19 00:14:413427 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:473428 }
[email protected]ae51d192010-04-27 00:48:033429 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:503430 TextureUnit& unit = texture_units_[active_texture_unit_];
3431 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:473432 switch (target) {
3433 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:503434 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:473435 break;
3436 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:503437 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:473438 break;
[email protected]61eeb33f2011-07-26 15:30:313439 case GL_TEXTURE_EXTERNAL_OES:
3440 unit.bound_texture_external_oes = info;
[email protected]b0af4f52011-09-28 22:04:423441 if (info->IsStreamTexture()) {
3442 DCHECK(stream_texture_manager_);
3443 StreamTexture* stream_tex =
3444 stream_texture_manager_->LookupStreamTexture(info->service_id());
3445 if (stream_tex)
3446 stream_tex->Update();
3447 }
[email protected]61eeb33f2011-07-26 15:30:313448 break;
[email protected]e51bdf32011-11-23 22:21:463449 case GL_TEXTURE_RECTANGLE_ARB:
3450 unit.bound_texture_rectangle_arb = info;
3451 break;
[email protected]a93bb842010-02-16 23:03:473452 default:
3453 NOTREACHED(); // Validation should prevent us getting here.
3454 break;
3455 }
3456}
3457
[email protected]07f54fcc2009-12-22 02:46:303458void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443459 if (vertex_attrib_manager_->Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:123460 if (index != 0 ||
3461 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:243462 glDisableVertexAttribArray(index);
3463 }
[email protected]07f54fcc2009-12-22 02:46:303464 } else {
[email protected]8eee29c2010-04-29 03:38:293465 SetGLError(GL_INVALID_VALUE,
3466 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:303467 }
3468}
3469
3470void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443471 if (vertex_attrib_manager_->Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:303472 glEnableVertexAttribArray(index);
3473 } else {
[email protected]8eee29c2010-04-29 03:38:293474 SetGLError(GL_INVALID_VALUE,
3475 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:303476 }
3477}
3478
[email protected]a93bb842010-02-16 23:03:473479void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:503480 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]97dc7cbe2011-12-06 17:26:173481 if (!info ||
[email protected]80eb6b52012-01-19 00:14:413482 !texture_manager()->MarkMipmapsGenerated(info)) {
[email protected]8eee29c2010-04-29 03:38:293483 SetGLError(GL_INVALID_OPERATION,
3484 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:473485 return;
3486 }
[email protected]59f3ca02011-03-26 22:24:193487 // Workaround for Mac driver bug. In the large scheme of things setting
3488 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
[email protected]a8bad262011-10-21 18:28:563489 // hit so there's probably no need to make this conditional. The bug appears
3490 // to be that if the filtering mode is set to something that doesn't require
3491 // mipmaps for rendering, or is never set to something other than the default,
3492 // then glGenerateMipmap misbehaves.
3493 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
[email protected]a93bb842010-02-16 23:03:473494 glGenerateMipmapEXT(target);
[email protected]59f3ca02011-03-26 22:24:193495 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
[email protected]a93bb842010-02-16 23:03:473496}
3497
[email protected]b273e432010-04-12 17:23:583498bool GLES2DecoderImpl::GetHelper(
3499 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:583500 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:153501 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
3502 switch (pname) {
[email protected]b273e432010-04-12 17:23:583503 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
3504 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103505 if (params) {
[email protected]5094b0f2010-11-09 19:45:243506 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:103507 }
[email protected]b273e432010-04-12 17:23:583508 return true;
3509 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3510 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103511 if (params) {
[email protected]5094b0f2010-11-09 19:45:243512 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:103513 }
[email protected]b273e432010-04-12 17:23:583514 return true;
3515 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
3516 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103517 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483518 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:103519 }
[email protected]b273e432010-04-12 17:23:583520 return true;
3521 case GL_MAX_VARYING_VECTORS:
3522 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103523 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483524 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:103525 }
[email protected]b273e432010-04-12 17:23:583526 return true;
3527 case GL_MAX_VERTEX_UNIFORM_VECTORS:
3528 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103529 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483530 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:103531 }
[email protected]b273e432010-04-12 17:23:583532 return true;
[email protected]5cb735d2011-10-13 01:37:233533 }
3534 }
3535 switch (pname) {
[email protected]5094b0f2010-11-09 19:45:243536 case GL_MAX_VIEWPORT_DIMS:
3537 if (offscreen_target_frame_buffer_.get()) {
3538 *num_written = 2;
3539 if (params) {
3540 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3541 params[1] = renderbuffer_manager()->max_renderbuffer_size();
3542 }
3543 return true;
3544 }
[email protected]5cb735d2011-10-13 01:37:233545 return false;
[email protected]84afefa2011-10-19 21:45:533546 case GL_MAX_SAMPLES:
3547 *num_written = 1;
3548 if (params) {
3549 params[0] = renderbuffer_manager()->max_samples();
3550 }
3551 return true;
3552 case GL_MAX_RENDERBUFFER_SIZE:
3553 *num_written = 1;
3554 if (params) {
3555 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3556 }
3557 return true;
[email protected]5cb735d2011-10-13 01:37:233558 case GL_MAX_TEXTURE_SIZE:
3559 *num_written = 1;
3560 if (params) {
3561 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
3562 }
3563 return true;
3564 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
3565 *num_written = 1;
3566 if (params) {
3567 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
3568 }
3569 return true;
[email protected]297ca1c2011-06-20 23:08:463570 case GL_COLOR_WRITEMASK:
3571 *num_written = 4;
3572 if (params) {
3573 params[0] = mask_red_;
3574 params[1] = mask_green_;
3575 params[2] = mask_blue_;
3576 params[3] = mask_alpha_;
3577 }
3578 return true;
3579 case GL_DEPTH_WRITEMASK:
3580 *num_written = 1;
3581 if (params) {
3582 params[0] = mask_depth_;
3583 }
3584 return true;
3585 case GL_STENCIL_BACK_WRITEMASK:
3586 *num_written = 1;
3587 if (params) {
3588 params[0] = mask_stencil_back_;
3589 }
3590 return true;
3591 case GL_STENCIL_WRITEMASK:
3592 *num_written = 1;
3593 if (params) {
3594 params[0] = mask_stencil_front_;
3595 }
3596 return true;
3597 case GL_DEPTH_TEST:
3598 *num_written = 1;
3599 if (params) {
3600 params[0] = enable_depth_test_;
3601 }
3602 return true;
3603 case GL_STENCIL_TEST:
3604 *num_written = 1;
3605 if (params) {
3606 params[0] = enable_stencil_test_;
3607 }
3608 return true;
3609 case GL_ALPHA_BITS:
3610 *num_written = 1;
3611 if (params) {
3612 GLint v = 0;
3613 glGetIntegerv(GL_ALPHA_BITS, &v);
3614 params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0;
3615 }
3616 return true;
3617 case GL_DEPTH_BITS:
3618 *num_written = 1;
3619 if (params) {
3620 GLint v = 0;
3621 glGetIntegerv(GL_DEPTH_BITS, &v);
3622 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
3623 }
3624 return true;
3625 case GL_STENCIL_BITS:
3626 *num_written = 1;
3627 if (params) {
3628 GLint v = 0;
3629 glGetIntegerv(GL_STENCIL_BITS, &v);
3630 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
3631 }
3632 return true;
[email protected]656dcaad2010-05-07 17:18:373633 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113634 *num_written = validators_->compressed_texture_format.GetValues().size();
3635 if (params) {
3636 for (GLint ii = 0; ii < *num_written; ++ii) {
3637 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
3638 }
3639 }
[email protected]656dcaad2010-05-07 17:18:373640 return true;
[email protected]b273e432010-04-12 17:23:583641 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
3642 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103643 if (params) {
[email protected]302ce6d2011-07-07 23:28:113644 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103645 }
[email protected]b273e432010-04-12 17:23:583646 return true;
3647 case GL_NUM_SHADER_BINARY_FORMATS:
3648 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103649 if (params) {
[email protected]302ce6d2011-07-07 23:28:113650 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103651 }
[email protected]b273e432010-04-12 17:23:583652 return true;
3653 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113654 *num_written = validators_->shader_binary_format.GetValues().size();
3655 if (params) {
3656 for (GLint ii = 0; ii < *num_written; ++ii) {
3657 params[ii] = validators_->shader_binary_format.GetValues()[ii];
3658 }
3659 }
3660 return true;
[email protected]b273e432010-04-12 17:23:583661 case GL_SHADER_COMPILER:
3662 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103663 if (params) {
3664 *params = GL_TRUE;
3665 }
[email protected]b273e432010-04-12 17:23:583666 return true;
[email protected]6b8cf1a2010-05-06 16:13:583667 case GL_ARRAY_BUFFER_BINDING:
3668 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103669 if (params) {
3670 if (bound_array_buffer_) {
3671 GLuint client_id = 0;
3672 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
3673 &client_id);
3674 *params = client_id;
3675 } else {
3676 *params = 0;
3677 }
[email protected]6b8cf1a2010-05-06 16:13:583678 }
3679 return true;
3680 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3681 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103682 if (params) {
3683 if (bound_element_array_buffer_) {
3684 GLuint client_id = 0;
3685 buffer_manager()->GetClientId(
3686 bound_element_array_buffer_->service_id(),
3687 &client_id);
3688 *params = client_id;
3689 } else {
3690 *params = 0;
3691 }
[email protected]6b8cf1a2010-05-06 16:13:583692 }
3693 return true;
3694 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:303695 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:583696 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103697 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203698 FramebufferManager::FramebufferInfo* framebuffer =
3699 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3700 if (framebuffer) {
[email protected]4e8a5b122010-05-08 22:00:103701 GLuint client_id = 0;
3702 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203703 framebuffer->service_id(), &client_id);
[email protected]8e3e0662010-08-23 18:46:303704 *params = client_id;
3705 } else {
3706 *params = 0;
3707 }
3708 }
3709 return true;
3710 case GL_READ_FRAMEBUFFER_BINDING:
3711 *num_written = 1;
3712 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203713 FramebufferManager::FramebufferInfo* framebuffer =
3714 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
3715 if (framebuffer) {
[email protected]8e3e0662010-08-23 18:46:303716 GLuint client_id = 0;
3717 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203718 framebuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103719 *params = client_id;
3720 } else {
3721 *params = 0;
3722 }
[email protected]6b8cf1a2010-05-06 16:13:583723 }
3724 return true;
3725 case GL_RENDERBUFFER_BINDING:
3726 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103727 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203728 RenderbufferManager::RenderbufferInfo* renderbuffer =
3729 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
3730 if (renderbuffer) {
[email protected]4e8a5b122010-05-08 22:00:103731 GLuint client_id = 0;
3732 renderbuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203733 renderbuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103734 *params = client_id;
3735 } else {
3736 *params = 0;
3737 }
[email protected]6b8cf1a2010-05-06 16:13:583738 }
3739 return true;
3740 case GL_CURRENT_PROGRAM:
3741 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103742 if (params) {
3743 if (current_program_) {
3744 GLuint client_id = 0;
3745 program_manager()->GetClientId(
3746 current_program_->service_id(), &client_id);
3747 *params = client_id;
3748 } else {
3749 *params = 0;
3750 }
[email protected]6b8cf1a2010-05-06 16:13:583751 }
3752 return true;
[email protected]4e8a5b122010-05-08 22:00:103753 case GL_TEXTURE_BINDING_2D:
3754 *num_written = 1;
3755 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583756 TextureUnit& unit = texture_units_[active_texture_unit_];
3757 if (unit.bound_texture_2d) {
3758 GLuint client_id = 0;
3759 texture_manager()->GetClientId(
3760 unit.bound_texture_2d->service_id(), &client_id);
3761 *params = client_id;
3762 } else {
3763 *params = 0;
3764 }
[email protected]6b8cf1a2010-05-06 16:13:583765 }
[email protected]4e8a5b122010-05-08 22:00:103766 return true;
3767 case GL_TEXTURE_BINDING_CUBE_MAP:
3768 *num_written = 1;
3769 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583770 TextureUnit& unit = texture_units_[active_texture_unit_];
3771 if (unit.bound_texture_cube_map) {
3772 GLuint client_id = 0;
3773 texture_manager()->GetClientId(
3774 unit.bound_texture_cube_map->service_id(), &client_id);
3775 *params = client_id;
3776 } else {
3777 *params = 0;
3778 }
[email protected]6b8cf1a2010-05-06 16:13:583779 }
[email protected]4e8a5b122010-05-08 22:00:103780 return true;
[email protected]61eeb33f2011-07-26 15:30:313781 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3782 *num_written = 1;
3783 if (params) {
3784 TextureUnit& unit = texture_units_[active_texture_unit_];
3785 if (unit.bound_texture_external_oes) {
3786 GLuint client_id = 0;
3787 texture_manager()->GetClientId(
3788 unit.bound_texture_external_oes->service_id(), &client_id);
3789 *params = client_id;
3790 } else {
3791 *params = 0;
3792 }
3793 }
3794 return true;
[email protected]e51bdf32011-11-23 22:21:463795 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
3796 *num_written = 1;
3797 if (params) {
3798 TextureUnit& unit = texture_units_[active_texture_unit_];
3799 if (unit.bound_texture_rectangle_arb) {
3800 GLuint client_id = 0;
3801 texture_manager()->GetClientId(
3802 unit.bound_texture_rectangle_arb->service_id(), &client_id);
3803 *params = client_id;
3804 } else {
3805 *params = 0;
3806 }
3807 }
3808 return true;
[email protected]b273e432010-04-12 17:23:583809 default:
[email protected]4e8a5b122010-05-08 22:00:103810 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533811 return false;
[email protected]b273e432010-04-12 17:23:583812 }
3813}
3814
[email protected]4e8a5b122010-05-08 22:00:103815bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3816 GLenum pname, GLsizei* num_values) {
3817 return GetHelper(pname, NULL, num_values);
3818}
3819
[email protected]b273e432010-04-12 17:23:583820void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3821 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103822 GLsizei num_written = 0;
3823 if (GetHelper(pname, NULL, &num_written)) {
3824 scoped_array<GLint> values(new GLint[num_written]);
3825 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583826 for (GLsizei ii = 0; ii < num_written; ++ii) {
3827 params[ii] = static_cast<GLboolean>(values[ii]);
3828 }
3829 } else {
3830 glGetBooleanv(pname, params);
3831 }
3832}
3833
3834void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3835 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103836 GLsizei num_written = 0;
3837 if (GetHelper(pname, NULL, &num_written)) {
3838 scoped_array<GLint> values(new GLint[num_written]);
3839 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583840 for (GLsizei ii = 0; ii < num_written; ++ii) {
3841 params[ii] = static_cast<GLfloat>(values[ii]);
3842 }
3843 } else {
3844 glGetFloatv(pname, params);
3845 }
3846}
3847
3848void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3849 DCHECK(params);
3850 GLsizei num_written;
3851 if (!GetHelper(pname, params, &num_written)) {
3852 glGetIntegerv(pname, params);
3853 }
3854}
3855
[email protected]a0c3e972010-04-21 00:49:133856void GLES2DecoderImpl::DoGetProgramiv(
3857 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583858 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3859 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133860 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133861 return;
3862 }
3863 info->GetProgramiv(pname, params);
3864}
3865
[email protected]258a3313f2011-10-18 20:13:573866void GLES2DecoderImpl::DoBindAttribLocation(
3867 GLuint program, GLuint index, const char* name) {
3868 if (!StringIsValidForGLES(name)) {
3869 SetGLError(GL_INVALID_VALUE, "glBindAttribLocation: Invalid character");
3870 return;
3871 }
[email protected]6b8cf1a2010-05-06 16:13:583872 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3873 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033874 if (!info) {
[email protected]258a3313f2011-10-18 20:13:573875 return;
[email protected]558847a2010-03-24 07:02:543876 }
[email protected]c3e4c4e2012-03-02 19:23:243877 info->SetAttribLocationBinding(name, static_cast<GLint>(index));
[email protected]258a3313f2011-10-18 20:13:573878 glBindAttribLocation(info->service_id(), index, name);
3879}
3880
3881error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3882 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
3883 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543884 GLuint index = static_cast<GLuint>(c.index);
3885 uint32 name_size = c.data_size;
3886 const char* name = GetSharedMemoryAs<const char*>(
3887 c.name_shm_id, c.name_shm_offset, name_size);
3888 if (name == NULL) {
3889 return error::kOutOfBounds;
3890 }
3891 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573892 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543893 return error::kNoError;
3894}
3895
3896error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3897 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583898 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543899 GLuint index = static_cast<GLuint>(c.index);
3900 uint32 name_size = c.data_size;
3901 const char* name = GetImmediateDataAs<const char*>(
3902 c, name_size, immediate_data_size);
3903 if (name == NULL) {
3904 return error::kOutOfBounds;
3905 }
3906 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573907 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543908 return error::kNoError;
3909}
3910
3911error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3912 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583913 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543914 GLuint index = static_cast<GLuint>(c.index);
3915 Bucket* bucket = GetBucket(c.name_bucket_id);
3916 if (!bucket || bucket->size() == 0) {
3917 return error::kInvalidArguments;
3918 }
3919 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183920 if (!bucket->GetAsString(&name_str)) {
3921 return error::kInvalidArguments;
3922 }
[email protected]258a3313f2011-10-18 20:13:573923 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543924 return error::kNoError;
3925}
3926
[email protected]f7a64ee2010-02-01 22:24:143927error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463928 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033929 GLuint client_id = c.shader;
3930 if (client_id) {
3931 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3932 if (info) {
[email protected]ca488e12010-12-13 20:06:143933 if (!info->IsDeleted()) {
3934 glDeleteShader(info->service_id());
3935 shader_manager()->MarkAsDeleted(info);
3936 }
[email protected]ae51d192010-04-27 00:48:033937 } else {
[email protected]8eee29c2010-04-29 03:38:293938 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033939 }
[email protected]96449d2c2009-11-25 00:01:323940 }
[email protected]f7a64ee2010-02-01 22:24:143941 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323942}
3943
[email protected]f7a64ee2010-02-01 22:24:143944error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463945 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033946 GLuint client_id = c.program;
3947 if (client_id) {
3948 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3949 if (info) {
[email protected]ca488e12010-12-13 20:06:143950 if (!info->IsDeleted()) {
3951 glDeleteProgram(info->service_id());
3952 program_manager()->MarkAsDeleted(shader_manager(), info);
3953 }
[email protected]ae51d192010-04-27 00:48:033954 } else {
[email protected]8eee29c2010-04-29 03:38:293955 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033956 }
[email protected]96449d2c2009-11-25 00:01:323957 }
[email protected]f7a64ee2010-02-01 22:24:143958 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323959}
3960
[email protected]269200b12010-11-18 22:53:063961void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103962 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573963 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103964 for (GLsizei ii = 0; ii < n; ++ii) {
3965 id_allocator->FreeID(ids[ii]);
3966 }
3967}
3968
[email protected]269200b12010-11-18 22:53:063969error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
3970 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103971 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3972 GLsizei n = static_cast<GLsizei>(c.n);
3973 uint32 data_size;
3974 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3975 return error::kOutOfBounds;
3976 }
3977 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3978 c.ids_shm_id, c.ids_shm_offset, data_size);
3979 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063980 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103981 return error::kNoError;
3982 }
3983 if (ids == NULL) {
3984 return error::kOutOfBounds;
3985 }
[email protected]269200b12010-11-18 22:53:063986 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103987 return error::kNoError;
3988}
3989
[email protected]269200b12010-11-18 22:53:063990void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103991 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573992 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103993 if (id_offset == 0) {
3994 for (GLsizei ii = 0; ii < n; ++ii) {
3995 ids[ii] = id_allocator->AllocateID();
3996 }
3997 } else {
3998 for (GLsizei ii = 0; ii < n; ++ii) {
3999 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4000 id_offset = ids[ii] + 1;
4001 }
4002 }
4003}
4004
[email protected]269200b12010-11-18 22:53:064005error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4006 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104007 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4008 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4009 GLsizei n = static_cast<GLsizei>(c.n);
4010 uint32 data_size;
4011 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4012 return error::kOutOfBounds;
4013 }
4014 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4015 c.ids_shm_id, c.ids_shm_offset, data_size);
4016 if (n < 0) {
[email protected]269200b12010-11-18 22:53:064017 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:104018 return error::kNoError;
4019 }
4020 if (ids == NULL) {
4021 return error::kOutOfBounds;
4022 }
[email protected]269200b12010-11-18 22:53:064023 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:104024 return error::kNoError;
4025}
4026
[email protected]269200b12010-11-18 22:53:064027void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104028 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574029 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104030 for (GLsizei ii = 0; ii < n; ++ii) {
4031 if (!id_allocator->MarkAsUsed(ids[ii])) {
4032 for (GLsizei jj = 0; jj < ii; ++jj) {
4033 id_allocator->FreeID(ids[jj]);
4034 }
4035 SetGLError(
4036 GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:064037 "RegisterSharedIdsCHROMIUM: attempt to register "
4038 "id that already exists");
[email protected]066849e32010-05-03 19:14:104039 return;
4040 }
4041 }
4042}
4043
[email protected]269200b12010-11-18 22:53:064044error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4045 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104046 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4047 GLsizei n = static_cast<GLsizei>(c.n);
4048 uint32 data_size;
4049 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4050 return error::kOutOfBounds;
4051 }
4052 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4053 c.ids_shm_id, c.ids_shm_offset, data_size);
4054 if (n < 0) {
[email protected]269200b12010-11-18 22:53:064055 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:104056 return error::kNoError;
4057 }
4058 if (ids == NULL) {
4059 return error::kOutOfBounds;
4060 }
[email protected]269200b12010-11-18 22:53:064061 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:104062 return error::kNoError;
4063}
4064
[email protected]3a03a8f2011-03-19 00:51:274065void GLES2DecoderImpl::DoClear(GLbitfield mask) {
[email protected]0d6bfdc2011-11-02 01:32:204066 if (CheckBoundFramebuffersValid("glClear")) {
[email protected]529c6672012-01-04 02:18:264067 UNSHIPPED_TRACE_EVENT_INSTANT2("test_gpu", "DoClear", "red", clear_red_,
4068 "green", clear_green_);
[email protected]297ca1c2011-06-20 23:08:464069 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:274070 glClear(mask);
4071 }
4072}
4073
[email protected]36cef8ce2010-03-16 07:34:454074void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4075 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:034076 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:304077 FramebufferManager::FramebufferInfo* framebuffer_info =
4078 GetFramebufferInfoForTarget(target);
4079 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294080 SetGLError(GL_INVALID_OPERATION,
4081 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454082 return;
4083 }
[email protected]ae51d192010-04-27 00:48:034084 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:284085 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:034086 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:284087 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:034088 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294089 SetGLError(GL_INVALID_OPERATION,
4090 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:034091 return;
4092 }
4093 service_id = info->service_id();
4094 }
[email protected]9edc6b22010-12-23 02:00:264095 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034096 glFramebufferRenderbufferEXT(
4097 target, attachment, renderbuffertarget, service_id);
[email protected]1002c2d2011-06-28 22:39:044098 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264099 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:304100 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]3a2e7c7b2010-08-06 01:12:284101 }
[email protected]297ca1c2011-06-20 23:08:464102 if (framebuffer_info == bound_draw_framebuffer_) {
4103 state_dirty_ = true;
4104 }
[email protected]3a2e7c7b2010-08-06 01:12:284105}
4106
[email protected]297ca1c2011-06-20 23:08:464107bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
[email protected]3a2e7c7b2010-08-06 01:12:284108 switch (cap) {
4109 case GL_SCISSOR_TEST:
4110 enable_scissor_test_ = enabled;
[email protected]297ca1c2011-06-20 23:08:464111 return true;
4112 case GL_DEPTH_TEST: {
4113 if (enable_depth_test_ != enabled) {
4114 enable_depth_test_ = enabled;
4115 state_dirty_ = true;
4116 }
4117 return false;
4118 }
4119 case GL_STENCIL_TEST:
4120 if (enable_stencil_test_ != enabled) {
4121 enable_stencil_test_ = enabled;
4122 state_dirty_ = true;
4123 }
4124 return false;
[email protected]3a2e7c7b2010-08-06 01:12:284125 default:
[email protected]297ca1c2011-06-20 23:08:464126 return true;
[email protected]3a2e7c7b2010-08-06 01:12:284127 }
4128}
4129
4130void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464131 if (SetCapabilityState(cap, false)) {
4132 glDisable(cap);
4133 }
[email protected]3a2e7c7b2010-08-06 01:12:284134}
4135
4136void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464137 if (SetCapabilityState(cap, true)) {
4138 glEnable(cap);
4139 }
[email protected]3a2e7c7b2010-08-06 01:12:284140}
4141
4142void GLES2DecoderImpl::DoClearColor(
4143 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
4144 clear_red_ = red;
4145 clear_green_ = green;
4146 clear_blue_ = blue;
4147 clear_alpha_ = alpha;
4148 glClearColor(red, green, blue, alpha);
4149}
4150
4151void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
4152 clear_depth_ = depth;
4153 glClearDepth(depth);
4154}
4155
4156void GLES2DecoderImpl::DoClearStencil(GLint s) {
4157 clear_stencil_ = s;
4158 glClearStencil(s);
4159}
4160
4161void GLES2DecoderImpl::DoColorMask(
4162 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
4163 mask_red_ = red;
4164 mask_green_ = green;
4165 mask_blue_ = blue;
4166 mask_alpha_ = alpha;
[email protected]297ca1c2011-06-20 23:08:464167 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284168}
4169
4170void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
4171 mask_depth_ = depth;
[email protected]297ca1c2011-06-20 23:08:464172 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284173}
4174
4175void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
4176 mask_stencil_front_ = mask;
4177 mask_stencil_back_ = mask;
[email protected]297ca1c2011-06-20 23:08:464178 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284179}
4180
4181void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
[email protected]297ca1c2011-06-20 23:08:464182 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284183 mask_stencil_front_ = mask;
[email protected]297ca1c2011-06-20 23:08:464184 }
4185 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284186 mask_stencil_back_ = mask;
4187 }
[email protected]297ca1c2011-06-20 23:08:464188 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284189}
4190
[email protected]0d6bfdc2011-11-02 01:32:204191// Assumes framebuffer is complete.
4192void GLES2DecoderImpl::ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:304193 GLenum target, FramebufferManager::FramebufferInfo* info) {
4194 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204195 // bind this to the DRAW point, clear then bind back to READ
4196 // TODO(gman): I don't think there is any guarantee that an FBO that
4197 // is complete on the READ attachment will be complete as a DRAW
4198 // attachment.
4199 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
4200 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, info->service_id());
[email protected]8e3e0662010-08-23 18:46:304201 }
[email protected]3a2e7c7b2010-08-06 01:12:284202 GLbitfield clear_bits = 0;
4203 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:464204 glClearColor(
[email protected]0d6bfdc2011-11-02 01:32:204205 0.0f, 0.0f, 0.0f,
[email protected]297ca1c2011-06-20 23:08:464206 (GLES2Util::GetChannelsForFormat(
[email protected]0d6bfdc2011-11-02 01:32:204207 info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f : 1.0f);
[email protected]3a2e7c7b2010-08-06 01:12:284208 glColorMask(true, true, true, true);
4209 clear_bits |= GL_COLOR_BUFFER_BIT;
4210 }
4211
4212 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4213 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4214 glClearStencil(0);
4215 glStencilMask(-1);
4216 clear_bits |= GL_STENCIL_BUFFER_BIT;
4217 }
4218
4219 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4220 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4221 glClearDepth(1.0f);
4222 glDepthMask(true);
4223 clear_bits |= GL_DEPTH_BUFFER_BIT;
4224 }
4225
4226 glDisable(GL_SCISSOR_TEST);
4227 glClear(clear_bits);
4228
[email protected]968351b2011-12-20 08:26:514229 framebuffer_manager()->MarkAttachmentsAsCleared(
4230 info, renderbuffer_manager(), texture_manager());
[email protected]3a2e7c7b2010-08-06 01:12:284231
[email protected]c007aa02010-09-02 22:22:404232 RestoreClearState();
4233
4234 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204235 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, info->service_id());
[email protected]87d1a3fe2011-12-01 04:25:484236 FramebufferManager::FramebufferInfo* framebuffer =
4237 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4238 GLuint service_id =
4239 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
4240 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
[email protected]c007aa02010-09-02 22:22:404241 }
4242}
4243
4244void GLES2DecoderImpl::RestoreClearState() {
[email protected]297ca1c2011-06-20 23:08:464245 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284246 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
[email protected]3a2e7c7b2010-08-06 01:12:284247 glClearStencil(clear_stencil_);
[email protected]3a2e7c7b2010-08-06 01:12:284248 glClearDepth(clear_depth_);
[email protected]3a2e7c7b2010-08-06 01:12:284249 if (enable_scissor_test_) {
4250 glEnable(GL_SCISSOR_TEST);
4251 }
[email protected]36cef8ce2010-03-16 07:34:454252}
4253
4254GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]0d6bfdc2011-11-02 01:32:204255 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]8e3e0662010-08-23 18:46:304256 GetFramebufferInfoForTarget(target);
[email protected]0d6bfdc2011-11-02 01:32:204257 if (!framebuffer) {
[email protected]36cef8ce2010-03-16 07:34:454258 return GL_FRAMEBUFFER_COMPLETE;
4259 }
[email protected]0d6bfdc2011-11-02 01:32:204260 GLenum completeness = framebuffer->IsPossiblyComplete();
4261 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4262 return completeness;
4263 }
[email protected]36cef8ce2010-03-16 07:34:454264 return glCheckFramebufferStatusEXT(target);
4265}
4266
4267void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:034268 GLenum target, GLenum attachment, GLenum textarget,
4269 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:304270 FramebufferManager::FramebufferInfo* framebuffer_info =
4271 GetFramebufferInfoForTarget(target);
4272 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294273 SetGLError(GL_INVALID_OPERATION,
4274 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:454275 return;
4276 }
[email protected]ae51d192010-04-27 00:48:034277 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:284278 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:034279 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:284280 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:034281 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294282 SetGLError(GL_INVALID_OPERATION,
4283 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:034284 return;
4285 }
4286 service_id = info->service_id();
4287 }
[email protected]0d6bfdc2011-11-02 01:32:204288
[email protected]80eb6b52012-01-19 00:14:414289 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
[email protected]0d6bfdc2011-11-02 01:32:204290 SetGLError(GL_INVALID_VALUE,
4291 "glFramebufferTexture2D: level out of range");
4292 return;
4293 }
4294
[email protected]9edc6b22010-12-23 02:00:264295 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034296 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]1002c2d2011-06-28 22:39:044297 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264298 if (error == GL_NO_ERROR) {
4299 framebuffer_info->AttachTexture(attachment, info, textarget, level);
[email protected]3a2e7c7b2010-08-06 01:12:284300 }
[email protected]297ca1c2011-06-20 23:08:464301 if (framebuffer_info == bound_draw_framebuffer_) {
4302 state_dirty_ = true;
4303 }
[email protected]36cef8ce2010-03-16 07:34:454304}
4305
4306void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4307 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:304308 FramebufferManager::FramebufferInfo* framebuffer_info =
4309 GetFramebufferInfoForTarget(target);
4310 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294311 SetGLError(GL_INVALID_OPERATION,
4312 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454313 return;
4314 }
4315 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:574316 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4317 GLint type = 0;
4318 GLuint client_id = 0;
4319 glGetFramebufferAttachmentParameterivEXT(
4320 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
4321 switch (type) {
4322 case GL_RENDERBUFFER: {
4323 renderbuffer_manager()->GetClientId(*params, &client_id);
4324 break;
4325 }
4326 case GL_TEXTURE: {
4327 texture_manager()->GetClientId(*params, &client_id);
4328 break;
4329 }
4330 default:
4331 break;
4332 }
4333 *params = client_id;
4334 }
[email protected]36cef8ce2010-03-16 07:34:454335}
4336
4337void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4338 GLenum target, GLenum pname, GLint* params) {
[email protected]0d6bfdc2011-11-02 01:32:204339 RenderbufferManager::RenderbufferInfo* renderbuffer =
4340 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4341 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294342 SetGLError(GL_INVALID_OPERATION,
4343 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454344 return;
4345 }
[email protected]3a03a8f2011-03-19 00:51:274346 switch (pname) {
4347 case GL_RENDERBUFFER_INTERNAL_FORMAT:
[email protected]0d6bfdc2011-11-02 01:32:204348 *params = renderbuffer->internal_format();
[email protected]3a03a8f2011-03-19 00:51:274349 break;
4350 case GL_RENDERBUFFER_WIDTH:
[email protected]0d6bfdc2011-11-02 01:32:204351 *params = renderbuffer->width();
[email protected]3a03a8f2011-03-19 00:51:274352 break;
4353 case GL_RENDERBUFFER_HEIGHT:
[email protected]0d6bfdc2011-11-02 01:32:204354 *params = renderbuffer->height();
[email protected]3a03a8f2011-03-19 00:51:274355 break;
4356 default:
4357 glGetRenderbufferParameterivEXT(target, pname, params);
4358 break;
[email protected]b71f52c2010-06-18 22:20:204359 }
[email protected]36cef8ce2010-03-16 07:34:454360}
4361
[email protected]8e3e0662010-08-23 18:46:304362void GLES2DecoderImpl::DoBlitFramebufferEXT(
4363 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
4364 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
4365 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:394366 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304367 SetGLError(GL_INVALID_OPERATION,
4368 "glBlitFramebufferEXT: function not available");
4369 }
[email protected]5094b0f2010-11-09 19:45:244370 if (IsAngle()) {
4371 glBlitFramebufferANGLE(
4372 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4373 } else {
4374 glBlitFramebufferEXT(
4375 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4376 }
[email protected]529c6672012-01-04 02:18:264377 UNSHIPPED_TRACE_EVENT_INSTANT1("test_gpu", "DoBlit", "width", srcX1 - srcX0);
[email protected]8e3e0662010-08-23 18:46:304378}
4379
4380void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
4381 GLenum target, GLsizei samples, GLenum internalformat,
4382 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:394383 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304384 SetGLError(GL_INVALID_OPERATION,
4385 "glRenderbufferStorageMultisampleEXT: function not available");
4386 return;
4387 }
[email protected]8e3e0662010-08-23 18:46:304388
[email protected]0d6bfdc2011-11-02 01:32:204389 RenderbufferManager::RenderbufferInfo* renderbuffer =
4390 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4391 if (!renderbuffer) {
4392 SetGLError(GL_INVALID_OPERATION,
4393 "glGetRenderbufferStorageMultisample: no renderbuffer bound");
4394 return;
4395 }
4396
[email protected]84afefa2011-10-19 21:45:534397 if (samples > renderbuffer_manager()->max_samples()) {
4398 SetGLError(GL_INVALID_VALUE,
4399 "glGetRenderbufferStorageMultisample: samples too large");
4400 return;
4401 }
4402
4403 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4404 height > renderbuffer_manager()->max_renderbuffer_size()) {
4405 SetGLError(GL_INVALID_VALUE,
4406 "glGetRenderbufferStorageMultisample: size too large");
4407 return;
4408 }
4409
[email protected]9edc6b22010-12-23 02:00:264410 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:304411 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264412 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:304413 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264414 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:304415 break;
4416 case GL_RGBA4:
4417 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264418 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:304419 break;
4420 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264421 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:304422 break;
4423 }
4424 }
4425
[email protected]9edc6b22010-12-23 02:00:264426 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:084427 if (IsAngle()) {
4428 glRenderbufferStorageMultisampleANGLE(
4429 target, samples, impl_format, width, height);
4430 } else {
4431 glRenderbufferStorageMultisampleEXT(
4432 target, samples, impl_format, width, height);
4433 }
[email protected]1002c2d2011-06-28 22:39:044434 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264435 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514436 // TODO(gman): If renderbuffers tracked which framebuffers they were
4437 // attached to we could just mark those framebuffers as not complete.
4438 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204439 renderbuffer_manager()->SetInfo(
4440 renderbuffer, samples, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264441 }
[email protected]8e3e0662010-08-23 18:46:304442}
4443
[email protected]36cef8ce2010-03-16 07:34:454444void GLES2DecoderImpl::DoRenderbufferStorage(
4445 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]0d6bfdc2011-11-02 01:32:204446 RenderbufferManager::RenderbufferInfo* renderbuffer =
4447 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4448 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294449 SetGLError(GL_INVALID_OPERATION,
4450 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454451 return;
4452 }
[email protected]876f6fee2010-08-02 23:10:324453
[email protected]84afefa2011-10-19 21:45:534454 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4455 height > renderbuffer_manager()->max_renderbuffer_size()) {
4456 SetGLError(GL_INVALID_VALUE,
4457 "glGetRenderbufferStorage: size too large");
4458 return;
4459 }
4460
[email protected]9edc6b22010-12-23 02:00:264461 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:324462 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264463 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:324464 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264465 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:324466 break;
4467 case GL_RGBA4:
4468 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264469 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:324470 break;
4471 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264472 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:324473 break;
4474 }
[email protected]b71f52c2010-06-18 22:20:204475 }
[email protected]876f6fee2010-08-02 23:10:324476
[email protected]9edc6b22010-12-23 02:00:264477 CopyRealGLErrorsToWrapper();
4478 glRenderbufferStorageEXT(target, impl_format, width, height);
[email protected]1002c2d2011-06-28 22:39:044479 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264480 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514481 // TODO(gman): If tetxures tracked which framebuffers they were attached to
4482 // we could just mark those framebuffers as not complete.
4483 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204484 renderbuffer_manager()->SetInfo(
4485 renderbuffer, 0, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264486 }
[email protected]36cef8ce2010-03-16 07:34:454487}
4488
[email protected]07f54fcc2009-12-22 02:46:304489void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]0c8fabf2011-06-14 19:35:224490 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]6b8cf1a2010-05-06 16:13:584491 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4492 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:474493 if (!info) {
[email protected]a93bb842010-02-16 23:03:474494 return;
4495 }
[email protected]05afda12011-01-20 00:17:344496
[email protected]d685a682011-04-29 16:19:574497 info->Link();
[email protected]07f54fcc2009-12-22 02:46:304498};
4499
[email protected]3916c97e2010-02-25 03:20:504500void GLES2DecoderImpl::DoTexParameterf(
4501 GLenum target, GLenum pname, GLfloat param) {
4502 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:304503 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294504 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244505 return;
[email protected]07f54fcc2009-12-22 02:46:304506 }
[email protected]cbb22e42011-05-12 23:36:244507
4508 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414509 info, pname, static_cast<GLint>(param))) {
[email protected]cbb22e42011-05-12 23:36:244510 SetGLError(GL_INVALID_ENUM, "glTexParameterf: param GL_INVALID_ENUM");
4511 return;
4512 }
4513 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:304514}
4515
[email protected]3916c97e2010-02-25 03:20:504516void GLES2DecoderImpl::DoTexParameteri(
4517 GLenum target, GLenum pname, GLint param) {
4518 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4519 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294520 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244521 return;
[email protected]3916c97e2010-02-25 03:20:504522 }
[email protected]cbb22e42011-05-12 23:36:244523
[email protected]80eb6b52012-01-19 00:14:414524 if (!texture_manager()->SetParameter(info, pname, param)) {
[email protected]cbb22e42011-05-12 23:36:244525 SetGLError(GL_INVALID_ENUM, "glTexParameteri: param GL_INVALID_ENUM");
4526 return;
4527 }
4528 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:504529}
4530
4531void GLES2DecoderImpl::DoTexParameterfv(
4532 GLenum target, GLenum pname, const GLfloat* params) {
4533 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4534 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294535 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244536 return;
[email protected]3916c97e2010-02-25 03:20:504537 }
[email protected]cbb22e42011-05-12 23:36:244538
4539 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414540 info, pname, static_cast<GLint>(params[0]))) {
[email protected]cbb22e42011-05-12 23:36:244541 SetGLError(GL_INVALID_ENUM, "glTexParameterfv: param GL_INVALID_ENUM");
4542 return;
4543 }
4544 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504545}
4546
4547void GLES2DecoderImpl::DoTexParameteriv(
4548 GLenum target, GLenum pname, const GLint* params) {
4549 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4550 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294551 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244552 return;
[email protected]3916c97e2010-02-25 03:20:504553 }
[email protected]cbb22e42011-05-12 23:36:244554
[email protected]80eb6b52012-01-19 00:14:414555 if (!texture_manager()->SetParameter(info, pname, *params)) {
[email protected]cbb22e42011-05-12 23:36:244556 SetGLError(GL_INVALID_ENUM, "glTexParameteriv: param GL_INVALID_ENUM");
4557 return;
4558 }
4559 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504560}
4561
[email protected]939e7362010-05-13 20:49:104562bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:144563 if (!current_program_) {
[email protected]939e7362010-05-13 20:49:104564 // The program does not exist.
4565 SetGLError(GL_INVALID_OPERATION,
4566 (std::string(function_name) + ": no program in use").c_str());
4567 return false;
4568 }
[email protected]ca488e12010-12-13 20:06:144569 if (!current_program_->InUse()) {
[email protected]939e7362010-05-13 20:49:104570 SetGLError(GL_INVALID_OPERATION,
4571 (std::string(function_name) + ": program not linked").c_str());
4572 return false;
4573 }
4574 return true;
4575}
4576
4577bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
4578 GLint location, const char* function_name) {
4579 if (!CheckCurrentProgram(function_name)) {
4580 return false;
4581 }
4582 return location != -1;
4583}
4584
[email protected]43c2f1f2011-03-25 18:35:364585bool GLES2DecoderImpl::PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124586 GLint fake_location, const char* function_name,
4587 GLint* real_location, GLenum* type, GLsizei* count) {
[email protected]43c2f1f2011-03-25 18:35:364588 DCHECK(type);
4589 DCHECK(count);
[email protected]1b0a6752012-02-22 03:44:124590 DCHECK(real_location);
4591 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
[email protected]939e7362010-05-13 20:49:104592 return false;
4593 }
[email protected]43c2f1f2011-03-25 18:35:364594 GLint array_index = -1;
4595 const ProgramManager::ProgramInfo::UniformInfo* info =
[email protected]1b0a6752012-02-22 03:44:124596 current_program_->GetUniformInfoByFakeLocation(
4597 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:364598 if (!info) {
[email protected]939e7362010-05-13 20:49:104599 SetGLError(GL_INVALID_OPERATION,
[email protected]43c2f1f2011-03-25 18:35:364600 (std::string(function_name) + ": unknown location").c_str());
[email protected]939e7362010-05-13 20:49:104601 return false;
4602 }
[email protected]43c2f1f2011-03-25 18:35:364603 if (*count > 1 && !info->is_array) {
4604 SetGLError(
4605 GL_INVALID_OPERATION,
4606 (std::string(function_name) + ": count > 1 for non-array").c_str());
4607 return false;
4608 }
4609 *count = std::min(info->size - array_index, *count);
4610 if (*count <= 0) {
4611 return false;
4612 }
4613 *type = info->type;
[email protected]939e7362010-05-13 20:49:104614 return true;
4615}
4616
[email protected]1b0a6752012-02-22 03:44:124617void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
4618 GLenum type = 0;
4619 GLsizei count = 1;
4620 GLint real_location = -1;
4621 if (!PrepForSetUniformByLocation(
4622 fake_location, "glUniform1iv", &real_location, &type, &count)) {
[email protected]3916c97e2010-02-25 03:20:504623 return;
4624 }
[email protected]1b0a6752012-02-22 03:44:124625 current_program_->SetSamplers(fake_location, 1, &v0);
4626 glUniform1i(real_location, v0);
[email protected]3916c97e2010-02-25 03:20:504627}
4628
4629void GLES2DecoderImpl::DoUniform1iv(
[email protected]1b0a6752012-02-22 03:44:124630 GLint fake_location, GLsizei count, const GLint *value) {
[email protected]43c2f1f2011-03-25 18:35:364631 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124632 GLint real_location = -1;
4633 if (!PrepForSetUniformByLocation(
4634 fake_location, "glUniform1iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364635 return;
4636 }
[email protected]61eeb33f2011-07-26 15:30:314637 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
4638 type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]1b0a6752012-02-22 03:44:124639 current_program_->SetSamplers(fake_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364640 }
[email protected]1b0a6752012-02-22 03:44:124641 glUniform1iv(real_location, count, value);
[email protected]3916c97e2010-02-25 03:20:504642}
4643
[email protected]939e7362010-05-13 20:49:104644void GLES2DecoderImpl::DoUniform1fv(
[email protected]1b0a6752012-02-22 03:44:124645 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364646 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124647 GLint real_location = -1;
4648 if (!PrepForSetUniformByLocation(
4649 fake_location, "glUniform1fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104650 return;
4651 }
4652 if (type == GL_BOOL) {
4653 scoped_array<GLint> temp(new GLint[count]);
4654 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:534655 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104656 }
[email protected]1b0a6752012-02-22 03:44:124657 DoUniform1iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104658 } else {
[email protected]1b0a6752012-02-22 03:44:124659 glUniform1fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104660 }
4661}
4662
4663void GLES2DecoderImpl::DoUniform2fv(
[email protected]1b0a6752012-02-22 03:44:124664 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364665 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124666 GLint real_location = -1;
4667 if (!PrepForSetUniformByLocation(
4668 fake_location, "glUniform2fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104669 return;
4670 }
4671 if (type == GL_BOOL_VEC2) {
4672 GLsizei num_values = count * 2;
4673 scoped_array<GLint> temp(new GLint[num_values]);
4674 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534675 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104676 }
[email protected]1b0a6752012-02-22 03:44:124677 glUniform2iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104678 } else {
[email protected]1b0a6752012-02-22 03:44:124679 glUniform2fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104680 }
4681}
4682
4683void GLES2DecoderImpl::DoUniform3fv(
[email protected]1b0a6752012-02-22 03:44:124684 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364685 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124686 GLint real_location = -1;
4687 if (!PrepForSetUniformByLocation(
4688 fake_location, "glUniform3fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104689 return;
4690 }
4691 if (type == GL_BOOL_VEC3) {
4692 GLsizei num_values = count * 3;
4693 scoped_array<GLint> temp(new GLint[num_values]);
4694 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534695 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104696 }
[email protected]1b0a6752012-02-22 03:44:124697 glUniform3iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104698 } else {
[email protected]1b0a6752012-02-22 03:44:124699 glUniform3fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104700 }
4701}
4702
4703void GLES2DecoderImpl::DoUniform4fv(
[email protected]1b0a6752012-02-22 03:44:124704 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364705 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124706 GLint real_location = -1;
4707 if (!PrepForSetUniformByLocation(
4708 fake_location, "glUniform4fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104709 return;
4710 }
4711 if (type == GL_BOOL_VEC4) {
4712 GLsizei num_values = count * 4;
4713 scoped_array<GLint> temp(new GLint[num_values]);
4714 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534715 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104716 }
[email protected]1b0a6752012-02-22 03:44:124717 glUniform4iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104718 } else {
[email protected]1b0a6752012-02-22 03:44:124719 glUniform4fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104720 }
4721}
4722
[email protected]43c2f1f2011-03-25 18:35:364723void GLES2DecoderImpl::DoUniform2iv(
[email protected]1b0a6752012-02-22 03:44:124724 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364725 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124726 GLint real_location = -1;
4727 if (!PrepForSetUniformByLocation(
4728 fake_location, "glUniform2iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364729 return;
4730 }
[email protected]1b0a6752012-02-22 03:44:124731 glUniform2iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364732}
4733
4734void GLES2DecoderImpl::DoUniform3iv(
[email protected]1b0a6752012-02-22 03:44:124735 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364736 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124737 GLint real_location = -1;
4738 if (!PrepForSetUniformByLocation(
4739 fake_location, "glUniform3iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364740 return;
4741 }
[email protected]1b0a6752012-02-22 03:44:124742 glUniform3iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364743}
4744
4745void GLES2DecoderImpl::DoUniform4iv(
[email protected]1b0a6752012-02-22 03:44:124746 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364747 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124748 GLint real_location = -1;
4749 if (!PrepForSetUniformByLocation(
4750 fake_location, "glUniform4iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364751 return;
4752 }
[email protected]1b0a6752012-02-22 03:44:124753 glUniform4iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364754}
4755
4756void GLES2DecoderImpl::DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:124757 GLint fake_location, GLsizei count, GLboolean transpose,
4758 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364759 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124760 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364761 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124762 fake_location, "glUniformMatrix2fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364763 return;
4764 }
[email protected]1b0a6752012-02-22 03:44:124765 glUniformMatrix2fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364766}
4767
4768void GLES2DecoderImpl::DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:124769 GLint fake_location, GLsizei count, GLboolean transpose,
4770 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364771 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124772 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364773 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124774 fake_location, "glUniformMatrix3fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364775 return;
4776 }
[email protected]1b0a6752012-02-22 03:44:124777 glUniformMatrix3fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364778}
4779
4780void GLES2DecoderImpl::DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:124781 GLint fake_location, GLsizei count, GLboolean transpose,
4782 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364783 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124784 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364785 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124786 fake_location, "glUniformMatrix4fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364787 return;
4788 }
[email protected]1b0a6752012-02-22 03:44:124789 glUniformMatrix4fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364790}
4791
[email protected]3916c97e2010-02-25 03:20:504792void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:034793 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:504794 ProgramManager::ProgramInfo* info = NULL;
4795 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:584796 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:504797 if (!info) {
[email protected]ae51d192010-04-27 00:48:034798 return;
4799 }
4800 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:504801 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:294802 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:504803 return;
4804 }
[email protected]ae51d192010-04-27 00:48:034805 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:504806 }
[email protected]ca488e12010-12-13 20:06:144807 if (current_program_) {
4808 program_manager()->UnuseProgram(shader_manager(), current_program_);
4809 }
[email protected]3916c97e2010-02-25 03:20:504810 current_program_ = info;
[email protected]ca488e12010-12-13 20:06:144811 if (current_program_) {
4812 program_manager()->UseProgram(current_program_);
4813 }
[email protected]ae51d192010-04-27 00:48:034814 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:504815}
4816
[email protected]96449d2c2009-11-25 00:01:324817GLenum GLES2DecoderImpl::GetGLError() {
4818 // Check the GL error first, then our wrapped error.
4819 GLenum error = glGetError();
4820 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:374821 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:324822 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:294823 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:324824 break;
4825 }
4826 }
4827 }
4828
4829 if (error != GL_NO_ERROR) {
4830 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:294831 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324832 }
4833 return error;
4834}
4835
[email protected]1002c2d2011-06-28 22:39:044836GLenum GLES2DecoderImpl::PeekGLError() {
4837 GLenum error = glGetError();
4838 if (error != GL_NO_ERROR) {
4839 SetGLError(error, "");
4840 }
4841 return error;
4842}
4843
[email protected]8eee29c2010-04-29 03:38:294844void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
4845 if (msg) {
4846 last_error_ = msg;
[email protected]b5d647c2012-02-10 01:41:324847 // LOG this unless logging is turned off as any chromium code that generates
4848 // these errors probably has a bug.
4849 if (log_synthesized_gl_errors()) {
4850 LOG(ERROR) << last_error_;
4851 }
[email protected]6b6e7ee2011-12-13 08:04:524852 if (!msg_callback_.is_null()) {
4853 msg_callback_.Run(0, GLES2Util::GetStringEnum(error) + " : " + msg);
4854 }
[email protected]8eee29c2010-04-29 03:38:294855 }
[email protected]ddd968b82010-03-02 00:44:294856 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324857}
4858
[email protected]07f54fcc2009-12-22 02:46:304859void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
4860 GLenum error;
4861 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294862 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:304863 }
4864}
4865
[email protected]6217d392010-03-25 22:08:354866void GLES2DecoderImpl::ClearRealGLErrors() {
4867 GLenum error;
4868 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]3ed14d112011-12-13 22:05:514869 if (error != GL_OUT_OF_MEMORY) {
4870 // GL_OUT_OF_MEMORY can legally happen on lost device.
4871 NOTREACHED() << "GL error " << error << " was unhandled.";
4872 }
[email protected]6217d392010-03-25 22:08:354873 }
4874}
4875
[email protected]ef526492010-06-02 23:12:254876bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:504877 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:254878 // Only check if there are some unrenderable textures.
4879 if (!texture_manager()->HaveUnrenderableTextures()) {
4880 return false;
4881 }
4882 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:504883 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4884 current_program_->sampler_indices();
4885 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4886 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4887 current_program_->GetUniformInfo(sampler_indices[ii]);
4888 DCHECK(uniform_info);
4889 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4890 GLuint texture_unit_index = uniform_info->texture_units[jj];
4891 if (texture_unit_index < group_->max_texture_units()) {
4892 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4893 TextureManager::TextureInfo* texture_info =
[email protected]61eeb33f2011-07-26 15:30:314894 texture_unit.GetInfoForSamplerType(uniform_info->type);
[email protected]80eb6b52012-01-19 00:14:414895 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]ef526492010-06-02 23:12:254896 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:504897 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4898 glBindTexture(
[email protected]61eeb33f2011-07-26 15:30:314899 GetBindTargetForSamplerType(uniform_info->type),
[email protected]00f893d2010-08-24 18:55:494900 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:504901 }
4902 }
4903 // else: should this be an error?
4904 }
4905 }
[email protected]ef526492010-06-02 23:12:254906 return textures_set;
[email protected]3916c97e2010-02-25 03:20:504907}
4908
4909void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
4910 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:504911 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4912 current_program_->sampler_indices();
4913 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4914 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4915 current_program_->GetUniformInfo(sampler_indices[ii]);
4916 DCHECK(uniform_info);
4917 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4918 GLuint texture_unit_index = uniform_info->texture_units[jj];
4919 if (texture_unit_index < group_->max_texture_units()) {
4920 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4921 TextureManager::TextureInfo* texture_info =
4922 uniform_info->type == GL_SAMPLER_2D ?
4923 texture_unit.bound_texture_2d :
4924 texture_unit.bound_texture_cube_map;
[email protected]80eb6b52012-01-19 00:14:414925 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]3916c97e2010-02-25 03:20:504926 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4927 // Get the texture info that was previously bound here.
4928 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
4929 texture_unit.bound_texture_2d :
4930 texture_unit.bound_texture_cube_map;
4931 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:034932 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:504933 }
4934 }
4935 }
4936 }
4937 // Set the active texture back to whatever the user had it as.
4938 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:304939}
4940
[email protected]0d6bfdc2011-11-02 01:32:204941bool GLES2DecoderImpl::ClearUnclearedTextures() {
4942 // Only check if there are some uncleared textures.
4943 if (!texture_manager()->HaveUnsafeTextures()) {
4944 return true;
4945 }
4946
4947 // 1: Check all textures we are about to render with.
4948 if (current_program_) {
4949 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4950 current_program_->sampler_indices();
4951 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4952 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4953 current_program_->GetUniformInfo(sampler_indices[ii]);
4954 DCHECK(uniform_info);
4955 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4956 GLuint texture_unit_index = uniform_info->texture_units[jj];
4957 if (texture_unit_index < group_->max_texture_units()) {
4958 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4959 TextureManager::TextureInfo* texture_info =
4960 texture_unit.GetInfoForSamplerType(uniform_info->type);
4961 if (texture_info && !texture_info->SafeToRenderFrom()) {
4962 if (!texture_manager()->ClearRenderableLevels(this, texture_info)) {
4963 return false;
4964 }
4965 }
4966 }
4967 }
4968 }
4969 }
4970 return true;
4971}
4972
[email protected]c6aef902012-02-14 03:31:424973bool GLES2DecoderImpl::IsDrawValid(
4974 GLuint max_vertex_accessed, GLsizei primcount) {
[email protected]689fa1c52010-06-09 18:35:034975 // NOTE: We specifically do not check current_program->IsValid() because
4976 // it could never be invalid since glUseProgram would have failed. While
4977 // glLinkProgram could later mark the program as invalid the previous
4978 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:144979 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:504980 // The program does not exist.
4981 // But GL says no ERROR.
4982 return false;
4983 }
[email protected]c6aef902012-02-14 03:31:424984
4985 // true if any enabled, used divisor is zero
4986 bool divisor0 = false;
[email protected]f39f4b3f2010-05-12 17:04:084987 // Validate all attribs currently enabled. If they are used by the current
4988 // program then check that they have enough elements to handle the draw call.
4989 // If they are not used by the current program check that they have a buffer
4990 // assigned.
4991 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:444992 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]f39f4b3f2010-05-12 17:04:084993 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:404994 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:084995 const VertexAttribManager::VertexAttribInfo* info = *it;
4996 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4997 current_program_->GetAttribInfoByLocation(info->index());
4998 if (attrib_info) {
[email protected]c6aef902012-02-14 03:31:424999 divisor0 |= (info->divisor() == 0);
5000 GLuint count = info->MaxVertexAccessed(primcount, max_vertex_accessed);
[email protected]f39f4b3f2010-05-12 17:04:085001 // This attrib is used in the current program.
[email protected]c6aef902012-02-14 03:31:425002 if (!info->CanAccess(count)) {
[email protected]f39f4b3f2010-05-12 17:04:085003 SetGLError(GL_INVALID_OPERATION,
5004 "glDrawXXX: attempt to access out of range vertices");
5005 return false;
5006 }
5007 } else {
5008 // This attrib is not used in the current program.
[email protected]a0b78dc2011-11-11 10:43:105009 if (!info->buffer()) {
[email protected]f39f4b3f2010-05-12 17:04:085010 SetGLError(
5011 GL_INVALID_OPERATION,
5012 "glDrawXXX: attempt to render with no buffer attached to enabled "
5013 "attrib");
5014 return false;
5015 }
[email protected]1d32bc82010-01-13 22:06:465016 }
[email protected]07f54fcc2009-12-22 02:46:305017 }
[email protected]c6aef902012-02-14 03:31:425018
5019 if (primcount && !divisor0) {
5020 SetGLError(
5021 GL_INVALID_OPERATION,
5022 "glDrawXXX: attempt instanced render with all attributes having "
5023 "non-zero divisors");
5024 return false;
5025 }
5026
[email protected]3916c97e2010-02-25 03:20:505027 return true;
[email protected]b1122982010-05-17 23:04:245028}
5029
[email protected]c13e1da62011-09-09 21:48:305030bool GLES2DecoderImpl::SimulateAttrib0(
5031 GLuint max_vertex_accessed, bool* simulated) {
5032 DCHECK(simulated);
5033 *simulated = false;
5034
[email protected]876f6fee2010-08-02 23:10:325035 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
[email protected]c13e1da62011-09-09 21:48:305036 return true;
[email protected]876f6fee2010-08-02 23:10:325037
[email protected]b1122982010-05-17 23:04:245038 const VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445039 vertex_attrib_manager_->GetVertexAttribInfo(0);
[email protected]b1122982010-05-17 23:04:245040 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:495041 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
5042 if (info->enabled() && attrib_0_used) {
[email protected]c13e1da62011-09-09 21:48:305043 return true;
[email protected]b1122982010-05-17 23:04:245044 }
5045
[email protected]b1122982010-05-17 23:04:245046 // Make a buffer with a single repeated vec4 value enough to
5047 // simulate the constant value that is supposed to be here.
5048 // This is required to emulate GLES2 on GL.
[email protected]c13e1da62011-09-09 21:48:305049 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
5050
5051 GLuint num_vertices = max_vertex_accessed + 1;
5052 GLuint size_needed = 0;
5053
5054 if (num_vertices == 0 ||
5055 !SafeMultiply(num_vertices, static_cast<GLuint>(sizeof(Vec4)),
5056 &size_needed) ||
5057 size_needed > 0x7FFFFFFFU) {
5058 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
5059 return false;
5060 }
5061
5062 CopyRealGLErrorsToWrapper();
5063 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
5064
5065 if (static_cast<GLsizei>(size_needed) > attrib_0_size_) {
[email protected]fc753442011-02-04 19:49:495066 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305067 GLenum error = glGetError();
5068 if (error != GL_NO_ERROR) {
5069 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
5070 return false;
5071 }
[email protected]fc753442011-02-04 19:49:495072 attrib_0_buffer_matches_value_ = false;
5073 }
5074 if (attrib_0_used &&
5075 (!attrib_0_buffer_matches_value_ ||
5076 (info->value().v[0] != attrib_0_value_.v[0] ||
5077 info->value().v[1] != attrib_0_value_.v[1] ||
5078 info->value().v[2] != attrib_0_value_.v[2] ||
5079 info->value().v[3] != attrib_0_value_.v[3]))) {
5080 std::vector<Vec4> temp(num_vertices, info->value());
5081 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
5082 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:245083 attrib_0_value_ = info->value();
5084 attrib_0_size_ = size_needed;
5085 }
5086
5087 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5088
[email protected]c6aef902012-02-14 03:31:425089 if (info->divisor())
5090 glVertexAttribDivisorANGLE(0, 0);
5091
[email protected]c13e1da62011-09-09 21:48:305092 *simulated = true;
[email protected]b1122982010-05-17 23:04:245093 return true;
[email protected]b1122982010-05-17 23:04:245094}
5095
5096void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
5097 const VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445098 vertex_attrib_manager_->GetVertexAttribInfo(0);
[email protected]b1122982010-05-17 23:04:245099 const void* ptr = reinterpret_cast<const void*>(info->offset());
5100 BufferManager::BufferInfo* buffer_info = info->buffer();
5101 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
5102 glVertexAttribPointer(
5103 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
5104 ptr);
[email protected]c6aef902012-02-14 03:31:425105 if (info->divisor())
5106 glVertexAttribDivisorANGLE(0, info->divisor());
[email protected]b1122982010-05-17 23:04:245107 glBindBuffer(GL_ARRAY_BUFFER,
5108 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
5109}
[email protected]07f54fcc2009-12-22 02:46:305110
[email protected]8fbedc02010-11-18 18:43:405111bool GLES2DecoderImpl::SimulateFixedAttribs(
[email protected]c6aef902012-02-14 03:31:425112 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
[email protected]8fbedc02010-11-18 18:43:405113 DCHECK(simulated);
5114 *simulated = false;
5115 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
5116 return true;
5117
[email protected]3757a372012-01-19 05:20:445118 if (!vertex_attrib_manager_->HaveFixedAttribs()) {
[email protected]8fbedc02010-11-18 18:43:405119 return true;
5120 }
5121
5122 // NOTE: we could be smart and try to check if a buffer is used
5123 // twice in 2 different attribs, find the overlapping parts and therefore
5124 // duplicate the minimum amount of data but this whole code path is not meant
5125 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
5126 // tests so we just add to the buffer attrib used.
5127
[email protected]c13e1da62011-09-09 21:48:305128 GLuint elements_needed = 0;
[email protected]8fbedc02010-11-18 18:43:405129 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:445130 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]8fbedc02010-11-18 18:43:405131 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5132 infos.begin(); it != infos.end(); ++it) {
5133 const VertexAttribManager::VertexAttribInfo* info = *it;
5134 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5135 current_program_->GetAttribInfoByLocation(info->index());
[email protected]c6aef902012-02-14 03:31:425136 GLuint max_accessed = info->MaxVertexAccessed(primcount,
5137 max_vertex_accessed);
5138 GLuint num_vertices = max_accessed + 1;
5139 if (num_vertices == 0) {
5140 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
5141 return false;
5142 }
[email protected]8fbedc02010-11-18 18:43:405143 if (attrib_info &&
[email protected]c6aef902012-02-14 03:31:425144 info->CanAccess(max_accessed) &&
[email protected]8fbedc02010-11-18 18:43:405145 info->type() == GL_FIXED) {
[email protected]c13e1da62011-09-09 21:48:305146 GLuint elements_used = 0;
5147 if (!SafeMultiply(num_vertices,
5148 static_cast<GLuint>(info->size()), &elements_used) ||
[email protected]8fbedc02010-11-18 18:43:405149 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
5150 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5151 return false;
5152 }
5153 }
5154 }
5155
[email protected]c13e1da62011-09-09 21:48:305156 const GLuint kSizeOfFloat = sizeof(float); // NOLINT
5157 GLuint size_needed = 0;
5158 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed) ||
5159 size_needed > 0x7FFFFFFFU) {
[email protected]8fbedc02010-11-18 18:43:405160 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5161 return false;
5162 }
5163
[email protected]c13e1da62011-09-09 21:48:305164 CopyRealGLErrorsToWrapper();
[email protected]8fbedc02010-11-18 18:43:405165
5166 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
[email protected]c13e1da62011-09-09 21:48:305167 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
[email protected]8fbedc02010-11-18 18:43:405168 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305169 GLenum error = glGetError();
5170 if (error != GL_NO_ERROR) {
5171 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5172 return false;
5173 }
[email protected]8fbedc02010-11-18 18:43:405174 }
5175
5176 // Copy the elements and convert to float
5177 GLintptr offset = 0;
5178 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5179 infos.begin(); it != infos.end(); ++it) {
5180 const VertexAttribManager::VertexAttribInfo* info = *it;
5181 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5182 current_program_->GetAttribInfoByLocation(info->index());
[email protected]c6aef902012-02-14 03:31:425183 GLuint max_accessed = info->MaxVertexAccessed(primcount,
5184 max_vertex_accessed);
5185 GLuint num_vertices = max_accessed + 1;
5186 if (num_vertices == 0) {
5187 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
5188 return false;
5189 }
[email protected]8fbedc02010-11-18 18:43:405190 if (attrib_info &&
[email protected]c6aef902012-02-14 03:31:425191 info->CanAccess(max_accessed) &&
[email protected]8fbedc02010-11-18 18:43:405192 info->type() == GL_FIXED) {
5193 int num_elements = info->size() * kSizeOfFloat;
5194 int size = num_elements * num_vertices;
5195 scoped_array<float> data(new float[size]);
5196 const int32* src = reinterpret_cast<const int32 *>(
5197 info->buffer()->GetRange(info->offset(), size));
5198 const int32* end = src + num_elements;
5199 float* dst = data.get();
5200 while (src != end) {
5201 *dst++ = static_cast<float>(*src++) / 65536.0f;
5202 }
5203 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
5204 glVertexAttribPointer(
5205 info->index(), info->size(), GL_FLOAT, false, 0,
5206 reinterpret_cast<GLvoid*>(offset));
5207 offset += size;
5208 }
5209 }
5210 *simulated = true;
5211 return true;
5212}
5213
5214void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
5215 // There's no need to call glVertexAttribPointer because we shadow all the
5216 // settings and passing GL_FIXED to it will not work.
5217 glBindBuffer(GL_ARRAY_BUFFER,
5218 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
5219}
5220
[email protected]c6aef902012-02-14 03:31:425221error::Error GLES2DecoderImpl::DoDrawArrays(bool instanced,
5222 GLenum mode,
5223 GLint first,
5224 GLsizei count,
5225 GLsizei primcount) {
[email protected]38d139d2011-07-14 00:38:435226 if (!validators_->draw_mode.IsValid(mode)) {
5227 SetGLError(GL_INVALID_ENUM, "glDrawArrays: mode GL_INVALID_ENUM");
5228 return error::kNoError;
5229 }
5230 if (count < 0) {
5231 SetGLError(GL_INVALID_VALUE, "glDrawArrays: count < 0");
5232 return error::kNoError;
5233 }
[email protected]c6aef902012-02-14 03:31:425234 if (primcount < 0) {
5235 SetGLError(GL_INVALID_VALUE, "glDrawArrays: primcount < 0");
5236 return error::kNoError;
5237 }
[email protected]0d6bfdc2011-11-02 01:32:205238 if (!CheckBoundFramebuffersValid("glDrawArrays")) {
[email protected]38d139d2011-07-14 00:38:435239 return error::kNoError;
5240 }
5241 // We have to check this here because the prototype for glDrawArrays
5242 // is GLint not GLsizei.
5243 if (first < 0) {
5244 SetGLError(GL_INVALID_VALUE, "glDrawArrays: first < 0");
5245 return error::kNoError;
5246 }
5247
[email protected]c6aef902012-02-14 03:31:425248 if (count == 0 || (instanced && primcount == 0)) {
[email protected]38d139d2011-07-14 00:38:435249 return error::kNoError;
5250 }
5251
5252 GLuint max_vertex_accessed = first + count - 1;
[email protected]c6aef902012-02-14 03:31:425253 if (IsDrawValid(max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:205254 if (!ClearUnclearedTextures()) {
5255 SetGLError(GL_INVALID_VALUE, "glDrawArrays: out of memory");
5256 return error::kNoError;
5257 }
[email protected]c13e1da62011-09-09 21:48:305258 bool simulated_attrib_0 = false;
5259 if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
5260 return error::kNoError;
5261 }
[email protected]38d139d2011-07-14 00:38:435262 bool simulated_fixed_attribs = false;
[email protected]c6aef902012-02-14 03:31:425263 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs,
5264 primcount)) {
[email protected]38d139d2011-07-14 00:38:435265 bool textures_set = SetBlackTextureForNonRenderableTextures();
5266 ApplyDirtyState();
[email protected]c6aef902012-02-14 03:31:425267 if (!instanced) {
5268 glDrawArrays(mode, first, count);
5269 } else {
5270 glDrawArraysInstancedANGLE(mode, first, count, primcount);
5271 }
[email protected]22e3f552012-03-13 01:54:195272 ProcessPendingQueries();
[email protected]38d139d2011-07-14 00:38:435273 if (textures_set) {
5274 RestoreStateForNonRenderableTextures();
5275 }
5276 if (simulated_fixed_attribs) {
5277 RestoreStateForSimulatedFixedAttribs();
5278 }
5279 }
5280 if (simulated_attrib_0) {
5281 RestoreStateForSimulatedAttrib0();
5282 }
5283 if (WasContextLost()) {
5284 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawArrays.";
5285 return error::kLostContext;
5286 }
5287 }
5288 return error::kNoError;
5289}
5290
[email protected]c6aef902012-02-14 03:31:425291error::Error GLES2DecoderImpl::HandleDrawArrays(
5292 uint32 immediate_data_size, const gles2::DrawArrays& c) {
5293 return DoDrawArrays(false,
5294 static_cast<GLenum>(c.mode),
5295 static_cast<GLint>(c.first),
5296 static_cast<GLsizei>(c.count),
5297 0);
5298}
5299
5300error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
5301 uint32 immediate_data_size, const gles2::DrawArraysInstancedANGLE& c) {
5302 if (!feature_info_->feature_flags().angle_instanced_arrays) {
5303 SetGLError(GL_INVALID_OPERATION,
5304 "glDrawArraysInstancedANGLE: function not available");
5305 return error::kNoError;
5306 }
5307 return DoDrawArrays(true,
5308 static_cast<GLenum>(c.mode),
5309 static_cast<GLint>(c.first),
5310 static_cast<GLsizei>(c.count),
5311 static_cast<GLsizei>(c.primcount));
5312}
5313
5314error::Error GLES2DecoderImpl::DoDrawElements(bool instanced,
5315 GLenum mode,
5316 GLsizei count,
5317 GLenum type,
5318 int32 offset,
5319 GLsizei primcount) {
[email protected]a0b78dc2011-11-11 10:43:105320 if (!bound_element_array_buffer_) {
[email protected]8eee29c2010-04-29 03:38:295321 SetGLError(GL_INVALID_OPERATION,
5322 "glDrawElements: No element array buffer bound");
5323 return error::kNoError;
5324 }
5325
[email protected]8eee29c2010-04-29 03:38:295326 if (count < 0) {
5327 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
5328 return error::kNoError;
5329 }
5330 if (offset < 0) {
5331 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
5332 return error::kNoError;
5333 }
[email protected]9438b012010-06-15 22:55:055334 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:295335 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
5336 return error::kNoError;
5337 }
[email protected]9438b012010-06-15 22:55:055338 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295339 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
5340 return error::kNoError;
5341 }
[email protected]c6aef902012-02-14 03:31:425342 if (primcount < 0) {
5343 SetGLError(GL_INVALID_VALUE, "glDrawElements: primcount < 0");
5344 return error::kNoError;
5345 }
[email protected]8eee29c2010-04-29 03:38:295346
[email protected]0d6bfdc2011-11-02 01:32:205347 if (!CheckBoundFramebuffersValid("glDrawElements")) {
[email protected]3a03a8f2011-03-19 00:51:275348 return error::kNoError;
5349 }
5350
[email protected]c6aef902012-02-14 03:31:425351 if (count == 0 || (instanced && primcount == 0)) {
[email protected]6c788fb72010-08-26 02:16:315352 return error::kNoError;
5353 }
5354
[email protected]8eee29c2010-04-29 03:38:295355 GLuint max_vertex_accessed;
5356 if (!bound_element_array_buffer_->GetMaxValueForRange(
5357 offset, count, type, &max_vertex_accessed)) {
5358 SetGLError(GL_INVALID_OPERATION,
5359 "glDrawElements: range out of bounds for buffer");
5360 return error::kNoError;
5361 }
5362
[email protected]c6aef902012-02-14 03:31:425363 if (IsDrawValid(max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:205364 if (!ClearUnclearedTextures()) {
5365 SetGLError(GL_INVALID_VALUE, "glDrawElements: out of memory");
5366 return error::kNoError;
5367 }
[email protected]c13e1da62011-09-09 21:48:305368 bool simulated_attrib_0 = false;
5369 if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
5370 return error::kNoError;
5371 }
[email protected]8fbedc02010-11-18 18:43:405372 bool simulated_fixed_attribs = false;
[email protected]c6aef902012-02-14 03:31:425373 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs,
5374 primcount)) {
[email protected]8fbedc02010-11-18 18:43:405375 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:465376 ApplyDirtyState();
[email protected]8fbedc02010-11-18 18:43:405377 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
[email protected]c6aef902012-02-14 03:31:425378 if (!instanced) {
5379 glDrawElements(mode, count, type, indices);
5380 } else {
5381 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
5382 }
[email protected]22e3f552012-03-13 01:54:195383 ProcessPendingQueries();
[email protected]8fbedc02010-11-18 18:43:405384 if (textures_set) {
5385 RestoreStateForNonRenderableTextures();
5386 }
5387 if (simulated_fixed_attribs) {
5388 RestoreStateForSimulatedFixedAttribs();
5389 }
[email protected]ba3176a2009-12-16 18:19:465390 }
[email protected]b1122982010-05-17 23:04:245391 if (simulated_attrib_0) {
5392 RestoreStateForSimulatedAttrib0();
5393 }
[email protected]38d139d2011-07-14 00:38:435394 if (WasContextLost()) {
5395 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawElements.";
5396 return error::kLostContext;
5397 }
[email protected]96449d2c2009-11-25 00:01:325398 }
[email protected]f7a64ee2010-02-01 22:24:145399 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325400}
5401
[email protected]c6aef902012-02-14 03:31:425402error::Error GLES2DecoderImpl::HandleDrawElements(
5403 uint32 immediate_data_size, const gles2::DrawElements& c) {
5404 return DoDrawElements(false,
5405 static_cast<GLenum>(c.mode),
5406 static_cast<GLsizei>(c.count),
5407 static_cast<GLenum>(c.type),
5408 static_cast<int32>(c.index_offset),
5409 0);
5410}
5411
5412error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
5413 uint32 immediate_data_size, const gles2::DrawElementsInstancedANGLE& c) {
5414 if (!feature_info_->feature_flags().angle_instanced_arrays) {
5415 SetGLError(GL_INVALID_OPERATION,
5416 "glDrawElementsInstancedANGLE: function not available");
5417 return error::kNoError;
5418 }
5419 return DoDrawElements(true,
5420 static_cast<GLenum>(c.mode),
5421 static_cast<GLsizei>(c.count),
5422 static_cast<GLenum>(c.type),
5423 static_cast<int32>(c.index_offset),
5424 static_cast<GLsizei>(c.primcount));
5425}
5426
[email protected]269200b12010-11-18 22:53:065427GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:235428 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
5429 GLuint max_vertex_accessed = 0;
5430 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:295431 if (!info) {
[email protected]ae51d192010-04-27 00:48:035432 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:295433 SetGLError(GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:065434 "GetMaxValueInBufferCHROMIUM: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:235435 } else {
5436 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:035437 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:065438 SetGLError(
5439 GL_INVALID_OPERATION,
5440 "GetMaxValueInBufferCHROMIUM: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:235441 }
5442 }
5443 return max_vertex_accessed;
5444}
5445
[email protected]96449d2c2009-11-25 00:01:325446// Calls glShaderSource for the various versions of the ShaderSource command.
5447// Assumes that data / data_size points to a piece of memory that is in range
5448// of whatever context it came from (shared memory, immediate memory, bucket
5449// memory.)
[email protected]45bf5152010-02-12 00:11:315450error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035451 GLuint client_id, const char* data, uint32 data_size) {
[email protected]258a3313f2011-10-18 20:13:575452 std::string str(data, data + data_size);
[email protected]6b8cf1a2010-05-06 16:13:585453 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5454 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:315455 if (!info) {
[email protected]45bf5152010-02-12 00:11:315456 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325457 }
[email protected]45bf5152010-02-12 00:11:315458 // Note: We don't actually call glShaderSource here. We wait until
5459 // the call to glCompileShader.
[email protected]258a3313f2011-10-18 20:13:575460 info->UpdateSource(str.c_str());
[email protected]f7a64ee2010-02-01 22:24:145461 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325462}
5463
[email protected]f7a64ee2010-02-01 22:24:145464error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:195465 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:325466 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315467 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:325468 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:465469 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145470 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325471 }
[email protected]ae51d192010-04-27 00:48:035472 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:325473}
5474
[email protected]f7a64ee2010-02-01 22:24:145475error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:195476 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:325477 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315478 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:305479 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465480 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145481 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325482 }
[email protected]ae51d192010-04-27 00:48:035483 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:315484}
5485
[email protected]558847a2010-03-24 07:02:545486error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
5487 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:545488 Bucket* bucket = GetBucket(c.data_bucket_id);
5489 if (!bucket || bucket->size() == 0) {
5490 return error::kInvalidArguments;
5491 }
5492 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035493 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:545494 bucket->size() - 1);
5495}
5496
[email protected]ae51d192010-04-27 00:48:035497void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]0c8fabf2011-06-14 19:35:225498 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]6b8cf1a2010-05-06 16:13:585499 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5500 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:315501 if (!info) {
[email protected]45bf5152010-02-12 00:11:315502 return;
5503 }
[email protected]de17df392010-04-23 21:09:415504 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
5505 // glShaderSource and then glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:525506 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:345507 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:185508 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:345509 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:455510 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:235511
[email protected]a550584e2010-09-17 18:01:455512 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:345513 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:185514 return;
5515 }
[email protected]a550584e2010-09-17 18:01:455516 shader_src = translator->translated_shader();
[email protected]93297702011-11-05 05:09:465517 if (!feature_info_->feature_flags().angle_translated_shader_source)
[email protected]d6a53e42011-10-05 00:09:365518 info->UpdateTranslatedSource(shader_src);
[email protected]de17df392010-04-23 21:09:415519 }
[email protected]de17df392010-04-23 21:09:415520
[email protected]ae51d192010-04-27 00:48:035521 glShaderSource(info->service_id(), 1, &shader_src, NULL);
5522 glCompileShader(info->service_id());
[email protected]93297702011-11-05 05:09:465523 if (feature_info_->feature_flags().angle_translated_shader_source) {
[email protected]d6a53e42011-10-05 00:09:365524 GLint max_len = 0;
5525 glGetShaderiv(info->service_id(),
5526 GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
5527 &max_len);
5528 scoped_array<char> temp(new char[max_len]);
5529 GLint len = 0;
5530 glGetTranslatedShaderSourceANGLE(
5531 info->service_id(), max_len, &len, temp.get());
5532 DCHECK(max_len == 0 || len < max_len);
5533 DCHECK(len == 0 || temp[len] == '\0');
5534 info->UpdateTranslatedSource(temp.get());
5535 }
5536
[email protected]e5186162010-06-14 18:54:415537 GLint status = GL_FALSE;
5538 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
5539 if (status) {
[email protected]f57bb282010-11-12 00:51:345540 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:415541 } else {
[email protected]d9977d42010-09-01 20:27:025542 // We cannot reach here if we are using the shader translator.
5543 // All invalid shaders must be rejected by the translator.
5544 // All translated shaders must compile.
5545 LOG_IF(ERROR, use_shader_translator_)
5546 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:335547 GLint max_len = 0;
5548 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
5549 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:415550 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:335551 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
5552 DCHECK(max_len == 0 || len < max_len);
[email protected]d6a53e42011-10-05 00:09:365553 DCHECK(len == 0 || temp[len] == '\0');
[email protected]df6cf1ad2011-01-29 01:20:525554 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
[email protected]e5186162010-06-14 18:54:415555 }
[email protected]45bf5152010-02-12 00:11:315556};
5557
[email protected]ddd968b82010-03-02 00:44:295558void GLES2DecoderImpl::DoGetShaderiv(
5559 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:585560 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5561 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:295562 if (!info) {
[email protected]ddd968b82010-03-02 00:44:295563 return;
5564 }
[email protected]8f1ccdac2010-05-19 21:01:485565 switch (pname) {
5566 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525567 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:485568 return;
5569 case GL_COMPILE_STATUS:
[email protected]062c38b2012-01-18 03:25:105570 *params = compile_shader_always_succeeds_ ? true : info->IsValid();
[email protected]e5186162010-06-14 18:54:415571 return;
[email protected]8f1ccdac2010-05-19 21:01:485572 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525573 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:415574 return;
[email protected]d6a53e42011-10-05 00:09:365575 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5576 *params = info->translated_source() ?
5577 info->translated_source()->size() + 1 : 0;
5578 return;
[email protected]8f1ccdac2010-05-19 21:01:485579 default:
5580 break;
[email protected]ddd968b82010-03-02 00:44:295581 }
[email protected]8f1ccdac2010-05-19 21:01:485582 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:295583}
5584
[email protected]ae51d192010-04-27 00:48:035585error::Error GLES2DecoderImpl::HandleGetShaderSource(
5586 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
5587 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:035588 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5589 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:585590 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5591 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:525592 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:295593 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:295594 return error::kNoError;
5595 }
[email protected]df6cf1ad2011-01-29 01:20:525596 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:035597 return error::kNoError;
5598}
5599
[email protected]d6a53e42011-10-05 00:09:365600error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
5601 uint32 immediate_data_size,
5602 const gles2::GetTranslatedShaderSourceANGLE& c) {
5603 GLuint shader = c.shader;
5604
5605 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5606 Bucket* bucket = CreateBucket(bucket_id);
5607 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5608 shader, "glTranslatedGetShaderSourceANGLE");
5609 if (!info) {
5610 bucket->SetSize(0);
5611 return error::kNoError;
5612 }
5613
5614 bucket->SetFromString(info->translated_source() ?
5615 info->translated_source()->c_str() : NULL);
5616 return error::kNoError;
5617}
5618
[email protected]ae51d192010-04-27 00:48:035619error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
5620 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
5621 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:585622 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5623 Bucket* bucket = CreateBucket(bucket_id);
5624 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5625 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525626 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465627 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035628 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:315629 }
[email protected]df6cf1ad2011-01-29 01:20:525630 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035631 return error::kNoError;
5632}
5633
5634error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
5635 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
5636 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:585637 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5638 Bucket* bucket = CreateBucket(bucket_id);
5639 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5640 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525641 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465642 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035643 return error::kNoError;
5644 }
[email protected]df6cf1ad2011-01-29 01:20:525645 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035646 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325647}
5648
[email protected]1958e0e2010-04-22 05:17:155649bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105650 const BufferManager::BufferInfo* buffer = GetBufferInfo(client_id);
5651 return buffer && buffer->IsValid() && !buffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155652}
5653
5654bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105655 const FramebufferManager::FramebufferInfo* framebuffer =
[email protected]06c8b082011-01-05 18:00:365656 GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105657 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155658}
5659
5660bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365661 // IsProgram is true for programs as soon as they are created, until they are
5662 // deleted and no longer in use.
[email protected]a0b78dc2011-11-11 10:43:105663 const ProgramManager::ProgramInfo* program = GetProgramInfo(client_id);
5664 return program != NULL && !program->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155665}
5666
5667bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105668 const RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]06c8b082011-01-05 18:00:365669 GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105670 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155671}
5672
5673bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365674 // IsShader is true for shaders as soon as they are created, until they
5675 // are deleted and not attached to any programs.
[email protected]a0b78dc2011-11-11 10:43:105676 const ShaderManager::ShaderInfo* shader = GetShaderInfo(client_id);
5677 return shader != NULL && !shader->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155678}
5679
5680bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105681 const TextureManager::TextureInfo* texture = GetTextureInfo(client_id);
5682 return texture && texture->IsValid() && !texture->IsDeleted();
[email protected]ae51d192010-04-27 00:48:035683}
5684
5685void GLES2DecoderImpl::DoAttachShader(
5686 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585687 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5688 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035689 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035690 return;
[email protected]1958e0e2010-04-22 05:17:155691 }
[email protected]6b8cf1a2010-05-06 16:13:585692 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5693 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035694 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035695 return;
5696 }
[email protected]ca488e12010-12-13 20:06:145697 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:315698 SetGLError(GL_INVALID_OPERATION,
5699 "glAttachShader: can not attach more than"
5700 " one shader of the same type.");
5701 return;
5702 }
[email protected]ae51d192010-04-27 00:48:035703 glAttachShader(program_info->service_id(), shader_info->service_id());
5704}
5705
5706void GLES2DecoderImpl::DoDetachShader(
5707 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585708 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5709 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035710 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035711 return;
5712 }
[email protected]6b8cf1a2010-05-06 16:13:585713 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5714 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035715 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035716 return;
5717 }
[email protected]9a0ccd42011-03-16 23:58:225718 if (!program_info->DetachShader(shader_manager(), shader_info)) {
5719 SetGLError(GL_INVALID_OPERATION,
5720 "glDetachShader: shader not attached to program");
5721 return;
5722 }
[email protected]ae51d192010-04-27 00:48:035723 glDetachShader(program_info->service_id(), shader_info->service_id());
5724}
5725
5726void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585727 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5728 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:035729 if (!info) {
[email protected]ae51d192010-04-27 00:48:035730 return;
5731 }
[email protected]d685a682011-04-29 16:19:575732 info->Validate();
[email protected]1958e0e2010-04-22 05:17:155733}
5734
[email protected]b1122982010-05-17 23:04:245735void GLES2DecoderImpl::DoGetVertexAttribfv(
5736 GLuint index, GLenum pname, GLfloat* params) {
5737 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445738 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245739 if (!info) {
5740 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
5741 return;
5742 }
5743 switch (pname) {
5744 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5745 BufferManager::BufferInfo* buffer = info->buffer();
5746 if (buffer && !buffer->IsDeleted()) {
5747 GLuint client_id;
5748 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5749 *params = static_cast<GLfloat>(client_id);
5750 }
5751 break;
5752 }
5753 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5754 *params = static_cast<GLfloat>(info->enabled());
5755 break;
5756 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5757 *params = static_cast<GLfloat>(info->size());
5758 break;
5759 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5760 *params = static_cast<GLfloat>(info->gl_stride());
5761 break;
5762 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5763 *params = static_cast<GLfloat>(info->type());
5764 break;
5765 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5766 *params = static_cast<GLfloat>(info->normalized());
5767 break;
5768 case GL_CURRENT_VERTEX_ATTRIB:
5769 params[0] = info->value().v[0];
5770 params[1] = info->value().v[1];
5771 params[2] = info->value().v[2];
5772 params[3] = info->value().v[3];
5773 break;
[email protected]c6aef902012-02-14 03:31:425774 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
5775 *params = static_cast<GLfloat>(info->divisor());
5776 break;
[email protected]b1122982010-05-17 23:04:245777 default:
5778 NOTREACHED();
5779 break;
5780 }
5781}
5782
5783void GLES2DecoderImpl::DoGetVertexAttribiv(
5784 GLuint index, GLenum pname, GLint* params) {
5785 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445786 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245787 if (!info) {
5788 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
5789 return;
5790 }
5791 switch (pname) {
5792 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5793 BufferManager::BufferInfo* buffer = info->buffer();
5794 if (buffer && !buffer->IsDeleted()) {
5795 GLuint client_id;
5796 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5797 *params = client_id;
5798 }
5799 break;
5800 }
5801 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5802 *params = info->enabled();
5803 break;
5804 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5805 *params = info->size();
5806 break;
5807 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5808 *params = info->gl_stride();
5809 break;
5810 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5811 *params = info->type();
5812 break;
5813 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5814 *params = static_cast<GLint>(info->normalized());
5815 break;
[email protected]c6aef902012-02-14 03:31:425816 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
5817 *params = info->divisor();
5818 break;
[email protected]b1122982010-05-17 23:04:245819 case GL_CURRENT_VERTEX_ATTRIB:
5820 params[0] = static_cast<GLint>(info->value().v[0]);
5821 params[1] = static_cast<GLint>(info->value().v[1]);
5822 params[2] = static_cast<GLint>(info->value().v[2]);
5823 params[3] = static_cast<GLint>(info->value().v[3]);
5824 break;
5825 default:
5826 NOTREACHED();
5827 break;
5828 }
5829}
5830
5831void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
5832 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445833 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245834 if (!info) {
5835 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
5836 return;
5837 }
5838 VertexAttribManager::VertexAttribInfo::Vec4 value;
5839 value.v[0] = v0;
5840 value.v[1] = 0.0f;
5841 value.v[2] = 0.0f;
5842 value.v[3] = 1.0f;
5843 info->set_value(value);
5844 glVertexAttrib1f(index, v0);
5845}
5846
5847void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
5848 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445849 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245850 if (!info) {
5851 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
5852 return;
5853 }
5854 VertexAttribManager::VertexAttribInfo::Vec4 value;
5855 value.v[0] = v0;
5856 value.v[1] = v1;
5857 value.v[2] = 0.0f;
5858 value.v[3] = 1.0f;
5859 info->set_value(value);
5860 glVertexAttrib2f(index, v0, v1);
5861}
5862
5863void GLES2DecoderImpl::DoVertexAttrib3f(
5864 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
5865 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445866 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245867 if (!info) {
5868 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
5869 return;
5870 }
5871 VertexAttribManager::VertexAttribInfo::Vec4 value;
5872 value.v[0] = v0;
5873 value.v[1] = v1;
5874 value.v[2] = v2;
5875 value.v[3] = 1.0f;
5876 info->set_value(value);
5877 glVertexAttrib3f(index, v0, v1, v2);
5878}
5879
5880void GLES2DecoderImpl::DoVertexAttrib4f(
5881 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
5882 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445883 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245884 if (!info) {
5885 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
5886 return;
5887 }
5888 VertexAttribManager::VertexAttribInfo::Vec4 value;
5889 value.v[0] = v0;
5890 value.v[1] = v1;
5891 value.v[2] = v2;
5892 value.v[3] = v3;
5893 info->set_value(value);
5894 glVertexAttrib4f(index, v0, v1, v2, v3);
5895}
5896
5897void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
5898 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445899 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245900 if (!info) {
5901 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
5902 return;
5903 }
5904 VertexAttribManager::VertexAttribInfo::Vec4 value;
5905 value.v[0] = v[0];
5906 value.v[1] = 0.0f;
5907 value.v[2] = 0.0f;
5908 value.v[3] = 1.0f;
5909 info->set_value(value);
5910 glVertexAttrib1fv(index, v);
5911}
5912
5913void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
5914 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445915 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245916 if (!info) {
5917 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
5918 return;
5919 }
5920 VertexAttribManager::VertexAttribInfo::Vec4 value;
5921 value.v[0] = v[0];
5922 value.v[1] = v[1];
5923 value.v[2] = 0.0f;
5924 value.v[3] = 1.0f;
5925 info->set_value(value);
5926 glVertexAttrib2fv(index, v);
5927}
5928
5929void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
5930 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445931 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245932 if (!info) {
5933 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
5934 return;
5935 }
5936 VertexAttribManager::VertexAttribInfo::Vec4 value;
5937 value.v[0] = v[0];
5938 value.v[1] = v[1];
5939 value.v[2] = v[2];
5940 value.v[3] = 1.0f;
5941 info->set_value(value);
5942 glVertexAttrib3fv(index, v);
5943}
5944
5945void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
5946 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445947 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245948 if (!info) {
5949 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
5950 return;
5951 }
5952 VertexAttribManager::VertexAttribInfo::Vec4 value;
5953 value.v[0] = v[0];
5954 value.v[1] = v[1];
5955 value.v[2] = v[2];
5956 value.v[3] = v[3];
5957 info->set_value(value);
5958 glVertexAttrib4fv(index, v);
5959}
5960
[email protected]f7a64ee2010-02-01 22:24:145961error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:195962 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:295963 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
5964 SetGLError(GL_INVALID_VALUE,
5965 "glVertexAttribPointer: no array buffer bound");
5966 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325967 }
[email protected]8eee29c2010-04-29 03:38:295968
5969 GLuint indx = c.indx;
5970 GLint size = c.size;
5971 GLenum type = c.type;
5972 GLboolean normalized = c.normalized;
5973 GLsizei stride = c.stride;
5974 GLsizei offset = c.offset;
5975 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:055976 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295977 SetGLError(GL_INVALID_ENUM,
5978 "glVertexAttribPointer: type GL_INVALID_ENUM");
5979 return error::kNoError;
5980 }
[email protected]9438b012010-06-15 22:55:055981 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:315982 SetGLError(GL_INVALID_VALUE,
[email protected]8eee29c2010-04-29 03:38:295983 "glVertexAttribPointer: size GL_INVALID_VALUE");
5984 return error::kNoError;
5985 }
5986 if (indx >= group_->max_vertex_attribs()) {
5987 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
5988 return error::kNoError;
5989 }
5990 if (stride < 0) {
5991 SetGLError(GL_INVALID_VALUE,
5992 "glVertexAttribPointer: stride < 0");
5993 return error::kNoError;
5994 }
5995 if (stride > 255) {
5996 SetGLError(GL_INVALID_VALUE,
5997 "glVertexAttribPointer: stride > 255");
5998 return error::kNoError;
5999 }
6000 if (offset < 0) {
6001 SetGLError(GL_INVALID_VALUE,
6002 "glVertexAttribPointer: offset < 0");
6003 return error::kNoError;
6004 }
6005 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:316006 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:296007 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:316008 SetGLError(GL_INVALID_OPERATION,
6009 "glVertexAttribPointer: offset not valid for type");
6010 return error::kNoError;
6011 }
6012 if (stride % component_size > 0) {
6013 SetGLError(GL_INVALID_OPERATION,
[email protected]8eee29c2010-04-29 03:38:296014 "glVertexAttribPointer: stride not valid for type");
6015 return error::kNoError;
6016 }
[email protected]3757a372012-01-19 05:20:446017 vertex_attrib_manager_->SetAttribInfo(
[email protected]8fbedc02010-11-18 18:43:406018 indx,
[email protected]8eee29c2010-04-29 03:38:296019 bound_array_buffer_,
6020 size,
6021 type,
[email protected]b1122982010-05-17 23:04:246022 normalized,
6023 stride,
6024 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:296025 offset);
[email protected]8fbedc02010-11-18 18:43:406026 if (type != GL_FIXED) {
6027 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
6028 }
[email protected]f7a64ee2010-02-01 22:24:146029 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326030}
6031
[email protected]c6aef902012-02-14 03:31:426032error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
6033 uint32 immediate_data_size, const gles2::VertexAttribDivisorANGLE& c) {
6034 if (!feature_info_->feature_flags().angle_instanced_arrays) {
6035 SetGLError(GL_INVALID_OPERATION,
6036 "glVertexAttribDivisorANGLE: function not available");
6037 }
6038 GLuint index = c.index;
6039 GLuint divisor = c.divisor;
6040 if (index >= group_->max_vertex_attribs()) {
6041 SetGLError(GL_INVALID_VALUE,
6042 "glVertexAttribDivisorANGLE: index out of range");
6043 return error::kNoError;
6044 }
6045
6046 vertex_attrib_manager_->SetDivisor(
6047 index,
6048 divisor);
6049 glVertexAttribDivisorANGLE(index, divisor);
6050 return error::kNoError;
6051}
6052
[email protected]f7a64ee2010-02-01 22:24:146053error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:196054 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:316055 GLint x = c.x;
6056 GLint y = c.y;
6057 GLsizei width = c.width;
6058 GLsizei height = c.height;
6059 GLenum format = c.format;
6060 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:566061 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:296062 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:566063 return error::kNoError;
6064 }
[email protected]a51788e2010-02-24 21:54:256065 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:186066 uint32 pixels_size;
6067 if (!GLES2Util::ComputeImageDataSize(
6068 width, height, format, type, pack_alignment_, &pixels_size)) {
6069 return error::kOutOfBounds;
6070 }
[email protected]612d2f82009-12-08 20:49:316071 void* pixels = GetSharedMemoryAs<void*>(
6072 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:256073 Result* result = GetSharedMemoryAs<Result*>(
6074 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6075 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:146076 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466077 }
[email protected]a51788e2010-02-24 21:54:256078
[email protected]9438b012010-06-15 22:55:056079 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:296080 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
6081 return error::kNoError;
6082 }
[email protected]9438b012010-06-15 22:55:056083 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:296084 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:126085 return error::kNoError;
6086 }
[email protected]57f223832010-03-19 01:57:566087 if (width == 0 || height == 0) {
6088 return error::kNoError;
6089 }
6090
[email protected]57f223832010-03-19 01:57:566091 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:306092 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:566093
6094 GLint max_x;
6095 GLint max_y;
6096 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:296097 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:146098 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:316099 }
[email protected]57f223832010-03-19 01:57:566100
[email protected]0d6bfdc2011-11-02 01:32:206101 if (!CheckBoundFramebuffersValid("glReadPixels")) {
6102 return error::kNoError;
6103 }
6104
[email protected]a0b78dc2011-11-11 10:43:106105 CopyRealGLErrorsToWrapper();
6106
6107 ScopedResolvedFrameBufferBinder binder(this, false, true);
6108
[email protected]d37231fa2010-04-09 21:16:026109 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:566110 // The user requested an out of range area. Get the results 1 line
6111 // at a time.
6112 uint32 temp_size;
6113 if (!GLES2Util::ComputeImageDataSize(
6114 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:296115 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:566116 return error::kNoError;
6117 }
6118 GLsizei unpadded_row_size = temp_size;
6119 if (!GLES2Util::ComputeImageDataSize(
6120 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:296121 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:566122 return error::kNoError;
6123 }
6124 GLsizei padded_row_size = temp_size - unpadded_row_size;
6125 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:296126 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:566127 return error::kNoError;
6128 }
6129
6130 GLint dest_x_offset = std::max(-x, 0);
6131 uint32 dest_row_offset;
6132 if (!GLES2Util::ComputeImageDataSize(
6133 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:296134 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:566135 return error::kNoError;
6136 }
6137
6138 // Copy each row into the larger dest rect.
6139 int8* dst = static_cast<int8*>(pixels);
6140 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:026141 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:566142 GLint read_width = read_end_x - read_x;
6143 for (GLint yy = 0; yy < height; ++yy) {
6144 GLint ry = y + yy;
6145
6146 // Clear the row.
6147 memset(dst, 0, unpadded_row_size);
6148
6149 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:026150 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:566151 glReadPixels(
6152 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
6153 }
6154 dst += padded_row_size;
6155 }
6156 } else {
6157 glReadPixels(x, y, width, height, format, type, pixels);
6158 }
[email protected]1002c2d2011-06-28 22:39:046159 GLenum error = PeekGLError();
[email protected]a51788e2010-02-24 21:54:256160 if (error == GL_NO_ERROR) {
6161 *result = true;
[email protected]4848b9f82011-03-10 18:37:566162
6163 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6164 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6165 if ((channels_exist & 0x0008) == 0) {
6166 // Set the alpha to 255 because some drivers are buggy in this regard.
6167 uint32 temp_size;
6168 if (!GLES2Util::ComputeImageDataSize(
6169 width, 1, format, type, pack_alignment_, &temp_size)) {
6170 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
6171 return error::kNoError;
6172 }
6173 GLsizei unpadded_row_size = temp_size;
6174 if (!GLES2Util::ComputeImageDataSize(
6175 width, 2, format, type, pack_alignment_, &temp_size)) {
6176 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
6177 return error::kNoError;
6178 }
6179 GLsizei padded_row_size = temp_size - unpadded_row_size;
6180 if (padded_row_size < 0 || unpadded_row_size < 0) {
6181 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
6182 return error::kNoError;
6183 }
6184 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
6185 // of this implementation.
6186 if (type != GL_UNSIGNED_BYTE) {
6187 SetGLError(GL_INVALID_OPERATION, "unsupported readPixel format");
6188 return error::kNoError;
6189 }
6190 switch (format) {
6191 case GL_RGBA:
[email protected]297ca1c2011-06-20 23:08:466192 case GL_BGRA_EXT:
[email protected]4848b9f82011-03-10 18:37:566193 case GL_ALPHA: {
6194 int offset = (format == GL_ALPHA) ? 0 : 3;
6195 int step = (format == GL_ALPHA) ? 1 : 4;
6196 uint8* dst = static_cast<uint8*>(pixels) + offset;
6197 for (GLint yy = 0; yy < height; ++yy) {
6198 uint8* end = dst + unpadded_row_size;
6199 for (uint8* d = dst; d < end; d += step) {
6200 *d = 255;
6201 }
6202 dst += padded_row_size;
6203 }
6204 break;
6205 }
6206 default:
6207 break;
6208 }
6209 }
[email protected]a51788e2010-02-24 21:54:256210 }
[email protected]4848b9f82011-03-10 18:37:566211
[email protected]f7a64ee2010-02-01 22:24:146212 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326213}
6214
[email protected]f7a64ee2010-02-01 22:24:146215error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:196216 uint32 immediate_data_size, const gles2::PixelStorei& c) {
6217 GLenum pname = c.pname;
6218 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:056219 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:296220 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:126221 return error::kNoError;
6222 }
[email protected]222471d2011-11-30 18:06:396223 switch (pname) {
6224 case GL_PACK_ALIGNMENT:
6225 case GL_UNPACK_ALIGNMENT:
6226 if (!validators_->pixel_store_alignment.IsValid(param)) {
6227 SetGLError(GL_INVALID_VALUE,
6228 "glPixelSTore: param GL_INVALID_VALUE");
6229 return error::kNoError;
6230 }
6231 default:
6232 break;
[email protected]b9849abf2009-11-25 19:13:196233 }
6234 glPixelStorei(pname, param);
6235 switch (pname) {
6236 case GL_PACK_ALIGNMENT:
6237 pack_alignment_ = param;
6238 break;
[email protected]222471d2011-11-30 18:06:396239 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
6240 break;
[email protected]b9849abf2009-11-25 19:13:196241 case GL_UNPACK_ALIGNMENT:
6242 unpack_alignment_ = param;
6243 break;
6244 default:
6245 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:376246 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:196247 break;
6248 }
[email protected]f7a64ee2010-02-01 22:24:146249 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196250}
6251
[email protected]1c75a3702011-11-11 14:15:286252error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
6253 uint32 immediate_data_size, const gles2::PostSubBufferCHROMIUM& c) {
6254 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
[email protected]aa258822011-11-22 13:52:256255 if (!context_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
[email protected]1c75a3702011-11-11 14:15:286256 SetGLError(GL_INVALID_OPERATION,
6257 "glPostSubBufferCHROMIUM: command not supported by surface");
6258 return error::kNoError;
6259 }
6260 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height))
6261 return error::kNoError;
6262 else
6263 return error::kLostContext;
6264}
6265
[email protected]558847a2010-03-24 07:02:546266error::Error GLES2DecoderImpl::GetAttribLocationHelper(
6267 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6268 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576269 if (!StringIsValidForGLES(name_str.c_str())) {
6270 SetGLError(GL_INVALID_VALUE, "glGetAttribLocation: Invalid character");
6271 return error::kNoError;
6272 }
[email protected]6b8cf1a2010-05-06 16:13:586273 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6274 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:036275 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146276 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196277 }
[email protected]ae51d192010-04-27 00:48:036278 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:296279 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:256280 return error::kNoError;
6281 }
[email protected]b9849abf2009-11-25 19:13:196282 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546283 location_shm_id, location_shm_offset, sizeof(GLint));
6284 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146285 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196286 }
[email protected]558847a2010-03-24 07:02:546287 // Require the client to init this incase the context is lost and we are no
6288 // longer executing commands.
6289 if (*location != -1) {
6290 return error::kGenericError;
6291 }
[email protected]0bfd9882010-02-05 23:02:256292 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:146293 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196294}
6295
[email protected]558847a2010-03-24 07:02:546296error::Error GLES2DecoderImpl::HandleGetAttribLocation(
6297 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
6298 uint32 name_size = c.data_size;
6299 const char* name = GetSharedMemoryAs<const char*>(
6300 c.name_shm_id, c.name_shm_offset, name_size);
6301 if (!name) {
6302 return error::kOutOfBounds;
6303 }
6304 String name_str(name, name_size);
6305 return GetAttribLocationHelper(
6306 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6307}
6308
[email protected]f7a64ee2010-02-01 22:24:146309error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196310 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:546311 uint32 name_size = c.data_size;
6312 const char* name = GetImmediateDataAs<const char*>(
6313 c, name_size, immediate_data_size);
6314 if (!name) {
6315 return error::kOutOfBounds;
6316 }
6317 String name_str(name, name_size);
6318 return GetAttribLocationHelper(
6319 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6320}
6321
6322error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
6323 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
6324 Bucket* bucket = GetBucket(c.name_bucket_id);
6325 if (!bucket) {
6326 return error::kInvalidArguments;
6327 }
6328 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186329 if (!bucket->GetAsString(&name_str)) {
6330 return error::kInvalidArguments;
6331 }
[email protected]558847a2010-03-24 07:02:546332 return GetAttribLocationHelper(
6333 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6334}
6335
6336error::Error GLES2DecoderImpl::GetUniformLocationHelper(
6337 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6338 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576339 if (!StringIsValidForGLES(name_str.c_str())) {
6340 SetGLError(GL_INVALID_VALUE, "glGetUniformLocation: Invalid character");
6341 return error::kNoError;
6342 }
[email protected]6b8cf1a2010-05-06 16:13:586343 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6344 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:036345 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146346 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196347 }
[email protected]ae51d192010-04-27 00:48:036348 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:296349 SetGLError(GL_INVALID_OPERATION,
6350 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:256351 return error::kNoError;
6352 }
[email protected]b9849abf2009-11-25 19:13:196353 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546354 location_shm_id, location_shm_offset, sizeof(GLint));
6355 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146356 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196357 }
[email protected]558847a2010-03-24 07:02:546358 // Require the client to init this incase the context is lost an we are no
6359 // longer executing commands.
6360 if (*location != -1) {
6361 return error::kGenericError;
6362 }
[email protected]5d4c6b22012-02-07 08:22:286363 *location = program_manager()->SwizzleLocation(
[email protected]1b0a6752012-02-22 03:44:126364 info->GetUniformFakeLocation(name_str));
[email protected]f7a64ee2010-02-01 22:24:146365 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196366}
6367
[email protected]f7a64ee2010-02-01 22:24:146368error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:196369 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:196370 uint32 name_size = c.data_size;
6371 const char* name = GetSharedMemoryAs<const char*>(
6372 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:546373 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146374 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196375 }
6376 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546377 return GetUniformLocationHelper(
6378 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196379}
6380
[email protected]f7a64ee2010-02-01 22:24:146381error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196382 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:196383 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:306384 const char* name = GetImmediateDataAs<const char*>(
6385 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:546386 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146387 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196388 }
6389 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546390 return GetUniformLocationHelper(
6391 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6392}
6393
6394error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
6395 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
6396 Bucket* bucket = GetBucket(c.name_bucket_id);
6397 if (!bucket) {
6398 return error::kInvalidArguments;
6399 }
6400 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186401 if (!bucket->GetAsString(&name_str)) {
6402 return error::kInvalidArguments;
6403 }
[email protected]558847a2010-03-24 07:02:546404 return GetUniformLocationHelper(
6405 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196406}
6407
[email protected]ddd968b82010-03-02 00:44:296408error::Error GLES2DecoderImpl::HandleGetString(
6409 uint32 immediate_data_size, const gles2::GetString& c) {
6410 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:056411 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:296412 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:296413 return error::kNoError;
6414 }
[email protected]1958e0e2010-04-22 05:17:156415 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
6416 const char* str = NULL;
[email protected]f0d74742011-10-03 16:31:046417 std::string extensions;
[email protected]1958e0e2010-04-22 05:17:156418 switch (name) {
6419 case GL_VERSION:
6420 str = "OpenGL ES 2.0 Chromium";
6421 break;
6422 case GL_SHADING_LANGUAGE_VERSION:
6423 str = "OpenGL ES GLSL ES 1.0 Chromium";
6424 break;
6425 case GL_EXTENSIONS:
[email protected]f0d74742011-10-03 16:31:046426 {
6427 // For WebGL contexts, strip out the OES derivatives extension if it has
6428 // not been enabled.
6429 if (force_webgl_glsl_validation_ &&
6430 !derivatives_explicitly_enabled_) {
6431 extensions = feature_info_->extensions();
6432 size_t offset = extensions.find(kOESDerivativeExtension);
6433 if (std::string::npos != offset) {
6434 extensions.replace(offset,
6435 offset + arraysize(kOESDerivativeExtension),
6436 std::string());
6437 }
6438 str = extensions.c_str();
6439 } else {
6440 str = feature_info_->extensions().c_str();
6441 }
[email protected]f0d74742011-10-03 16:31:046442 }
[email protected]1958e0e2010-04-22 05:17:156443 break;
6444 default:
6445 str = gl_str;
6446 break;
6447 }
[email protected]ddd968b82010-03-02 00:44:296448 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:156449 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:296450 return error::kNoError;
6451}
6452
[email protected]0c86dbf2010-03-05 08:14:116453void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:156454 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:056455 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296456 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
6457 return;
6458 }
[email protected]9438b012010-06-15 22:55:056459 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:296460 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:116461 return;
[email protected]3b6ec202010-03-05 05:16:236462 }
6463 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:296464 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:286465 return;
[email protected]3b6ec202010-03-05 05:16:236466 }
6467 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
6468 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296469 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:286470 return;
[email protected]3b6ec202010-03-05 05:16:236471 }
6472 // Clear the buffer to 0 if no initial data was passed in.
6473 scoped_array<int8> zero;
6474 if (!data) {
6475 zero.reset(new int8[size]);
6476 memset(zero.get(), 0, size);
6477 data = zero.get();
6478 }
[email protected]473c01ccb2011-06-07 01:33:306479
6480 if (!bufferdata_faster_than_buffersubdata_ &&
6481 size == info->size() && usage == info->usage()) {
6482 glBufferSubData(target, 0, size, data);
6483 info->SetRange(0, size, data);
6484 return;
6485 }
6486
[email protected]3b6ec202010-03-05 05:16:236487 CopyRealGLErrorsToWrapper();
6488 glBufferData(target, size, data, usage);
[email protected]1002c2d2011-06-28 22:39:046489 GLenum error = PeekGLError();
6490 if (error == GL_NO_ERROR) {
[email protected]473c01ccb2011-06-07 01:33:306491 buffer_manager()->SetInfo(info, size, usage);
[email protected]0c86dbf2010-03-05 08:14:116492 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:236493 }
[email protected]0c86dbf2010-03-05 08:14:116494}
6495
6496error::Error GLES2DecoderImpl::HandleBufferData(
6497 uint32 immediate_data_size, const gles2::BufferData& c) {
6498 GLenum target = static_cast<GLenum>(c.target);
6499 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
6500 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6501 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6502 GLenum usage = static_cast<GLenum>(c.usage);
6503 const void* data = NULL;
6504 if (data_shm_id != 0 || data_shm_offset != 0) {
6505 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
6506 if (!data) {
6507 return error::kOutOfBounds;
6508 }
6509 }
6510 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:146511 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196512}
6513
[email protected]f7a64ee2010-02-01 22:24:146514error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:196515 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
6516 GLenum target = static_cast<GLenum>(c.target);
6517 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:306518 const void* data = GetImmediateDataAs<const void*>(
6519 c, size, immediate_data_size);
6520 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146521 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:306522 }
[email protected]b9849abf2009-11-25 19:13:196523 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:116524 DoBufferData(target, size, data, usage);
6525 return error::kNoError;
6526}
6527
6528void GLES2DecoderImpl::DoBufferSubData(
6529 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:506530 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476531 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296532 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:286533 return;
[email protected]a93bb842010-02-16 23:03:476534 }
[email protected]0c86dbf2010-03-05 08:14:116535 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:296536 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]473c01ccb2011-06-07 01:33:306537 return;
[email protected]07f54fcc2009-12-22 02:46:306538 }
[email protected]473c01ccb2011-06-07 01:33:306539 if (bufferdata_faster_than_buffersubdata_ &&
6540 offset == 0 && size == info->size()) {
6541 glBufferData(target, size, data, info->usage());
6542 return;
6543 }
6544 glBufferSubData(target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:196545}
6546
[email protected]0d6bfdc2011-11-02 01:32:206547bool GLES2DecoderImpl::ClearLevel(
6548 unsigned service_id,
6549 unsigned bind_target,
6550 unsigned target,
6551 int level,
6552 unsigned format,
6553 unsigned type,
6554 int width,
[email protected]4502e6492011-12-14 19:39:156555 int height,
6556 bool is_texture_immutable) {
[email protected]0d6bfdc2011-11-02 01:32:206557 // Assumes the size has already been checked.
6558 uint32 pixels_size = 0;
6559 if (!GLES2Util::ComputeImageDataSize(
6560 width, height, format, type, unpack_alignment_, &pixels_size)) {
6561 return false;
6562 }
6563 scoped_array<char> zero(new char[pixels_size]);
6564 memset(zero.get(), 0, pixels_size);
6565 glBindTexture(bind_target, service_id);
[email protected]4502e6492011-12-14 19:39:156566 if (is_texture_immutable) {
6567 glTexSubImage2D(
6568 target, level, 0, 0, width, height, format, type, zero.get());
6569 } else {
6570 WrappedTexImage2D(
6571 target, level, format, width, height, 0, format, type, zero.get());
6572 }
[email protected]0d6bfdc2011-11-02 01:32:206573 TextureManager::TextureInfo* info = GetTextureInfoForTarget(bind_target);
6574 glBindTexture(bind_target, info ? info->service_id() : 0);
6575 return true;
6576}
6577
[email protected]a93bb842010-02-16 23:03:476578error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
6579 GLenum target,
6580 GLint level,
6581 GLenum internal_format,
6582 GLsizei width,
6583 GLsizei height,
6584 GLint border,
6585 GLsizei image_size,
6586 const void* data) {
[email protected]a93bb842010-02-16 23:03:476587 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:056588 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296589 SetGLError(GL_INVALID_ENUM,
6590 "glCompressedTexImage2D: target GL_INVALID_ENUM");
6591 return error::kNoError;
6592 }
[email protected]9438b012010-06-15 22:55:056593 if (!validators_->compressed_texture_format.IsValid(
6594 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296595 SetGLError(GL_INVALID_ENUM,
6596 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:476597 return error::kNoError;
6598 }
[email protected]80eb6b52012-01-19 00:14:416599 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476600 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296601 SetGLError(GL_INVALID_VALUE,
6602 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476603 return error::kNoError;
6604 }
[email protected]3916c97e2010-02-25 03:20:506605 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476606 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296607 SetGLError(GL_INVALID_VALUE,
6608 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:476609 return error::kNoError;
6610 }
[email protected]97dc7cbe2011-12-06 17:26:176611 if (info->IsImmutable()) {
6612 SetGLError(GL_INVALID_OPERATION,
6613 "glCompressedTexImage2D: texture is immutable");
6614 return error::kNoError;
6615 }
[email protected]968351b2011-12-20 08:26:516616
6617 if (info->IsAttachedToFramebuffer()) {
6618 state_dirty_ = true;
6619 // TODO(gman): If textures tracked which framebuffers they were attached to
6620 // we could just mark those framebuffers as not complete.
6621 framebuffer_manager()->IncFramebufferStateChangeCount();
6622 }
6623
[email protected]a93bb842010-02-16 23:03:476624 scoped_array<int8> zero;
6625 if (!data) {
6626 zero.reset(new int8[image_size]);
6627 memset(zero.get(), 0, image_size);
6628 data = zero.get();
6629 }
[email protected]cadde4a2010-07-31 17:10:436630 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:476631 glCompressedTexImage2D(
6632 target, level, internal_format, width, height, border, image_size, data);
[email protected]1002c2d2011-06-28 22:39:046633 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436634 if (error == GL_NO_ERROR) {
6635 texture_manager()->SetLevelInfo(
[email protected]0d6bfdc2011-11-02 01:32:206636 info, target, level, internal_format, width, height, 1, border, 0, 0,
6637 true);
[email protected]cadde4a2010-07-31 17:10:436638 }
[email protected]a93bb842010-02-16 23:03:476639 return error::kNoError;
6640}
6641
[email protected]f7a64ee2010-02-01 22:24:146642error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196643 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
6644 GLenum target = static_cast<GLenum>(c.target);
6645 GLint level = static_cast<GLint>(c.level);
6646 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6647 GLsizei width = static_cast<GLsizei>(c.width);
6648 GLsizei height = static_cast<GLsizei>(c.height);
6649 GLint border = static_cast<GLint>(c.border);
6650 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
6651 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6652 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6653 const void* data = NULL;
6654 if (data_shm_id != 0 || data_shm_offset != 0) {
6655 data = GetSharedMemoryAs<const void*>(
6656 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:466657 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146658 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196659 }
6660 }
[email protected]a93bb842010-02-16 23:03:476661 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196662 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:196663}
6664
[email protected]f7a64ee2010-02-01 22:24:146665error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:196666 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
6667 GLenum target = static_cast<GLenum>(c.target);
6668 GLint level = static_cast<GLint>(c.level);
6669 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6670 GLsizei width = static_cast<GLsizei>(c.width);
6671 GLsizei height = static_cast<GLsizei>(c.height);
6672 GLint border = static_cast<GLint>(c.border);
6673 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:306674 const void* data = GetImmediateDataAs<const void*>(
6675 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466676 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146677 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466678 }
[email protected]a93bb842010-02-16 23:03:476679 return DoCompressedTexImage2D(
6680 target, level, internal_format, width, height, border, image_size, data);
6681}
6682
[email protected]b6140d02010-05-17 14:47:166683error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
6684 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
6685 GLenum target = static_cast<GLenum>(c.target);
6686 GLint level = static_cast<GLint>(c.level);
6687 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6688 GLsizei width = static_cast<GLsizei>(c.width);
6689 GLsizei height = static_cast<GLsizei>(c.height);
6690 GLint border = static_cast<GLint>(c.border);
6691 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:286692 if (!bucket) {
6693 return error::kInvalidArguments;
6694 }
6695 uint32 data_size = bucket->size();
6696 GLsizei imageSize = data_size;
6697 const void* data = bucket->GetData(0, data_size);
6698 if (!data) {
6699 return error::kInvalidArguments;
6700 }
[email protected]b6140d02010-05-17 14:47:166701 return DoCompressedTexImage2D(
6702 target, level, internal_format, width, height, border,
[email protected]12f93d82011-10-17 21:16:286703 imageSize, data);
[email protected]b6140d02010-05-17 14:47:166704}
6705
6706error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
6707 uint32 immediate_data_size,
6708 const gles2::CompressedTexSubImage2DBucket& c) {
6709 GLenum target = static_cast<GLenum>(c.target);
6710 GLint level = static_cast<GLint>(c.level);
6711 GLint xoffset = static_cast<GLint>(c.xoffset);
6712 GLint yoffset = static_cast<GLint>(c.yoffset);
6713 GLsizei width = static_cast<GLsizei>(c.width);
6714 GLsizei height = static_cast<GLsizei>(c.height);
6715 GLenum format = static_cast<GLenum>(c.format);
6716 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:286717 if (!bucket) {
6718 return error::kInvalidArguments;
6719 }
[email protected]b6140d02010-05-17 14:47:166720 uint32 data_size = bucket->size();
6721 GLsizei imageSize = data_size;
6722 const void* data = bucket->GetData(0, data_size);
[email protected]12f93d82011-10-17 21:16:286723 if (!data) {
6724 return error::kInvalidArguments;
6725 }
[email protected]9438b012010-06-15 22:55:056726 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:166727 SetGLError(
6728 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
6729 return error::kNoError;
6730 }
[email protected]9438b012010-06-15 22:55:056731 if (!validators_->compressed_texture_format.IsValid(format)) {
6732 SetGLError(GL_INVALID_ENUM,
6733 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
6734 return error::kNoError;
6735 }
[email protected]b6140d02010-05-17 14:47:166736 if (width < 0) {
6737 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
6738 return error::kNoError;
6739 }
6740 if (height < 0) {
6741 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
6742 return error::kNoError;
6743 }
6744 if (imageSize < 0) {
6745 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
6746 return error::kNoError;
6747 }
[email protected]cadde4a2010-07-31 17:10:436748 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:166749 target, level, xoffset, yoffset, width, height, format, imageSize, data);
6750 return error::kNoError;
6751}
6752
[email protected]a93bb842010-02-16 23:03:476753error::Error GLES2DecoderImpl::DoTexImage2D(
6754 GLenum target,
6755 GLint level,
6756 GLenum internal_format,
6757 GLsizei width,
6758 GLsizei height,
6759 GLint border,
6760 GLenum format,
6761 GLenum type,
6762 const void* pixels,
6763 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:056764 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296765 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
6766 return error::kNoError;
6767 }
[email protected]9438b012010-06-15 22:55:056768 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296769 SetGLError(GL_INVALID_ENUM,
6770 "glTexImage2D: internal_format GL_INVALID_ENUM");
6771 return error::kNoError;
6772 }
[email protected]9438b012010-06-15 22:55:056773 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:296774 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
6775 return error::kNoError;
6776 }
[email protected]9438b012010-06-15 22:55:056777 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:296778 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:146779 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196780 }
[email protected]7b92c412010-07-20 17:48:256781 if (format != internal_format) {
6782 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
6783 return error::kNoError;
6784 }
[email protected]80eb6b52012-01-19 00:14:416785 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476786 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296787 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476788 return error::kNoError;
6789 }
[email protected]3916c97e2010-02-25 03:20:506790 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476791 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296792 SetGLError(GL_INVALID_OPERATION,
6793 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:476794 return error::kNoError;
6795 }
[email protected]0226c112011-07-22 03:25:076796
[email protected]97dc7cbe2011-12-06 17:26:176797 if (info->IsImmutable()) {
6798 SetGLError(GL_INVALID_OPERATION,
6799 "glTexImage2D: texture is immutable");
6800 return error::kNoError;
6801 }
6802
[email protected]0226c112011-07-22 03:25:076803 GLsizei tex_width = 0;
6804 GLsizei tex_height = 0;
6805 GLenum tex_type = 0;
6806 GLenum tex_format = 0;
6807 bool level_is_same =
6808 info->GetLevelSize(target, level, &tex_width, &tex_height) &&
6809 info->GetLevelType(target, level, &tex_type, &tex_format) &&
6810 width == tex_width && height == tex_height &&
6811 type == tex_type && format == tex_format;
6812
6813 if (level_is_same && !pixels) {
[email protected]1bed6222011-12-21 11:21:396814 // Just set the level info but mark the texture as uncleared.
6815 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416816 info,
[email protected]1bed6222011-12-21 11:21:396817 target, level, internal_format, width, height, 1, border, format, type,
6818 false);
[email protected]ea72ed222011-08-17 18:58:436819 tex_image_2d_failed_ = false;
[email protected]0226c112011-07-22 03:25:076820 return error::kNoError;
6821 }
6822
[email protected]297ca1c2011-06-20 23:08:466823 if (info->IsAttachedToFramebuffer()) {
6824 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:516825 // TODO(gman): If textures tracked which framebuffers they were attached to
6826 // we could just mark those framebuffers as not complete.
6827 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:466828 }
6829
[email protected]1bed6222011-12-21 11:21:396830 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same && pixels) {
[email protected]0226c112011-07-22 03:25:076831 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
[email protected]57edfdad2012-02-07 04:57:156832 texture_manager()->SetLevelCleared(info, target, level);
[email protected]0226c112011-07-22 03:25:076833 tex_image_2d_failed_ = false;
6834 return error::kNoError;
[email protected]7488d962010-07-16 02:41:586835 }
[email protected]876f6fee2010-08-02 23:10:326836
[email protected]cadde4a2010-07-31 17:10:436837 CopyRealGLErrorsToWrapper();
[email protected]473c01ccb2011-06-07 01:33:306838 WrappedTexImage2D(
6839 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476840 pixels);
[email protected]1002c2d2011-06-28 22:39:046841 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436842 if (error == GL_NO_ERROR) {
[email protected]0d6bfdc2011-11-02 01:32:206843 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416844 info,
[email protected]0d6bfdc2011-11-02 01:32:206845 target, level, internal_format, width, height, 1, border, format, type,
6846 pixels != NULL);
[email protected]b493ee622011-04-13 23:52:006847 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:436848 }
[email protected]f7a64ee2010-02-01 22:24:146849 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196850}
6851
[email protected]f7a64ee2010-02-01 22:24:146852error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196853 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]366ae242011-05-10 02:23:586854 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:006855 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:196856 GLenum target = static_cast<GLenum>(c.target);
6857 GLint level = static_cast<GLint>(c.level);
6858 GLint internal_format = static_cast<GLint>(c.internalformat);
6859 GLsizei width = static_cast<GLsizei>(c.width);
6860 GLsizei height = static_cast<GLsizei>(c.height);
6861 GLint border = static_cast<GLint>(c.border);
6862 GLenum format = static_cast<GLenum>(c.format);
6863 GLenum type = static_cast<GLenum>(c.type);
6864 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
6865 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:186866 uint32 pixels_size;
6867 if (!GLES2Util::ComputeImageDataSize(
6868 width, height, format, type, unpack_alignment_, &pixels_size)) {
6869 return error::kOutOfBounds;
6870 }
[email protected]b9849abf2009-11-25 19:13:196871 const void* pixels = NULL;
6872 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
6873 pixels = GetSharedMemoryAs<const void*>(
6874 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:466875 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146876 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196877 }
6878 }
[email protected]a93bb842010-02-16 23:03:476879 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196880 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476881 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:196882}
6883
[email protected]f7a64ee2010-02-01 22:24:146884error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:196885 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
6886 GLenum target = static_cast<GLenum>(c.target);
6887 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:466888 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:196889 GLsizei width = static_cast<GLsizei>(c.width);
6890 GLsizei height = static_cast<GLsizei>(c.height);
6891 GLint border = static_cast<GLint>(c.border);
6892 GLenum format = static_cast<GLenum>(c.format);
6893 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:186894 uint32 size;
6895 if (!GLES2Util::ComputeImageDataSize(
6896 width, height, format, type, unpack_alignment_, &size)) {
6897 return error::kOutOfBounds;
6898 }
[email protected]07f54fcc2009-12-22 02:46:306899 const void* pixels = GetImmediateDataAs<const void*>(
6900 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466901 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146902 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466903 }
[email protected]a93bb842010-02-16 23:03:476904 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:466905 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476906 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:146907 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326908}
6909
[email protected]cadde4a2010-07-31 17:10:436910void GLES2DecoderImpl::DoCompressedTexSubImage2D(
6911 GLenum target,
6912 GLint level,
6913 GLint xoffset,
6914 GLint yoffset,
6915 GLsizei width,
6916 GLsizei height,
6917 GLenum format,
6918 GLsizei image_size,
6919 const void * data) {
6920 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6921 if (!info) {
6922 SetGLError(GL_INVALID_OPERATION,
6923 "glCompressedTexSubImage2D: unknown texture for target");
6924 return;
6925 }
6926 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:526927 GLenum internal_format = 0;
6928 if (!info->GetLevelType(target, level, &type, &internal_format)) {
6929 SetGLError(
6930 GL_INVALID_OPERATION,
[email protected]4502e6492011-12-14 19:39:156931 "glCompressedTexSubImage2D: level does not exist.");
[email protected]df6cf1ad2011-01-29 01:20:526932 return;
6933 }
6934 if (internal_format != format) {
6935 SetGLError(
6936 GL_INVALID_OPERATION,
[email protected]4502e6492011-12-14 19:39:156937 "glCompressedTexSubImage2D: format does not match internal format.");
[email protected]df6cf1ad2011-01-29 01:20:526938 return;
6939 }
6940 if (!info->ValidForTexture(
6941 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:436942 SetGLError(GL_INVALID_VALUE,
[email protected]4502e6492011-12-14 19:39:156943 "glCompressedTexSubImage2D: bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:436944 return;
6945 }
[email protected]0d6bfdc2011-11-02 01:32:206946 // Note: There is no need to deal with texture cleared tracking here
6947 // because the validation above means you can only get here if the level
6948 // is already a matching compressed format and in that case
6949 // CompressedTexImage2D already cleared the texture.
[email protected]cadde4a2010-07-31 17:10:436950 glCompressedTexSubImage2D(
6951 target, level, xoffset, yoffset, width, height, format, image_size, data);
6952}
6953
[email protected]6e288612010-12-21 20:45:036954static void Clip(
6955 GLint start, GLint range, GLint sourceRange,
6956 GLint* out_start, GLint* out_range) {
6957 DCHECK(out_start);
6958 DCHECK(out_range);
6959 if (start < 0) {
6960 range += start;
6961 start = 0;
6962 }
6963 GLint end = start + range;
6964 if (end > sourceRange) {
6965 range -= end - sourceRange;
6966 }
6967 *out_start = start;
6968 *out_range = range;
6969}
6970
[email protected]cadde4a2010-07-31 17:10:436971void GLES2DecoderImpl::DoCopyTexImage2D(
6972 GLenum target,
6973 GLint level,
6974 GLenum internal_format,
6975 GLint x,
6976 GLint y,
6977 GLsizei width,
6978 GLsizei height,
6979 GLint border) {
6980 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6981 if (!info) {
6982 SetGLError(GL_INVALID_OPERATION,
6983 "glCopyTexImage2D: unknown texture for target");
6984 return;
6985 }
[email protected]97dc7cbe2011-12-06 17:26:176986 if (info->IsImmutable()) {
6987 SetGLError(GL_INVALID_OPERATION,
6988 "glCopyTexImage2D: texture is immutable");
6989 }
[email protected]80eb6b52012-01-19 00:14:416990 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:186991 border != 0) {
6992 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
6993 return;
6994 }
6995
[email protected]9edc6b22010-12-23 02:00:266996 // Check we have compatible formats.
6997 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6998 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6999 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
7000
7001 if ((channels_needed & channels_exist) != channels_needed) {
7002 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
7003 return;
7004 }
7005
[email protected]a0b78dc2011-11-11 10:43:107006 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
7007 return;
7008 }
7009
[email protected]cadde4a2010-07-31 17:10:437010 CopyRealGLErrorsToWrapper();
[email protected]de26b3c2011-08-03 21:54:277011 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:037012 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:267013
[email protected]297ca1c2011-06-20 23:08:467014 if (info->IsAttachedToFramebuffer()) {
7015 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:517016 // TODO(gman): If textures tracked which framebuffers they were attached to
7017 // we could just mark those framebuffers as not complete.
7018 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:467019 }
7020
[email protected]9edc6b22010-12-23 02:00:267021 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:037022 GLint copyX = 0;
7023 GLint copyY = 0;
7024 GLint copyWidth = 0;
7025 GLint copyHeight = 0;
7026 Clip(x, width, size.width(), &copyX, &copyWidth);
7027 Clip(y, height, size.height(), &copyY, &copyHeight);
7028
7029 if (copyX != x ||
7030 copyY != y ||
7031 copyWidth != width ||
7032 copyHeight != height) {
7033 // some part was clipped so clear the texture.
[email protected]0d6bfdc2011-11-02 01:32:207034 if (!ClearLevel(
7035 info->service_id(), info->target(),
[email protected]4502e6492011-12-14 19:39:157036 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
7037 info->IsImmutable())) {
[email protected]0d6bfdc2011-11-02 01:32:207038 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexImage2D: dimensions too big");
[email protected]6e288612010-12-21 20:45:037039 return;
7040 }
[email protected]6e288612010-12-21 20:45:037041 if (copyHeight > 0 && copyWidth > 0) {
7042 GLint dx = copyX - x;
7043 GLint dy = copyY - y;
7044 GLint destX = dx;
7045 GLint destY = dy;
7046 glCopyTexSubImage2D(target, level,
7047 destX, destY, copyX, copyY,
7048 copyWidth, copyHeight);
7049 }
7050 } else {
7051 glCopyTexImage2D(target, level, internal_format,
7052 copyX, copyY, copyWidth, copyHeight, border);
7053 }
[email protected]1002c2d2011-06-28 22:39:047054 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:437055 if (error == GL_NO_ERROR) {
7056 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:417057 info, target, level, internal_format, width, height, 1,
[email protected]0d6bfdc2011-11-02 01:32:207058 border, internal_format, GL_UNSIGNED_BYTE, true);
[email protected]cadde4a2010-07-31 17:10:437059 }
7060}
7061
7062void GLES2DecoderImpl::DoCopyTexSubImage2D(
7063 GLenum target,
7064 GLint level,
7065 GLint xoffset,
7066 GLint yoffset,
7067 GLint x,
7068 GLint y,
7069 GLsizei width,
7070 GLsizei height) {
7071 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7072 if (!info) {
7073 SetGLError(GL_INVALID_OPERATION,
7074 "glCopyTexSubImage2D: unknown texture for target");
7075 return;
7076 }
7077 GLenum type = 0;
7078 GLenum format = 0;
7079 if (!info->GetLevelType(target, level, &type, &format) ||
7080 !info->ValidForTexture(
7081 target, level, xoffset, yoffset, width, height, format, type)) {
7082 SetGLError(GL_INVALID_VALUE,
7083 "glCopyTexSubImage2D: bad dimensions.");
7084 return;
7085 }
[email protected]9edc6b22010-12-23 02:00:267086
7087 // Check we have compatible formats.
7088 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7089 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7090 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
7091
7092 if ((channels_needed & channels_exist) != channels_needed) {
7093 SetGLError(
7094 GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
7095 return;
7096 }
7097
[email protected]a0b78dc2011-11-11 10:43:107098 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
7099 return;
7100 }
7101
[email protected]de26b3c2011-08-03 21:54:277102 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:037103 gfx::Size size = GetBoundReadFrameBufferSize();
7104 GLint copyX = 0;
7105 GLint copyY = 0;
7106 GLint copyWidth = 0;
7107 GLint copyHeight = 0;
7108 Clip(x, width, size.width(), &copyX, &copyWidth);
7109 Clip(y, height, size.height(), &copyY, &copyHeight);
[email protected]0d6bfdc2011-11-02 01:32:207110
7111 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
7112 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D: dimensions too big");
7113 return;
7114 }
7115
[email protected]6e288612010-12-21 20:45:037116 if (copyX != x ||
7117 copyY != y ||
7118 copyWidth != width ||
7119 copyHeight != height) {
[email protected]0d6bfdc2011-11-02 01:32:207120 // some part was clipped so clear the sub rect.
[email protected]6e288612010-12-21 20:45:037121 uint32 pixels_size = 0;
7122 if (!GLES2Util::ComputeImageDataSize(
7123 width, height, format, type, unpack_alignment_, &pixels_size)) {
7124 SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large");
7125 return;
7126 }
7127 scoped_array<char> zero(new char[pixels_size]);
7128 memset(zero.get(), 0, pixels_size);
7129 glTexSubImage2D(
7130 target, level, xoffset, yoffset, width, height,
7131 format, type, zero.get());
7132 }
[email protected]0d6bfdc2011-11-02 01:32:207133
[email protected]6e288612010-12-21 20:45:037134 if (copyHeight > 0 && copyWidth > 0) {
7135 GLint dx = copyX - x;
7136 GLint dy = copyY - y;
7137 GLint destX = xoffset + dx;
7138 GLint destY = yoffset + dy;
7139 glCopyTexSubImage2D(target, level,
7140 destX, destY, copyX, copyY,
7141 copyWidth, copyHeight);
7142 }
[email protected]cadde4a2010-07-31 17:10:437143}
7144
7145void GLES2DecoderImpl::DoTexSubImage2D(
7146 GLenum target,
7147 GLint level,
7148 GLint xoffset,
7149 GLint yoffset,
7150 GLsizei width,
7151 GLsizei height,
7152 GLenum format,
7153 GLenum type,
7154 const void * data) {
7155 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7156 if (!info) {
7157 SetGLError(GL_INVALID_OPERATION,
7158 "glTexSubImage2D: unknown texture for target");
7159 return;
7160 }
[email protected]df6cf1ad2011-01-29 01:20:527161 GLenum current_type = 0;
7162 GLenum internal_format = 0;
7163 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
7164 SetGLError(
7165 GL_INVALID_OPERATION,
7166 "glTexSubImage2D: level does not exist.");
7167 return;
7168 }
7169 if (format != internal_format) {
7170 SetGLError(GL_INVALID_OPERATION,
7171 "glTexSubImage2D: format does not match internal format.");
7172 return;
7173 }
7174 if (type != current_type) {
7175 SetGLError(GL_INVALID_OPERATION,
7176 "glTexSubImage2D: type does not match type of texture.");
7177 return;
7178 }
7179
[email protected]cadde4a2010-07-31 17:10:437180 if (!info->ValidForTexture(
7181 target, level, xoffset, yoffset, width, height, format, type)) {
7182 SetGLError(GL_INVALID_VALUE,
7183 "glTexSubImage2D: bad dimensions.");
7184 return;
7185 }
[email protected]473c01ccb2011-06-07 01:33:307186
[email protected]4502e6492011-12-14 19:39:157187 GLsizei tex_width = 0;
7188 GLsizei tex_height = 0;
7189 bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height);
7190 DCHECK(ok);
7191 if (xoffset != 0 || yoffset != 0 ||
7192 width != tex_width || height != tex_height) {
7193 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
7194 SetGLError(GL_OUT_OF_MEMORY, "glTexSubImage2D: dimensions too big");
[email protected]473c01ccb2011-06-07 01:33:307195 return;
7196 }
[email protected]4502e6492011-12-14 19:39:157197 glTexSubImage2D(
7198 target, level, xoffset, yoffset, width, height, format, type, data);
[email protected]0d6bfdc2011-11-02 01:32:207199 return;
7200 }
[email protected]4502e6492011-12-14 19:39:157201
7202 if (teximage2d_faster_than_texsubimage2d_ && !info->IsImmutable()) {
7203 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
7204 // same as internal_foramt. If that changes we'll need to look them up.
7205 WrappedTexImage2D(
7206 target, level, format, width, height, 0, format, type, data);
7207 } else {
7208 glTexSubImage2D(
7209 target, level, xoffset, yoffset, width, height, format, type, data);
7210 }
7211 texture_manager()->SetLevelCleared(info, target, level);
[email protected]cadde4a2010-07-31 17:10:437212}
7213
[email protected]b493ee622011-04-13 23:52:007214error::Error GLES2DecoderImpl::HandleTexSubImage2D(
7215 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]366ae242011-05-10 02:23:587216 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:007217 GLboolean internal = static_cast<GLboolean>(c.internal);
7218 if (internal == GL_TRUE && tex_image_2d_failed_)
7219 return error::kNoError;
7220
7221 GLenum target = static_cast<GLenum>(c.target);
7222 GLint level = static_cast<GLint>(c.level);
7223 GLint xoffset = static_cast<GLint>(c.xoffset);
7224 GLint yoffset = static_cast<GLint>(c.yoffset);
7225 GLsizei width = static_cast<GLsizei>(c.width);
7226 GLsizei height = static_cast<GLsizei>(c.height);
7227 GLenum format = static_cast<GLenum>(c.format);
7228 GLenum type = static_cast<GLenum>(c.type);
7229 uint32 data_size;
7230 if (!GLES2Util::ComputeImageDataSize(
7231 width, height, format, type, unpack_alignment_, &data_size)) {
7232 return error::kOutOfBounds;
7233 }
7234 const void* pixels = GetSharedMemoryAs<const void*>(
7235 c.pixels_shm_id, c.pixels_shm_offset, data_size);
7236 if (!validators_->texture_target.IsValid(target)) {
7237 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
7238 return error::kNoError;
7239 }
7240 if (width < 0) {
7241 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
7242 return error::kNoError;
7243 }
7244 if (height < 0) {
7245 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
7246 return error::kNoError;
7247 }
7248 if (!validators_->texture_format.IsValid(format)) {
7249 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
7250 return error::kNoError;
7251 }
7252 if (!validators_->pixel_type.IsValid(type)) {
7253 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
7254 return error::kNoError;
7255 }
7256 if (pixels == NULL) {
7257 return error::kOutOfBounds;
7258 }
7259 DoTexSubImage2D(
7260 target, level, xoffset, yoffset, width, height, format, type, pixels);
7261 return error::kNoError;
7262}
7263
7264error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
7265 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
7266 GLboolean internal = static_cast<GLboolean>(c.internal);
7267 if (internal == GL_TRUE && tex_image_2d_failed_)
7268 return error::kNoError;
7269
7270 GLenum target = static_cast<GLenum>(c.target);
7271 GLint level = static_cast<GLint>(c.level);
7272 GLint xoffset = static_cast<GLint>(c.xoffset);
7273 GLint yoffset = static_cast<GLint>(c.yoffset);
7274 GLsizei width = static_cast<GLsizei>(c.width);
7275 GLsizei height = static_cast<GLsizei>(c.height);
7276 GLenum format = static_cast<GLenum>(c.format);
7277 GLenum type = static_cast<GLenum>(c.type);
7278 uint32 data_size;
7279 if (!GLES2Util::ComputeImageDataSize(
7280 width, height, format, type, unpack_alignment_, &data_size)) {
7281 return error::kOutOfBounds;
7282 }
7283 const void* pixels = GetImmediateDataAs<const void*>(
7284 c, data_size, immediate_data_size);
7285 if (!validators_->texture_target.IsValid(target)) {
7286 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
7287 return error::kNoError;
7288 }
7289 if (width < 0) {
7290 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
7291 return error::kNoError;
7292 }
7293 if (height < 0) {
7294 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
7295 return error::kNoError;
7296 }
7297 if (!validators_->texture_format.IsValid(format)) {
7298 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
7299 return error::kNoError;
7300 }
7301 if (!validators_->pixel_type.IsValid(type)) {
7302 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
7303 return error::kNoError;
7304 }
7305 if (pixels == NULL) {
7306 return error::kOutOfBounds;
7307 }
7308 DoTexSubImage2D(
7309 target, level, xoffset, yoffset, width, height, format, type, pixels);
7310 return error::kNoError;
7311}
7312
[email protected]f7a64ee2010-02-01 22:24:147313error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:197314 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:367315 GLuint index = static_cast<GLuint>(c.index);
7316 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:257317 typedef gles2::GetVertexAttribPointerv::Result Result;
7318 Result* result = GetSharedMemoryAs<Result*>(
7319 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:367320 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:147321 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:367322 }
[email protected]07d0cc82010-02-17 04:51:407323 // Check that the client initialized the result.
7324 if (result->size != 0) {
7325 return error::kInvalidArguments;
7326 }
[email protected]9438b012010-06-15 22:55:057327 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:297328 SetGLError(GL_INVALID_ENUM,
7329 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:147330 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367331 }
[email protected]3916c97e2010-02-25 03:20:507332 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:297333 SetGLError(GL_INVALID_VALUE,
7334 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:147335 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367336 }
[email protected]0bfd9882010-02-05 23:02:257337 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:087338 *result->GetData() =
[email protected]3757a372012-01-19 05:20:447339 vertex_attrib_manager_->GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:147340 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327341}
7342
[email protected]f7b85372010-02-03 01:11:377343bool GLES2DecoderImpl::GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127344 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:377345 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:127346 error::Error* error, GLint* real_location,
7347 GLuint* service_id, void** result_pointer, GLenum* result_type) {
[email protected]939e7362010-05-13 20:49:107348 DCHECK(error);
7349 DCHECK(service_id);
7350 DCHECK(result_pointer);
7351 DCHECK(result_type);
[email protected]1b0a6752012-02-22 03:44:127352 DCHECK(real_location);
[email protected]f7b85372010-02-03 01:11:377353 *error = error::kNoError;
7354 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:257355 SizedResult<GLint>* result;
7356 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7357 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
7358 if (!result) {
[email protected]f7b85372010-02-03 01:11:377359 *error = error::kOutOfBounds;
7360 return false;
7361 }
[email protected]0bfd9882010-02-05 23:02:257362 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:377363 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:257364 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:587365 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7366 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:377367 if (!info) {
[email protected]ae51d192010-04-27 00:48:037368 return false;
7369 }
7370 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:377371 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:297372 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:377373 return false;
7374 }
[email protected]ae51d192010-04-27 00:48:037375 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:367376 GLint array_index = -1;
7377 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
[email protected]1b0a6752012-02-22 03:44:127378 info->GetUniformInfoByFakeLocation(
7379 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:367380 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:377381 // No such location.
[email protected]8eee29c2010-04-29 03:38:297382 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:377383 return false;
7384 }
[email protected]43c2f1f2011-03-25 18:35:367385 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:507386 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:377387 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:297388 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:377389 return false;
7390 }
[email protected]0bfd9882010-02-05 23:02:257391 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7392 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
7393 if (!result) {
[email protected]f7b85372010-02-03 01:11:377394 *error = error::kOutOfBounds;
7395 return false;
7396 }
[email protected]0bfd9882010-02-05 23:02:257397 result->size = size;
[email protected]939e7362010-05-13 20:49:107398 *result_type = type;
[email protected]f7b85372010-02-03 01:11:377399 return true;
7400}
7401
[email protected]f7a64ee2010-02-01 22:24:147402error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:197403 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:377404 GLuint program = c.program;
[email protected]1b0a6752012-02-22 03:44:127405 GLint fake_location = program_manager()->UnswizzleLocation(c.location);
[email protected]f7b85372010-02-03 01:11:377406 GLuint service_id;
[email protected]939e7362010-05-13 20:49:107407 GLenum result_type;
[email protected]1b0a6752012-02-22 03:44:127408 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:377409 Error error;
[email protected]0bfd9882010-02-05 23:02:257410 void* result;
[email protected]f7b85372010-02-03 01:11:377411 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127412 program, fake_location, c.params_shm_id, c.params_shm_offset,
7413 &error, &real_location, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:257414 glGetUniformiv(
[email protected]1b0a6752012-02-22 03:44:127415 service_id, real_location,
[email protected]0bfd9882010-02-05 23:02:257416 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:377417 }
7418 return error;
[email protected]96449d2c2009-11-25 00:01:327419}
7420
[email protected]f7a64ee2010-02-01 22:24:147421error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:197422 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:377423 GLuint program = c.program;
[email protected]1b0a6752012-02-22 03:44:127424 GLint fake_location = program_manager()->UnswizzleLocation(c.location);
[email protected]f7b85372010-02-03 01:11:377425 GLuint service_id;
[email protected]1b0a6752012-02-22 03:44:127426 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:377427 Error error;
[email protected]0bfd9882010-02-05 23:02:257428 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:107429 Result* result;
7430 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:377431 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127432 program, fake_location, c.params_shm_id, c.params_shm_offset,
7433 &error, &real_location, &service_id,
7434 reinterpret_cast<void**>(&result), &result_type)) {
[email protected]939e7362010-05-13 20:49:107435 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
7436 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
7437 GLsizei num_values = result->GetNumResults();
7438 scoped_array<GLint> temp(new GLint[num_values]);
[email protected]1b0a6752012-02-22 03:44:127439 glGetUniformiv(service_id, real_location, temp.get());
[email protected]939e7362010-05-13 20:49:107440 GLfloat* dst = result->GetData();
7441 for (GLsizei ii = 0; ii < num_values; ++ii) {
7442 dst[ii] = (temp[ii] != 0);
7443 }
7444 } else {
[email protected]1b0a6752012-02-22 03:44:127445 glGetUniformfv(service_id, real_location, result->GetData());
[email protected]939e7362010-05-13 20:49:107446 }
[email protected]f7b85372010-02-03 01:11:377447 }
7448 return error;
[email protected]96449d2c2009-11-25 00:01:327449}
7450
[email protected]f7a64ee2010-02-01 22:24:147451error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:197452 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:257453 GLenum shader_type = static_cast<GLenum>(c.shadertype);
7454 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
7455 typedef gles2::GetShaderPrecisionFormat::Result Result;
7456 Result* result = GetSharedMemoryAs<Result*>(
7457 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7458 if (!result) {
7459 return error::kOutOfBounds;
7460 }
[email protected]07d0cc82010-02-17 04:51:407461 // Check that the client initialized the result.
7462 if (result->success != 0) {
7463 return error::kInvalidArguments;
7464 }
[email protected]9438b012010-06-15 22:55:057465 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:297466 SetGLError(GL_INVALID_ENUM,
7467 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
7468 return error::kNoError;
7469 }
[email protected]9438b012010-06-15 22:55:057470 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:297471 SetGLError(GL_INVALID_ENUM,
7472 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
7473 return error::kNoError;
7474 }
7475
7476 result->success = 1; // true
7477 switch (precision_type) {
7478 case GL_LOW_INT:
7479 case GL_MEDIUM_INT:
7480 case GL_HIGH_INT:
7481 result->min_range = -31;
7482 result->max_range = 31;
7483 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:107484 break;
[email protected]8eee29c2010-04-29 03:38:297485 case GL_LOW_FLOAT:
7486 case GL_MEDIUM_FLOAT:
7487 case GL_HIGH_FLOAT:
7488 result->min_range = -62;
7489 result->max_range = 62;
7490 result->precision = -16;
7491 break;
7492 default:
7493 NOTREACHED();
7494 break;
[email protected]0bfd9882010-02-05 23:02:257495 }
[email protected]f7a64ee2010-02-01 22:24:147496 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327497}
7498
[email protected]f7a64ee2010-02-01 22:24:147499error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:197500 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:257501 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:587502 GLuint program = static_cast<GLuint>(c.program);
7503 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7504 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:037505 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257506 return error::kNoError;
7507 }
7508 typedef gles2::GetAttachedShaders::Result Result;
7509 uint32 max_count = Result::ComputeMaxResults(result_size);
7510 Result* result = GetSharedMemoryAs<Result*>(
7511 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
7512 if (!result) {
7513 return error::kOutOfBounds;
7514 }
[email protected]07d0cc82010-02-17 04:51:407515 // Check that the client initialized the result.
7516 if (result->size != 0) {
7517 return error::kInvalidArguments;
7518 }
[email protected]0bfd9882010-02-05 23:02:257519 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:037520 glGetAttachedShaders(
7521 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:257522 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:037523 if (!shader_manager()->GetClientId(result->GetData()[ii],
7524 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:257525 NOTREACHED();
7526 return error::kGenericError;
7527 }
7528 }
7529 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:147530 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327531}
7532
[email protected]f7a64ee2010-02-01 22:24:147533error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:197534 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:257535 GLuint program = c.program;
7536 GLuint index = c.index;
7537 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:257538 typedef gles2::GetActiveUniform::Result Result;
7539 Result* result = GetSharedMemoryAs<Result*>(
7540 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7541 if (!result) {
7542 return error::kOutOfBounds;
7543 }
[email protected]07d0cc82010-02-17 04:51:407544 // Check that the client initialized the result.
7545 if (result->success != 0) {
7546 return error::kInvalidArguments;
7547 }
[email protected]6b8cf1a2010-05-06 16:13:587548 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7549 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:037550 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257551 return error::kNoError;
7552 }
7553 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
7554 info->GetUniformInfo(index);
7555 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:297556 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:257557 return error::kNoError;
7558 }
7559 result->success = 1; // true.
7560 result->size = uniform_info->size;
7561 result->type = uniform_info->type;
7562 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297563 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:147564 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327565}
7566
[email protected]f7a64ee2010-02-01 22:24:147567error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:197568 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:257569 GLuint program = c.program;
7570 GLuint index = c.index;
7571 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:257572 typedef gles2::GetActiveAttrib::Result Result;
7573 Result* result = GetSharedMemoryAs<Result*>(
7574 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7575 if (!result) {
7576 return error::kOutOfBounds;
7577 }
[email protected]07d0cc82010-02-17 04:51:407578 // Check that the client initialized the result.
7579 if (result->success != 0) {
7580 return error::kInvalidArguments;
7581 }
[email protected]6b8cf1a2010-05-06 16:13:587582 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7583 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:037584 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257585 return error::kNoError;
7586 }
7587 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
7588 info->GetAttribInfo(index);
7589 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:297590 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:257591 return error::kNoError;
7592 }
7593 result->success = 1; // true.
7594 result->size = attrib_info->size;
7595 result->type = attrib_info->type;
7596 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297597 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:147598 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327599}
7600
[email protected]b273e432010-04-12 17:23:587601error::Error GLES2DecoderImpl::HandleShaderBinary(
7602 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
7603#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:297604 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:587605 return error::kNoError;
7606#else
7607 GLsizei n = static_cast<GLsizei>(c.n);
7608 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:297609 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:587610 return error::kNoError;
7611 }
7612 GLsizei length = static_cast<GLsizei>(c.length);
7613 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:297614 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:587615 return error::kNoError;
7616 }
7617 uint32 data_size;
7618 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
7619 return error::kOutOfBounds;
7620 }
7621 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
7622 c.shaders_shm_id, c.shaders_shm_offset, data_size);
7623 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
7624 const void* binary = GetSharedMemoryAs<const void*>(
7625 c.binary_shm_id, c.binary_shm_offset, length);
7626 if (shaders == NULL || binary == NULL) {
7627 return error::kOutOfBounds;
7628 }
7629 scoped_array<GLuint> service_ids(new GLuint[n]);
7630 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:037631 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
7632 if (!info) {
[email protected]8eee29c2010-04-29 03:38:297633 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:587634 return error::kNoError;
7635 }
[email protected]ae51d192010-04-27 00:48:037636 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:587637 }
7638 // TODO(gman): call glShaderBinary
7639 return error::kNoError;
7640#endif
7641}
7642
[email protected]6217d392010-03-25 22:08:357643error::Error GLES2DecoderImpl::HandleSwapBuffers(
7644 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:497645 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7646 int this_frame_number = frame_number_++;
[email protected]da151512011-11-11 23:27:387647 // TRACE_EVENT for gpu tests:
[email protected]529c6672012-01-04 02:18:267648 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers",
7649 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
7650 "width", (is_offscreen ? offscreen_size_.width() :
7651 surface_->GetSize().width()));
[email protected]64ace852011-05-19 21:49:497652 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
7653 "offscreen", is_offscreen,
7654 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:357655 // If offscreen then don't actually SwapBuffers to the display. Just copy
7656 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:497657 if (is_offscreen) {
[email protected]1fb8c482011-08-31 01:01:537658 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
7659 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
7660 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
7661 // fix this.
7662 if (needs_mac_nvidia_driver_workaround_) {
7663 offscreen_saved_frame_buffer_->Create();
7664 glFinish();
7665 }
7666
7667 // Allocate the offscreen saved color texture.
7668 DCHECK(offscreen_saved_color_format_);
7669 offscreen_saved_color_texture_->AllocateStorage(
7670 offscreen_size_, offscreen_saved_color_format_);
[email protected]1078f912011-12-23 13:12:147671 UpdateBackbufferMemoryAccounting();
[email protected]1fb8c482011-08-31 01:01:537672
7673 offscreen_saved_frame_buffer_->AttachRenderTexture(
7674 offscreen_saved_color_texture_.get());
7675 if (offscreen_saved_frame_buffer_->CheckStatus() !=
7676 GL_FRAMEBUFFER_COMPLETE) {
7677 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
7678 << "because offscreen saved FBO was incomplete.";
7679 return error::kLostContext;
7680 }
7681
[email protected]1fb8c482011-08-31 01:01:537682 // Clear the offscreen color texture.
7683 // TODO(piman): Is this still necessary?
7684 {
7685 ScopedFrameBufferBinder binder(this,
7686 offscreen_saved_frame_buffer_->id());
7687 glClearColor(0, 0, 0, 0);
7688 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
7689 glDisable(GL_SCISSOR_TEST);
7690 glClear(GL_COLOR_BUFFER_BIT);
7691 RestoreClearState();
7692 }
7693
7694 UpdateParentTextureInfo();
7695 }
7696
[email protected]6217d392010-03-25 22:08:357697 ScopedGLErrorSuppressor suppressor(this);
7698
[email protected]34ff8b0c2010-10-01 20:06:027699 if (IsOffscreenBufferMultisampled()) {
[email protected]51411e32012-01-19 20:21:137700 // For multisampled buffers, resolve the frame buffer.
[email protected]de26b3c2011-08-03 21:54:277701 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]89d6ed02011-04-20 00:23:237702 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:487703 } else {
[email protected]9a5afa432011-07-22 18:16:397704 if (surface_->IsOffscreen()) {
[email protected]51411e32012-01-19 20:21:137705 ScopedFrameBufferBinder binder(this,
7706 offscreen_target_frame_buffer_->id());
7707
[email protected]8a61d872012-01-20 12:43:567708 if (offscreen_target_buffer_preserved_) {
7709 // Copy the target frame buffer to the saved offscreen texture.
7710 offscreen_saved_color_texture_->Copy(
7711 offscreen_saved_color_texture_->size(),
7712 offscreen_saved_color_format_);
7713 } else {
7714 // Flip the textures in the parent context via the texture manager.
7715 if (!!offscreen_saved_color_texture_info_.get())
7716 offscreen_saved_color_texture_info_->
7717 SetServiceId(offscreen_target_color_texture_->id());
7718
7719 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
7720 offscreen_target_frame_buffer_->AttachRenderTexture(
7721 offscreen_target_color_texture_.get());
7722 }
[email protected]b86b14982010-10-11 18:45:487723
[email protected]a3ded6d2010-10-19 06:44:397724 // Ensure the side effects of the copy are visible to the parent
7725 // context. There is no need to do this for ANGLE because it uses a
7726 // single D3D device for all contexts.
[email protected]b86b14982010-10-11 18:45:487727 if (!IsAngle())
7728 glFlush();
7729 }
[email protected]89d6ed02011-04-20 00:23:237730 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:397731 }
[email protected]6217d392010-03-25 22:08:357732 } else {
[email protected]64ace852011-05-19 21:49:497733 TRACE_EVENT1("gpu", "GLContext::SwapBuffers", "frame", this_frame_number);
[email protected]f62a5ab2011-05-23 20:34:157734 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:017735 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:027736 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:017737 }
[email protected]6217d392010-03-25 22:08:357738 }
7739
[email protected]89d6ed02011-04-20 00:23:237740 return error::kNoError;
[email protected]6217d392010-03-25 22:08:357741}
7742
[email protected]d4239852011-08-12 04:51:227743error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
7744 uint32 immediate_data_size, const gles2::EnableFeatureCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:187745 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287746 if (!bucket || bucket->size() == 0) {
7747 return error::kInvalidArguments;
7748 }
[email protected]d4239852011-08-12 04:51:227749 typedef gles2::EnableFeatureCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:187750 Result* result = GetSharedMemoryAs<Result*>(
7751 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7752 if (!result) {
7753 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:107754 }
[email protected]b1d2dcb2010-05-17 19:24:187755 // Check that the client initialized the result.
7756 if (*result != 0) {
7757 return error::kInvalidArguments;
7758 }
7759 std::string feature_str;
7760 if (!bucket->GetAsString(&feature_str)) {
7761 return error::kInvalidArguments;
7762 }
7763
7764 // TODO(gman): make this some kind of table to function pointer thingy.
[email protected]d4239852011-08-12 04:51:227765 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
[email protected]b1d2dcb2010-05-17 19:24:187766 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]d4239852011-08-12 04:51:227767 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
[email protected]8fbedc02010-11-18 18:43:407768 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
7769 // TODO(gman): decide how to remove the need for this const_cast.
7770 // I could make validators_ non const but that seems bad as this is the only
7771 // place it is needed. I could make some special friend class of validators
7772 // just to allow this to set them. That seems silly. I could refactor this
7773 // code to use the extension mechanism or the initialization attributes to
7774 // turn this feature on. Given that the only real point of this is to make
7775 // the conformance tests pass and given that there is lots of real work that
7776 // needs to be done it seems like refactoring for one to one of those
7777 // methods is a very low priority.
7778 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]f0d74742011-10-03 16:31:047779 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
7780 force_webgl_glsl_validation_ = true;
7781 InitializeShaderTranslator();
[email protected]b1d2dcb2010-05-17 19:24:187782 } else {
7783 return error::kNoError;
7784 }
7785
7786 *result = 1; // true.
7787 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:107788}
7789
[email protected]c2f8c8402010-12-06 18:07:247790error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
7791 uint32 immediate_data_size,
7792 const gles2::GetRequestableExtensionsCHROMIUM& c) {
7793 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]80eb6b52012-01-19 00:14:417794 FeatureInfo::Ref info(new FeatureInfo());
[email protected]e82fb792011-09-22 00:33:297795 info->Initialize(disallowed_features_, NULL);
[email protected]c2f8c8402010-12-06 18:07:247796 bucket->SetFromString(info->extensions().c_str());
7797 return error::kNoError;
7798}
7799
7800error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
7801 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
7802 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287803 if (!bucket || bucket->size() == 0) {
7804 return error::kInvalidArguments;
7805 }
[email protected]c2f8c8402010-12-06 18:07:247806 std::string feature_str;
7807 if (!bucket->GetAsString(&feature_str)) {
7808 return error::kInvalidArguments;
7809 }
7810
7811 bool std_derivatives_enabled =
7812 feature_info_->feature_flags().oes_standard_derivatives;
7813 bool webglsl_enabled =
7814 feature_info_->feature_flags().chromium_webglsl;
7815
7816 feature_info_->AddFeatures(feature_str.c_str());
7817
[email protected]f0d74742011-10-03 16:31:047818 bool initialization_required = false;
7819 if (force_webgl_glsl_validation_ && !derivatives_explicitly_enabled_) {
7820 size_t derivatives_offset = feature_str.find(kOESDerivativeExtension);
7821 if (std::string::npos != derivatives_offset) {
7822 derivatives_explicitly_enabled_ = true;
7823 initialization_required = true;
7824 }
7825 }
7826
[email protected]c2f8c8402010-12-06 18:07:247827 // If we just enabled a feature which affects the shader translator,
7828 // we may need to re-initialize it.
7829 if (std_derivatives_enabled !=
7830 feature_info_->feature_flags().oes_standard_derivatives ||
7831 webglsl_enabled !=
[email protected]f0d74742011-10-03 16:31:047832 feature_info_->feature_flags().chromium_webglsl ||
7833 initialization_required) {
[email protected]c2f8c8402010-12-06 18:07:247834 InitializeShaderTranslator();
7835 }
7836
[email protected]302ce6d2011-07-07 23:28:117837 UpdateCapabilities();
7838
[email protected]c2f8c8402010-12-06 18:07:247839 return error::kNoError;
7840}
7841
[email protected]372e0412011-06-28 16:08:567842error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
7843 uint32 immediate_data_size, const gles2::GetMultipleIntegervCHROMIUM& c) {
7844 GLuint count = c.count;
7845 uint32 pnames_size;
7846 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
7847 return error::kOutOfBounds;
7848 }
7849 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
7850 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
7851 if (pnames == NULL) {
7852 return error::kOutOfBounds;
7853 }
7854
7855 // We have to copy them since we use them twice so the client
7856 // can't change them between the time we validate them and the time we use
7857 // them.
7858 scoped_array<GLenum> enums(new GLenum[count]);
7859 memcpy(enums.get(), pnames, pnames_size);
7860
7861 // Count up the space needed for the result.
7862 uint32 num_results = 0;
7863 for (GLuint ii = 0; ii < count; ++ii) {
7864 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
7865 if (num == 0) {
7866 SetGLError(GL_INVALID_ENUM,
7867 "glGetMulitpleCHROMIUM: pname GL_INVALID_ENUM");
7868 return error::kNoError;
7869 }
7870 // Num will never be more than 4.
7871 DCHECK_LE(num, 4u);
7872 if (!SafeAdd(num_results, num, &num_results)) {
7873 return error::kOutOfBounds;
7874 }
7875 }
7876
7877 uint32 result_size = 0;
7878 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
7879 return error::kOutOfBounds;
7880 }
7881
7882 if (result_size != static_cast<uint32>(c.size)) {
7883 SetGLError(GL_INVALID_VALUE,
7884 "glGetMulitpleCHROMIUM: bad size GL_INVALID_VALUE");
7885 return error::kNoError;
7886 }
7887
7888 GLint* results = GetSharedMemoryAs<GLint*>(
7889 c.results_shm_id, c.results_shm_offset, result_size);
7890 if (results == NULL) {
7891 return error::kOutOfBounds;
7892 }
7893
7894 // Check the results have been cleared in case the context was lost.
7895 for (uint32 ii = 0; ii < num_results; ++ii) {
7896 if (results[ii]) {
7897 return error::kInvalidArguments;
7898 }
7899 }
7900
7901 // Get each result.
7902 GLint* start = results;
7903 for (GLuint ii = 0; ii < count; ++ii) {
7904 GLsizei num_written = 0;
7905 if (!GetHelper(enums[ii], results, &num_written)) {
7906 glGetIntegerv(enums[ii], results);
7907 }
7908 results += num_written;
7909 }
7910
7911 // Just to verify. Should this be a DCHECK?
7912 if (static_cast<uint32>(results - start) != num_results) {
7913 return error::kOutOfBounds;
7914 }
7915
7916 return error::kNoError;
7917}
7918
[email protected]2318d342011-07-11 22:27:427919error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
7920 uint32 immediate_data_size, const gles2::GetProgramInfoCHROMIUM& c) {
7921 GLuint program = static_cast<GLuint>(c.program);
7922 uint32 bucket_id = c.bucket_id;
7923 Bucket* bucket = CreateBucket(bucket_id);
7924 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
7925 ProgramManager::ProgramInfo* info = NULL;
[email protected]9a14ae612011-08-08 17:51:467926 info = GetProgramInfo(program);
7927 if (!info || !info->IsValid()) {
7928 return error::kNoError;
[email protected]2318d342011-07-11 22:27:427929 }
[email protected]5d4c6b22012-02-07 08:22:287930 info->GetProgramInfo(program_manager(), bucket);
[email protected]2318d342011-07-11 22:27:427931 return error::kNoError;
7932}
7933
[email protected]38d139d2011-07-14 00:38:437934error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
7935 switch (reset_status_) {
7936 case GL_NO_ERROR:
7937 // TODO(kbr): improve the precision of the error code in this case.
7938 // Consider delegating to context for error code if MakeCurrent fails.
7939 return error::kUnknown;
7940 case GL_GUILTY_CONTEXT_RESET_ARB:
7941 return error::kGuilty;
7942 case GL_INNOCENT_CONTEXT_RESET_ARB:
7943 return error::kInnocent;
7944 case GL_UNKNOWN_CONTEXT_RESET_ARB:
7945 return error::kUnknown;
7946 }
7947
7948 NOTREACHED();
7949 return error::kUnknown;
7950}
7951
7952bool GLES2DecoderImpl::WasContextLost() {
7953 if (context_->WasAllocatedUsingARBRobustness() && has_arb_robustness_) {
7954 GLenum status = glGetGraphicsResetStatusARB();
7955 if (status != GL_NO_ERROR) {
7956 // The graphics card was reset. Signal a lost context to the application.
7957 reset_status_ = status;
7958 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
7959 << " context lost via ARB_robustness. Reset status = 0x"
7960 << std::hex << status << std::dec;
7961 return true;
7962 }
7963 }
7964 return false;
7965}
7966
[email protected]882ba1e22012-03-08 19:02:537967bool GLES2DecoderImpl::GenQueriesEXTHelper(
7968 GLsizei n, const GLuint* client_ids) {
7969 for (GLsizei ii = 0; ii < n; ++ii) {
7970 if (query_manager_->GetQuery(client_ids[ii])) {
7971 return false;
7972 }
7973 }
[email protected]c45f1972012-03-14 07:27:367974 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
[email protected]882ba1e22012-03-08 19:02:537975 return true;
7976}
7977
7978void GLES2DecoderImpl::DeleteQueriesEXTHelper(
7979 GLsizei n, const GLuint* client_ids) {
7980 for (GLsizei ii = 0; ii < n; ++ii) {
7981 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
7982 if (query && !query->IsDeleted()) {
7983 if (query == current_query_) {
7984 current_query_ = NULL;
7985 }
[email protected]c45f1972012-03-14 07:27:367986 query->Destroy(true);
[email protected]882ba1e22012-03-08 19:02:537987 query_manager_->RemoveQuery(client_ids[ii]);
7988 }
7989 }
7990}
7991
[email protected]22e3f552012-03-13 01:54:197992bool GLES2DecoderImpl::ProcessPendingQueries() {
7993 if (query_manager_.get() == NULL) {
7994 return false;
7995 }
[email protected]c45f1972012-03-14 07:27:367996 if (!query_manager_->ProcessPendingQueries()) {
[email protected]22e3f552012-03-13 01:54:197997 current_decoder_error_ = error::kOutOfBounds;
7998 }
7999 return query_manager_->HavePendingQueries();
8000}
8001
[email protected]882ba1e22012-03-08 19:02:538002error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
8003 uint32 immediate_data_size, const gles2::BeginQueryEXT& c) {
8004 GLenum target = static_cast<GLenum>(c.target);
8005 GLuint client_id = static_cast<GLuint>(c.id);
8006 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
8007 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
8008
[email protected]c45f1972012-03-14 07:27:368009 switch (target) {
8010 case GL_COMMANDS_ISSUED_CHROMIUM:
8011 break;
8012 default:
8013 if (!feature_info_->feature_flags().occlusion_query_boolean) {
8014 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT: not enabled");
8015 return error::kNoError;
8016 }
8017 break;
[email protected]882ba1e22012-03-08 19:02:538018 }
8019
8020 if (current_query_) {
8021 SetGLError(
8022 GL_INVALID_OPERATION, "glBeginQueryEXT: query already in progress");
8023 return error::kNoError;
8024 }
8025
8026 if (client_id == 0) {
8027 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT: id is 0");
8028 return error::kNoError;
8029 }
8030
8031 QueryManager::Query* query = query_manager_->GetQuery(client_id);
8032 if (!query) {
[email protected]c45f1972012-03-14 07:27:368033 // TODO(gman): Decide if we need this check.
8034 //
[email protected]882ba1e22012-03-08 19:02:538035 // Checks id was made by glGenQueries
[email protected]c45f1972012-03-14 07:27:368036 //
8037 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
8038 // for all Query ids but from the POV of the command buffer service maybe
8039 // you don't.
8040 //
8041 // The client can enforce this. I don't think the service cares.
8042 //
8043 // IdAllocatorInterface* id_allocator =
8044 // group_->GetIdAllocator(id_namespaces::kQueries);
8045 // if (!id_allocator->InUse(client_id)) {
8046 // SetGLError(GL_INVALID_OPERATION,
8047 // "glBeginQueryEXT: id not made by glGenQueriesEXT");
8048 // return error::kNoError;
8049 // }
8050 query = query_manager_->CreateQuery(
8051 target, client_id, sync_shm_id, sync_shm_offset);
[email protected]882ba1e22012-03-08 19:02:538052 }
8053
[email protected]c45f1972012-03-14 07:27:368054 if (query->target() != target) {
[email protected]882ba1e22012-03-08 19:02:538055 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT: target does not match");
8056 return error::kNoError;
8057 } else if (query->shm_id() != sync_shm_id ||
8058 query->shm_offset() != sync_shm_offset) {
8059 DLOG(ERROR) << "Shared memory used by query not the same as before";
8060 return error::kInvalidArguments;
8061 }
8062
[email protected]c45f1972012-03-14 07:27:368063 if (!query_manager_->BeginQuery(query)) {
8064 return error::kOutOfBounds;
8065 }
[email protected]882ba1e22012-03-08 19:02:538066
[email protected]882ba1e22012-03-08 19:02:538067 current_query_ = query;
[email protected]882ba1e22012-03-08 19:02:538068 return error::kNoError;
8069}
8070
8071error::Error GLES2DecoderImpl::HandleEndQueryEXT(
8072 uint32 immediate_data_size, const gles2::EndQueryEXT& c) {
8073 GLenum target = static_cast<GLenum>(c.target);
8074 uint32 submit_count = static_cast<GLuint>(c.submit_count);
8075
8076 if (!current_query_) {
8077 SetGLError(GL_INVALID_OPERATION, "glEndQueryEXT: No active query");
8078 return error::kNoError;
8079 }
8080 if (current_query_->target() != target) {
8081 SetGLError(GL_INVALID_OPERATION,
8082 "glEndQueryEXT: target does not match active query");
8083 return error::kNoError;
8084 }
[email protected]882ba1e22012-03-08 19:02:538085
[email protected]c45f1972012-03-14 07:27:368086 if (!query_manager_->EndQuery(current_query_, submit_count)) {
8087 return error::kOutOfBounds;
8088 }
8089
8090 current_query_ = NULL;
[email protected]882ba1e22012-03-08 19:02:538091 return error::kNoError;
8092}
8093
[email protected]b0af4f52011-09-28 22:04:428094error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
8095 uint32 immediate_data_size,
8096 const gles2::CreateStreamTextureCHROMIUM& c) {
8097 if (!feature_info_->feature_flags().chromium_stream_texture) {
8098 SetGLError(GL_INVALID_OPERATION,
8099 "glOpenStreamTextureCHROMIUM: "
8100 "not supported.");
8101 return error::kNoError;
8102 }
8103
8104 uint32 client_id = c.client_id;
8105 typedef gles2::CreateStreamTextureCHROMIUM::Result Result;
8106 Result* result = GetSharedMemoryAs<Result*>(
8107 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8108
[email protected]e5081262012-01-05 23:09:038109 if (!result)
8110 return error::kOutOfBounds;
[email protected]b0af4f52011-09-28 22:04:428111 *result = GL_ZERO;
8112 TextureManager::TextureInfo* info =
8113 texture_manager()->GetTextureInfo(client_id);
8114 if (!info) {
8115 SetGLError(GL_INVALID_VALUE,
8116 "glCreateStreamTextureCHROMIUM: "
8117 "bad texture id.");
8118 return error::kNoError;
8119 }
8120
8121 if (info->IsStreamTexture()) {
8122 SetGLError(GL_INVALID_OPERATION,
8123 "glCreateStreamTextureCHROMIUM: "
8124 "is already a stream texture.");
8125 return error::kNoError;
8126 }
8127
8128 if (info->target() && info->target() != GL_TEXTURE_EXTERNAL_OES) {
8129 SetGLError(GL_INVALID_OPERATION,
8130 "glCreateStreamTextureCHROMIUM: "
8131 "is already bound to incompatible target.");
8132 return error::kNoError;
8133 }
8134
8135 if (!stream_texture_manager_)
8136 return error::kInvalidArguments;
8137
8138 GLuint object_id = stream_texture_manager_->CreateStreamTexture(
8139 info->service_id(), client_id);
8140
8141 if (object_id) {
8142 info->SetStreamTexture(true);
8143 } else {
8144 SetGLError(GL_OUT_OF_MEMORY,
8145 "glCreateStreamTextureCHROMIUM: "
8146 "failed to create platform texture.");
8147 }
8148
8149 *result = object_id;
8150 return error::kNoError;
8151}
8152
8153error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
8154 uint32 immediate_data_size,
8155 const gles2::DestroyStreamTextureCHROMIUM& c) {
8156 GLuint client_id = c.texture;
8157 TextureManager::TextureInfo* info =
8158 texture_manager()->GetTextureInfo(client_id);
8159 if (info && info->IsStreamTexture()) {
8160 if (!stream_texture_manager_)
8161 return error::kInvalidArguments;
8162
8163 stream_texture_manager_->DestroyStreamTexture(info->service_id());
8164 info->SetStreamTexture(false);
[email protected]80eb6b52012-01-19 00:14:418165 texture_manager()->SetInfoTarget(info, 0);
[email protected]b0af4f52011-09-28 22:04:428166 } else {
8167 SetGLError(GL_INVALID_VALUE,
8168 "glDestroyStreamTextureCHROMIUM: bad texture id.");
8169 }
8170
8171 return error::kNoError;
8172}
8173
[email protected]e51bdf32011-11-23 22:21:468174#if defined(OS_MACOSX)
8175void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
8176 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
8177 texture_id);
8178 if (it != texture_to_io_surface_map_.end()) {
8179 // Found a previous IOSurface bound to this texture; release it.
8180 CFTypeRef surface = it->second;
8181 CFRelease(surface);
8182 texture_to_io_surface_map_.erase(it);
8183 }
8184}
8185#endif
8186
8187void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
8188 GLenum target, GLsizei width, GLsizei height,
8189 GLuint io_surface_id, GLuint plane) {
8190#if defined(OS_MACOSX)
8191 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
8192 SetGLError(GL_INVALID_OPERATION,
8193 "glTexImageIOSurface2DCHROMIUM: only supported on desktop GL.");
8194 return;
8195 }
8196
8197 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
8198 if (!surface_support) {
8199 SetGLError(GL_INVALID_OPERATION,
8200 "glTexImageIOSurface2DCHROMIUM: only supported on 10.6.");
8201 return;
8202 }
8203
8204 if (target != GL_TEXTURE_RECTANGLE_ARB) {
8205 // This might be supported in the future, and if we could require
8206 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
8207 // could delete a lot of code. For now, perform strict validation so we
8208 // know what's going on.
8209 SetGLError(
8210 GL_INVALID_OPERATION,
8211 "glTexImageIOSurface2DCHROMIUM: requires TEXTURE_RECTANGLE_ARB target");
8212 return;
8213 }
8214
8215 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8216 if (!info) {
8217 SetGLError(GL_INVALID_OPERATION,
8218 "glTexImageIOSurface2DCHROMIUM: no rectangle texture bound");
8219 return;
8220 }
8221 if (info == texture_manager()->GetDefaultTextureInfo(target)) {
8222 // Maybe this is conceptually valid, but disallow it to avoid accidents.
8223 SetGLError(GL_INVALID_OPERATION,
8224 "glTexImageIOSurface2DCHROMIUM: can't bind default texture");
8225 return;
8226 }
8227
8228 // Look up the new IOSurface. Note that because of asynchrony
8229 // between processes this might fail; during live resizing the
8230 // plugin process might allocate and release an IOSurface before
8231 // this process gets a chance to look it up. Hold on to any old
8232 // IOSurface in this case.
8233 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
8234 if (!surface) {
8235 SetGLError(GL_INVALID_OPERATION,
8236 "glTexImageIOSurface2DCHROMIUM: no IOSurface with the given ID");
8237 return;
8238 }
8239
8240 // Release any IOSurface previously bound to this texture.
8241 ReleaseIOSurfaceForTexture(info->service_id());
8242
8243 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
8244 texture_to_io_surface_map_.insert(
8245 std::make_pair(info->service_id(), surface));
8246
8247 CGLContextObj context =
8248 static_cast<CGLContextObj>(context_->GetHandle());
8249
8250 CGLError err = surface_support->CGLTexImageIOSurface2D(
8251 context,
8252 target,
8253 GL_RGBA,
8254 width,
8255 height,
8256 GL_BGRA,
8257 GL_UNSIGNED_INT_8_8_8_8_REV,
8258 surface,
8259 plane);
8260
8261 if (err != kCGLNoError) {
8262 SetGLError(
8263 GL_INVALID_OPERATION,
8264 "glTexImageIOSurface2DCHROMIUM: error in CGLTexImageIOSurface2D");
8265 return;
8266 }
8267
8268 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:418269 info, target, 0, GL_RGBA, width, height, 1, 0,
[email protected]e51bdf32011-11-23 22:21:468270 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
8271
8272#else
8273 SetGLError(GL_INVALID_OPERATION,
8274 "glTexImageIOSurface2DCHROMIUM: not supported.");
8275#endif
8276}
8277
[email protected]97dc7cbe2011-12-06 17:26:178278static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
8279 switch (internalformat) {
8280 case GL_RGB565:
8281 return GL_RGB;
8282 case GL_RGBA4:
8283 return GL_RGBA;
8284 case GL_RGB5_A1:
8285 return GL_RGBA;
8286 case GL_RGB8_OES:
8287 return GL_RGB;
8288 case GL_RGBA8_OES:
8289 return GL_RGBA;
8290 case GL_LUMINANCE8_ALPHA8_EXT:
8291 return GL_LUMINANCE_ALPHA;
8292 case GL_LUMINANCE8_EXT:
8293 return GL_LUMINANCE;
8294 case GL_ALPHA8_EXT:
8295 return GL_ALPHA;
8296 case GL_RGBA32F_EXT:
8297 return GL_RGBA;
8298 case GL_RGB32F_EXT:
8299 return GL_RGB;
8300 case GL_ALPHA32F_EXT:
8301 return GL_ALPHA;
8302 case GL_LUMINANCE32F_EXT:
8303 return GL_LUMINANCE;
8304 case GL_LUMINANCE_ALPHA32F_EXT:
8305 return GL_LUMINANCE_ALPHA;
8306 case GL_RGBA16F_EXT:
8307 return GL_RGBA;
8308 case GL_RGB16F_EXT:
8309 return GL_RGB;
8310 case GL_ALPHA16F_EXT:
8311 return GL_ALPHA;
8312 case GL_LUMINANCE16F_EXT:
8313 return GL_LUMINANCE;
8314 case GL_LUMINANCE_ALPHA16F_EXT:
8315 return GL_LUMINANCE_ALPHA;
8316 case GL_BGRA8_EXT:
8317 return GL_BGRA_EXT;
8318 default:
8319 return GL_NONE;
8320 }
8321}
8322
8323static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
8324 switch (internalformat) {
8325 case GL_RGB565:
8326 return GL_UNSIGNED_SHORT_5_6_5;
8327 case GL_RGBA4:
8328 return GL_UNSIGNED_SHORT_4_4_4_4;
8329 case GL_RGB5_A1:
8330 return GL_UNSIGNED_SHORT_5_5_5_1;
8331 case GL_RGB8_OES:
8332 return GL_UNSIGNED_BYTE;
8333 case GL_RGBA8_OES:
8334 return GL_UNSIGNED_BYTE;
8335 case GL_LUMINANCE8_ALPHA8_EXT:
8336 return GL_UNSIGNED_BYTE;
8337 case GL_LUMINANCE8_EXT:
8338 return GL_UNSIGNED_BYTE;
8339 case GL_ALPHA8_EXT:
8340 return GL_UNSIGNED_BYTE;
8341 case GL_RGBA32F_EXT:
8342 return GL_FLOAT;
8343 case GL_RGB32F_EXT:
8344 return GL_FLOAT;
8345 case GL_ALPHA32F_EXT:
8346 return GL_FLOAT;
8347 case GL_LUMINANCE32F_EXT:
8348 return GL_FLOAT;
8349 case GL_LUMINANCE_ALPHA32F_EXT:
8350 return GL_FLOAT;
8351 case GL_RGBA16F_EXT:
8352 return GL_HALF_FLOAT_OES;
8353 case GL_RGB16F_EXT:
8354 return GL_HALF_FLOAT_OES;
8355 case GL_ALPHA16F_EXT:
8356 return GL_HALF_FLOAT_OES;
8357 case GL_LUMINANCE16F_EXT:
8358 return GL_HALF_FLOAT_OES;
8359 case GL_LUMINANCE_ALPHA16F_EXT:
8360 return GL_HALF_FLOAT_OES;
8361 case GL_BGRA8_EXT:
8362 return GL_UNSIGNED_BYTE;
8363 default:
8364 return GL_NONE;
8365 }
8366}
8367
8368void GLES2DecoderImpl::DoTexStorage2DEXT(
8369 GLenum target,
8370 GLint levels,
8371 GLenum internal_format,
8372 GLsizei width,
8373 GLsizei height) {
[email protected]80eb6b52012-01-19 00:14:418374 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
[email protected]97dc7cbe2011-12-06 17:26:178375 TextureManager::ComputeMipMapCount(width, height, 1) < levels) {
8376 SetGLError(GL_INVALID_VALUE, "glTexStorage2DEXT: dimensions out of range");
8377 return;
8378 }
8379 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8380 if (!info) {
8381 SetGLError(GL_INVALID_OPERATION,
8382 "glTexStorage2DEXT: unknown texture for target");
8383 return;
8384 }
8385 if (info->IsAttachedToFramebuffer()) {
8386 state_dirty_ = true;
8387 }
8388 if (info->IsImmutable()) {
8389 SetGLError(GL_INVALID_OPERATION,
8390 "glTexStorage2DEXT: texture is immutable");
8391 return;
8392 }
8393 CopyRealGLErrorsToWrapper();
[email protected]f0e6a34f2012-01-04 20:53:408394 glTexStorage2DEXT(target, levels, GetTexInternalFormat(internal_format),
8395 width, height);
[email protected]97dc7cbe2011-12-06 17:26:178396 GLenum error = PeekGLError();
8397 if (error == GL_NO_ERROR) {
8398 GLenum format = ExtractFormatFromStorageFormat(internal_format);
8399 GLenum type = ExtractTypeFromStorageFormat(internal_format);
[email protected]4502e6492011-12-14 19:39:158400 GLsizei level_width = width;
8401 GLsizei level_height = height;
8402 for (int ii = 0; ii < levels; ++ii) {
8403 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:418404 info, target, 0, format, level_width, level_height, 1, 0, format,
8405 type, false);
[email protected]4502e6492011-12-14 19:39:158406 level_width = std::max(1, level_width >> 1);
8407 level_height = std::max(1, level_height >> 1);
8408 }
[email protected]97dc7cbe2011-12-06 17:26:178409 info->SetImmutable(true);
8410 }
[email protected]97dc7cbe2011-12-06 17:26:178411}
[email protected]e51bdf32011-11-23 22:21:468412
[email protected]96449d2c2009-11-25 00:01:328413// Include the auto-generated part of this file. We split this because it means
8414// we can easily edit the non-auto generated parts right here in this file
8415// instead of having to edit some template or the code generator.
8416#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
8417
8418} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:258419} // namespace gpu