blob: eafb386927e79d3ba0aaaea26fb18c05b724f5ec [file] [log] [blame]
[email protected]529c6672012-01-04 02:18:261// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]96449d2c2009-11-25 00:01:322// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]8a837bb2010-01-05 00:21:245#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
[email protected]74470702010-01-06 18:51:166
7#include <stdio.h>
8
[email protected]1aef98132010-02-23 18:00:079#include <algorithm>
[email protected]f39f4b3f2010-05-12 17:04:0810#include <list>
[email protected]96449d2c2009-11-25 00:01:3211#include <map>
[email protected]f39f4b3f2010-05-12 17:04:0812#include <string>
13#include <vector>
[email protected]5a6db6c2010-04-22 18:32:0614
[email protected]1e6f58d2011-03-24 00:00:4015#include "base/atomicops.h"
[email protected]00eb49a2010-08-12 20:46:5716#include "base/at_exit.h"
[email protected]9d37f062011-11-22 01:24:5217#include "base/bind.h"
[email protected]e844ae22012-01-14 03:36:2618#include "base/command_line.h"
[email protected]1078f912011-12-23 13:12:1419#include "base/debug/trace_event.h"
[email protected]e51bdf32011-11-23 22:21:4620#if defined(OS_MACOSX)
21#include "base/mac/scoped_cftyperef.h"
22#endif
[email protected]3b63f8f42011-03-28 01:54:1523#include "base/memory/scoped_ptr.h"
24#include "base/memory/weak_ptr.h"
[email protected]d37231fa2010-04-09 21:16:0225#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3226#define GLES2_GPU_SERVICE 1
27#include "gpu/command_buffer/common/gles2_cmd_format.h"
28#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1029#include "gpu/command_buffer/common/id_allocator.h"
[email protected]3916c97e2010-02-25 03:20:5030#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3231#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5032#include "gpu/command_buffer/service/context_group.h"
[email protected]915a59a12010-09-30 21:29:1133#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5834#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3235#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4636#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]e844ae22012-01-14 03:36:2637#include "gpu/command_buffer/service/gpu_switches.h"
[email protected]a93bb842010-02-16 23:03:4738#include "gpu/command_buffer/service/program_manager.h"
[email protected]a25fa872010-03-25 02:57:5839#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4740#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4541#include "gpu/command_buffer/service/shader_translator.h"
[email protected]b0af4f52011-09-28 22:04:4242#include "gpu/command_buffer/service/stream_texture.h"
43#include "gpu/command_buffer/service/stream_texture_manager.h"
[email protected]a93bb842010-02-16 23:03:4744#include "gpu/command_buffer/service/texture_manager.h"
[email protected]d8ea9772011-07-11 18:11:4345#include "gpu/command_buffer/service/vertex_attrib_manager.h"
[email protected]5ae0b282011-03-28 19:24:4946#include "ui/gfx/gl/gl_context.h"
47#include "ui/gfx/gl/gl_implementation.h"
[email protected]f62a5ab2011-05-23 20:34:1548#include "ui/gfx/gl/gl_surface.h"
[email protected]e51bdf32011-11-23 22:21:4649#if defined(OS_MACOSX)
50#include "ui/gfx/surface/io_surface_support_mac.h"
51#endif
[email protected]de17df392010-04-23 21:09:4152
[email protected]6217d392010-03-25 22:08:3553#if !defined(GL_DEPTH24_STENCIL8)
54#define GL_DEPTH24_STENCIL8 0x88F0
55#endif
56
[email protected]a7a27ace2009-12-12 00:11:2557namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3258namespace gles2 {
59
[email protected]f0d74742011-10-03 16:31:0460namespace {
61static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
62}
63
[email protected]6217d392010-03-25 22:08:3564class GLES2DecoderImpl;
65
[email protected]07f54fcc2009-12-22 02:46:3066// Check that certain assumptions the code makes are true. There are places in
67// the code where shared memory is passed direclty to GL. Example, glUniformiv,
68// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
69// a few others) are 32bits. If they are not 32bits the code will have to change
70// to call those GL functions with service side memory and then copy the results
71// to shared memory, converting the sizes.
72COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
73 GLint_not_same_size_as_uint32);
74COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
75 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3776COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
77 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3078
[email protected]43f28f832010-02-03 02:28:4879// TODO(kbr): the use of this anonymous namespace core dumps the
80// linker on Mac OS X 10.6 when the symbol ordering file is used
81// namespace {
[email protected]96449d2c2009-11-25 00:01:3282
83// Returns the address of the first byte after a struct.
84template <typename T>
85const void* AddressAfterStruct(const T& pod) {
86 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
87}
88
[email protected]07f54fcc2009-12-22 02:46:3089// Returns the address of the frst byte after the struct or NULL if size >
90// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3291template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3092RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
93 uint32 size,
94 uint32 immediate_data_size) {
95 return (size <= immediate_data_size) ?
96 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
97 NULL;
[email protected]96449d2c2009-11-25 00:01:3298}
99
[email protected]07f54fcc2009-12-22 02:46:30100// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:18101bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:32102 GLuint count,
103 size_t size,
[email protected]a76b0052010-03-05 00:33:18104 unsigned int elements_per_unit,
105 uint32* dst) {
106 uint32 value;
107 if (!SafeMultiplyUint32(count, size, &value)) {
108 return false;
109 }
110 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
111 return false;
112 }
113 *dst = value;
114 return true;
[email protected]96449d2c2009-11-25 00:01:32115}
116
117// A struct to hold info about each command.
118struct CommandInfo {
119 int arg_flags; // How to handle the arguments for this command
120 int arg_count; // How many arguments are expected for this command.
121};
122
123// A table of CommandInfo for all the commands.
124const CommandInfo g_command_info[] = {
125 #define GLES2_CMD_OP(name) { \
126 name::kArgFlags, \
127 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
128
129 GLES2_COMMAND_LIST(GLES2_CMD_OP)
130
131 #undef GLES2_CMD_OP
132};
133
[email protected]34ff8b0c2010-10-01 20:06:02134static bool IsAngle() {
135#if defined(OS_WIN)
136 return gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
137#else
138 return false;
139#endif
140}
141
[email protected]258a3313f2011-10-18 20:13:57142// Return true if a character belongs to the ASCII subset as defined in
143// GLSL ES 1.0 spec section 3.1.
144static bool CharacterIsValidForGLES(unsigned char c) {
145 // Printing characters are valid except " $ ` @ \ ' DEL.
146 if (c >= 32 && c <= 126 &&
147 c != '"' &&
148 c != '$' &&
149 c != '`' &&
150 c != '@' &&
151 c != '\\' &&
152 c != '\'') {
153 return true;
154 }
155 // Horizontal tab, line feed, vertical tab, form feed, carriage return
156 // are also valid.
157 if (c >= 9 && c <= 13) {
158 return true;
159 }
160
161 return false;
162}
163
164static bool StringIsValidForGLES(const char* str) {
165 for (; *str; ++str) {
166 if (!CharacterIsValidForGLES(*str)) {
167 return false;
168 }
169 }
170 return true;
171}
172
[email protected]f0e6a34f2012-01-04 20:53:40173static inline GLenum GetTexInternalFormat(GLenum internal_format) {
174 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
175 if (internal_format == GL_BGRA_EXT || internal_format == GL_BGRA8_EXT)
176 return GL_RGBA8;
177 }
178 return internal_format;
179}
180
[email protected]297ca1c2011-06-20 23:08:46181static void WrappedTexImage2D(
[email protected]473c01ccb2011-06-07 01:33:30182 GLenum target,
183 GLint level,
184 GLenum internal_format,
185 GLsizei width,
186 GLsizei height,
187 GLint border,
188 GLenum format,
189 GLenum type,
190 const void* pixels) {
[email protected]f0e6a34f2012-01-04 20:53:40191 GLenum gl_internal_format = GetTexInternalFormat(internal_format);
[email protected]473c01ccb2011-06-07 01:33:30192 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]f0e6a34f2012-01-04 20:53:40193 if (type == GL_FLOAT) {
[email protected]473c01ccb2011-06-07 01:33:30194 if (format == GL_RGBA) {
195 gl_internal_format = GL_RGBA32F_ARB;
196 } else if (format == GL_RGB) {
197 gl_internal_format = GL_RGB32F_ARB;
198 }
199 } else if (type == GL_HALF_FLOAT_OES) {
200 if (format == GL_RGBA) {
201 gl_internal_format = GL_RGBA16F_ARB;
202 } else if (format == GL_RGB) {
203 gl_internal_format = GL_RGB16F_ARB;
204 }
205 }
206 }
207 glTexImage2D(
208 target, level, gl_internal_format, width, height, border, format, type,
209 pixels);
210}
211
[email protected]297ca1c2011-06-20 23:08:46212// Wrapper for glEnable/glDisable that doesn't suck.
213static void EnableDisable(GLenum pname, bool enable) {
214 if (enable) {
215 glEnable(pname);
216 } else {
217 glDisable(pname);
218 }
219}
220
[email protected]6217d392010-03-25 22:08:35221// This class prevents any GL errors that occur when it is in scope from
222// being reported to the client.
223class ScopedGLErrorSuppressor {
224 public:
225 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
226 ~ScopedGLErrorSuppressor();
227 private:
228 GLES2DecoderImpl* decoder_;
229 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
230};
231
232// Temporarily changes a decoder's bound 2D texture and restore it when this
233// object goes out of scope. Also temporarily switches to using active texture
234// unit zero in case the client has changed that to something invalid.
235class ScopedTexture2DBinder {
236 public:
237 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
238 ~ScopedTexture2DBinder();
239
240 private:
241 GLES2DecoderImpl* decoder_;
242 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
243};
244
245// Temporarily changes a decoder's bound render buffer and restore it when this
246// object goes out of scope.
247class ScopedRenderBufferBinder {
248 public:
249 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
250 ~ScopedRenderBufferBinder();
251
252 private:
253 GLES2DecoderImpl* decoder_;
254 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
255};
256
257// Temporarily changes a decoder's bound frame buffer and restore it when this
258// object goes out of scope.
259class ScopedFrameBufferBinder {
260 public:
261 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
262 ~ScopedFrameBufferBinder();
263
264 private:
265 GLES2DecoderImpl* decoder_;
266 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
267};
268
[email protected]34ff8b0c2010-10-01 20:06:02269// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52270// the multisampled offscreen render buffer if that buffer is multisampled, and,
[email protected]de26b3c2011-08-03 21:54:27271// if it is bound or enforce_internal_framebuffer is true. If internal is
272// true, the resolved framebuffer is not visible to the parent.
[email protected]34ff8b0c2010-10-01 20:06:02273class ScopedResolvedFrameBufferBinder {
274 public:
[email protected]e7e38032011-07-26 17:25:25275 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
[email protected]de26b3c2011-08-03 21:54:27276 bool enforce_internal_framebuffer,
277 bool internal);
[email protected]34ff8b0c2010-10-01 20:06:02278 ~ScopedResolvedFrameBufferBinder();
279
280 private:
281 GLES2DecoderImpl* decoder_;
282 bool resolve_and_bind_;
283 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
284};
285
[email protected]6217d392010-03-25 22:08:35286// Encapsulates an OpenGL texture.
287class Texture {
288 public:
289 explicit Texture(GLES2DecoderImpl* decoder);
290 ~Texture();
291
292 // Create a new render texture.
293 void Create();
294
295 // Set the initial size and format of a render texture or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02296 bool AllocateStorage(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35297
298 // Copy the contents of the currently bound frame buffer.
[email protected]3a4d0c52011-06-29 23:11:58299 void Copy(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35300
301 // Destroy the render texture. This must be explicitly called before
302 // destroying this object.
303 void Destroy();
304
[email protected]97872062010-11-03 19:07:05305 // Invalidate the texture. This can be used when a context is lost and it is
306 // not possible to make it current in order to free the resource.
307 void Invalidate();
308
[email protected]6217d392010-03-25 22:08:35309 GLuint id() const {
310 return id_;
311 }
312
[email protected]d37231fa2010-04-09 21:16:02313 gfx::Size size() const {
314 return size_;
315 }
316
[email protected]1078f912011-12-23 13:12:14317 size_t estimated_size() const {
318 return estimated_size_;
319 }
320
[email protected]6217d392010-03-25 22:08:35321 private:
322 GLES2DecoderImpl* decoder_;
323 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02324 gfx::Size size_;
[email protected]1078f912011-12-23 13:12:14325 size_t estimated_size_;
[email protected]6217d392010-03-25 22:08:35326 DISALLOW_COPY_AND_ASSIGN(Texture);
327};
328
329// Encapsulates an OpenGL render buffer of any format.
330class RenderBuffer {
331 public:
332 explicit RenderBuffer(GLES2DecoderImpl* decoder);
333 ~RenderBuffer();
334
335 // Create a new render buffer.
336 void Create();
337
338 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02339 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35340
341 // Destroy the render buffer. This must be explicitly called before destroying
342 // this object.
343 void Destroy();
344
[email protected]97872062010-11-03 19:07:05345 // Invalidate the render buffer. This can be used when a context is lost and
346 // it is not possible to make it current in order to free the resource.
347 void Invalidate();
348
[email protected]6217d392010-03-25 22:08:35349 GLuint id() const {
350 return id_;
351 }
352
[email protected]1078f912011-12-23 13:12:14353 size_t estimated_size() const {
354 return estimated_size_;
355 }
356
[email protected]6217d392010-03-25 22:08:35357 private:
358 GLES2DecoderImpl* decoder_;
359 GLuint id_;
[email protected]1078f912011-12-23 13:12:14360 size_t estimated_size_;
[email protected]6217d392010-03-25 22:08:35361 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
362};
363
364// Encapsulates an OpenGL frame buffer.
365class FrameBuffer {
366 public:
367 explicit FrameBuffer(GLES2DecoderImpl* decoder);
368 ~FrameBuffer();
369
370 // Create a new frame buffer.
371 void Create();
372
373 // Attach a color render buffer to a frame buffer.
374 void AttachRenderTexture(Texture* texture);
375
[email protected]b9363b22010-06-09 22:06:15376 // Attach a render buffer to a frame buffer. Note that this unbinds any
377 // currently bound frame buffer.
378 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35379
[email protected]6217d392010-03-25 22:08:35380 // Destroy the frame buffer. This must be explicitly called before destroying
381 // this object.
382 void Destroy();
383
[email protected]97872062010-11-03 19:07:05384 // Invalidate the frame buffer. This can be used when a context is lost and it
385 // is not possible to make it current in order to free the resource.
386 void Invalidate();
387
[email protected]6217d392010-03-25 22:08:35388 // See glCheckFramebufferStatusEXT.
389 GLenum CheckStatus();
390
391 GLuint id() const {
392 return id_;
393 }
394
395 private:
396 GLES2DecoderImpl* decoder_;
397 GLuint id_;
398 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
399};
[email protected]34ff8b0c2010-10-01 20:06:02400
401class ContextCreationAttribParser {
402 public:
403 ContextCreationAttribParser();
404 bool Parse(const std::vector<int32>& attribs);
405
406 // -1 if invalid or unspecified.
407 int32 alpha_size_;
408 int32 blue_size_;
409 int32 green_size_;
410 int32 red_size_;
411 int32 depth_size_;
412 int32 stencil_size_;
413 int32 samples_;
414 int32 sample_buffers_;
[email protected]8a61d872012-01-20 12:43:56415 bool buffer_preserved_;
[email protected]34ff8b0c2010-10-01 20:06:02416};
417
418ContextCreationAttribParser::ContextCreationAttribParser()
419 : alpha_size_(-1),
420 blue_size_(-1),
421 green_size_(-1),
422 red_size_(-1),
423 depth_size_(-1),
424 stencil_size_(-1),
425 samples_(-1),
[email protected]8a61d872012-01-20 12:43:56426 sample_buffers_(-1),
427 buffer_preserved_(true) {
[email protected]34ff8b0c2010-10-01 20:06:02428}
429
430bool ContextCreationAttribParser::Parse(const std::vector<int32>& attribs) {
431 // From <EGL/egl.h>.
432 const int32 EGL_ALPHA_SIZE = 0x3021;
433 const int32 EGL_BLUE_SIZE = 0x3022;
434 const int32 EGL_GREEN_SIZE = 0x3023;
435 const int32 EGL_RED_SIZE = 0x3024;
436 const int32 EGL_DEPTH_SIZE = 0x3025;
437 const int32 EGL_STENCIL_SIZE = 0x3026;
438 const int32 EGL_SAMPLES = 0x3031;
439 const int32 EGL_SAMPLE_BUFFERS = 0x3032;
440 const int32 EGL_NONE = 0x3038;
[email protected]8a61d872012-01-20 12:43:56441 const int32 EGL_SWAP_BEHAVIOR = 0x3093;
442 const int32 EGL_BUFFER_PRESERVED = 0x3094;
[email protected]34ff8b0c2010-10-01 20:06:02443
444 for (size_t i = 0; i < attribs.size(); i += 2) {
445 const int32 attrib = attribs[i];
446 if (i + 1 >= attribs.size()) {
447 if (attrib == EGL_NONE)
448 return true;
449
450 DLOG(ERROR) << "Missing value after context creation attribute: "
451 << attrib;
452 return false;
453 }
454
455 const int32 value = attribs[i+1];
456 switch (attrib) {
457 case EGL_ALPHA_SIZE:
458 alpha_size_ = value;
459 break;
460 case EGL_BLUE_SIZE:
461 blue_size_ = value;
462 break;
463 case EGL_GREEN_SIZE:
464 green_size_ = value;
465 break;
466 case EGL_RED_SIZE:
467 red_size_ = value;
468 break;
469 case EGL_DEPTH_SIZE:
470 depth_size_ = value;
471 break;
472 case EGL_STENCIL_SIZE:
473 stencil_size_ = value;
474 break;
475 case EGL_SAMPLES:
476 samples_ = value;
477 break;
478 case EGL_SAMPLE_BUFFERS:
479 sample_buffers_ = value;
480 break;
[email protected]8a61d872012-01-20 12:43:56481 case EGL_SWAP_BEHAVIOR:
482 buffer_preserved_ = value == EGL_BUFFER_PRESERVED;
483 break;
[email protected]34ff8b0c2010-10-01 20:06:02484 case EGL_NONE:
485 // Terminate list, even if more attributes.
486 return true;
487 default:
488 DLOG(ERROR) << "Invalid context creation attribute: " << attrib;
489 return false;
490 }
491 }
492
493 return true;
494}
495
[email protected]43f28f832010-02-03 02:28:48496// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32497
[email protected]ddb1e5a2010-12-13 20:10:45498bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
499 uint32* service_texture_id) {
500 return false;
501}
502
[email protected]a3ded6d2010-10-19 06:44:39503GLES2Decoder::GLES2Decoder()
[email protected]e844ae22012-01-14 03:36:26504 : debug_(false),
505 log_commands_(false) {
[email protected]96449d2c2009-11-25 00:01:32506}
507
[email protected]3916c97e2010-02-25 03:20:50508GLES2Decoder::~GLES2Decoder() {
509}
510
[email protected]f39f4b3f2010-05-12 17:04:08511// This class implements GLES2Decoder so we don't have to expose all the GLES2
512// cmd stuff to outside this class.
513class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
514 public GLES2Decoder {
515 public:
[email protected]aa7666122011-09-02 19:45:52516 explicit GLES2DecoderImpl(ContextGroup* group);
[email protected]80eb6b52012-01-19 00:14:41517 ~GLES2DecoderImpl();
[email protected]f39f4b3f2010-05-12 17:04:08518
[email protected]96449d2c2009-11-25 00:01:32519 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14520 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50521 unsigned int arg_count,
522 const void* args);
[email protected]96449d2c2009-11-25 00:01:32523
524 // Overridden from AsyncAPIInterface.
525 virtual const char* GetCommandName(unsigned int command_id) const;
526
527 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38528 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
529 const scoped_refptr<gfx::GLContext>& context,
[email protected]6217d392010-03-25 22:08:35530 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:29531 const DisallowedFeatures& disallowed_features,
[email protected]a3ded6d2010-10-19 06:44:39532 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:24533 const std::vector<int32>& attribs);
[email protected]96449d2c2009-11-25 00:01:32534 virtual void Destroy();
[email protected]3c644d82011-06-20 19:58:24535 virtual bool SetParent(GLES2Decoder* parent_decoder,
536 uint32 parent_texture_id);
[email protected]799b4b22011-08-22 17:09:59537 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]9a5afa432011-07-22 18:16:39538 void UpdateParentTextureInfo();
[email protected]eb54a562010-01-20 21:55:18539 virtual bool MakeCurrent();
[email protected]a96a6022011-11-04 00:58:12540 virtual void ReleaseCurrent();
[email protected]56ac89b2010-03-17 21:16:55541 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30542 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]f62a5ab2011-05-23 20:34:15543 virtual gfx::GLSurface* GetGLSurface() { return surface_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39544 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]43f28f832010-02-03 02:28:48545
[email protected]0d6bfdc2011-11-02 01:32:20546 virtual void SetGLError(GLenum error, const char* msg);
[email protected]9d37f062011-11-22 01:24:52547 virtual void SetResizeCallback(
548 const base::Callback<void(gfx::Size)>& callback);
[email protected]22f320a2011-08-30 01:17:00549
[email protected]6b6e7ee2011-12-13 08:04:52550 virtual void SetMsgCallback(const MsgCallback& callback);
[email protected]22f320a2011-08-30 01:17:00551
[email protected]b0af4f52011-09-28 22:04:42552 virtual void SetStreamTextureManager(StreamTextureManager* manager);
[email protected]1318e922010-09-17 22:03:16553 virtual bool GetServiceTextureId(uint32 client_texture_id,
554 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48555
[email protected]8e3e0662010-08-23 18:46:30556 // Restores the current state to the user's settings.
557 void RestoreCurrentFramebufferBindings();
558 void RestoreCurrentRenderbufferBindings();
559 void RestoreCurrentTexture2DBindings();
560
[email protected]297ca1c2011-06-20 23:08:46561 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
562 void ApplyDirtyState();
563
564 // These check the state of the currently bound framebuffer or the
565 // backbuffer if no framebuffer is bound.
566 bool BoundFramebufferHasColorAttachmentWithAlpha();
567 bool BoundFramebufferHasDepthAttachment();
568 bool BoundFramebufferHasStencilAttachment();
569
[email protected]38d139d2011-07-14 00:38:43570 virtual error::ContextLostReason GetContextLostReason();
571
[email protected]96449d2c2009-11-25 00:01:32572 private:
[email protected]6217d392010-03-25 22:08:35573 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02574 friend class ScopedResolvedFrameBufferBinder;
[email protected]1078f912011-12-23 13:12:14575 friend class Texture;
[email protected]6217d392010-03-25 22:08:35576 friend class RenderBuffer;
577 friend class FrameBuffer;
578
[email protected]3916c97e2010-02-25 03:20:50579 // State associated with each texture unit.
580 struct TextureUnit {
581 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
582
583 // The last target that was bound to this texture unit.
584 GLenum bind_target;
585
586 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
587 TextureManager::TextureInfo::Ref bound_texture_2d;
588
589 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
590 // glBindTexture
591 TextureManager::TextureInfo::Ref bound_texture_cube_map;
[email protected]61eeb33f2011-07-26 15:30:31592
593 // texture currently bound to this unit's GL_TEXTURE_EXTERNAL_OES with
594 // glBindTexture
595 TextureManager::TextureInfo::Ref bound_texture_external_oes;
596
[email protected]e51bdf32011-11-23 22:21:46597 // texture currently bound to this unit's GL_TEXTURE_RECTANGLE_ARB with
598 // glBindTexture
599 TextureManager::TextureInfo::Ref bound_texture_rectangle_arb;
600
[email protected]61eeb33f2011-07-26 15:30:31601 TextureManager::TextureInfo::Ref GetInfoForSamplerType(GLenum type) {
602 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:46603 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
604 switch (type) {
605 case GL_SAMPLER_2D:
606 return bound_texture_2d;
607 case GL_SAMPLER_CUBE:
608 return bound_texture_cube_map;
609 case GL_SAMPLER_EXTERNAL_OES:
610 return bound_texture_external_oes;
611 case GL_SAMPLER_2D_RECT_ARB:
612 return bound_texture_rectangle_arb;
613 }
614
615 NOTREACHED();
616 return NULL;
[email protected]61eeb33f2011-07-26 15:30:31617 }
[email protected]a0b78dc2011-11-11 10:43:10618
619 void Unbind(TextureManager::TextureInfo* texture) {
620 if (bound_texture_2d == texture) {
621 bound_texture_2d = NULL;
622 }
623 if (bound_texture_cube_map == texture) {
624 bound_texture_cube_map = NULL;
625 }
626 if (bound_texture_external_oes == texture) {
627 bound_texture_external_oes = NULL;
628 }
629 }
[email protected]3916c97e2010-02-25 03:20:50630 };
631
[email protected]c2f8c8402010-12-06 18:07:24632 // Initialize or re-initialize the shader translator.
633 bool InitializeShaderTranslator();
634
[email protected]302ce6d2011-07-07 23:28:11635 void UpdateCapabilities();
636
[email protected]ae51d192010-04-27 00:48:03637 // Helpers for the glGen and glDelete functions.
638 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
639 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
640 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
641 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
642 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
643 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
644 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
645 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47646
[email protected]3916c97e2010-02-25 03:20:50647 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50648 BufferManager* buffer_manager() {
649 return group_->buffer_manager();
650 }
651
[email protected]a25fa872010-03-25 02:57:58652 RenderbufferManager* renderbuffer_manager() {
653 return group_->renderbuffer_manager();
654 }
655
656 FramebufferManager* framebuffer_manager() {
657 return group_->framebuffer_manager();
658 }
659
[email protected]3916c97e2010-02-25 03:20:50660 ProgramManager* program_manager() {
661 return group_->program_manager();
662 }
663
664 ShaderManager* shader_manager() {
665 return group_->shader_manager();
666 }
667
668 TextureManager* texture_manager() {
669 return group_->texture_manager();
670 }
671
[email protected]34ff8b0c2010-10-01 20:06:02672 bool IsOffscreenBufferMultisampled() const {
673 return offscreen_target_samples_ > 1;
674 }
675
[email protected]a93bb842010-02-16 23:03:47676 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03677 TextureManager::TextureInfo* CreateTextureInfo(
678 GLuint client_id, GLuint service_id) {
[email protected]80eb6b52012-01-19 00:14:41679 return texture_manager()->CreateTextureInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47680 }
681
682 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03683 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50684 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03685 texture_manager()->GetTextureInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10686 return info;
[email protected]a93bb842010-02-16 23:03:47687 }
688
689 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03690 void RemoveTextureInfo(GLuint client_id) {
[email protected]80eb6b52012-01-19 00:14:41691 texture_manager()->RemoveTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50692 }
[email protected]a93bb842010-02-16 23:03:47693
[email protected]d37231fa2010-04-09 21:16:02694 // Get the size (in pixels) of the currently bound frame buffer (either FBO
695 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30696 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02697
[email protected]9edc6b22010-12-23 02:00:26698 // Get the format of the currently bound frame buffer (either FBO or regular
699 // back buffer)
700 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46701 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26702
[email protected]a93bb842010-02-16 23:03:47703 // Wrapper for CompressedTexImage2D commands.
704 error::Error DoCompressedTexImage2D(
705 GLenum target,
706 GLint level,
707 GLenum internal_format,
708 GLsizei width,
709 GLsizei height,
710 GLint border,
711 GLsizei image_size,
712 const void* data);
713
[email protected]cadde4a2010-07-31 17:10:43714 // Wrapper for CompressedTexSubImage2D.
715 void DoCompressedTexSubImage2D(
716 GLenum target,
717 GLint level,
718 GLint xoffset,
719 GLint yoffset,
720 GLsizei width,
721 GLsizei height,
722 GLenum format,
723 GLsizei imageSize,
724 const void * data);
725
726 // Wrapper for CopyTexImage2D.
727 void DoCopyTexImage2D(
728 GLenum target,
729 GLint level,
730 GLenum internal_format,
731 GLint x,
732 GLint y,
733 GLsizei width,
734 GLsizei height,
735 GLint border);
736
737 // Wrapper for CopyTexSubImage2D.
738 void DoCopyTexSubImage2D(
739 GLenum target,
740 GLint level,
741 GLint xoffset,
742 GLint yoffset,
743 GLint x,
744 GLint y,
745 GLsizei width,
746 GLsizei height);
747
[email protected]a93bb842010-02-16 23:03:47748 // Wrapper for TexImage2D commands.
749 error::Error DoTexImage2D(
750 GLenum target,
751 GLint level,
752 GLenum internal_format,
753 GLsizei width,
754 GLsizei height,
755 GLint border,
756 GLenum format,
757 GLenum type,
758 const void* pixels,
759 uint32 pixels_size);
760
[email protected]cadde4a2010-07-31 17:10:43761 // Wrapper for TexSubImage2D.
762 void DoTexSubImage2D(
763 GLenum target,
764 GLint level,
765 GLint xoffset,
766 GLint yoffset,
767 GLsizei width,
768 GLsizei height,
769 GLenum format,
770 GLenum type,
771 const void * data);
772
[email protected]e51bdf32011-11-23 22:21:46773 // Wrapper for TexImageIOSurface2DCHROMIUM.
774 void DoTexImageIOSurface2DCHROMIUM(
775 GLenum target,
776 GLsizei width,
777 GLsizei height,
778 GLuint io_surface_id,
779 GLuint plane);
780
[email protected]97dc7cbe2011-12-06 17:26:17781 // Wrapper for TexStorage2DEXT.
782 void DoTexStorage2DEXT(
783 GLenum target,
784 GLint levels,
785 GLenum internal_format,
786 GLsizei width,
787 GLsizei height);
788
[email protected]a93bb842010-02-16 23:03:47789 // Creates a ProgramInfo for the given program.
[email protected]d685a682011-04-29 16:19:57790 ProgramManager::ProgramInfo* CreateProgramInfo(
791 GLuint client_id, GLuint service_id) {
792 return program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47793 }
794
[email protected]07f54fcc2009-12-22 02:46:30795 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03796 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14797 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46798 }
[email protected]07f54fcc2009-12-22 02:46:30799
[email protected]6b8cf1a2010-05-06 16:13:58800 // Gets the program info for the given program. If it's not a program
801 // generates a GL error. Returns NULL if not program.
802 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
803 GLuint client_id, const char* function_name) {
804 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
805 if (!info) {
806 if (GetShaderInfo(client_id)) {
807 SetGLError(GL_INVALID_OPERATION,
808 (std::string(function_name) +
809 ": shader passed for program").c_str());
810 } else {
811 SetGLError(GL_INVALID_VALUE,
812 (std::string(function_name) + ": unknown program").c_str());
813 }
814 }
815 return info;
816 }
817
818
[email protected]45bf5152010-02-12 00:11:31819 // Creates a ShaderInfo for the given shader.
[email protected]d685a682011-04-29 16:19:57820 ShaderManager::ShaderInfo* CreateShaderInfo(
821 GLuint client_id,
822 GLuint service_id,
823 GLenum shader_type) {
824 return shader_manager()->CreateShaderInfo(
825 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31826 }
827
828 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03829 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14830 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31831 }
832
[email protected]6b8cf1a2010-05-06 16:13:58833 // Gets the shader info for the given shader. If it's not a shader generates a
834 // GL error. Returns NULL if not shader.
835 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
836 GLuint client_id, const char* function_name) {
837 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
838 if (!info) {
839 if (GetProgramInfo(client_id)) {
840 SetGLError(
841 GL_INVALID_OPERATION,
842 (std::string(function_name) +
843 ": program passed for shader").c_str());
844 } else {
845 SetGLError(GL_INVALID_VALUE,
846 (std::string(function_name) + ": unknown shader").c_str());
847 }
848 }
849 return info;
850 }
851
[email protected]a93bb842010-02-16 23:03:47852 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03853 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
854 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47855 }
856
[email protected]07f54fcc2009-12-22 02:46:30857 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03858 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
859 BufferManager::BufferInfo* info =
860 buffer_manager()->GetBufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10861 return info;
[email protected]1d32bc82010-01-13 22:06:46862 }
[email protected]07f54fcc2009-12-22 02:46:30863
[email protected]a93bb842010-02-16 23:03:47864 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
865 // on glDeleteBuffers so we can make sure the user does not try to render
866 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03867 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47868
[email protected]a25fa872010-03-25 02:57:58869 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03870 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
871 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58872 }
873
874 // Gets the framebuffer info for the given framebuffer.
875 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03876 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58877 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03878 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10879 return info;
[email protected]a25fa872010-03-25 02:57:58880 }
881
882 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03883 void RemoveFramebufferInfo(GLuint client_id) {
884 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58885 }
886
887 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03888 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
889 return renderbuffer_manager()->CreateRenderbufferInfo(
890 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58891 }
892
893 // Gets the renderbuffer info for the given renderbuffer.
894 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03895 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58896 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03897 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10898 return info;
[email protected]a25fa872010-03-25 02:57:58899 }
900
901 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03902 void RemoveRenderbufferInfo(GLuint client_id) {
903 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58904 }
905
[email protected]258a3313f2011-10-18 20:13:57906 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
907
[email protected]558847a2010-03-24 07:02:54908 error::Error GetAttribLocationHelper(
909 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
910 const std::string& name_str);
911
912 error::Error GetUniformLocationHelper(
913 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
914 const std::string& name_str);
915
[email protected]3916c97e2010-02-25 03:20:50916 // Helper for glShaderSource.
917 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03918 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30919
[email protected]0d6bfdc2011-11-02 01:32:20920 // Clear any textures used by the current program.
921 bool ClearUnclearedTextures();
922
923 // Clear any uncleared level in texture.
924 // Returns false if there was a generated GL error.
925 bool ClearTexture(TextureManager::TextureInfo* info);
926
927 // Clears any uncleared attachments attached to the given frame buffer.
928 // Returns false if there was a generated GL error.
929 void ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:30930 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28931
[email protected]0d6bfdc2011-11-02 01:32:20932 // overridden from GLES2Decoder
933 virtual bool ClearLevel(
934 unsigned service_id,
935 unsigned bind_target,
936 unsigned target,
937 int level,
938 unsigned format,
939 unsigned type,
940 int width,
[email protected]4502e6492011-12-14 19:39:15941 int height,
942 bool is_texture_immutable);
[email protected]0d6bfdc2011-11-02 01:32:20943
[email protected]c007aa02010-09-02 22:22:40944 // Restore all GL state that affects clearing.
945 void RestoreClearState();
946
[email protected]3a2e7c7b2010-08-06 01:12:28947 // Remembers the state of some capabilities.
[email protected]297ca1c2011-06-20 23:08:46948 // Returns: true if glEnable/glDisable should actually be called.
949 bool SetCapabilityState(GLenum cap, bool enabled);
[email protected]3a2e7c7b2010-08-06 01:12:28950
[email protected]0d6bfdc2011-11-02 01:32:20951 // Check that the currently bound framebuffers are valid.
952 // Generates GL error if not.
953 bool CheckBoundFramebuffersValid(const char* func_name);
954
955 // Check if a framebuffer meets our requirements.
956 bool CheckFramebufferValid(
957 FramebufferManager::FramebufferInfo* framebuffer,
958 GLenum target,
959 const char* func_name);
[email protected]3a03a8f2011-03-19 00:51:27960
[email protected]939e7362010-05-13 20:49:10961 // Checks if the current program exists and is valid. If not generates the
962 // appropriate GL error. Returns true if the current program is in a usable
963 // state.
964 bool CheckCurrentProgram(const char* function_name);
965
966 // Checks if the current program exists and is valid and that location is not
967 // -1. If the current program is not valid generates the appropriate GL
968 // error. Returns true if the current program is in a usable state and
969 // location is not -1.
970 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
971
972 // Gets the type of a uniform for a location in the current program. Sets GL
973 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:36974 // program is valid and the location exists. Adjusts count so it
975 // does not overflow the uniform.
976 bool PrepForSetUniformByLocation(
977 GLint location, const char* function_name, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:10978
[email protected]b177ae22011-11-01 03:29:11979 // Gets the service id for any simulated backbuffer fbo.
980 GLuint GetBackbufferServiceId();
981
[email protected]b273e432010-04-12 17:23:58982 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
983 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
984
[email protected]96449d2c2009-11-25 00:01:32985 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03986 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32987
988 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03989 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32990
[email protected]3916c97e2010-02-25 03:20:50991 // Wrapper for glActiveTexture
992 void DoActiveTexture(GLenum texture_unit);
993
[email protected]ae51d192010-04-27 00:48:03994 // Wrapper for glAttachShader
995 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
996
[email protected]96449d2c2009-11-25 00:01:32997 // Wrapper for glBindBuffer since we need to track the current targets.
998 void DoBindBuffer(GLenum target, GLuint buffer);
999
[email protected]86093972010-03-11 00:13:561000 // Wrapper for glBindFramebuffer since we need to track the current targets.
1001 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1002
1003 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1004 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1005
[email protected]a93bb842010-02-16 23:03:471006 // Wrapper for glBindTexture since we need to track the current targets.
1007 void DoBindTexture(GLenum target, GLuint texture);
1008
[email protected]8e3e0662010-08-23 18:46:301009 // Wrapper for glBlitFramebufferEXT.
1010 void DoBlitFramebufferEXT(
1011 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1012 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1013 GLbitfield mask, GLenum filter);
1014
[email protected]36cef8ce2010-03-16 07:34:451015 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:111016 void DoBufferData(
1017 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
1018
[email protected]36cef8ce2010-03-16 07:34:451019 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:111020 void DoBufferSubData(
1021 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1022
[email protected]36cef8ce2010-03-16 07:34:451023 // Wrapper for glCheckFramebufferStatus
1024 GLenum DoCheckFramebufferStatus(GLenum target);
1025
[email protected]3a03a8f2011-03-19 00:51:271026 // Wrapper for glClear
1027 void DoClear(GLbitfield mask);
1028
[email protected]3a2e7c7b2010-08-06 01:12:281029 // Wrappers for clear and mask settings functions.
1030 void DoClearColor(
1031 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
1032 void DoClearDepthf(GLclampf depth);
1033 void DoClearStencil(GLint s);
1034 void DoColorMask(
1035 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
1036 void DoDepthMask(GLboolean depth);
1037 void DoStencilMask(GLuint mask);
1038 void DoStencilMaskSeparate(GLenum face, GLuint mask);
1039
[email protected]45bf5152010-02-12 00:11:311040 // Wrapper for glCompileShader.
1041 void DoCompileShader(GLuint shader);
1042
[email protected]269200b12010-11-18 22:53:061043 // Helper for DeleteSharedIdsCHROMIUM commands.
1044 void DoDeleteSharedIdsCHROMIUM(
1045 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101046
[email protected]ae51d192010-04-27 00:48:031047 // Wrapper for glDetachShader
1048 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1049
[email protected]3a2e7c7b2010-08-06 01:12:281050 // Wrapper for glDisable
1051 void DoDisable(GLenum cap);
1052
[email protected]07f54fcc2009-12-22 02:46:301053 // Wrapper for glDisableVertexAttribArray.
1054 void DoDisableVertexAttribArray(GLuint index);
1055
[email protected]3a2e7c7b2010-08-06 01:12:281056 // Wrapper for glEnable
1057 void DoEnable(GLenum cap);
1058
[email protected]07f54fcc2009-12-22 02:46:301059 // Wrapper for glEnableVertexAttribArray.
1060 void DoEnableVertexAttribArray(GLuint index);
1061
[email protected]36cef8ce2010-03-16 07:34:451062 // Wrapper for glFramebufferRenderbufffer.
1063 void DoFramebufferRenderbuffer(
1064 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1065 GLuint renderbuffer);
1066
1067 // Wrapper for glFramebufferTexture2D.
1068 void DoFramebufferTexture2D(
1069 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1070 GLint level);
1071
[email protected]a93bb842010-02-16 23:03:471072 // Wrapper for glGenerateMipmap
1073 void DoGenerateMipmap(GLenum target);
1074
[email protected]269200b12010-11-18 22:53:061075 // Helper for GenSharedIdsCHROMIUM commands.
1076 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:101077 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1078
[email protected]b273e432010-04-12 17:23:581079 // Wrapper for DoGetBooleanv.
1080 void DoGetBooleanv(GLenum pname, GLboolean* params);
1081
1082 // Wrapper for DoGetFloatv.
1083 void DoGetFloatv(GLenum pname, GLfloat* params);
1084
[email protected]36cef8ce2010-03-16 07:34:451085 // Wrapper for glGetFramebufferAttachmentParameteriv.
1086 void DoGetFramebufferAttachmentParameteriv(
1087 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1088
[email protected]a0c3e972010-04-21 00:49:131089 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581090 void DoGetIntegerv(GLenum pname, GLint* params);
1091
[email protected]29a9eb52010-04-13 09:04:231092 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:061093 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:231094 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1095
[email protected]a0c3e972010-04-21 00:49:131096 // Wrapper for glGetProgramiv.
1097 void DoGetProgramiv(
1098 GLuint program_id, GLenum pname, GLint* params);
1099
[email protected]36cef8ce2010-03-16 07:34:451100 // Wrapper for glRenderbufferParameteriv.
1101 void DoGetRenderbufferParameteriv(
1102 GLenum target, GLenum pname, GLint* params);
1103
[email protected]ddd968b82010-03-02 00:44:291104 // Wrapper for glGetShaderiv
1105 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1106
[email protected]b1122982010-05-17 23:04:241107 // Wrappers for glGetVertexAttrib.
1108 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1109 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1110
[email protected]1958e0e2010-04-22 05:17:151111 // Wrappers for glIsXXX functions.
1112 bool DoIsBuffer(GLuint client_id);
1113 bool DoIsFramebuffer(GLuint client_id);
1114 bool DoIsProgram(GLuint client_id);
1115 bool DoIsRenderbuffer(GLuint client_id);
1116 bool DoIsShader(GLuint client_id);
1117 bool DoIsTexture(GLuint client_id);
1118
[email protected]07f54fcc2009-12-22 02:46:301119 // Wrapper for glLinkProgram
1120 void DoLinkProgram(GLuint program);
1121
[email protected]269200b12010-11-18 22:53:061122 // Helper for RegisterSharedIdsCHROMIUM.
1123 void DoRegisterSharedIdsCHROMIUM(
1124 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101125
[email protected]36cef8ce2010-03-16 07:34:451126 // Wrapper for glRenderbufferStorage.
1127 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031128 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451129
[email protected]8e3e0662010-08-23 18:46:301130 // Wrapper for glRenderbufferStorageMultisampleEXT.
1131 void DoRenderbufferStorageMultisample(
1132 GLenum target, GLsizei samples, GLenum internalformat,
1133 GLsizei width, GLsizei height);
1134
[email protected]b273e432010-04-12 17:23:581135 // Wrapper for glReleaseShaderCompiler.
1136 void DoReleaseShaderCompiler() { }
1137
[email protected]3916c97e2010-02-25 03:20:501138 // Wrappers for glTexParameter functions.
1139 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1140 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1141 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1142 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1143
1144 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1145 // spec only these 2 functions can be used to set sampler uniforms.
1146 void DoUniform1i(GLint location, GLint v0);
[email protected]939e7362010-05-13 20:49:101147 void DoUniform1iv(GLint location, GLsizei count, const GLint* value);
[email protected]43c2f1f2011-03-25 18:35:361148 void DoUniform2iv(GLint location, GLsizei count, const GLint* value);
1149 void DoUniform3iv(GLint location, GLsizei count, const GLint* value);
1150 void DoUniform4iv(GLint location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101151
1152 // Wrappers for glUniformfv because some drivers don't correctly accept
1153 // bool uniforms.
1154 void DoUniform1fv(GLint location, GLsizei count, const GLfloat* value);
1155 void DoUniform2fv(GLint location, GLsizei count, const GLfloat* value);
1156 void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value);
1157 void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501158
[email protected]43c2f1f2011-03-25 18:35:361159 void DoUniformMatrix2fv(
1160 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1161 void DoUniformMatrix3fv(
1162 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1163 void DoUniformMatrix4fv(
1164 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1165
[email protected]b1122982010-05-17 23:04:241166 // Wrappers for glVertexAttrib??
1167 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1168 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1169 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1170 void DoVertexAttrib4f(
1171 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1172 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1173 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1174 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1175 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1176
[email protected]07f54fcc2009-12-22 02:46:301177 // Wrapper for glUseProgram
1178 void DoUseProgram(GLuint program);
1179
[email protected]ae51d192010-04-27 00:48:031180 // Wrapper for glValidateProgram.
1181 void DoValidateProgram(GLuint program_client_id);
1182
[email protected]4e8a5b122010-05-08 22:00:101183 // Gets the number of values that will be returned by glGetXXX. Returns
1184 // false if pname is unknown.
1185 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1186
[email protected]96449d2c2009-11-25 00:01:321187 // Gets the GLError through our wrapper.
1188 GLenum GetGLError();
1189
[email protected]1002c2d2011-06-28 22:39:041190 // Gets the GLError and stores it in our wrapper. Effectively
1191 // this lets us peek at the error without losing it.
1192 GLenum PeekGLError();
1193
[email protected]07f54fcc2009-12-22 02:46:301194 // Copies the real GL errors to the wrapper. This is so we can
1195 // make sure there are no native GL errors before calling some GL function
1196 // so that on return we know any error generated was for that specific
1197 // command.
1198 void CopyRealGLErrorsToWrapper();
1199
[email protected]6217d392010-03-25 22:08:351200 // Clear all real GL errors. This is to prevent the client from seeing any
1201 // errors caused by GL calls that it was not responsible for issuing.
1202 void ClearRealGLErrors();
1203
[email protected]07f54fcc2009-12-22 02:46:301204 // Checks if the current program and vertex attributes are valid for drawing.
1205 bool IsDrawValid(GLuint max_vertex_accessed);
1206
[email protected]c13e1da62011-09-09 21:48:301207 // Returns true if successful, simulated will be true if attrib0 was
1208 // simulated.
1209 bool SimulateAttrib0(GLuint max_vertex_accessed, bool* simulated);
[email protected]b1122982010-05-17 23:04:241210 void RestoreStateForSimulatedAttrib0();
1211
[email protected]ef526492010-06-02 23:12:251212 // Returns true if textures were set.
1213 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501214 void RestoreStateForNonRenderableTextures();
1215
[email protected]8fbedc02010-11-18 18:43:401216 // Returns true if GL_FIXED attribs were simulated.
1217 bool SimulateFixedAttribs(GLuint max_vertex_accessed, bool* simulated);
1218 void RestoreStateForSimulatedFixedAttribs();
1219
[email protected]07f54fcc2009-12-22 02:46:301220 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501221 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301222 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501223 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1224 bound_array_buffer_ : bound_element_array_buffer_;
[email protected]a0b78dc2011-11-11 10:43:101225 return info;
[email protected]07f54fcc2009-12-22 02:46:301226 }
1227
[email protected]a93bb842010-02-16 23:03:471228 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501229 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1230 TextureUnit& unit = texture_units_[active_texture_unit_];
1231 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471232 switch (target) {
1233 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501234 info = unit.bound_texture_2d;
1235 break;
[email protected]a93bb842010-02-16 23:03:471236 case GL_TEXTURE_CUBE_MAP:
1237 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1238 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1239 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1240 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1241 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1242 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501243 info = unit.bound_texture_cube_map;
1244 break;
[email protected]61eeb33f2011-07-26 15:30:311245 case GL_TEXTURE_EXTERNAL_OES:
1246 info = unit.bound_texture_external_oes;
1247 break;
[email protected]e51bdf32011-11-23 22:21:461248 case GL_TEXTURE_RECTANGLE_ARB:
1249 info = unit.bound_texture_rectangle_arb;
1250 break;
[email protected]a93bb842010-02-16 23:03:471251 default:
1252 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501253 return NULL;
[email protected]a93bb842010-02-16 23:03:471254 }
[email protected]a0b78dc2011-11-11 10:43:101255 return info;
[email protected]a93bb842010-02-16 23:03:471256 }
1257
[email protected]61eeb33f2011-07-26 15:30:311258 GLenum GetBindTargetForSamplerType(GLenum type) {
1259 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:461260 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1261 switch (type) {
1262 case GL_SAMPLER_2D:
1263 return GL_TEXTURE_2D;
1264 case GL_SAMPLER_CUBE:
1265 return GL_TEXTURE_CUBE_MAP;
1266 case GL_SAMPLER_EXTERNAL_OES:
1267 return GL_TEXTURE_EXTERNAL_OES;
1268 case GL_SAMPLER_2D_RECT_ARB:
1269 return GL_TEXTURE_RECTANGLE_ARB;
1270 }
1271
1272 NOTREACHED();
1273 return 0;
[email protected]61eeb33f2011-07-26 15:30:311274 }
1275
[email protected]8e3e0662010-08-23 18:46:301276 // Gets the framebuffer info for a particular target.
1277 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1278 GLenum target) {
1279 FramebufferManager::FramebufferInfo* info = NULL;
1280 switch (target) {
1281 case GL_FRAMEBUFFER:
1282 case GL_DRAW_FRAMEBUFFER:
1283 info = bound_draw_framebuffer_;
1284 break;
1285 case GL_READ_FRAMEBUFFER:
1286 info = bound_read_framebuffer_;
1287 break;
1288 default:
1289 NOTREACHED();
1290 break;
1291 }
[email protected]a0b78dc2011-11-11 10:43:101292 return info;
[email protected]8e3e0662010-08-23 18:46:301293 }
1294
[email protected]0d6bfdc2011-11-02 01:32:201295 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfoForTarget(
1296 GLenum target) {
1297 RenderbufferManager::RenderbufferInfo* info = NULL;
1298 switch (target) {
1299 case GL_RENDERBUFFER:
1300 info = bound_renderbuffer_;
1301 break;
1302 default:
1303 NOTREACHED();
1304 break;
1305 }
[email protected]a0b78dc2011-11-11 10:43:101306 return info;
[email protected]0d6bfdc2011-11-02 01:32:201307 }
1308
[email protected]f7b85372010-02-03 01:11:371309 // Validates the program and location for a glGetUniform call and returns
1310 // a SizeResult setup to receive the result. Returns true if glGetUniform
1311 // should be called.
1312 bool GetUniformSetup(
1313 GLuint program, GLint location,
1314 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:101315 error::Error* error, GLuint* service_id, void** result,
1316 GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371317
[email protected]1078f912011-12-23 13:12:141318 // Computes the estimated memory used for the backbuffer and passes it to
1319 // the tracing system.
1320 void UpdateBackbufferMemoryAccounting();
1321
[email protected]38d139d2011-07-14 00:38:431322 // Returns true if the context was just lost due to e.g. GL_ARB_robustness.
1323 bool WasContextLost();
1324
[email protected]e51bdf32011-11-23 22:21:461325#if defined(OS_MACOSX)
1326 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1327#endif
1328
[email protected]96449d2c2009-11-25 00:01:321329 // Generate a member function prototype for each command in an automated and
1330 // typesafe way.
1331 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141332 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191333 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321334 const gles2::name& args); \
1335
1336 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1337
1338 #undef GLES2_CMD_OP
1339
[email protected]2f2d7042010-04-14 21:45:581340 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381341 scoped_refptr<gfx::GLSurface> surface_;
1342 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021343
[email protected]a3ded6d2010-10-19 06:44:391344 // The ContextGroup for this decoder uses to track resources.
1345 ContextGroup::Ref group_;
1346
[email protected]6217d392010-03-25 22:08:351347 // A parent decoder can access this decoders saved offscreen frame buffer.
1348 // The parent pointer is reset if the parent is destroyed.
1349 base::WeakPtr<GLES2DecoderImpl> parent_;
1350
[email protected]34ff8b0c2010-10-01 20:06:021351 // Current width and height of the offscreen frame buffer.
1352 gfx::Size offscreen_size_;
1353
[email protected]96449d2c2009-11-25 00:01:321354 // Current GL error bits.
1355 uint32 error_bits_;
1356
[email protected]96449d2c2009-11-25 00:01:321357 // Util to help with GL.
1358 GLES2Util util_;
1359
1360 // pack alignment as last set by glPixelStorei
1361 GLint pack_alignment_;
1362
1363 // unpack alignment as last set by glPixelStorei
1364 GLint unpack_alignment_;
1365
1366 // The currently bound array buffer. If this is 0 it is illegal to call
1367 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501368 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321369
1370 // The currently bound element array buffer. If this is 0 it is illegal
1371 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501372 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301373
[email protected]f39f4b3f2010-05-12 17:04:081374 // Class that manages vertex attribs.
[email protected]3757a372012-01-19 05:20:441375 scoped_ptr<VertexAttribManager> vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301376
[email protected]b1122982010-05-17 23:04:241377 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1378 GLuint attrib_0_buffer_id_;
1379
1380 // The value currently in attrib_0.
1381 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1382
[email protected]fc753442011-02-04 19:49:491383 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1384 bool attrib_0_buffer_matches_value_;
1385
[email protected]b1122982010-05-17 23:04:241386 // The size of attrib 0.
1387 GLsizei attrib_0_size_;
1388
[email protected]8fbedc02010-11-18 18:43:401389 // The buffer used to simulate GL_FIXED attribs.
1390 GLuint fixed_attrib_buffer_id_;
1391
1392 // The size of fiixed attrib buffer.
1393 GLsizei fixed_attrib_buffer_size_;
1394
[email protected]3916c97e2010-02-25 03:20:501395 // Current active texture by 0 - n index.
1396 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1397 // be 2.
1398 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301399
[email protected]3916c97e2010-02-25 03:20:501400 // Which textures are bound to texture units through glActiveTexture.
1401 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471402
[email protected]3a2e7c7b2010-08-06 01:12:281403 // state saved for clearing so we can clear render buffers and then
1404 // restore to these values.
1405 GLclampf clear_red_;
1406 GLclampf clear_green_;
1407 GLclampf clear_blue_;
1408 GLclampf clear_alpha_;
1409 GLboolean mask_red_;
1410 GLboolean mask_green_;
1411 GLboolean mask_blue_;
1412 GLboolean mask_alpha_;
1413 GLint clear_stencil_;
1414 GLuint mask_stencil_front_;
1415 GLuint mask_stencil_back_;
1416 GLclampf clear_depth_;
1417 GLboolean mask_depth_;
1418 bool enable_scissor_test_;
[email protected]297ca1c2011-06-20 23:08:461419 bool enable_depth_test_;
1420 bool enable_stencil_test_;
1421 bool state_dirty_;
[email protected]3a2e7c7b2010-08-06 01:12:281422
[email protected]1d32bc82010-01-13 22:06:461423 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501424 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301425
[email protected]8e3e0662010-08-23 18:46:301426 // The currently bound framebuffers
1427 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1428 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561429
1430 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081431 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561432
[email protected]b9363b22010-06-09 22:06:151433 // The offscreen frame buffer that the client renders to. With EGL, the
1434 // depth and stencil buffers are separate. With regular GL there is a single
1435 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1436 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351437 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1438 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021439 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151440 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1441 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021442 GLenum offscreen_target_color_format_;
1443 GLenum offscreen_target_depth_format_;
1444 GLenum offscreen_target_stencil_format_;
1445 GLsizei offscreen_target_samples_;
[email protected]8a61d872012-01-20 12:43:561446 GLboolean offscreen_target_buffer_preserved_;
[email protected]6217d392010-03-25 22:08:351447
[email protected]de26b3c2011-08-03 21:54:271448 // The copy that is saved when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021449 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351450 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]8a61d872012-01-20 12:43:561451 TextureManager::TextureInfo::Ref offscreen_saved_color_texture_info_;
[email protected]de26b3c2011-08-03 21:54:271452
1453 // The copy that is used as the destination for multi-sample resolves.
1454 scoped_ptr<FrameBuffer> offscreen_resolved_frame_buffer_;
1455 scoped_ptr<Texture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051456 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351457
[email protected]9d37f062011-11-22 01:24:521458 base::Callback<void(gfx::Size)> resize_callback_;
[email protected]22f320a2011-08-30 01:17:001459
[email protected]6b6e7ee2011-12-13 08:04:521460 MsgCallback msg_callback_;
[email protected]43f28f832010-02-03 02:28:481461
[email protected]b0af4f52011-09-28 22:04:421462 StreamTextureManager* stream_texture_manager_;
1463
[email protected]32fe9aa2011-01-21 23:47:131464 // The format of the back buffer_
1465 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461466 bool back_buffer_has_depth_;
1467 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131468
[email protected]473c01ccb2011-06-07 01:33:301469 bool teximage2d_faster_than_texsubimage2d_;
1470 bool bufferdata_faster_than_buffersubdata_;
1471
[email protected]8eee29c2010-04-29 03:38:291472 // The last error message set.
1473 std::string last_error_;
1474
[email protected]a3a93e7b2010-08-28 00:48:561475 // The current decoder error.
1476 error::Error current_decoder_error_;
1477
[email protected]b1d2dcb2010-05-17 19:24:181478 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451479 scoped_ptr<ShaderTranslator> vertex_translator_;
1480 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181481
[email protected]e82fb792011-09-22 00:33:291482 DisallowedFeatures disallowed_features_;
[email protected]c410da802011-03-14 19:17:411483
[email protected]915a59a12010-09-30 21:29:111484 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051485 const Validators* validators_;
[email protected]80eb6b52012-01-19 00:14:411486 FeatureInfo::Ref feature_info_;
[email protected]9438b012010-06-15 22:55:051487
[email protected]b493ee622011-04-13 23:52:001488 // This indicates all the following texSubImage2D calls that are part of the
1489 // failed texImage2D call should be ignored.
1490 bool tex_image_2d_failed_;
1491
[email protected]65225772011-05-12 21:10:241492 int frame_number_;
1493
[email protected]38d139d2011-07-14 00:38:431494 bool has_arb_robustness_;
1495 GLenum reset_status_;
1496
[email protected]75c023c2011-08-22 23:54:511497 bool needs_mac_nvidia_driver_workaround_;
[email protected]a2a0fe762011-09-20 00:59:121498 bool needs_glsl_built_in_function_emulation_;
[email protected]75c023c2011-08-22 23:54:511499
[email protected]f0d74742011-10-03 16:31:041500 // These flags are used to override the state of the shared feature_info_
1501 // member. Because the same FeatureInfo instance may be shared among many
1502 // contexts, the assumptions on the availablity of extensions in WebGL
1503 // contexts may be broken. These flags override the shared state to preserve
1504 // WebGL semantics.
1505 bool force_webgl_glsl_validation_;
1506 bool derivatives_explicitly_enabled_;
1507
[email protected]062c38b2012-01-18 03:25:101508 bool compile_shader_always_succeeds_;
1509
[email protected]e51bdf32011-11-23 22:21:461510#if defined(OS_MACOSX)
1511 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1512 TextureToIOSurfaceMap texture_to_io_surface_map_;
1513#endif
1514
[email protected]96449d2c2009-11-25 00:01:321515 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1516};
1517
[email protected]6217d392010-03-25 22:08:351518ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1519 : decoder_(decoder) {
1520 decoder_->CopyRealGLErrorsToWrapper();
1521}
1522
1523ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1524 decoder_->ClearRealGLErrors();
1525}
1526
1527ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1528 GLuint id)
1529 : decoder_(decoder) {
1530 ScopedGLErrorSuppressor suppressor(decoder_);
1531
1532 // TODO(apatrick): Check if there are any other states that need to be reset
1533 // before binding a new texture.
1534 glActiveTexture(GL_TEXTURE0);
1535 glBindTexture(GL_TEXTURE_2D, id);
1536}
1537
1538ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1539 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301540 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351541}
1542
1543ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1544 GLuint id)
1545 : decoder_(decoder) {
1546 ScopedGLErrorSuppressor suppressor(decoder_);
1547 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1548}
1549
1550ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1551 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301552 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351553}
1554
1555ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1556 GLuint id)
1557 : decoder_(decoder) {
1558 ScopedGLErrorSuppressor suppressor(decoder_);
1559 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1560}
1561
1562ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1563 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301564 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351565}
1566
[email protected]34ff8b0c2010-10-01 20:06:021567ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271568 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521569 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021570 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1571 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]c0701082011-04-20 00:34:521572 (!decoder_->bound_read_framebuffer_.get() ||
1573 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021574 if (!resolve_and_bind_)
1575 return;
1576
1577 ScopedGLErrorSuppressor suppressor(decoder_);
1578 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1579 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271580 GLuint targetid;
1581 if (internal) {
1582 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1583 decoder_->offscreen_resolved_frame_buffer_.reset(
1584 new FrameBuffer(decoder_));
1585 decoder_->offscreen_resolved_frame_buffer_->Create();
1586 decoder_->offscreen_resolved_color_texture_.reset(new Texture(decoder_));
1587 decoder_->offscreen_resolved_color_texture_->Create();
1588
1589 DCHECK(decoder_->offscreen_saved_color_format_);
1590 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1591 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_);
[email protected]de26b3c2011-08-03 21:54:271592 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1593 decoder_->offscreen_resolved_color_texture_.get());
1594 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1595 GL_FRAMEBUFFER_COMPLETE) {
1596 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1597 << "because offscreen resolved FBO was incomplete.";
1598 return;
1599 }
1600 }
1601 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1602 } else {
1603 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1604 }
1605 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021606 const int width = decoder_->offscreen_size_.width();
1607 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181608 glDisable(GL_SCISSOR_TEST);
[email protected]34ff8b0c2010-10-01 20:06:021609 if (IsAngle()) {
1610 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1611 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1612 } else {
1613 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1614 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1615 }
[email protected]de26b3c2011-08-03 21:54:271616 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021617}
1618
1619ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1620 if (!resolve_and_bind_)
1621 return;
1622
1623 ScopedGLErrorSuppressor suppressor(decoder_);
1624 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181625 if (decoder_->enable_scissor_test_) {
1626 glEnable(GL_SCISSOR_TEST);
1627 }
[email protected]34ff8b0c2010-10-01 20:06:021628}
1629
[email protected]6217d392010-03-25 22:08:351630Texture::Texture(GLES2DecoderImpl* decoder)
1631 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141632 id_(0),
1633 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351634}
1635
1636Texture::~Texture() {
1637 // This does not destroy the render texture because that would require that
1638 // the associated GL context was current. Just check that it was explicitly
1639 // destroyed.
1640 DCHECK_EQ(id_, 0u);
1641}
1642
1643void Texture::Create() {
1644 ScopedGLErrorSuppressor suppressor(decoder_);
1645 Destroy();
1646 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581647 ScopedTexture2DBinder binder(decoder_, id_);
1648 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1649 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1650 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1651 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]62788802011-10-03 17:57:161652
1653 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1654 // never called on an offscreen context, no data will ever be uploaded to the
1655 // saved offscreen color texture (it is deferred until to when SwapBuffers
1656 // is called). My idea is that some nvidia drivers might have a bug where
1657 // deleting a texture that has never been populated might cause a
1658 // crash.
1659 glTexImage2D(
1660 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
[email protected]1078f912011-12-23 13:12:141661 estimated_size_ = 16u * 16u * 4u;
1662 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351663}
1664
[email protected]34ff8b0c2010-10-01 20:06:021665bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351666 DCHECK_NE(id_, 0u);
1667 ScopedGLErrorSuppressor suppressor(decoder_);
1668 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]6217d392010-03-25 22:08:351669
[email protected]f0e6a34f2012-01-04 20:53:401670 WrappedTexImage2D(GL_TEXTURE_2D,
1671 0, // mip level
1672 format,
1673 size.width(),
1674 size.height(),
1675 0, // border
1676 format,
1677 GL_UNSIGNED_BYTE,
1678 NULL);
[email protected]6217d392010-03-25 22:08:351679
[email protected]d37231fa2010-04-09 21:16:021680 size_ = size;
1681
[email protected]1078f912011-12-23 13:12:141682 bool success = glGetError() == GL_NO_ERROR;
1683 if (success) {
1684 uint32 image_size = 0;
1685 GLES2Util::ComputeImageDataSize(
1686 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 4, &image_size);
1687 estimated_size_ = image_size;
1688 decoder_->UpdateBackbufferMemoryAccounting();
1689 }
1690 return success;
[email protected]6217d392010-03-25 22:08:351691}
1692
[email protected]3a4d0c52011-06-29 23:11:581693void Texture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351694 DCHECK_NE(id_, 0u);
1695 ScopedGLErrorSuppressor suppressor(decoder_);
1696 ScopedTexture2DBinder binder(decoder_, id_);
1697 glCopyTexImage2D(GL_TEXTURE_2D,
1698 0, // level
[email protected]3a4d0c52011-06-29 23:11:581699 format,
[email protected]6217d392010-03-25 22:08:351700 0, 0,
1701 size.width(),
1702 size.height(),
1703 0); // border
1704}
1705
1706void Texture::Destroy() {
1707 if (id_ != 0) {
1708 ScopedGLErrorSuppressor suppressor(decoder_);
1709 glDeleteTextures(1, &id_);
1710 id_ = 0;
[email protected]1078f912011-12-23 13:12:141711 estimated_size_ = 0;
1712 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351713 }
1714}
1715
[email protected]97872062010-11-03 19:07:051716void Texture::Invalidate() {
1717 id_ = 0;
1718}
1719
[email protected]6217d392010-03-25 22:08:351720RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1721 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141722 id_(0),
1723 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351724}
1725
1726RenderBuffer::~RenderBuffer() {
1727 // This does not destroy the render buffer because that would require that
1728 // the associated GL context was current. Just check that it was explicitly
1729 // destroyed.
1730 DCHECK_EQ(id_, 0u);
1731}
1732
1733void RenderBuffer::Create() {
1734 ScopedGLErrorSuppressor suppressor(decoder_);
1735 Destroy();
1736 glGenRenderbuffersEXT(1, &id_);
1737}
1738
[email protected]34ff8b0c2010-10-01 20:06:021739bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1740 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351741 ScopedGLErrorSuppressor suppressor(decoder_);
1742 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021743 if (samples <= 1) {
1744 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1745 format,
1746 size.width(),
1747 size.height());
1748 } else {
1749 if (IsAngle()) {
1750 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1751 samples,
1752 format,
1753 size.width(),
1754 size.height());
1755 } else {
1756 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1757 samples,
1758 format,
1759 size.width(),
1760 size.height());
1761 }
1762 }
[email protected]1078f912011-12-23 13:12:141763 bool success = glGetError() == GL_NO_ERROR;
1764 if (success) {
1765 estimated_size_ = size.width() * size.height() * samples *
1766 GLES2Util::RenderbufferBytesPerPixel(format);
1767 decoder_->UpdateBackbufferMemoryAccounting();
1768 }
1769 return success;
[email protected]6217d392010-03-25 22:08:351770}
1771
1772void RenderBuffer::Destroy() {
1773 if (id_ != 0) {
1774 ScopedGLErrorSuppressor suppressor(decoder_);
1775 glDeleteRenderbuffersEXT(1, &id_);
1776 id_ = 0;
[email protected]1078f912011-12-23 13:12:141777 estimated_size_ = 0;
1778 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351779 }
1780}
1781
[email protected]97872062010-11-03 19:07:051782void RenderBuffer::Invalidate() {
1783 id_ = 0;
1784}
1785
[email protected]6217d392010-03-25 22:08:351786FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1787 : decoder_(decoder),
1788 id_(0) {
1789}
1790
1791FrameBuffer::~FrameBuffer() {
1792 // This does not destroy the frame buffer because that would require that
1793 // the associated GL context was current. Just check that it was explicitly
1794 // destroyed.
1795 DCHECK_EQ(id_, 0u);
1796}
1797
1798void FrameBuffer::Create() {
1799 ScopedGLErrorSuppressor suppressor(decoder_);
1800 Destroy();
1801 glGenFramebuffersEXT(1, &id_);
1802}
1803
1804void FrameBuffer::AttachRenderTexture(Texture* texture) {
1805 DCHECK_NE(id_, 0u);
1806 ScopedGLErrorSuppressor suppressor(decoder_);
1807 ScopedFrameBufferBinder binder(decoder_, id_);
1808 GLuint attach_id = texture ? texture->id() : 0;
1809 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1810 GL_COLOR_ATTACHMENT0,
1811 GL_TEXTURE_2D,
1812 attach_id,
1813 0);
1814}
1815
[email protected]b9363b22010-06-09 22:06:151816void FrameBuffer::AttachRenderBuffer(GLenum target,
1817 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351818 DCHECK_NE(id_, 0u);
1819 ScopedGLErrorSuppressor suppressor(decoder_);
1820 ScopedFrameBufferBinder binder(decoder_, id_);
1821 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1822 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151823 target,
[email protected]6217d392010-03-25 22:08:351824 GL_RENDERBUFFER,
1825 attach_id);
1826}
1827
[email protected]6217d392010-03-25 22:08:351828void FrameBuffer::Destroy() {
1829 if (id_ != 0) {
1830 ScopedGLErrorSuppressor suppressor(decoder_);
1831 glDeleteFramebuffersEXT(1, &id_);
1832 id_ = 0;
1833 }
1834}
1835
[email protected]97872062010-11-03 19:07:051836void FrameBuffer::Invalidate() {
1837 id_ = 0;
1838}
1839
[email protected]6217d392010-03-25 22:08:351840GLenum FrameBuffer::CheckStatus() {
1841 DCHECK_NE(id_, 0u);
1842 ScopedGLErrorSuppressor suppressor(decoder_);
1843 ScopedFrameBufferBinder binder(decoder_, id_);
1844 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1845}
1846
[email protected]aa7666122011-09-02 19:45:521847GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1848 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321849}
1850
[email protected]aa7666122011-09-02 19:45:521851GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391852 : GLES2Decoder(),
[email protected]3b1ecc262011-08-03 22:49:571853 group_(group),
[email protected]96449d2c2009-11-25 00:01:321854 error_bits_(0),
[email protected]96449d2c2009-11-25 00:01:321855 pack_alignment_(4),
1856 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241857 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491858 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241859 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401860 fixed_attrib_buffer_id_(0),
1861 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501862 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281863 clear_red_(0),
1864 clear_green_(0),
1865 clear_blue_(0),
1866 clear_alpha_(0),
1867 mask_red_(true),
1868 mask_green_(true),
1869 mask_blue_(true),
1870 mask_alpha_(true),
1871 clear_stencil_(0),
1872 mask_stencil_front_(-1),
1873 mask_stencil_back_(-1),
1874 clear_depth_(1.0f),
1875 mask_depth_(true),
1876 enable_scissor_test_(false),
[email protected]297ca1c2011-06-20 23:08:461877 enable_depth_test_(false),
1878 enable_stencil_test_(false),
1879 state_dirty_(true),
[email protected]34ff8b0c2010-10-01 20:06:021880 offscreen_target_color_format_(0),
1881 offscreen_target_depth_format_(0),
1882 offscreen_target_stencil_format_(0),
1883 offscreen_target_samples_(0),
[email protected]8a61d872012-01-20 12:43:561884 offscreen_target_buffer_preserved_(true),
[email protected]97872062010-11-03 19:07:051885 offscreen_saved_color_format_(0),
[email protected]b0af4f52011-09-28 22:04:421886 stream_texture_manager_(NULL),
[email protected]32fe9aa2011-01-21 23:47:131887 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:461888 back_buffer_has_depth_(false),
1889 back_buffer_has_stencil_(false),
[email protected]473c01ccb2011-06-07 01:33:301890 teximage2d_faster_than_texsubimage2d_(true),
1891 bufferdata_faster_than_buffersubdata_(true),
[email protected]a3a93e7b2010-08-28 00:48:561892 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051893 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111894 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001895 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241896 tex_image_2d_failed_(false),
[email protected]38d139d2011-07-14 00:38:431897 frame_number_(0),
1898 has_arb_robustness_(false),
[email protected]75c023c2011-08-22 23:54:511899 reset_status_(GL_NO_ERROR),
[email protected]a2a0fe762011-09-20 00:59:121900 needs_mac_nvidia_driver_workaround_(false),
[email protected]f0d74742011-10-03 16:31:041901 needs_glsl_built_in_function_emulation_(false),
1902 force_webgl_glsl_validation_(false),
[email protected]062c38b2012-01-18 03:25:101903 derivatives_explicitly_enabled_(false),
1904 compile_shader_always_succeeds_(false) {
[email protected]3b1ecc262011-08-03 22:49:571905 DCHECK(group);
1906
[email protected]b1122982010-05-17 23:04:241907 attrib_0_value_.v[0] = 0.0f;
1908 attrib_0_value_.v[1] = 0.0f;
1909 attrib_0_value_.v[2] = 0.0f;
1910 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151911
[email protected]c2f8c8402010-12-06 18:07:241912 // The shader translator is used for WebGL even when running on EGL
1913 // because additional restrictions are needed (like only enabling
1914 // GL_OES_standard_derivatives on demand). It is used for the unit
1915 // tests because
1916 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1917 // empty string to CompileShader and this is not a valid shader.
1918 // TODO(apatrick): fix this test.
1919 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:041920 !feature_info_->feature_flags().chromium_webglsl &&
1921 !force_webgl_glsl_validation_) ||
[email protected]b9363b22010-06-09 22:06:151922 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) {
1923 use_shader_translator_ = false;
1924 }
[email protected]473c01ccb2011-06-07 01:33:301925
1926 // TODO(gman): Consider setting these based on GPU and/or driver.
1927 if (IsAngle()) {
1928 teximage2d_faster_than_texsubimage2d_ = false;
1929 bufferdata_faster_than_buffersubdata_ = false;
1930 }
[email protected]96449d2c2009-11-25 00:01:321931}
1932
[email protected]80eb6b52012-01-19 00:14:411933GLES2DecoderImpl::~GLES2DecoderImpl() {
1934}
1935
[email protected]c410da802011-03-14 19:17:411936bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:381937 const scoped_refptr<gfx::GLSurface>& surface,
1938 const scoped_refptr<gfx::GLContext>& context,
[email protected]c410da802011-03-14 19:17:411939 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:291940 const DisallowedFeatures& disallowed_features,
[email protected]c410da802011-03-14 19:17:411941 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:241942 const std::vector<int32>& attribs) {
[email protected]4bedba72010-04-20 22:08:541943 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301944 DCHECK(!context_.get());
1945
[email protected]e844ae22012-01-14 03:36:261946 if (CommandLine::ForCurrentProcess()->HasSwitch(
1947 switches::kEnableGPUDebugging)) {
1948 set_debug(true);
1949 }
1950
[email protected]062c38b2012-01-18 03:25:101951 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
1952 switches::kCompileShaderAlwaysSucceeds);
1953
[email protected]fbe20372011-06-01 01:46:381954 // Take ownership of the GLSurface. TODO(apatrick): once the parent / child
1955 // context is retired, the decoder should not take an initial surface as
1956 // an argument to this function.
1957 // Maybe create a short lived offscreen GLSurface for the purpose of
1958 // initializing the decoder's GLContext.
1959 surface_ = surface;
[email protected]f62a5ab2011-05-23 20:34:151960
[email protected]66791e382010-07-14 20:48:301961 // Take ownership of the GLContext.
[email protected]fbe20372011-06-01 01:46:381962 context_ = context;
[email protected]d37231fa2010-04-09 21:16:021963
[email protected]246a70452010-03-05 21:53:501964 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:011965 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
1966 << "MakeCurrent failed.";
[email protected]1871a092011-10-10 21:46:421967 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]246a70452010-03-05 21:53:501968 Destroy();
1969 return false;
[email protected]eb54a562010-01-20 21:55:181970 }
1971
[email protected]e82fb792011-09-22 00:33:291972 if (!group_->Initialize(disallowed_features, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:221973 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:391974 << "failed to initialize.";
[email protected]1871a092011-10-10 21:46:421975 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]a3ded6d2010-10-19 06:44:391976 Destroy();
[email protected]ae1741092010-11-17 19:16:031977 return false;
[email protected]a3ded6d2010-10-19 06:44:391978 }
1979
[email protected]246a70452010-03-05 21:53:501980 CHECK_GL_ERROR();
[email protected]e82fb792011-09-22 00:33:291981 disallowed_features_ = disallowed_features;
[email protected]246a70452010-03-05 21:53:501982
[email protected]3757a372012-01-19 05:20:441983 vertex_attrib_manager_.reset(new VertexAttribManager());
1984 vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:321985
[email protected]302ce6d2011-07-07 23:28:111986 util_.set_num_compressed_texture_formats(
1987 validators_->compressed_texture_format.GetValues().size());
1988
[email protected]1071e572011-02-09 20:00:121989 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1990 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
1991 // OpenGL ES 2.0 does not have this issue.
1992 glEnableVertexAttribArray(0);
1993 }
[email protected]b1122982010-05-17 23:04:241994 glGenBuffersARB(1, &attrib_0_buffer_id_);
1995 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
1996 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
1997 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:401998 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:081999
[email protected]246a70452010-03-05 21:53:502000 texture_units_.reset(
2001 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:152002 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:492003 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:312004 // We want the last bind to be 2D.
2005 TextureManager::TextureInfo* info;
2006 if (feature_info_->feature_flags().oes_egl_image_external) {
2007 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_EXTERNAL_OES);
2008 texture_units_[tt].bound_texture_external_oes = info;
2009 glBindTexture(GL_TEXTURE_EXTERNAL_OES, info->service_id());
2010 }
[email protected]e51bdf32011-11-23 22:21:462011 if (feature_info_->feature_flags().arb_texture_rectangle) {
2012 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_RECTANGLE_ARB);
2013 texture_units_[tt].bound_texture_rectangle_arb = info;
2014 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, info->service_id());
2015 }
[email protected]61eeb33f2011-07-26 15:30:312016 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:492017 texture_units_[tt].bound_texture_cube_map = info;
2018 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
2019 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2020 texture_units_[tt].bound_texture_2d = info;
2021 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:152022 }
[email protected]00f893d2010-08-24 18:55:492023 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:502024 CHECK_GL_ERROR();
2025
[email protected]297ca1c2011-06-20 23:08:462026 ContextCreationAttribParser attrib_parser;
2027 if (!attrib_parser.Parse(attribs))
2028 return false;
[email protected]41c56362011-06-14 16:47:432029
[email protected]297ca1c2011-06-20 23:08:462030 // These are NOT if the back buffer has these proprorties. They are
2031 // if we want the command buffer to enforce them regardless of what
2032 // the real backbuffer is assuming the real back buffer gives us more than
2033 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2034 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2035 // can't do anything about that.
2036
2037 GLint v = 0;
2038 glGetIntegerv(GL_ALPHA_BITS, &v);
2039 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2040 // user requested RGB then RGB. If the user did not specify a preference than
2041 // use whatever we were given. Same for DEPTH and STENCIL.
2042 back_buffer_color_format_ =
2043 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2044 glGetIntegerv(GL_DEPTH_BITS, &v);
2045 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2046 glGetIntegerv(GL_STENCIL_BITS, &v);
2047 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2048
2049 if (surface_->IsOffscreen()) {
[email protected]34ff8b0c2010-10-01 20:06:022050 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:542051 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:022052 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
2053 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:432054 // max_sample_count must be initialized to a sane value. If
2055 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2056 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:022057 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2058 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2059 max_sample_count);
2060 } else {
2061 offscreen_target_samples_ = 1;
2062 }
[email protected]8a61d872012-01-20 12:43:562063 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
[email protected]34ff8b0c2010-10-01 20:06:022064
2065 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2066 const bool rgb8_supported =
2067 context_->HasExtension("GL_OES_rgb8_rgba8");
2068 // The only available default render buffer formats in GLES2 have very
2069 // little precision. Don't enable multisampling unless 8-bit render
2070 // buffer formats are available--instead fall back to 8-bit textures.
2071 if (rgb8_supported && offscreen_target_samples_ > 1) {
2072 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2073 GL_RGBA8 : GL_RGB8;
2074 } else {
2075 offscreen_target_samples_ = 1;
2076 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2077 GL_RGBA : GL_RGB;
2078 }
2079
2080 // ANGLE only supports packed depth/stencil formats, so use it if it is
2081 // available.
2082 const bool depth24_stencil8_supported =
2083 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272084 VLOG(1) << "GL_OES_packed_depth_stencil "
2085 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:002086 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2087 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022088 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2089 offscreen_target_stencil_format_ = 0;
2090 } else {
2091 // It may be the case that this depth/stencil combination is not
2092 // supported, but this will be checked later by CheckFramebufferStatus.
2093 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2094 GL_DEPTH_COMPONENT16 : 0;
2095 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2096 GL_STENCIL_INDEX8 : 0;
2097 }
2098 } else {
2099 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2100 GL_RGBA : GL_RGB;
2101
2102 // If depth is requested at all, use the packed depth stencil format if
2103 // it's available, as some desktop GL drivers don't support any non-packed
2104 // formats for depth attachments.
2105 const bool depth24_stencil8_supported =
2106 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272107 VLOG(1) << "GL_EXT_packed_depth_stencil "
2108 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:022109
[email protected]71ee3642010-10-14 18:08:002110 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2111 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022112 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2113 offscreen_target_stencil_format_ = 0;
2114 } else {
2115 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2116 GL_DEPTH_COMPONENT : 0;
2117 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2118 GL_STENCIL_INDEX : 0;
2119 }
2120 }
2121
[email protected]97872062010-11-03 19:07:052122 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2123 GL_RGBA : GL_RGB;
2124
[email protected]6217d392010-03-25 22:08:352125 // Create the target frame buffer. This is the one that the client renders
2126 // directly to.
2127 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
2128 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022129 // Due to GLES2 format limitations, either the color texture (for
2130 // non-multisampling) or the color render buffer (for multisampling) will be
2131 // attached to the offscreen frame buffer. The render buffer has more
2132 // limited formats available to it, but the texture can't do multisampling.
2133 if (IsOffscreenBufferMultisampled()) {
2134 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
2135 offscreen_target_color_render_buffer_->Create();
2136 } else {
2137 offscreen_target_color_texture_.reset(new Texture(this));
2138 offscreen_target_color_texture_->Create();
2139 }
2140 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152141 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022142 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152143 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:352144
2145 // Create the saved offscreen texture. The target frame buffer is copied
2146 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:022147 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
2148 offscreen_saved_frame_buffer_->Create();
2149 //
[email protected]6217d392010-03-25 22:08:352150 offscreen_saved_color_texture_.reset(new Texture(this));
2151 offscreen_saved_color_texture_->Create();
2152
[email protected]6217d392010-03-25 22:08:352153 // Allocate the render buffers at their initial size and check the status
2154 // of the frame buffers is okay.
[email protected]799b4b22011-08-22 17:09:592155 if (!ResizeOffscreenFrameBuffer(size)) {
[email protected]d0498742010-09-20 20:27:012156 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:352157 Destroy();
2158 return false;
2159 }
2160
2161 // Bind to the new default frame buffer (the offscreen target frame buffer).
2162 // This should now be associated with ID zero.
2163 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2164 }
2165
[email protected]76a0ee102010-04-07 21:03:042166 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2167 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2168 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372169 // mailing list archives. It also implicitly enables the desktop GL
2170 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2171 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152172 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2173 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372174 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152175 }
[email protected]de17df392010-04-23 21:09:412176
[email protected]38d139d2011-07-14 00:38:432177 has_arb_robustness_ = context->HasExtension("GL_ARB_robustness");
2178
[email protected]e82fb792011-09-22 00:33:292179 if (!disallowed_features_.driver_bug_workarounds) {
[email protected]75c023c2011-08-22 23:54:512180#if defined(OS_MACOSX)
[email protected]a2a0fe762011-09-20 00:59:122181 const char* vendor_str = reinterpret_cast<const char*>(
2182 glGetString(GL_VENDOR));
2183 needs_mac_nvidia_driver_workaround_ =
2184 vendor_str && strstr(vendor_str, "NVIDIA");
2185 needs_glsl_built_in_function_emulation_ =
2186 vendor_str && (strstr(vendor_str, "ATI") || strstr(vendor_str, "AMD"));
2187#elif defined(OS_WIN)
2188 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
2189 needs_glsl_built_in_function_emulation_ = true;
[email protected]75c023c2011-08-22 23:54:512190#endif
[email protected]a2a0fe762011-09-20 00:59:122191 }
[email protected]75c023c2011-08-22 23:54:512192
[email protected]c2f8c8402010-12-06 18:07:242193 if (!InitializeShaderTranslator()) {
2194 return false;
[email protected]de17df392010-04-23 21:09:412195 }
[email protected]76a0ee102010-04-07 21:03:042196
[email protected]246a70452010-03-05 21:53:502197 return true;
[email protected]96449d2c2009-11-25 00:01:322198}
2199
[email protected]302ce6d2011-07-07 23:28:112200void GLES2DecoderImpl::UpdateCapabilities() {
2201 util_.set_num_compressed_texture_formats(
2202 validators_->compressed_texture_format.GetValues().size());
2203 util_.set_num_shader_binary_formats(
2204 validators_->shader_binary_format.GetValues().size());
2205}
2206
[email protected]c2f8c8402010-12-06 18:07:242207bool GLES2DecoderImpl::InitializeShaderTranslator() {
2208 // Re-check the state of use_shader_translator_ each time this is called.
2209 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:042210 (feature_info_->feature_flags().chromium_webglsl ||
2211 force_webgl_glsl_validation_) &&
[email protected]c2f8c8402010-12-06 18:07:242212 !use_shader_translator_) {
2213 use_shader_translator_ = true;
2214 }
2215 if (!use_shader_translator_) {
2216 return true;
2217 }
2218 ShBuiltInResources resources;
2219 ShInitBuiltInResources(&resources);
2220 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2221 resources.MaxVertexUniformVectors =
2222 group_->max_vertex_uniform_vectors();
2223 resources.MaxVaryingVectors = group_->max_varying_vectors();
2224 resources.MaxVertexTextureImageUnits =
2225 group_->max_vertex_texture_image_units();
2226 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2227 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2228 resources.MaxFragmentUniformVectors =
2229 group_->max_fragment_uniform_vectors();
2230 resources.MaxDrawBuffers = 1;
[email protected]f0d74742011-10-03 16:31:042231
2232 if (force_webgl_glsl_validation_) {
2233 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2234 } else {
2235 resources.OES_standard_derivatives =
2236 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
[email protected]e51bdf32011-11-23 22:21:462237 resources.ARB_texture_rectangle =
2238 feature_info_->feature_flags().arb_texture_rectangle ? 1 : 0;
[email protected]f0d74742011-10-03 16:31:042239 }
2240
[email protected]c2f8c8402010-12-06 18:07:242241 vertex_translator_.reset(new ShaderTranslator);
[email protected]f0d74742011-10-03 16:31:042242 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ||
2243 feature_info_->feature_flags().chromium_webglsl ?
2244 SH_WEBGL_SPEC : SH_GLES2_SPEC;
[email protected]a2a0fe762011-09-20 00:59:122245 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2246 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2247 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2248 ShaderTranslatorInterface::GlslBuiltInFunctionBehavior function_behavior =
2249 needs_glsl_built_in_function_emulation_ ?
2250 ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated :
2251 ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal;
[email protected]c2f8c8402010-12-06 18:07:242252 if (!vertex_translator_->Init(
[email protected]a2a0fe762011-09-20 00:59:122253 SH_VERTEX_SHADER, shader_spec, &resources,
2254 implementation_type, function_behavior)) {
[email protected]c2f8c8402010-12-06 18:07:242255 LOG(ERROR) << "Could not initialize vertex shader translator.";
2256 Destroy();
2257 return false;
2258 }
2259 fragment_translator_.reset(new ShaderTranslator);
2260 if (!fragment_translator_->Init(
[email protected]a2a0fe762011-09-20 00:59:122261 SH_FRAGMENT_SHADER, shader_spec, &resources,
2262 implementation_type, function_behavior)) {
[email protected]c2f8c8402010-12-06 18:07:242263 LOG(ERROR) << "Could not initialize fragment shader translator.";
2264 Destroy();
2265 return false;
2266 }
2267 return true;
2268}
2269
[email protected]ae51d192010-04-27 00:48:032270bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472271 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032272 if (GetBufferInfo(client_ids[ii])) {
2273 return false;
2274 }
2275 }
2276 scoped_array<GLuint> service_ids(new GLuint[n]);
2277 glGenBuffersARB(n, service_ids.get());
2278 for (GLsizei ii = 0; ii < n; ++ii) {
2279 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2280 }
2281 return true;
2282}
2283
2284bool GLES2DecoderImpl::GenFramebuffersHelper(
2285 GLsizei n, const GLuint* client_ids) {
2286 for (GLsizei ii = 0; ii < n; ++ii) {
2287 if (GetFramebufferInfo(client_ids[ii])) {
2288 return false;
2289 }
2290 }
2291 scoped_array<GLuint> service_ids(new GLuint[n]);
2292 glGenFramebuffersEXT(n, service_ids.get());
2293 for (GLsizei ii = 0; ii < n; ++ii) {
2294 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2295 }
2296 return true;
2297}
2298
2299bool GLES2DecoderImpl::GenRenderbuffersHelper(
2300 GLsizei n, const GLuint* client_ids) {
2301 for (GLsizei ii = 0; ii < n; ++ii) {
2302 if (GetRenderbufferInfo(client_ids[ii])) {
2303 return false;
2304 }
2305 }
2306 scoped_array<GLuint> service_ids(new GLuint[n]);
2307 glGenRenderbuffersEXT(n, service_ids.get());
2308 for (GLsizei ii = 0; ii < n; ++ii) {
2309 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2310 }
2311 return true;
2312}
2313
2314bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2315 for (GLsizei ii = 0; ii < n; ++ii) {
2316 if (GetTextureInfo(client_ids[ii])) {
2317 return false;
2318 }
2319 }
2320 scoped_array<GLuint> service_ids(new GLuint[n]);
2321 glGenTextures(n, service_ids.get());
2322 for (GLsizei ii = 0; ii < n; ++ii) {
2323 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2324 }
2325 return true;
2326}
2327
2328void GLES2DecoderImpl::DeleteBuffersHelper(
2329 GLsizei n, const GLuint* client_ids) {
2330 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102331 BufferManager::BufferInfo* buffer = GetBufferInfo(client_ids[ii]);
2332 if (buffer && !buffer->IsDeleted()) {
[email protected]3757a372012-01-19 05:20:442333 vertex_attrib_manager_->Unbind(buffer);
[email protected]a0b78dc2011-11-11 10:43:102334 if (bound_array_buffer_ == buffer) {
2335 bound_array_buffer_ = NULL;
2336 }
2337 if (bound_element_array_buffer_ == buffer) {
2338 bound_element_array_buffer_ = NULL;
2339 }
2340 GLuint service_id = buffer->service_id();
[email protected]ae51d192010-04-27 00:48:032341 glDeleteBuffersARB(1, &service_id);
2342 RemoveBufferInfo(client_ids[ii]);
2343 }
[email protected]a93bb842010-02-16 23:03:472344 }
[email protected]07f54fcc2009-12-22 02:46:302345}
2346
[email protected]ae51d192010-04-27 00:48:032347void GLES2DecoderImpl::DeleteFramebuffersHelper(
2348 GLsizei n, const GLuint* client_ids) {
[email protected]b177ae22011-11-01 03:29:112349 bool supports_seperate_framebuffer_binds =
2350 feature_info_->feature_flags().chromium_framebuffer_multisample;
2351
[email protected]a25fa872010-03-25 02:57:582352 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102353 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ae51d192010-04-27 00:48:032354 GetFramebufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102355 if (framebuffer && !framebuffer->IsDeleted()) {
2356 if (framebuffer == bound_draw_framebuffer_) {
[email protected]297ca1c2011-06-20 23:08:462357 bound_draw_framebuffer_ = NULL;
2358 state_dirty_ = true;
[email protected]b177ae22011-11-01 03:29:112359 GLenum target = supports_seperate_framebuffer_binds ?
2360 GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER;
2361 glBindFramebufferEXT(target, GetBackbufferServiceId());
2362 }
[email protected]a0b78dc2011-11-11 10:43:102363 if (framebuffer == bound_read_framebuffer_) {
[email protected]b177ae22011-11-01 03:29:112364 bound_read_framebuffer_ = NULL;
2365 GLenum target = supports_seperate_framebuffer_binds ?
2366 GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER;
2367 glBindFramebufferEXT(target, GetBackbufferServiceId());
[email protected]297ca1c2011-06-20 23:08:462368 }
[email protected]a0b78dc2011-11-11 10:43:102369 GLuint service_id = framebuffer->service_id();
[email protected]ae51d192010-04-27 00:48:032370 glDeleteFramebuffersEXT(1, &service_id);
2371 RemoveFramebufferInfo(client_ids[ii]);
2372 }
[email protected]a25fa872010-03-25 02:57:582373 }
[email protected]07f54fcc2009-12-22 02:46:302374}
2375
[email protected]ae51d192010-04-27 00:48:032376void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2377 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102378 bool supports_seperate_framebuffer_binds =
2379 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a25fa872010-03-25 02:57:582380 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102381 RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]ae51d192010-04-27 00:48:032382 GetRenderbufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102383 if (renderbuffer && !renderbuffer->IsDeleted()) {
2384 if (bound_renderbuffer_ == renderbuffer) {
2385 bound_renderbuffer_ = NULL;
2386 }
2387 // Unbind from current framebuffers.
2388 if (supports_seperate_framebuffer_binds) {
2389 if (bound_read_framebuffer_) {
2390 bound_read_framebuffer_->UnbindRenderbuffer(
2391 GL_READ_FRAMEBUFFER, renderbuffer);
2392 }
2393 if (bound_draw_framebuffer_) {
2394 bound_draw_framebuffer_->UnbindRenderbuffer(
2395 GL_DRAW_FRAMEBUFFER, renderbuffer);
2396 }
2397 } else {
2398 if (bound_draw_framebuffer_) {
2399 bound_draw_framebuffer_->UnbindRenderbuffer(
2400 GL_FRAMEBUFFER, renderbuffer);
2401 }
2402 }
[email protected]297ca1c2011-06-20 23:08:462403 state_dirty_ = true;
[email protected]a0b78dc2011-11-11 10:43:102404 GLuint service_id = renderbuffer->service_id();
[email protected]ae51d192010-04-27 00:48:032405 glDeleteRenderbuffersEXT(1, &service_id);
2406 RemoveRenderbufferInfo(client_ids[ii]);
2407 }
[email protected]a25fa872010-03-25 02:57:582408 }
[email protected]07f54fcc2009-12-22 02:46:302409}
2410
[email protected]ae51d192010-04-27 00:48:032411void GLES2DecoderImpl::DeleteTexturesHelper(
2412 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102413 bool supports_seperate_framebuffer_binds =
2414 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a93bb842010-02-16 23:03:472415 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102416 TextureManager::TextureInfo* texture = GetTextureInfo(client_ids[ii]);
2417 if (texture && !texture->IsDeleted()) {
2418 if (texture->IsAttachedToFramebuffer()) {
[email protected]297ca1c2011-06-20 23:08:462419 state_dirty_ = true;
2420 }
[email protected]a0b78dc2011-11-11 10:43:102421 // Unbind texture from texture units.
2422 for (size_t jj = 0; jj < group_->max_texture_units(); ++jj) {
2423 texture_units_[ii].Unbind(texture);
2424 }
2425 // Unbind from current framebuffers.
2426 if (supports_seperate_framebuffer_binds) {
2427 if (bound_read_framebuffer_) {
2428 bound_read_framebuffer_->UnbindTexture(GL_READ_FRAMEBUFFER, texture);
2429 }
2430 if (bound_draw_framebuffer_) {
2431 bound_draw_framebuffer_->UnbindTexture(GL_DRAW_FRAMEBUFFER, texture);
2432 }
2433 } else {
2434 if (bound_draw_framebuffer_) {
2435 bound_draw_framebuffer_->UnbindTexture(GL_FRAMEBUFFER, texture);
2436 }
2437 }
2438 GLuint service_id = texture->service_id();
2439 if (texture->IsStreamTexture() && stream_texture_manager_) {
[email protected]b0af4f52011-09-28 22:04:422440 stream_texture_manager_->DestroyStreamTexture(service_id);
2441 }
[email protected]e51bdf32011-11-23 22:21:462442#if defined(OS_MACOSX)
2443 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2444 ReleaseIOSurfaceForTexture(service_id);
2445 }
2446#endif
[email protected]5f4f2a732011-07-30 00:47:552447 glDeleteTextures(1, &service_id);
[email protected]ae51d192010-04-27 00:48:032448 RemoveTextureInfo(client_ids[ii]);
2449 }
[email protected]a93bb842010-02-16 23:03:472450 }
[email protected]07f54fcc2009-12-22 02:46:302451}
2452
[email protected]43f28f832010-02-03 02:28:482453// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322454
[email protected]eb54a562010-01-20 21:55:182455bool GLES2DecoderImpl::MakeCurrent() {
[email protected]38d139d2011-07-14 00:38:432456 bool result = context_.get() ? context_->MakeCurrent(surface_.get()) : false;
2457 if (result && WasContextLost()) {
2458 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2459 result = false;
2460 }
2461
2462 return result;
[email protected]eb54a562010-01-20 21:55:182463}
2464
[email protected]a96a6022011-11-04 00:58:122465void GLES2DecoderImpl::ReleaseCurrent() {
2466 if (context_.get())
2467 context_->ReleaseCurrent(surface_.get());
2468}
2469
[email protected]8e3e0662010-08-23 18:46:302470void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
[email protected]0d6bfdc2011-11-02 01:32:202471 RenderbufferManager::RenderbufferInfo* renderbuffer =
2472 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
[email protected]8e3e0662010-08-23 18:46:302473 glBindRenderbufferEXT(
[email protected]0d6bfdc2011-11-02 01:32:202474 GL_RENDERBUFFER, renderbuffer ? renderbuffer->service_id() : 0);
[email protected]8e3e0662010-08-23 18:46:302475}
2476
2477static void RebindCurrentFramebuffer(
2478 GLenum target,
2479 FramebufferManager::FramebufferInfo* info,
[email protected]a3783712012-01-20 22:18:242480 GLuint back_buffer_service_id) {
[email protected]8e3e0662010-08-23 18:46:302481 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462482
[email protected]a3783712012-01-20 22:18:242483 if (framebuffer_id == 0) {
2484 framebuffer_id = back_buffer_service_id;
[email protected]8e3e0662010-08-23 18:46:302485 }
[email protected]297ca1c2011-06-20 23:08:462486
[email protected]8e3e0662010-08-23 18:46:302487 glBindFramebufferEXT(target, framebuffer_id);
2488}
2489
2490void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]297ca1c2011-06-20 23:08:462491 state_dirty_ = true;
2492
[email protected]a3ded6d2010-10-19 06:44:392493 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302494 RebindCurrentFramebuffer(
2495 GL_FRAMEBUFFER,
2496 bound_draw_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242497 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302498 } else {
2499 RebindCurrentFramebuffer(
2500 GL_READ_FRAMEBUFFER_EXT,
2501 bound_read_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242502 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302503 RebindCurrentFramebuffer(
2504 GL_DRAW_FRAMEBUFFER_EXT,
2505 bound_draw_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242506 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302507 }
2508}
2509
2510void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2511 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2512 GLuint last_id;
2513 if (info.bound_texture_2d) {
2514 last_id = info.bound_texture_2d->service_id();
2515 } else {
2516 last_id = 0;
2517 }
2518
2519 glBindTexture(GL_TEXTURE_2D, last_id);
2520 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2521}
2522
[email protected]0d6bfdc2011-11-02 01:32:202523bool GLES2DecoderImpl::CheckFramebufferValid(
2524 FramebufferManager::FramebufferInfo* framebuffer,
2525 GLenum target, const char* func_name) {
[email protected]a0b78dc2011-11-11 10:43:102526 if (!framebuffer) {
[email protected]0d6bfdc2011-11-02 01:32:202527 return true;
2528 }
2529
[email protected]968351b2011-12-20 08:26:512530 if (framebuffer_manager()->IsComplete(framebuffer)) {
2531 return true;
2532 }
2533
[email protected]0d6bfdc2011-11-02 01:32:202534 GLenum completeness = framebuffer->IsPossiblyComplete();
2535 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
2536 SetGLError(
2537 GL_INVALID_FRAMEBUFFER_OPERATION,
2538 (std::string(func_name) + " framebuffer incomplete").c_str());
[email protected]3a03a8f2011-03-19 00:51:272539 return false;
2540 }
[email protected]0d6bfdc2011-11-02 01:32:202541
2542 // Are all the attachments cleared?
2543 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2544 texture_manager()->HaveUnclearedMips()) {
2545 if (!framebuffer->IsCleared()) {
2546 // Can we clear them?
2547 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2548 SetGLError(
2549 GL_INVALID_FRAMEBUFFER_OPERATION,
2550 (std::string(func_name) +
2551 " framebuffer incomplete (clear)").c_str());
2552 return false;
2553 }
2554 ClearUnclearedAttachments(target, framebuffer);
2555 }
2556 }
2557
[email protected]968351b2011-12-20 08:26:512558 if (!framebuffer_manager()->IsComplete(framebuffer)) {
2559 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2560 SetGLError(
2561 GL_INVALID_FRAMEBUFFER_OPERATION,
2562 (std::string(func_name) +
2563 " framebuffer incomplete (check)").c_str());
2564 return false;
2565 }
2566 framebuffer_manager()->MarkAsComplete(framebuffer);
2567 }
2568
[email protected]0d6bfdc2011-11-02 01:32:202569 // NOTE: At this point we don't know if the framebuffer is complete but
2570 // we DO know that everything that needs to be cleared has been cleared.
[email protected]3a03a8f2011-03-19 00:51:272571 return true;
2572}
2573
[email protected]0d6bfdc2011-11-02 01:32:202574bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
2575 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
2576 return CheckFramebufferValid(
2577 bound_draw_framebuffer_, GL_FRAMEBUFFER_EXT, func_name);
2578 }
2579 return CheckFramebufferValid(
2580 bound_draw_framebuffer_, GL_DRAW_FRAMEBUFFER_EXT, func_name) &&
2581 CheckFramebufferValid(
2582 bound_read_framebuffer_, GL_READ_FRAMEBUFFER_EXT, func_name);
2583}
2584
[email protected]8e3e0662010-08-23 18:46:302585gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
[email protected]0d6bfdc2011-11-02 01:32:202586 FramebufferManager::FramebufferInfo* framebuffer =
2587 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2588 if (framebuffer != NULL) {
[email protected]9edc6b22010-12-23 02:00:262589 const FramebufferManager::FramebufferInfo::Attachment* attachment =
[email protected]0d6bfdc2011-11-02 01:32:202590 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
[email protected]9edc6b22010-12-23 02:00:262591 if (attachment) {
2592 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502593 }
[email protected]9edc6b22010-12-23 02:00:262594 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022595 } else if (offscreen_target_frame_buffer_.get()) {
2596 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352597 } else {
[email protected]f62a5ab2011-05-23 20:34:152598 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022599 }
[email protected]246a70452010-03-05 21:53:502600}
2601
[email protected]9edc6b22010-12-23 02:00:262602GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202603 FramebufferManager::FramebufferInfo* framebuffer =
2604 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2605 if (framebuffer != NULL) {
2606 return framebuffer->GetColorAttachmentFormat();
[email protected]297ca1c2011-06-20 23:08:462607 } else if (offscreen_target_frame_buffer_.get()) {
2608 return offscreen_target_color_format_;
2609 } else {
2610 return back_buffer_color_format_;
2611 }
2612}
2613
2614GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202615 FramebufferManager::FramebufferInfo* framebuffer =
2616 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
2617 if (framebuffer != NULL) {
2618 return framebuffer->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262619 } else if (offscreen_target_frame_buffer_.get()) {
2620 return offscreen_target_color_format_;
2621 } else {
[email protected]32fe9aa2011-01-21 23:47:132622 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262623 }
2624}
2625
[email protected]9a5afa432011-07-22 18:16:392626void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]34ff8b0c2010-10-01 20:06:022627 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582628 // Update the info about the offscreen saved color texture in the parent.
2629 // The reference to the parent is a weak pointer and will become null if the
2630 // parent is later destroyed.
[email protected]262d7aa2010-12-03 22:07:292631 TextureManager* parent_texture_manager = parent_->texture_manager();
[email protected]262d7aa2010-12-03 22:07:292632 parent_texture_manager->SetLevelInfo(
[email protected]8a61d872012-01-20 12:43:562633 offscreen_saved_color_texture_info_,
[email protected]ef526492010-06-02 23:12:252634 GL_TEXTURE_2D,
2635 0, // level
2636 GL_RGBA,
[email protected]799b4b22011-08-22 17:09:592637 offscreen_size_.width(),
2638 offscreen_size_.height(),
[email protected]ef526492010-06-02 23:12:252639 1, // depth
2640 0, // border
2641 GL_RGBA,
[email protected]0d6bfdc2011-11-02 01:32:202642 GL_UNSIGNED_BYTE,
2643 true);
[email protected]262d7aa2010-12-03 22:07:292644 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562645 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042646 GL_TEXTURE_MAG_FILTER,
2647 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292648 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562649 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042650 GL_TEXTURE_MIN_FILTER,
2651 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292652 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562653 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042654 GL_TEXTURE_WRAP_S,
2655 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292656 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562657 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042658 GL_TEXTURE_WRAP_T,
2659 GL_CLAMP_TO_EDGE);
[email protected]8a61d872012-01-20 12:43:562660 } else {
2661 offscreen_saved_color_texture_info_ = NULL;
[email protected]0c8c9d22010-06-25 17:36:392662 }
[email protected]6217d392010-03-25 22:08:352663}
2664
[email protected]799b4b22011-08-22 17:09:592665void GLES2DecoderImpl::SetResizeCallback(
[email protected]9d37f062011-11-22 01:24:522666 const base::Callback<void(gfx::Size)>& callback) {
2667 resize_callback_ = callback;
[email protected]7ff86b92010-11-25 17:50:002668}
2669
[email protected]6b6e7ee2011-12-13 08:04:522670void GLES2DecoderImpl::SetMsgCallback(const MsgCallback& callback) {
2671 msg_callback_ = callback;
2672}
2673
[email protected]b0af4f52011-09-28 22:04:422674void GLES2DecoderImpl::SetStreamTextureManager(StreamTextureManager* manager) {
2675 stream_texture_manager_ = manager;
2676}
2677
[email protected]1318e922010-09-17 22:03:162678bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2679 uint32* service_texture_id) {
2680 TextureManager::TextureInfo* texture =
2681 texture_manager()->GetTextureInfo(client_texture_id);
2682 if (texture) {
2683 *service_texture_id = texture->service_id();
2684 return true;
2685 }
2686 return false;
2687}
2688
[email protected]96449d2c2009-11-25 00:01:322689void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392690 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052691
[email protected]3c644d82011-06-20 19:58:242692 SetParent(NULL, 0);
2693
[email protected]80eb6b52012-01-19 00:14:412694 // Unbind everything.
[email protected]3757a372012-01-19 05:20:442695 vertex_attrib_manager_.reset();
[email protected]80eb6b52012-01-19 00:14:412696 texture_units_.reset();
2697 bound_array_buffer_ = NULL;
2698 bound_element_array_buffer_ = NULL;
2699 current_program_ = NULL;
2700 bound_read_framebuffer_ = NULL;
2701 bound_draw_framebuffer_ = NULL;
2702 bound_renderbuffer_ = NULL;
2703
[email protected]eadc96792010-10-27 19:39:392704 if (have_context) {
[email protected]ca488e12010-12-13 20:06:142705 if (current_program_) {
2706 program_manager()->UnuseProgram(shader_manager(), current_program_);
2707 current_program_ = NULL;
2708 }
2709
[email protected]b1122982010-05-17 23:04:242710 if (attrib_0_buffer_id_) {
2711 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2712 }
[email protected]8fbedc02010-11-18 18:43:402713 if (fixed_attrib_buffer_id_) {
2714 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2715 }
[email protected]b1122982010-05-17 23:04:242716
[email protected]97872062010-11-03 19:07:052717 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542718 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052719 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542720 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052721 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022722 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052723 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152724 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052725 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152726 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052727 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022728 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052729 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542730 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:272731 if (offscreen_resolved_frame_buffer_.get())
2732 offscreen_resolved_frame_buffer_->Destroy();
2733 if (offscreen_resolved_color_texture_.get())
2734 offscreen_resolved_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052735 } else {
2736 if (offscreen_target_frame_buffer_.get())
2737 offscreen_target_frame_buffer_->Invalidate();
2738 if (offscreen_target_color_texture_.get())
2739 offscreen_target_color_texture_->Invalidate();
2740 if (offscreen_target_color_render_buffer_.get())
2741 offscreen_target_color_render_buffer_->Invalidate();
2742 if (offscreen_target_depth_render_buffer_.get())
2743 offscreen_target_depth_render_buffer_->Invalidate();
2744 if (offscreen_target_stencil_render_buffer_.get())
2745 offscreen_target_stencil_render_buffer_->Invalidate();
2746 if (offscreen_saved_frame_buffer_.get())
2747 offscreen_saved_frame_buffer_->Invalidate();
2748 if (offscreen_saved_color_texture_.get())
2749 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:272750 if (offscreen_resolved_frame_buffer_.get())
2751 offscreen_resolved_frame_buffer_->Invalidate();
2752 if (offscreen_resolved_color_texture_.get())
2753 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022754 }
[email protected]97872062010-11-03 19:07:052755
[email protected]1871a092011-10-10 21:46:422756 if (group_) {
2757 group_->Destroy(have_context);
2758 group_ = NULL;
2759 }
[email protected]3ae019382011-10-05 19:42:412760
[email protected]fe871662011-06-16 20:43:052761 if (context_.get()) {
2762 context_->ReleaseCurrent(NULL);
[email protected]79311e82011-09-20 00:40:502763 context_ = NULL;
[email protected]fe871662011-06-16 20:43:052764 }
[email protected]0fc35742011-04-13 17:57:542765
[email protected]97872062010-11-03 19:07:052766 offscreen_target_frame_buffer_.reset();
2767 offscreen_target_color_texture_.reset();
2768 offscreen_target_color_render_buffer_.reset();
2769 offscreen_target_depth_render_buffer_.reset();
2770 offscreen_target_stencil_render_buffer_.reset();
2771 offscreen_saved_frame_buffer_.reset();
2772 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:272773 offscreen_resolved_frame_buffer_.reset();
2774 offscreen_resolved_color_texture_.reset();
[email protected]e51bdf32011-11-23 22:21:462775
2776#if defined(OS_MACOSX)
2777 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
2778 it != texture_to_io_surface_map_.end(); ++it) {
2779 CFRelease(it->second);
2780 }
2781 texture_to_io_surface_map_.clear();
2782#endif
[email protected]96449d2c2009-11-25 00:01:322783}
2784
[email protected]3c644d82011-06-20 19:58:242785bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
2786 uint32 new_parent_texture_id) {
[email protected]9a5afa432011-07-22 18:16:392787 if (!offscreen_saved_color_texture_.get())
2788 return false;
2789
[email protected]3c644d82011-06-20 19:58:242790 // Remove the saved frame buffer mapping from the parent decoder. The
2791 // parent pointer is a weak pointer so it will be null if the parent has
2792 // already been destroyed.
2793 if (parent_) {
2794 // First check the texture has been mapped into the parent. This might not
2795 // be the case if initialization failed midway through.
2796 GLuint service_id = offscreen_saved_color_texture_->id();
2797 GLuint client_id = 0;
2798 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
[email protected]80eb6b52012-01-19 00:14:412799 parent_->texture_manager()->RemoveTextureInfo(client_id);
[email protected]3c644d82011-06-20 19:58:242800 }
2801 }
2802
2803 GLES2DecoderImpl* new_parent_impl = static_cast<GLES2DecoderImpl*>(
2804 new_parent);
2805 if (new_parent_impl) {
2806 // Map the ID of the saved offscreen texture into the parent so that
2807 // it can reference it.
2808 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]98687862011-07-11 23:31:302809
2810 // Replace texture info when ID is already in use by parent.
2811 if (new_parent_impl->texture_manager()->GetTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412812 new_parent_texture_id))
[email protected]98687862011-07-11 23:31:302813 new_parent_impl->texture_manager()->RemoveTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412814 new_parent_texture_id);
[email protected]98687862011-07-11 23:31:302815
[email protected]8a61d872012-01-20 12:43:562816 offscreen_saved_color_texture_info_ =
[email protected]5f4f2a732011-07-30 00:47:552817 new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id);
[email protected]8a61d872012-01-20 12:43:562818 offscreen_saved_color_texture_info_->SetNotOwned();
2819 new_parent_impl->texture_manager()->
2820 SetInfoTarget(offscreen_saved_color_texture_info_, GL_TEXTURE_2D);
[email protected]3c644d82011-06-20 19:58:242821
2822 parent_ = new_parent_impl->AsWeakPtr();
[email protected]9a5afa432011-07-22 18:16:392823
2824 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:242825 } else {
2826 parent_.reset();
[email protected]8a61d872012-01-20 12:43:562827 offscreen_saved_color_texture_info_ = NULL;
[email protected]3c644d82011-06-20 19:58:242828 }
2829
2830 return true;
2831}
2832
[email protected]1078f912011-12-23 13:12:142833void GLES2DecoderImpl::UpdateBackbufferMemoryAccounting() {
2834 size_t total = 0;
2835 if (offscreen_target_frame_buffer_.get()) {
2836 if (offscreen_target_color_texture_.get()) {
2837 total += offscreen_target_color_texture_->estimated_size();
2838 }
2839 if (offscreen_target_color_render_buffer_.get()) {
2840 total += offscreen_target_color_render_buffer_->estimated_size();
2841 }
2842 if (offscreen_target_depth_render_buffer_.get()) {
2843 total += offscreen_target_depth_render_buffer_->estimated_size();
2844 }
2845 if (offscreen_target_stencil_render_buffer_.get()) {
2846 total += offscreen_target_stencil_render_buffer_->estimated_size();
2847 }
2848 if (offscreen_saved_color_texture_.get()) {
2849 total += offscreen_saved_color_texture_->estimated_size();
2850 }
2851 if (offscreen_resolved_color_texture_.get()) {
2852 total += offscreen_resolved_color_texture_->estimated_size();
2853 }
2854 } else {
2855 gfx::Size size = surface_->GetSize();
2856 total += size.width() * size.height() *
2857 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_);
2858 }
2859 TRACE_COUNTER_ID1(
2860 "GLES2DecoderImpl", "BackbufferMemory", this, total);
2861}
2862
[email protected]799b4b22011-08-22 17:09:592863bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2864 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
2865 if (!is_offscreen) {
2866 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
2867 << " with an onscreen framebuffer.";
2868 return false;
2869 }
2870
2871 if (offscreen_size_ == size)
2872 return true;
2873
2874 offscreen_size_ = size;
2875 int w = offscreen_size_.width();
2876 int h = offscreen_size_.height();
2877 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
2878 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2879 << "to allocate storage due to excessive dimensions.";
2880 return false;
2881 }
2882
2883 // Reallocate the offscreen target buffers.
2884 DCHECK(offscreen_target_color_format_);
2885 if (IsOffscreenBufferMultisampled()) {
2886 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2887 offscreen_size_, offscreen_target_color_format_,
2888 offscreen_target_samples_)) {
2889 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2890 << "to allocate storage for offscreen target color buffer.";
2891 return false;
2892 }
2893 } else {
2894 if (!offscreen_target_color_texture_->AllocateStorage(
2895 offscreen_size_, offscreen_target_color_format_)) {
2896 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2897 << "to allocate storage for offscreen target color texture.";
2898 return false;
2899 }
2900 }
2901 if (offscreen_target_depth_format_ &&
2902 !offscreen_target_depth_render_buffer_->AllocateStorage(
2903 offscreen_size_, offscreen_target_depth_format_,
2904 offscreen_target_samples_)) {
2905 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2906 << "to allocate storage for offscreen target depth buffer.";
2907 return false;
2908 }
2909 if (offscreen_target_stencil_format_ &&
2910 !offscreen_target_stencil_render_buffer_->AllocateStorage(
2911 offscreen_size_, offscreen_target_stencil_format_,
2912 offscreen_target_samples_)) {
2913 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2914 << "to allocate storage for offscreen target stencil buffer.";
2915 return false;
2916 }
[email protected]1078f912011-12-23 13:12:142917 UpdateBackbufferMemoryAccounting();
[email protected]799b4b22011-08-22 17:09:592918
2919 // Attach the offscreen target buffers to the target frame buffer.
2920 if (IsOffscreenBufferMultisampled()) {
2921 offscreen_target_frame_buffer_->AttachRenderBuffer(
2922 GL_COLOR_ATTACHMENT0,
2923 offscreen_target_color_render_buffer_.get());
2924 } else {
2925 offscreen_target_frame_buffer_->AttachRenderTexture(
2926 offscreen_target_color_texture_.get());
2927 }
2928 if (offscreen_target_depth_format_) {
2929 offscreen_target_frame_buffer_->AttachRenderBuffer(
2930 GL_DEPTH_ATTACHMENT,
2931 offscreen_target_depth_render_buffer_.get());
2932 }
2933 const bool packed_depth_stencil =
2934 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2935 if (packed_depth_stencil) {
2936 offscreen_target_frame_buffer_->AttachRenderBuffer(
2937 GL_STENCIL_ATTACHMENT,
2938 offscreen_target_depth_render_buffer_.get());
2939 } else if (offscreen_target_stencil_format_) {
2940 offscreen_target_frame_buffer_->AttachRenderBuffer(
2941 GL_STENCIL_ATTACHMENT,
2942 offscreen_target_stencil_render_buffer_.get());
2943 }
2944
2945 if (offscreen_target_frame_buffer_->CheckStatus() !=
2946 GL_FRAMEBUFFER_COMPLETE) {
2947 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2948 << "because offscreen FBO was incomplete.";
2949 return false;
2950 }
2951
2952 // Clear the target frame buffer.
2953 {
2954 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
2955 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2956 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
2957 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2958 glClearStencil(0);
2959 glStencilMaskSeparate(GL_FRONT, -1);
2960 glStencilMaskSeparate(GL_BACK, -1);
2961 glClearDepth(0);
2962 glDepthMask(GL_TRUE);
2963 glDisable(GL_SCISSOR_TEST);
2964 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2965 RestoreClearState();
2966 }
[email protected]d85ef76d2011-09-08 22:21:432967
2968 // Destroy the offscreen resolved framebuffers.
2969 if (offscreen_resolved_frame_buffer_.get())
2970 offscreen_resolved_frame_buffer_->Destroy();
2971 if (offscreen_resolved_color_texture_.get())
2972 offscreen_resolved_color_texture_->Destroy();
2973 offscreen_resolved_color_texture_.reset();
2974 offscreen_resolved_frame_buffer_.reset();
2975
[email protected]799b4b22011-08-22 17:09:592976 return true;
[email protected]6217d392010-03-25 22:08:352977}
2978
[email protected]799b4b22011-08-22 17:09:592979error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
2980 uint32 immediate_data_size, const gles2::ResizeCHROMIUM& c) {
2981 GLuint width = static_cast<GLuint>(c.width);
2982 GLuint height = static_cast<GLuint>(c.height);
2983 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
[email protected]a0d989162011-11-22 13:15:072984#if defined(OS_POSIX) && !defined(OS_MACOSX) && \
2985 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
[email protected]7ff86b92010-11-25 17:50:002986 // Make sure that we are done drawing to the back buffer before resizing.
2987 glFinish();
2988#endif
[email protected]799b4b22011-08-22 17:09:592989 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
2990 if (is_offscreen) {
2991 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height)))
2992 return error::kLostContext;
[email protected]7ff86b92010-11-25 17:50:002993 }
[email protected]799b4b22011-08-22 17:09:592994
[email protected]9d37f062011-11-22 01:24:522995 if (!resize_callback_.is_null()) {
2996 resize_callback_.Run(gfx::Size(width, height));
[email protected]c777de52011-09-09 23:08:562997 DCHECK(context_->IsCurrent(surface_.get()));
2998 if (!context_->IsCurrent(surface_.get()))
[email protected]658f7562011-09-09 05:24:052999 return error::kLostContext;
[email protected]658f7562011-09-09 05:24:053000 }
[email protected]799b4b22011-08-22 17:09:593001
[email protected]1078f912011-12-23 13:12:143002 UpdateBackbufferMemoryAccounting();
3003
[email protected]799b4b22011-08-22 17:09:593004 return error::kNoError;
[email protected]43ecf372010-11-16 19:19:393005}
3006
[email protected]96449d2c2009-11-25 00:01:323007const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3008 if (command_id > kStartPoint && command_id < kNumCommands) {
3009 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3010 }
3011 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3012}
3013
3014// Decode command with its arguments, and call the corresponding GL function.
3015// Note: args is a pointer to the command buffer. As such, it could be changed
3016// by a (malicious) client at any time, so if validation has to happen, it
3017// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:143018error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:323019 unsigned int command,
3020 unsigned int arg_count,
3021 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:143022 error::Error result = error::kNoError;
[email protected]e844ae22012-01-14 03:36:263023 if (log_commands()) {
[email protected]4297cbe2011-11-03 18:04:003024 LOG(INFO) << "[" << this << "]" << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193025 }
[email protected]96449d2c2009-11-25 00:01:323026 unsigned int command_index = command - kStartPoint - 1;
3027 if (command_index < arraysize(g_command_info)) {
3028 const CommandInfo& info = g_command_info[command_index];
3029 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3030 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3031 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:193032 uint32 immediate_data_size =
3033 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:323034 switch (command) {
3035 #define GLES2_CMD_OP(name) \
3036 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:193037 result = Handle ## name( \
3038 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:323039 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:193040 break; \
[email protected]96449d2c2009-11-25 00:01:323041
3042 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:323043 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:383044 }
3045 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:303046 GLenum error;
3047 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]e844ae22012-01-14 03:36:263048 SetGLError(error, "GL error from driver");
3049 LOG(INFO) << "[" << this << "]"
3050 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3051 << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193052 }
[email protected]96449d2c2009-11-25 00:01:323053 }
3054 } else {
[email protected]f7a64ee2010-02-01 22:24:143055 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:323056 }
[email protected]b9849abf2009-11-25 19:13:193057 } else {
3058 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:323059 }
[email protected]a3a93e7b2010-08-28 00:48:563060 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3061 result = current_decoder_error_;
3062 current_decoder_error_ = error::kNoError;
3063 }
[email protected]b9849abf2009-11-25 19:13:193064 return result;
[email protected]96449d2c2009-11-25 00:01:323065}
3066
[email protected]ae51d192010-04-27 00:48:033067void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
3068 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:503069}
3070
[email protected]ae51d192010-04-27 00:48:033071bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3072 if (GetProgramInfo(client_id)) {
3073 return false;
3074 }
[email protected]96449d2c2009-11-25 00:01:323075 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:033076 if (service_id != 0) {
3077 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:323078 }
[email protected]ae51d192010-04-27 00:48:033079 return true;
[email protected]96449d2c2009-11-25 00:01:323080}
3081
[email protected]ae51d192010-04-27 00:48:033082bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3083 if (GetShaderInfo(client_id)) {
3084 return false;
[email protected]96449d2c2009-11-25 00:01:323085 }
[email protected]ae51d192010-04-27 00:48:033086 GLuint service_id = glCreateShader(type);
3087 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:383088 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:033089 }
3090 return true;
[email protected]96449d2c2009-11-25 00:01:323091}
3092
[email protected]3916c97e2010-02-25 03:20:503093void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:453094 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]660858b2011-07-13 23:16:143095 if (texture_index >= group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:293096 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:503097 return;
3098 }
[email protected]36cef8ce2010-03-16 07:34:453099 active_texture_unit_ = texture_index;
3100 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:503101}
3102
[email protected]051b1372010-04-12 02:42:083103void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:503104 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083105 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033106 if (client_id != 0) {
3107 info = GetBufferInfo(client_id);
3108 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353109 if (!group_->bind_generates_resource()) {
3110 SetGLError(GL_INVALID_VALUE,
3111 "glBindBuffer: id not generated by glGenBuffers");
3112 return;
3113 }
3114
[email protected]ae51d192010-04-27 00:48:033115 // It's a new id so make a buffer info for it.
3116 glGenBuffersARB(1, &service_id);
3117 CreateBufferInfo(client_id, service_id);
3118 info = GetBufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573119 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103120 group_->GetIdAllocator(id_namespaces::kBuffers);
3121 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033122 }
[email protected]051b1372010-04-12 02:42:083123 }
[email protected]ae51d192010-04-27 00:48:033124 if (info) {
[email protected]4e8a5b122010-05-08 22:00:103125 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:293126 SetGLError(GL_INVALID_OPERATION,
3127 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:473128 return;
3129 }
[email protected]ae51d192010-04-27 00:48:033130 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:473131 }
[email protected]96449d2c2009-11-25 00:01:323132 switch (target) {
3133 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503134 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323135 break;
3136 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503137 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323138 break;
3139 default:
[email protected]a93bb842010-02-16 23:03:473140 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:323141 break;
3142 }
[email protected]051b1372010-04-12 02:42:083143 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:323144}
3145
[email protected]297ca1c2011-06-20 23:08:463146bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
3147 return (GLES2Util::GetChannelsForFormat(
3148 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3149}
3150
3151bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203152 FramebufferManager::FramebufferInfo* framebuffer =
3153 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3154 if (framebuffer) {
3155 return framebuffer->HasDepthAttachment();
[email protected]297ca1c2011-06-20 23:08:463156 }
3157 if (offscreen_target_frame_buffer_.get()) {
3158 return offscreen_target_depth_format_ != 0;
3159 }
3160 return back_buffer_has_depth_;
3161}
3162
3163bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203164 FramebufferManager::FramebufferInfo* framebuffer =
3165 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3166 if (framebuffer) {
3167 return framebuffer->HasStencilAttachment();
[email protected]297ca1c2011-06-20 23:08:463168 }
3169 if (offscreen_target_frame_buffer_.get()) {
3170 return offscreen_target_stencil_format_ != 0 ||
3171 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3172 }
3173 return back_buffer_has_stencil_;
3174}
3175
3176void GLES2DecoderImpl::ApplyDirtyState() {
3177 if (state_dirty_) {
3178 glColorMask(
3179 mask_red_, mask_green_, mask_blue_,
3180 mask_alpha_ && BoundFramebufferHasColorAttachmentWithAlpha());
3181 bool have_depth = BoundFramebufferHasDepthAttachment();
3182 glDepthMask(mask_depth_ && have_depth);
3183 EnableDisable(GL_DEPTH_TEST, enable_depth_test_ && have_depth);
3184 bool have_stencil = BoundFramebufferHasStencilAttachment();
3185 glStencilMaskSeparate(GL_FRONT, have_stencil ? mask_stencil_front_ : 0);
3186 glStencilMaskSeparate(GL_BACK, have_stencil ? mask_stencil_back_ : 0);
3187 EnableDisable(GL_STENCIL_TEST, enable_stencil_test_ && have_stencil);
3188 state_dirty_ = false;
3189 }
3190}
3191
[email protected]b177ae22011-11-01 03:29:113192GLuint GLES2DecoderImpl::GetBackbufferServiceId() {
3193 return (offscreen_target_frame_buffer_.get()) ?
3194 offscreen_target_frame_buffer_->id() :
3195 surface_->GetBackingFrameBufferObject();
3196}
3197
[email protected]051b1372010-04-12 02:42:083198void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3199 FramebufferManager::FramebufferInfo* info = NULL;
3200 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033201 if (client_id != 0) {
3202 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083203 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353204 if (!group_->bind_generates_resource()) {
3205 SetGLError(GL_INVALID_VALUE,
3206 "glBindFramebuffer: id not generated by glGenFramebuffers");
3207 return;
3208 }
3209
[email protected]ae51d192010-04-27 00:48:033210 // It's a new id so make a framebuffer info for it.
3211 glGenFramebuffersEXT(1, &service_id);
3212 CreateFramebufferInfo(client_id, service_id);
3213 info = GetFramebufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573214 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103215 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3216 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033217 } else {
3218 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083219 }
[email protected]06c8b082011-01-05 18:00:363220 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083221 }
[email protected]8e3e0662010-08-23 18:46:303222
3223 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
3224 bound_draw_framebuffer_ = info;
3225 }
3226 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
3227 bound_read_framebuffer_ = info;
3228 }
[email protected]6217d392010-03-25 22:08:353229
[email protected]297ca1c2011-06-20 23:08:463230 state_dirty_ = true;
3231
[email protected]b177ae22011-11-01 03:29:113232 // If we are rendering to the backbuffer get the FBO id for any simulated
3233 // backbuffer.
3234 if (info == NULL) {
3235 service_id = GetBackbufferServiceId();
[email protected]297ca1c2011-06-20 23:08:463236 }
[email protected]6217d392010-03-25 22:08:353237
[email protected]051b1372010-04-12 02:42:083238 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563239}
3240
[email protected]051b1372010-04-12 02:42:083241void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
3242 RenderbufferManager::RenderbufferInfo* info = NULL;
3243 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033244 if (client_id != 0) {
3245 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083246 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353247 if (!group_->bind_generates_resource()) {
3248 SetGLError(
3249 GL_INVALID_VALUE,
3250 "glBindRenderbuffer: id not generated by glGenRenderbuffers");
3251 return;
3252 }
3253
[email protected]ae51d192010-04-27 00:48:033254 // It's a new id so make a renderbuffer info for it.
3255 glGenRenderbuffersEXT(1, &service_id);
3256 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:103257 info = GetRenderbufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573258 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103259 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3260 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033261 } else {
3262 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083263 }
[email protected]06c8b082011-01-05 18:00:363264 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083265 }
3266 bound_renderbuffer_ = info;
3267 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563268}
3269
[email protected]051b1372010-04-12 02:42:083270void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033271 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083272 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033273 if (client_id != 0) {
3274 info = GetTextureInfo(client_id);
3275 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353276 if (!group_->bind_generates_resource()) {
3277 SetGLError(GL_INVALID_VALUE,
3278 "glBindTexture: id not generated by glGenTextures");
3279 return;
3280 }
3281
[email protected]ae51d192010-04-27 00:48:033282 // It's a new id so make a texture info for it.
3283 glGenTextures(1, &service_id);
[email protected]80eb6b52012-01-19 00:14:413284 DCHECK_NE(0u, service_id);
[email protected]ae51d192010-04-27 00:48:033285 CreateTextureInfo(client_id, service_id);
3286 info = GetTextureInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573287 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103288 group_->GetIdAllocator(id_namespaces::kTextures);
3289 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033290 }
3291 } else {
3292 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:083293 }
[email protected]ae51d192010-04-27 00:48:033294
[email protected]1958e0e2010-04-22 05:17:153295 // Check the texture exists
3296 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:033297 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:293298 SetGLError(GL_INVALID_OPERATION,
3299 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:153300 return;
3301 }
[email protected]b0af4f52011-09-28 22:04:423302 if (info->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
3303 SetGLError(GL_INVALID_OPERATION,
3304 "glBindTexture: illegal target for stream texture.");
3305 return;
3306 }
[email protected]1958e0e2010-04-22 05:17:153307 if (info->target() == 0) {
[email protected]80eb6b52012-01-19 00:14:413308 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:473309 }
[email protected]ae51d192010-04-27 00:48:033310 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:503311 TextureUnit& unit = texture_units_[active_texture_unit_];
3312 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:473313 switch (target) {
3314 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:503315 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:473316 break;
3317 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:503318 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:473319 break;
[email protected]61eeb33f2011-07-26 15:30:313320 case GL_TEXTURE_EXTERNAL_OES:
3321 unit.bound_texture_external_oes = info;
[email protected]b0af4f52011-09-28 22:04:423322 if (info->IsStreamTexture()) {
3323 DCHECK(stream_texture_manager_);
3324 StreamTexture* stream_tex =
3325 stream_texture_manager_->LookupStreamTexture(info->service_id());
3326 if (stream_tex)
3327 stream_tex->Update();
3328 }
[email protected]61eeb33f2011-07-26 15:30:313329 break;
[email protected]e51bdf32011-11-23 22:21:463330 case GL_TEXTURE_RECTANGLE_ARB:
3331 unit.bound_texture_rectangle_arb = info;
3332 break;
[email protected]a93bb842010-02-16 23:03:473333 default:
3334 NOTREACHED(); // Validation should prevent us getting here.
3335 break;
3336 }
3337}
3338
[email protected]07f54fcc2009-12-22 02:46:303339void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443340 if (vertex_attrib_manager_->Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:123341 if (index != 0 ||
3342 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:243343 glDisableVertexAttribArray(index);
3344 }
[email protected]07f54fcc2009-12-22 02:46:303345 } else {
[email protected]8eee29c2010-04-29 03:38:293346 SetGLError(GL_INVALID_VALUE,
3347 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:303348 }
3349}
3350
3351void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443352 if (vertex_attrib_manager_->Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:303353 glEnableVertexAttribArray(index);
3354 } else {
[email protected]8eee29c2010-04-29 03:38:293355 SetGLError(GL_INVALID_VALUE,
3356 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:303357 }
3358}
3359
[email protected]a93bb842010-02-16 23:03:473360void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:503361 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]97dc7cbe2011-12-06 17:26:173362 if (!info ||
[email protected]80eb6b52012-01-19 00:14:413363 !texture_manager()->MarkMipmapsGenerated(info)) {
[email protected]8eee29c2010-04-29 03:38:293364 SetGLError(GL_INVALID_OPERATION,
3365 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:473366 return;
3367 }
[email protected]59f3ca02011-03-26 22:24:193368 // Workaround for Mac driver bug. In the large scheme of things setting
3369 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
[email protected]a8bad262011-10-21 18:28:563370 // hit so there's probably no need to make this conditional. The bug appears
3371 // to be that if the filtering mode is set to something that doesn't require
3372 // mipmaps for rendering, or is never set to something other than the default,
3373 // then glGenerateMipmap misbehaves.
3374 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
[email protected]a93bb842010-02-16 23:03:473375 glGenerateMipmapEXT(target);
[email protected]59f3ca02011-03-26 22:24:193376 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
[email protected]a93bb842010-02-16 23:03:473377}
3378
[email protected]b273e432010-04-12 17:23:583379bool GLES2DecoderImpl::GetHelper(
3380 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:583381 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:153382 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
3383 switch (pname) {
[email protected]b273e432010-04-12 17:23:583384 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
3385 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103386 if (params) {
[email protected]5094b0f2010-11-09 19:45:243387 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:103388 }
[email protected]b273e432010-04-12 17:23:583389 return true;
3390 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3391 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103392 if (params) {
[email protected]5094b0f2010-11-09 19:45:243393 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:103394 }
[email protected]b273e432010-04-12 17:23:583395 return true;
3396 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
3397 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103398 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483399 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:103400 }
[email protected]b273e432010-04-12 17:23:583401 return true;
3402 case GL_MAX_VARYING_VECTORS:
3403 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103404 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483405 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:103406 }
[email protected]b273e432010-04-12 17:23:583407 return true;
3408 case GL_MAX_VERTEX_UNIFORM_VECTORS:
3409 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103410 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483411 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:103412 }
[email protected]b273e432010-04-12 17:23:583413 return true;
[email protected]5cb735d2011-10-13 01:37:233414 }
3415 }
3416 switch (pname) {
[email protected]5094b0f2010-11-09 19:45:243417 case GL_MAX_VIEWPORT_DIMS:
3418 if (offscreen_target_frame_buffer_.get()) {
3419 *num_written = 2;
3420 if (params) {
3421 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3422 params[1] = renderbuffer_manager()->max_renderbuffer_size();
3423 }
3424 return true;
3425 }
[email protected]5cb735d2011-10-13 01:37:233426 return false;
[email protected]84afefa2011-10-19 21:45:533427 case GL_MAX_SAMPLES:
3428 *num_written = 1;
3429 if (params) {
3430 params[0] = renderbuffer_manager()->max_samples();
3431 }
3432 return true;
3433 case GL_MAX_RENDERBUFFER_SIZE:
3434 *num_written = 1;
3435 if (params) {
3436 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3437 }
3438 return true;
[email protected]5cb735d2011-10-13 01:37:233439 case GL_MAX_TEXTURE_SIZE:
3440 *num_written = 1;
3441 if (params) {
3442 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
3443 }
3444 return true;
3445 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
3446 *num_written = 1;
3447 if (params) {
3448 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
3449 }
3450 return true;
[email protected]297ca1c2011-06-20 23:08:463451 case GL_COLOR_WRITEMASK:
3452 *num_written = 4;
3453 if (params) {
3454 params[0] = mask_red_;
3455 params[1] = mask_green_;
3456 params[2] = mask_blue_;
3457 params[3] = mask_alpha_;
3458 }
3459 return true;
3460 case GL_DEPTH_WRITEMASK:
3461 *num_written = 1;
3462 if (params) {
3463 params[0] = mask_depth_;
3464 }
3465 return true;
3466 case GL_STENCIL_BACK_WRITEMASK:
3467 *num_written = 1;
3468 if (params) {
3469 params[0] = mask_stencil_back_;
3470 }
3471 return true;
3472 case GL_STENCIL_WRITEMASK:
3473 *num_written = 1;
3474 if (params) {
3475 params[0] = mask_stencil_front_;
3476 }
3477 return true;
3478 case GL_DEPTH_TEST:
3479 *num_written = 1;
3480 if (params) {
3481 params[0] = enable_depth_test_;
3482 }
3483 return true;
3484 case GL_STENCIL_TEST:
3485 *num_written = 1;
3486 if (params) {
3487 params[0] = enable_stencil_test_;
3488 }
3489 return true;
3490 case GL_ALPHA_BITS:
3491 *num_written = 1;
3492 if (params) {
3493 GLint v = 0;
3494 glGetIntegerv(GL_ALPHA_BITS, &v);
3495 params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0;
3496 }
3497 return true;
3498 case GL_DEPTH_BITS:
3499 *num_written = 1;
3500 if (params) {
3501 GLint v = 0;
3502 glGetIntegerv(GL_DEPTH_BITS, &v);
3503 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
3504 }
3505 return true;
3506 case GL_STENCIL_BITS:
3507 *num_written = 1;
3508 if (params) {
3509 GLint v = 0;
3510 glGetIntegerv(GL_STENCIL_BITS, &v);
3511 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
3512 }
3513 return true;
[email protected]656dcaad2010-05-07 17:18:373514 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113515 *num_written = validators_->compressed_texture_format.GetValues().size();
3516 if (params) {
3517 for (GLint ii = 0; ii < *num_written; ++ii) {
3518 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
3519 }
3520 }
[email protected]656dcaad2010-05-07 17:18:373521 return true;
[email protected]b273e432010-04-12 17:23:583522 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
3523 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103524 if (params) {
[email protected]302ce6d2011-07-07 23:28:113525 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103526 }
[email protected]b273e432010-04-12 17:23:583527 return true;
3528 case GL_NUM_SHADER_BINARY_FORMATS:
3529 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103530 if (params) {
[email protected]302ce6d2011-07-07 23:28:113531 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103532 }
[email protected]b273e432010-04-12 17:23:583533 return true;
3534 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113535 *num_written = validators_->shader_binary_format.GetValues().size();
3536 if (params) {
3537 for (GLint ii = 0; ii < *num_written; ++ii) {
3538 params[ii] = validators_->shader_binary_format.GetValues()[ii];
3539 }
3540 }
3541 return true;
[email protected]b273e432010-04-12 17:23:583542 case GL_SHADER_COMPILER:
3543 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103544 if (params) {
3545 *params = GL_TRUE;
3546 }
[email protected]b273e432010-04-12 17:23:583547 return true;
[email protected]6b8cf1a2010-05-06 16:13:583548 case GL_ARRAY_BUFFER_BINDING:
3549 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103550 if (params) {
3551 if (bound_array_buffer_) {
3552 GLuint client_id = 0;
3553 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
3554 &client_id);
3555 *params = client_id;
3556 } else {
3557 *params = 0;
3558 }
[email protected]6b8cf1a2010-05-06 16:13:583559 }
3560 return true;
3561 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3562 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103563 if (params) {
3564 if (bound_element_array_buffer_) {
3565 GLuint client_id = 0;
3566 buffer_manager()->GetClientId(
3567 bound_element_array_buffer_->service_id(),
3568 &client_id);
3569 *params = client_id;
3570 } else {
3571 *params = 0;
3572 }
[email protected]6b8cf1a2010-05-06 16:13:583573 }
3574 return true;
3575 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:303576 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:583577 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103578 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203579 FramebufferManager::FramebufferInfo* framebuffer =
3580 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3581 if (framebuffer) {
[email protected]4e8a5b122010-05-08 22:00:103582 GLuint client_id = 0;
3583 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203584 framebuffer->service_id(), &client_id);
[email protected]8e3e0662010-08-23 18:46:303585 *params = client_id;
3586 } else {
3587 *params = 0;
3588 }
3589 }
3590 return true;
3591 case GL_READ_FRAMEBUFFER_BINDING:
3592 *num_written = 1;
3593 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203594 FramebufferManager::FramebufferInfo* framebuffer =
3595 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
3596 if (framebuffer) {
[email protected]8e3e0662010-08-23 18:46:303597 GLuint client_id = 0;
3598 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203599 framebuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103600 *params = client_id;
3601 } else {
3602 *params = 0;
3603 }
[email protected]6b8cf1a2010-05-06 16:13:583604 }
3605 return true;
3606 case GL_RENDERBUFFER_BINDING:
3607 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103608 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203609 RenderbufferManager::RenderbufferInfo* renderbuffer =
3610 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
3611 if (renderbuffer) {
[email protected]4e8a5b122010-05-08 22:00:103612 GLuint client_id = 0;
3613 renderbuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203614 renderbuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103615 *params = client_id;
3616 } else {
3617 *params = 0;
3618 }
[email protected]6b8cf1a2010-05-06 16:13:583619 }
3620 return true;
3621 case GL_CURRENT_PROGRAM:
3622 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103623 if (params) {
3624 if (current_program_) {
3625 GLuint client_id = 0;
3626 program_manager()->GetClientId(
3627 current_program_->service_id(), &client_id);
3628 *params = client_id;
3629 } else {
3630 *params = 0;
3631 }
[email protected]6b8cf1a2010-05-06 16:13:583632 }
3633 return true;
[email protected]4e8a5b122010-05-08 22:00:103634 case GL_TEXTURE_BINDING_2D:
3635 *num_written = 1;
3636 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583637 TextureUnit& unit = texture_units_[active_texture_unit_];
3638 if (unit.bound_texture_2d) {
3639 GLuint client_id = 0;
3640 texture_manager()->GetClientId(
3641 unit.bound_texture_2d->service_id(), &client_id);
3642 *params = client_id;
3643 } else {
3644 *params = 0;
3645 }
[email protected]6b8cf1a2010-05-06 16:13:583646 }
[email protected]4e8a5b122010-05-08 22:00:103647 return true;
3648 case GL_TEXTURE_BINDING_CUBE_MAP:
3649 *num_written = 1;
3650 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583651 TextureUnit& unit = texture_units_[active_texture_unit_];
3652 if (unit.bound_texture_cube_map) {
3653 GLuint client_id = 0;
3654 texture_manager()->GetClientId(
3655 unit.bound_texture_cube_map->service_id(), &client_id);
3656 *params = client_id;
3657 } else {
3658 *params = 0;
3659 }
[email protected]6b8cf1a2010-05-06 16:13:583660 }
[email protected]4e8a5b122010-05-08 22:00:103661 return true;
[email protected]61eeb33f2011-07-26 15:30:313662 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3663 *num_written = 1;
3664 if (params) {
3665 TextureUnit& unit = texture_units_[active_texture_unit_];
3666 if (unit.bound_texture_external_oes) {
3667 GLuint client_id = 0;
3668 texture_manager()->GetClientId(
3669 unit.bound_texture_external_oes->service_id(), &client_id);
3670 *params = client_id;
3671 } else {
3672 *params = 0;
3673 }
3674 }
3675 return true;
[email protected]e51bdf32011-11-23 22:21:463676 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
3677 *num_written = 1;
3678 if (params) {
3679 TextureUnit& unit = texture_units_[active_texture_unit_];
3680 if (unit.bound_texture_rectangle_arb) {
3681 GLuint client_id = 0;
3682 texture_manager()->GetClientId(
3683 unit.bound_texture_rectangle_arb->service_id(), &client_id);
3684 *params = client_id;
3685 } else {
3686 *params = 0;
3687 }
3688 }
3689 return true;
[email protected]b273e432010-04-12 17:23:583690 default:
[email protected]4e8a5b122010-05-08 22:00:103691 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533692 return false;
[email protected]b273e432010-04-12 17:23:583693 }
3694}
3695
[email protected]4e8a5b122010-05-08 22:00:103696bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3697 GLenum pname, GLsizei* num_values) {
3698 return GetHelper(pname, NULL, num_values);
3699}
3700
[email protected]b273e432010-04-12 17:23:583701void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3702 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103703 GLsizei num_written = 0;
3704 if (GetHelper(pname, NULL, &num_written)) {
3705 scoped_array<GLint> values(new GLint[num_written]);
3706 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583707 for (GLsizei ii = 0; ii < num_written; ++ii) {
3708 params[ii] = static_cast<GLboolean>(values[ii]);
3709 }
3710 } else {
3711 glGetBooleanv(pname, params);
3712 }
3713}
3714
3715void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3716 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103717 GLsizei num_written = 0;
3718 if (GetHelper(pname, NULL, &num_written)) {
3719 scoped_array<GLint> values(new GLint[num_written]);
3720 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583721 for (GLsizei ii = 0; ii < num_written; ++ii) {
3722 params[ii] = static_cast<GLfloat>(values[ii]);
3723 }
3724 } else {
3725 glGetFloatv(pname, params);
3726 }
3727}
3728
3729void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3730 DCHECK(params);
3731 GLsizei num_written;
3732 if (!GetHelper(pname, params, &num_written)) {
3733 glGetIntegerv(pname, params);
3734 }
3735}
3736
[email protected]a0c3e972010-04-21 00:49:133737void GLES2DecoderImpl::DoGetProgramiv(
3738 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583739 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3740 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133741 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133742 return;
3743 }
3744 info->GetProgramiv(pname, params);
3745}
3746
[email protected]258a3313f2011-10-18 20:13:573747void GLES2DecoderImpl::DoBindAttribLocation(
3748 GLuint program, GLuint index, const char* name) {
3749 if (!StringIsValidForGLES(name)) {
3750 SetGLError(GL_INVALID_VALUE, "glBindAttribLocation: Invalid character");
3751 return;
3752 }
[email protected]6b8cf1a2010-05-06 16:13:583753 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3754 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033755 if (!info) {
[email protected]258a3313f2011-10-18 20:13:573756 return;
[email protected]558847a2010-03-24 07:02:543757 }
[email protected]258a3313f2011-10-18 20:13:573758 glBindAttribLocation(info->service_id(), index, name);
3759}
3760
3761error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3762 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
3763 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543764 GLuint index = static_cast<GLuint>(c.index);
3765 uint32 name_size = c.data_size;
3766 const char* name = GetSharedMemoryAs<const char*>(
3767 c.name_shm_id, c.name_shm_offset, name_size);
3768 if (name == NULL) {
3769 return error::kOutOfBounds;
3770 }
3771 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573772 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543773 return error::kNoError;
3774}
3775
3776error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3777 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583778 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543779 GLuint index = static_cast<GLuint>(c.index);
3780 uint32 name_size = c.data_size;
3781 const char* name = GetImmediateDataAs<const char*>(
3782 c, name_size, immediate_data_size);
3783 if (name == NULL) {
3784 return error::kOutOfBounds;
3785 }
3786 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573787 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543788 return error::kNoError;
3789}
3790
3791error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3792 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583793 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543794 GLuint index = static_cast<GLuint>(c.index);
3795 Bucket* bucket = GetBucket(c.name_bucket_id);
3796 if (!bucket || bucket->size() == 0) {
3797 return error::kInvalidArguments;
3798 }
3799 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183800 if (!bucket->GetAsString(&name_str)) {
3801 return error::kInvalidArguments;
3802 }
[email protected]258a3313f2011-10-18 20:13:573803 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543804 return error::kNoError;
3805}
3806
[email protected]f7a64ee2010-02-01 22:24:143807error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463808 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033809 GLuint client_id = c.shader;
3810 if (client_id) {
3811 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3812 if (info) {
[email protected]ca488e12010-12-13 20:06:143813 if (!info->IsDeleted()) {
3814 glDeleteShader(info->service_id());
3815 shader_manager()->MarkAsDeleted(info);
3816 }
[email protected]ae51d192010-04-27 00:48:033817 } else {
[email protected]8eee29c2010-04-29 03:38:293818 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033819 }
[email protected]96449d2c2009-11-25 00:01:323820 }
[email protected]f7a64ee2010-02-01 22:24:143821 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323822}
3823
[email protected]f7a64ee2010-02-01 22:24:143824error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463825 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033826 GLuint client_id = c.program;
3827 if (client_id) {
3828 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3829 if (info) {
[email protected]ca488e12010-12-13 20:06:143830 if (!info->IsDeleted()) {
3831 glDeleteProgram(info->service_id());
3832 program_manager()->MarkAsDeleted(shader_manager(), info);
3833 }
[email protected]ae51d192010-04-27 00:48:033834 } else {
[email protected]8eee29c2010-04-29 03:38:293835 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033836 }
[email protected]96449d2c2009-11-25 00:01:323837 }
[email protected]f7a64ee2010-02-01 22:24:143838 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323839}
3840
[email protected]269200b12010-11-18 22:53:063841void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103842 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573843 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103844 for (GLsizei ii = 0; ii < n; ++ii) {
3845 id_allocator->FreeID(ids[ii]);
3846 }
3847}
3848
[email protected]269200b12010-11-18 22:53:063849error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
3850 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103851 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3852 GLsizei n = static_cast<GLsizei>(c.n);
3853 uint32 data_size;
3854 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3855 return error::kOutOfBounds;
3856 }
3857 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3858 c.ids_shm_id, c.ids_shm_offset, data_size);
3859 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063860 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103861 return error::kNoError;
3862 }
3863 if (ids == NULL) {
3864 return error::kOutOfBounds;
3865 }
[email protected]269200b12010-11-18 22:53:063866 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103867 return error::kNoError;
3868}
3869
[email protected]269200b12010-11-18 22:53:063870void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103871 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573872 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103873 if (id_offset == 0) {
3874 for (GLsizei ii = 0; ii < n; ++ii) {
3875 ids[ii] = id_allocator->AllocateID();
3876 }
3877 } else {
3878 for (GLsizei ii = 0; ii < n; ++ii) {
3879 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
3880 id_offset = ids[ii] + 1;
3881 }
3882 }
3883}
3884
[email protected]269200b12010-11-18 22:53:063885error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
3886 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103887 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3888 GLuint id_offset = static_cast<GLuint>(c.id_offset);
3889 GLsizei n = static_cast<GLsizei>(c.n);
3890 uint32 data_size;
3891 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3892 return error::kOutOfBounds;
3893 }
3894 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3895 c.ids_shm_id, c.ids_shm_offset, data_size);
3896 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063897 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103898 return error::kNoError;
3899 }
3900 if (ids == NULL) {
3901 return error::kOutOfBounds;
3902 }
[email protected]269200b12010-11-18 22:53:063903 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:103904 return error::kNoError;
3905}
3906
[email protected]269200b12010-11-18 22:53:063907void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103908 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573909 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103910 for (GLsizei ii = 0; ii < n; ++ii) {
3911 if (!id_allocator->MarkAsUsed(ids[ii])) {
3912 for (GLsizei jj = 0; jj < ii; ++jj) {
3913 id_allocator->FreeID(ids[jj]);
3914 }
3915 SetGLError(
3916 GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:063917 "RegisterSharedIdsCHROMIUM: attempt to register "
3918 "id that already exists");
[email protected]066849e32010-05-03 19:14:103919 return;
3920 }
3921 }
3922}
3923
[email protected]269200b12010-11-18 22:53:063924error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
3925 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103926 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3927 GLsizei n = static_cast<GLsizei>(c.n);
3928 uint32 data_size;
3929 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3930 return error::kOutOfBounds;
3931 }
3932 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3933 c.ids_shm_id, c.ids_shm_offset, data_size);
3934 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063935 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103936 return error::kNoError;
3937 }
3938 if (ids == NULL) {
3939 return error::kOutOfBounds;
3940 }
[email protected]269200b12010-11-18 22:53:063941 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103942 return error::kNoError;
3943}
3944
[email protected]3a03a8f2011-03-19 00:51:273945void GLES2DecoderImpl::DoClear(GLbitfield mask) {
[email protected]0d6bfdc2011-11-02 01:32:203946 if (CheckBoundFramebuffersValid("glClear")) {
[email protected]529c6672012-01-04 02:18:263947 UNSHIPPED_TRACE_EVENT_INSTANT2("test_gpu", "DoClear", "red", clear_red_,
3948 "green", clear_green_);
[email protected]297ca1c2011-06-20 23:08:463949 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:273950 glClear(mask);
3951 }
3952}
3953
[email protected]36cef8ce2010-03-16 07:34:453954void GLES2DecoderImpl::DoFramebufferRenderbuffer(
3955 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:033956 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:303957 FramebufferManager::FramebufferInfo* framebuffer_info =
3958 GetFramebufferInfoForTarget(target);
3959 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293960 SetGLError(GL_INVALID_OPERATION,
3961 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453962 return;
3963 }
[email protected]ae51d192010-04-27 00:48:033964 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283965 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033966 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283967 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:033968 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293969 SetGLError(GL_INVALID_OPERATION,
3970 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:033971 return;
3972 }
3973 service_id = info->service_id();
3974 }
[email protected]9edc6b22010-12-23 02:00:263975 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033976 glFramebufferRenderbufferEXT(
3977 target, attachment, renderbuffertarget, service_id);
[email protected]1002c2d2011-06-28 22:39:043978 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263979 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:303980 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]3a2e7c7b2010-08-06 01:12:283981 }
[email protected]297ca1c2011-06-20 23:08:463982 if (framebuffer_info == bound_draw_framebuffer_) {
3983 state_dirty_ = true;
3984 }
[email protected]3a2e7c7b2010-08-06 01:12:283985}
3986
[email protected]297ca1c2011-06-20 23:08:463987bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
[email protected]3a2e7c7b2010-08-06 01:12:283988 switch (cap) {
3989 case GL_SCISSOR_TEST:
3990 enable_scissor_test_ = enabled;
[email protected]297ca1c2011-06-20 23:08:463991 return true;
3992 case GL_DEPTH_TEST: {
3993 if (enable_depth_test_ != enabled) {
3994 enable_depth_test_ = enabled;
3995 state_dirty_ = true;
3996 }
3997 return false;
3998 }
3999 case GL_STENCIL_TEST:
4000 if (enable_stencil_test_ != enabled) {
4001 enable_stencil_test_ = enabled;
4002 state_dirty_ = true;
4003 }
4004 return false;
[email protected]3a2e7c7b2010-08-06 01:12:284005 default:
[email protected]297ca1c2011-06-20 23:08:464006 return true;
[email protected]3a2e7c7b2010-08-06 01:12:284007 }
4008}
4009
4010void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464011 if (SetCapabilityState(cap, false)) {
4012 glDisable(cap);
4013 }
[email protected]3a2e7c7b2010-08-06 01:12:284014}
4015
4016void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464017 if (SetCapabilityState(cap, true)) {
4018 glEnable(cap);
4019 }
[email protected]3a2e7c7b2010-08-06 01:12:284020}
4021
4022void GLES2DecoderImpl::DoClearColor(
4023 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
4024 clear_red_ = red;
4025 clear_green_ = green;
4026 clear_blue_ = blue;
4027 clear_alpha_ = alpha;
4028 glClearColor(red, green, blue, alpha);
4029}
4030
4031void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
4032 clear_depth_ = depth;
4033 glClearDepth(depth);
4034}
4035
4036void GLES2DecoderImpl::DoClearStencil(GLint s) {
4037 clear_stencil_ = s;
4038 glClearStencil(s);
4039}
4040
4041void GLES2DecoderImpl::DoColorMask(
4042 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
4043 mask_red_ = red;
4044 mask_green_ = green;
4045 mask_blue_ = blue;
4046 mask_alpha_ = alpha;
[email protected]297ca1c2011-06-20 23:08:464047 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284048}
4049
4050void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
4051 mask_depth_ = depth;
[email protected]297ca1c2011-06-20 23:08:464052 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284053}
4054
4055void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
4056 mask_stencil_front_ = mask;
4057 mask_stencil_back_ = mask;
[email protected]297ca1c2011-06-20 23:08:464058 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284059}
4060
4061void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
[email protected]297ca1c2011-06-20 23:08:464062 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284063 mask_stencil_front_ = mask;
[email protected]297ca1c2011-06-20 23:08:464064 }
4065 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284066 mask_stencil_back_ = mask;
4067 }
[email protected]297ca1c2011-06-20 23:08:464068 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284069}
4070
[email protected]0d6bfdc2011-11-02 01:32:204071// Assumes framebuffer is complete.
4072void GLES2DecoderImpl::ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:304073 GLenum target, FramebufferManager::FramebufferInfo* info) {
4074 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204075 // bind this to the DRAW point, clear then bind back to READ
4076 // TODO(gman): I don't think there is any guarantee that an FBO that
4077 // is complete on the READ attachment will be complete as a DRAW
4078 // attachment.
4079 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
4080 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, info->service_id());
[email protected]8e3e0662010-08-23 18:46:304081 }
[email protected]3a2e7c7b2010-08-06 01:12:284082 GLbitfield clear_bits = 0;
4083 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:464084 glClearColor(
[email protected]0d6bfdc2011-11-02 01:32:204085 0.0f, 0.0f, 0.0f,
[email protected]297ca1c2011-06-20 23:08:464086 (GLES2Util::GetChannelsForFormat(
[email protected]0d6bfdc2011-11-02 01:32:204087 info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f : 1.0f);
[email protected]3a2e7c7b2010-08-06 01:12:284088 glColorMask(true, true, true, true);
4089 clear_bits |= GL_COLOR_BUFFER_BIT;
4090 }
4091
4092 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4093 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4094 glClearStencil(0);
4095 glStencilMask(-1);
4096 clear_bits |= GL_STENCIL_BUFFER_BIT;
4097 }
4098
4099 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4100 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4101 glClearDepth(1.0f);
4102 glDepthMask(true);
4103 clear_bits |= GL_DEPTH_BUFFER_BIT;
4104 }
4105
4106 glDisable(GL_SCISSOR_TEST);
4107 glClear(clear_bits);
4108
[email protected]968351b2011-12-20 08:26:514109 framebuffer_manager()->MarkAttachmentsAsCleared(
4110 info, renderbuffer_manager(), texture_manager());
[email protected]3a2e7c7b2010-08-06 01:12:284111
[email protected]c007aa02010-09-02 22:22:404112 RestoreClearState();
4113
4114 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204115 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, info->service_id());
[email protected]87d1a3fe2011-12-01 04:25:484116 FramebufferManager::FramebufferInfo* framebuffer =
4117 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4118 GLuint service_id =
4119 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
4120 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
[email protected]c007aa02010-09-02 22:22:404121 }
4122}
4123
4124void GLES2DecoderImpl::RestoreClearState() {
[email protected]297ca1c2011-06-20 23:08:464125 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284126 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
[email protected]3a2e7c7b2010-08-06 01:12:284127 glClearStencil(clear_stencil_);
[email protected]3a2e7c7b2010-08-06 01:12:284128 glClearDepth(clear_depth_);
[email protected]3a2e7c7b2010-08-06 01:12:284129 if (enable_scissor_test_) {
4130 glEnable(GL_SCISSOR_TEST);
4131 }
[email protected]36cef8ce2010-03-16 07:34:454132}
4133
4134GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]0d6bfdc2011-11-02 01:32:204135 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]8e3e0662010-08-23 18:46:304136 GetFramebufferInfoForTarget(target);
[email protected]0d6bfdc2011-11-02 01:32:204137 if (!framebuffer) {
[email protected]36cef8ce2010-03-16 07:34:454138 return GL_FRAMEBUFFER_COMPLETE;
4139 }
[email protected]0d6bfdc2011-11-02 01:32:204140 GLenum completeness = framebuffer->IsPossiblyComplete();
4141 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4142 return completeness;
4143 }
[email protected]36cef8ce2010-03-16 07:34:454144 return glCheckFramebufferStatusEXT(target);
4145}
4146
4147void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:034148 GLenum target, GLenum attachment, GLenum textarget,
4149 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:304150 FramebufferManager::FramebufferInfo* framebuffer_info =
4151 GetFramebufferInfoForTarget(target);
4152 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294153 SetGLError(GL_INVALID_OPERATION,
4154 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:454155 return;
4156 }
[email protected]ae51d192010-04-27 00:48:034157 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:284158 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:034159 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:284160 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:034161 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294162 SetGLError(GL_INVALID_OPERATION,
4163 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:034164 return;
4165 }
4166 service_id = info->service_id();
4167 }
[email protected]0d6bfdc2011-11-02 01:32:204168
[email protected]80eb6b52012-01-19 00:14:414169 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
[email protected]0d6bfdc2011-11-02 01:32:204170 SetGLError(GL_INVALID_VALUE,
4171 "glFramebufferTexture2D: level out of range");
4172 return;
4173 }
4174
[email protected]9edc6b22010-12-23 02:00:264175 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034176 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]1002c2d2011-06-28 22:39:044177 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264178 if (error == GL_NO_ERROR) {
4179 framebuffer_info->AttachTexture(attachment, info, textarget, level);
[email protected]3a2e7c7b2010-08-06 01:12:284180 }
[email protected]297ca1c2011-06-20 23:08:464181 if (framebuffer_info == bound_draw_framebuffer_) {
4182 state_dirty_ = true;
4183 }
[email protected]36cef8ce2010-03-16 07:34:454184}
4185
4186void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4187 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:304188 FramebufferManager::FramebufferInfo* framebuffer_info =
4189 GetFramebufferInfoForTarget(target);
4190 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294191 SetGLError(GL_INVALID_OPERATION,
4192 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454193 return;
4194 }
4195 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:574196 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4197 GLint type = 0;
4198 GLuint client_id = 0;
4199 glGetFramebufferAttachmentParameterivEXT(
4200 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
4201 switch (type) {
4202 case GL_RENDERBUFFER: {
4203 renderbuffer_manager()->GetClientId(*params, &client_id);
4204 break;
4205 }
4206 case GL_TEXTURE: {
4207 texture_manager()->GetClientId(*params, &client_id);
4208 break;
4209 }
4210 default:
4211 break;
4212 }
4213 *params = client_id;
4214 }
[email protected]36cef8ce2010-03-16 07:34:454215}
4216
4217void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4218 GLenum target, GLenum pname, GLint* params) {
[email protected]0d6bfdc2011-11-02 01:32:204219 RenderbufferManager::RenderbufferInfo* renderbuffer =
4220 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4221 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294222 SetGLError(GL_INVALID_OPERATION,
4223 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454224 return;
4225 }
[email protected]3a03a8f2011-03-19 00:51:274226 switch (pname) {
4227 case GL_RENDERBUFFER_INTERNAL_FORMAT:
[email protected]0d6bfdc2011-11-02 01:32:204228 *params = renderbuffer->internal_format();
[email protected]3a03a8f2011-03-19 00:51:274229 break;
4230 case GL_RENDERBUFFER_WIDTH:
[email protected]0d6bfdc2011-11-02 01:32:204231 *params = renderbuffer->width();
[email protected]3a03a8f2011-03-19 00:51:274232 break;
4233 case GL_RENDERBUFFER_HEIGHT:
[email protected]0d6bfdc2011-11-02 01:32:204234 *params = renderbuffer->height();
[email protected]3a03a8f2011-03-19 00:51:274235 break;
4236 default:
4237 glGetRenderbufferParameterivEXT(target, pname, params);
4238 break;
[email protected]b71f52c2010-06-18 22:20:204239 }
[email protected]36cef8ce2010-03-16 07:34:454240}
4241
[email protected]8e3e0662010-08-23 18:46:304242void GLES2DecoderImpl::DoBlitFramebufferEXT(
4243 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
4244 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
4245 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:394246 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304247 SetGLError(GL_INVALID_OPERATION,
4248 "glBlitFramebufferEXT: function not available");
4249 }
[email protected]5094b0f2010-11-09 19:45:244250 if (IsAngle()) {
4251 glBlitFramebufferANGLE(
4252 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4253 } else {
4254 glBlitFramebufferEXT(
4255 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4256 }
[email protected]529c6672012-01-04 02:18:264257 UNSHIPPED_TRACE_EVENT_INSTANT1("test_gpu", "DoBlit", "width", srcX1 - srcX0);
[email protected]8e3e0662010-08-23 18:46:304258}
4259
4260void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
4261 GLenum target, GLsizei samples, GLenum internalformat,
4262 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:394263 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304264 SetGLError(GL_INVALID_OPERATION,
4265 "glRenderbufferStorageMultisampleEXT: function not available");
4266 return;
4267 }
[email protected]8e3e0662010-08-23 18:46:304268
[email protected]0d6bfdc2011-11-02 01:32:204269 RenderbufferManager::RenderbufferInfo* renderbuffer =
4270 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4271 if (!renderbuffer) {
4272 SetGLError(GL_INVALID_OPERATION,
4273 "glGetRenderbufferStorageMultisample: no renderbuffer bound");
4274 return;
4275 }
4276
[email protected]84afefa2011-10-19 21:45:534277 if (samples > renderbuffer_manager()->max_samples()) {
4278 SetGLError(GL_INVALID_VALUE,
4279 "glGetRenderbufferStorageMultisample: samples too large");
4280 return;
4281 }
4282
4283 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4284 height > renderbuffer_manager()->max_renderbuffer_size()) {
4285 SetGLError(GL_INVALID_VALUE,
4286 "glGetRenderbufferStorageMultisample: size too large");
4287 return;
4288 }
4289
[email protected]9edc6b22010-12-23 02:00:264290 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:304291 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264292 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:304293 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264294 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:304295 break;
4296 case GL_RGBA4:
4297 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264298 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:304299 break;
4300 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264301 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:304302 break;
4303 }
4304 }
4305
[email protected]9edc6b22010-12-23 02:00:264306 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:084307 if (IsAngle()) {
4308 glRenderbufferStorageMultisampleANGLE(
4309 target, samples, impl_format, width, height);
4310 } else {
4311 glRenderbufferStorageMultisampleEXT(
4312 target, samples, impl_format, width, height);
4313 }
[email protected]1002c2d2011-06-28 22:39:044314 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264315 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514316 // TODO(gman): If renderbuffers tracked which framebuffers they were
4317 // attached to we could just mark those framebuffers as not complete.
4318 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204319 renderbuffer_manager()->SetInfo(
4320 renderbuffer, samples, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264321 }
[email protected]8e3e0662010-08-23 18:46:304322}
4323
[email protected]36cef8ce2010-03-16 07:34:454324void GLES2DecoderImpl::DoRenderbufferStorage(
4325 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]0d6bfdc2011-11-02 01:32:204326 RenderbufferManager::RenderbufferInfo* renderbuffer =
4327 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4328 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294329 SetGLError(GL_INVALID_OPERATION,
4330 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454331 return;
4332 }
[email protected]876f6fee2010-08-02 23:10:324333
[email protected]84afefa2011-10-19 21:45:534334 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4335 height > renderbuffer_manager()->max_renderbuffer_size()) {
4336 SetGLError(GL_INVALID_VALUE,
4337 "glGetRenderbufferStorage: size too large");
4338 return;
4339 }
4340
[email protected]9edc6b22010-12-23 02:00:264341 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:324342 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264343 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:324344 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264345 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:324346 break;
4347 case GL_RGBA4:
4348 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264349 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:324350 break;
4351 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264352 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:324353 break;
4354 }
[email protected]b71f52c2010-06-18 22:20:204355 }
[email protected]876f6fee2010-08-02 23:10:324356
[email protected]9edc6b22010-12-23 02:00:264357 CopyRealGLErrorsToWrapper();
4358 glRenderbufferStorageEXT(target, impl_format, width, height);
[email protected]1002c2d2011-06-28 22:39:044359 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264360 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514361 // TODO(gman): If tetxures tracked which framebuffers they were attached to
4362 // we could just mark those framebuffers as not complete.
4363 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204364 renderbuffer_manager()->SetInfo(
4365 renderbuffer, 0, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264366 }
[email protected]36cef8ce2010-03-16 07:34:454367}
4368
[email protected]07f54fcc2009-12-22 02:46:304369void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]0c8fabf2011-06-14 19:35:224370 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]6b8cf1a2010-05-06 16:13:584371 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4372 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:474373 if (!info) {
[email protected]a93bb842010-02-16 23:03:474374 return;
4375 }
[email protected]05afda12011-01-20 00:17:344376
[email protected]d685a682011-04-29 16:19:574377 info->Link();
[email protected]07f54fcc2009-12-22 02:46:304378};
4379
[email protected]3916c97e2010-02-25 03:20:504380void GLES2DecoderImpl::DoTexParameterf(
4381 GLenum target, GLenum pname, GLfloat param) {
4382 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:304383 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294384 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244385 return;
[email protected]07f54fcc2009-12-22 02:46:304386 }
[email protected]cbb22e42011-05-12 23:36:244387
4388 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414389 info, pname, static_cast<GLint>(param))) {
[email protected]cbb22e42011-05-12 23:36:244390 SetGLError(GL_INVALID_ENUM, "glTexParameterf: param GL_INVALID_ENUM");
4391 return;
4392 }
4393 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:304394}
4395
[email protected]3916c97e2010-02-25 03:20:504396void GLES2DecoderImpl::DoTexParameteri(
4397 GLenum target, GLenum pname, GLint param) {
4398 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4399 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294400 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244401 return;
[email protected]3916c97e2010-02-25 03:20:504402 }
[email protected]cbb22e42011-05-12 23:36:244403
[email protected]80eb6b52012-01-19 00:14:414404 if (!texture_manager()->SetParameter(info, pname, param)) {
[email protected]cbb22e42011-05-12 23:36:244405 SetGLError(GL_INVALID_ENUM, "glTexParameteri: param GL_INVALID_ENUM");
4406 return;
4407 }
4408 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:504409}
4410
4411void GLES2DecoderImpl::DoTexParameterfv(
4412 GLenum target, GLenum pname, const GLfloat* params) {
4413 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4414 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294415 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244416 return;
[email protected]3916c97e2010-02-25 03:20:504417 }
[email protected]cbb22e42011-05-12 23:36:244418
4419 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414420 info, pname, static_cast<GLint>(params[0]))) {
[email protected]cbb22e42011-05-12 23:36:244421 SetGLError(GL_INVALID_ENUM, "glTexParameterfv: param GL_INVALID_ENUM");
4422 return;
4423 }
4424 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504425}
4426
4427void GLES2DecoderImpl::DoTexParameteriv(
4428 GLenum target, GLenum pname, const GLint* params) {
4429 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4430 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294431 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244432 return;
[email protected]3916c97e2010-02-25 03:20:504433 }
[email protected]cbb22e42011-05-12 23:36:244434
[email protected]80eb6b52012-01-19 00:14:414435 if (!texture_manager()->SetParameter(info, pname, *params)) {
[email protected]cbb22e42011-05-12 23:36:244436 SetGLError(GL_INVALID_ENUM, "glTexParameteriv: param GL_INVALID_ENUM");
4437 return;
4438 }
4439 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504440}
4441
[email protected]939e7362010-05-13 20:49:104442bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:144443 if (!current_program_) {
[email protected]939e7362010-05-13 20:49:104444 // The program does not exist.
4445 SetGLError(GL_INVALID_OPERATION,
4446 (std::string(function_name) + ": no program in use").c_str());
4447 return false;
4448 }
[email protected]ca488e12010-12-13 20:06:144449 if (!current_program_->InUse()) {
[email protected]939e7362010-05-13 20:49:104450 SetGLError(GL_INVALID_OPERATION,
4451 (std::string(function_name) + ": program not linked").c_str());
4452 return false;
4453 }
4454 return true;
4455}
4456
4457bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
4458 GLint location, const char* function_name) {
4459 if (!CheckCurrentProgram(function_name)) {
4460 return false;
4461 }
4462 return location != -1;
4463}
4464
[email protected]43c2f1f2011-03-25 18:35:364465bool GLES2DecoderImpl::PrepForSetUniformByLocation(
4466 GLint location, const char* function_name, GLenum* type, GLsizei* count) {
4467 DCHECK(type);
4468 DCHECK(count);
[email protected]939e7362010-05-13 20:49:104469 if (!CheckCurrentProgramForUniform(location, function_name)) {
4470 return false;
4471 }
[email protected]43c2f1f2011-03-25 18:35:364472 GLint array_index = -1;
4473 const ProgramManager::ProgramInfo::UniformInfo* info =
4474 current_program_->GetUniformInfoByLocation(location, &array_index);
4475 if (!info) {
[email protected]939e7362010-05-13 20:49:104476 SetGLError(GL_INVALID_OPERATION,
[email protected]43c2f1f2011-03-25 18:35:364477 (std::string(function_name) + ": unknown location").c_str());
[email protected]939e7362010-05-13 20:49:104478 return false;
4479 }
[email protected]43c2f1f2011-03-25 18:35:364480 if (*count > 1 && !info->is_array) {
4481 SetGLError(
4482 GL_INVALID_OPERATION,
4483 (std::string(function_name) + ": count > 1 for non-array").c_str());
4484 return false;
4485 }
4486 *count = std::min(info->size - array_index, *count);
4487 if (*count <= 0) {
4488 return false;
4489 }
4490 *type = info->type;
[email protected]939e7362010-05-13 20:49:104491 return true;
4492}
4493
[email protected]939e7362010-05-13 20:49:104494void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
4495 if (!CheckCurrentProgramForUniform(location, "glUniform1i")) {
[email protected]3916c97e2010-02-25 03:20:504496 return;
4497 }
4498 current_program_->SetSamplers(location, 1, &v0);
4499 glUniform1i(location, v0);
4500}
4501
4502void GLES2DecoderImpl::DoUniform1iv(
4503 GLint location, GLsizei count, const GLint *value) {
[email protected]939e7362010-05-13 20:49:104504 if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) {
[email protected]3916c97e2010-02-25 03:20:504505 return;
4506 }
[email protected]43c2f1f2011-03-25 18:35:364507 GLenum type = 0;
4508 if (!PrepForSetUniformByLocation(location, "glUniform1iv", &type, &count)) {
4509 return;
4510 }
[email protected]61eeb33f2011-07-26 15:30:314511 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
4512 type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]43c2f1f2011-03-25 18:35:364513 current_program_->SetSamplers(location, count, value);
4514 }
[email protected]3916c97e2010-02-25 03:20:504515 glUniform1iv(location, count, value);
4516}
4517
[email protected]939e7362010-05-13 20:49:104518void GLES2DecoderImpl::DoUniform1fv(
4519 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364520 GLenum type = 0;
4521 if (!PrepForSetUniformByLocation(location, "glUniform1fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104522 return;
4523 }
4524 if (type == GL_BOOL) {
4525 scoped_array<GLint> temp(new GLint[count]);
4526 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:534527 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104528 }
4529 DoUniform1iv(location, count, temp.get());
4530 } else {
4531 glUniform1fv(location, count, value);
4532 }
4533}
4534
4535void GLES2DecoderImpl::DoUniform2fv(
4536 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364537 GLenum type = 0;
4538 if (!PrepForSetUniformByLocation(location, "glUniform2fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104539 return;
4540 }
4541 if (type == GL_BOOL_VEC2) {
4542 GLsizei num_values = count * 2;
4543 scoped_array<GLint> temp(new GLint[num_values]);
4544 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534545 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104546 }
4547 glUniform2iv(location, count, temp.get());
4548 } else {
4549 glUniform2fv(location, count, value);
4550 }
4551}
4552
4553void GLES2DecoderImpl::DoUniform3fv(
4554 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364555 GLenum type = 0;
4556 if (!PrepForSetUniformByLocation(location, "glUniform3fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104557 return;
4558 }
4559 if (type == GL_BOOL_VEC3) {
4560 GLsizei num_values = count * 3;
4561 scoped_array<GLint> temp(new GLint[num_values]);
4562 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534563 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104564 }
4565 glUniform3iv(location, count, temp.get());
4566 } else {
4567 glUniform3fv(location, count, value);
4568 }
4569}
4570
4571void GLES2DecoderImpl::DoUniform4fv(
4572 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364573 GLenum type = 0;
4574 if (!PrepForSetUniformByLocation(location, "glUniform4fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104575 return;
4576 }
4577 if (type == GL_BOOL_VEC4) {
4578 GLsizei num_values = count * 4;
4579 scoped_array<GLint> temp(new GLint[num_values]);
4580 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534581 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104582 }
4583 glUniform4iv(location, count, temp.get());
4584 } else {
4585 glUniform4fv(location, count, value);
4586 }
4587}
4588
[email protected]43c2f1f2011-03-25 18:35:364589void GLES2DecoderImpl::DoUniform2iv(
4590 GLint location, GLsizei count, const GLint* value) {
4591 GLenum type = 0;
4592 if (!PrepForSetUniformByLocation(location, "glUniform2iv", &type, &count)) {
4593 return;
4594 }
4595 glUniform2iv(location, count, value);
4596}
4597
4598void GLES2DecoderImpl::DoUniform3iv(
4599 GLint location, GLsizei count, const GLint* value) {
4600 GLenum type = 0;
4601 if (!PrepForSetUniformByLocation(location, "glUniform3iv", &type, &count)) {
4602 return;
4603 }
4604 glUniform3iv(location, count, value);
4605}
4606
4607void GLES2DecoderImpl::DoUniform4iv(
4608 GLint location, GLsizei count, const GLint* value) {
4609 GLenum type = 0;
4610 if (!PrepForSetUniformByLocation(location, "glUniform4iv", &type, &count)) {
4611 return;
4612 }
4613 glUniform4iv(location, count, value);
4614}
4615
4616void GLES2DecoderImpl::DoUniformMatrix2fv(
4617 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4618 GLenum type = 0;
4619 if (!PrepForSetUniformByLocation(
4620 location, "glUniformMatrix2fv", &type, &count)) {
4621 return;
4622 }
[email protected]e5081262012-01-05 23:09:034623 glUniformMatrix2fv(location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364624}
4625
4626void GLES2DecoderImpl::DoUniformMatrix3fv(
4627 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4628 GLenum type = 0;
4629 if (!PrepForSetUniformByLocation(
4630 location, "glUniformMatrix3fv", &type, &count)) {
4631 return;
4632 }
[email protected]e5081262012-01-05 23:09:034633 glUniformMatrix3fv(location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364634}
4635
4636void GLES2DecoderImpl::DoUniformMatrix4fv(
4637 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4638 GLenum type = 0;
4639 if (!PrepForSetUniformByLocation(
4640 location, "glUniformMatrix4fv", &type, &count)) {
4641 return;
4642 }
[email protected]e5081262012-01-05 23:09:034643 glUniformMatrix4fv(location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364644}
4645
[email protected]3916c97e2010-02-25 03:20:504646void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:034647 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:504648 ProgramManager::ProgramInfo* info = NULL;
4649 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:584650 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:504651 if (!info) {
[email protected]ae51d192010-04-27 00:48:034652 return;
4653 }
4654 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:504655 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:294656 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:504657 return;
4658 }
[email protected]ae51d192010-04-27 00:48:034659 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:504660 }
[email protected]ca488e12010-12-13 20:06:144661 if (current_program_) {
4662 program_manager()->UnuseProgram(shader_manager(), current_program_);
4663 }
[email protected]3916c97e2010-02-25 03:20:504664 current_program_ = info;
[email protected]ca488e12010-12-13 20:06:144665 if (current_program_) {
4666 program_manager()->UseProgram(current_program_);
4667 }
[email protected]ae51d192010-04-27 00:48:034668 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:504669}
4670
[email protected]96449d2c2009-11-25 00:01:324671GLenum GLES2DecoderImpl::GetGLError() {
4672 // Check the GL error first, then our wrapped error.
4673 GLenum error = glGetError();
4674 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:374675 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:324676 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:294677 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:324678 break;
4679 }
4680 }
4681 }
4682
4683 if (error != GL_NO_ERROR) {
4684 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:294685 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324686 }
4687 return error;
4688}
4689
[email protected]1002c2d2011-06-28 22:39:044690GLenum GLES2DecoderImpl::PeekGLError() {
4691 GLenum error = glGetError();
4692 if (error != GL_NO_ERROR) {
4693 SetGLError(error, "");
4694 }
4695 return error;
4696}
4697
[email protected]8eee29c2010-04-29 03:38:294698void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
4699 if (msg) {
4700 last_error_ = msg;
[email protected]d0498742010-09-20 20:27:014701 LOG(ERROR) << last_error_;
[email protected]6b6e7ee2011-12-13 08:04:524702 if (!msg_callback_.is_null()) {
4703 msg_callback_.Run(0, GLES2Util::GetStringEnum(error) + " : " + msg);
4704 }
[email protected]8eee29c2010-04-29 03:38:294705 }
[email protected]ddd968b82010-03-02 00:44:294706 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324707}
4708
[email protected]07f54fcc2009-12-22 02:46:304709void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
4710 GLenum error;
4711 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294712 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:304713 }
4714}
4715
[email protected]6217d392010-03-25 22:08:354716void GLES2DecoderImpl::ClearRealGLErrors() {
4717 GLenum error;
4718 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]3ed14d112011-12-13 22:05:514719 if (error != GL_OUT_OF_MEMORY) {
4720 // GL_OUT_OF_MEMORY can legally happen on lost device.
4721 NOTREACHED() << "GL error " << error << " was unhandled.";
4722 }
[email protected]6217d392010-03-25 22:08:354723 }
4724}
4725
[email protected]ef526492010-06-02 23:12:254726bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:504727 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:254728 // Only check if there are some unrenderable textures.
4729 if (!texture_manager()->HaveUnrenderableTextures()) {
4730 return false;
4731 }
4732 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:504733 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4734 current_program_->sampler_indices();
4735 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4736 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4737 current_program_->GetUniformInfo(sampler_indices[ii]);
4738 DCHECK(uniform_info);
4739 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4740 GLuint texture_unit_index = uniform_info->texture_units[jj];
4741 if (texture_unit_index < group_->max_texture_units()) {
4742 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4743 TextureManager::TextureInfo* texture_info =
[email protected]61eeb33f2011-07-26 15:30:314744 texture_unit.GetInfoForSamplerType(uniform_info->type);
[email protected]80eb6b52012-01-19 00:14:414745 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]ef526492010-06-02 23:12:254746 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:504747 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4748 glBindTexture(
[email protected]61eeb33f2011-07-26 15:30:314749 GetBindTargetForSamplerType(uniform_info->type),
[email protected]00f893d2010-08-24 18:55:494750 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:504751 }
4752 }
4753 // else: should this be an error?
4754 }
4755 }
[email protected]ef526492010-06-02 23:12:254756 return textures_set;
[email protected]3916c97e2010-02-25 03:20:504757}
4758
4759void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
4760 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:504761 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4762 current_program_->sampler_indices();
4763 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4764 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4765 current_program_->GetUniformInfo(sampler_indices[ii]);
4766 DCHECK(uniform_info);
4767 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4768 GLuint texture_unit_index = uniform_info->texture_units[jj];
4769 if (texture_unit_index < group_->max_texture_units()) {
4770 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4771 TextureManager::TextureInfo* texture_info =
4772 uniform_info->type == GL_SAMPLER_2D ?
4773 texture_unit.bound_texture_2d :
4774 texture_unit.bound_texture_cube_map;
[email protected]80eb6b52012-01-19 00:14:414775 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]3916c97e2010-02-25 03:20:504776 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4777 // Get the texture info that was previously bound here.
4778 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
4779 texture_unit.bound_texture_2d :
4780 texture_unit.bound_texture_cube_map;
4781 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:034782 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:504783 }
4784 }
4785 }
4786 }
4787 // Set the active texture back to whatever the user had it as.
4788 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:304789}
4790
[email protected]0d6bfdc2011-11-02 01:32:204791bool GLES2DecoderImpl::ClearUnclearedTextures() {
4792 // Only check if there are some uncleared textures.
4793 if (!texture_manager()->HaveUnsafeTextures()) {
4794 return true;
4795 }
4796
4797 // 1: Check all textures we are about to render with.
4798 if (current_program_) {
4799 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4800 current_program_->sampler_indices();
4801 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4802 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4803 current_program_->GetUniformInfo(sampler_indices[ii]);
4804 DCHECK(uniform_info);
4805 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4806 GLuint texture_unit_index = uniform_info->texture_units[jj];
4807 if (texture_unit_index < group_->max_texture_units()) {
4808 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4809 TextureManager::TextureInfo* texture_info =
4810 texture_unit.GetInfoForSamplerType(uniform_info->type);
4811 if (texture_info && !texture_info->SafeToRenderFrom()) {
4812 if (!texture_manager()->ClearRenderableLevels(this, texture_info)) {
4813 return false;
4814 }
4815 }
4816 }
4817 }
4818 }
4819 }
4820 return true;
4821}
4822
[email protected]07f54fcc2009-12-22 02:46:304823bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]689fa1c52010-06-09 18:35:034824 // NOTE: We specifically do not check current_program->IsValid() because
4825 // it could never be invalid since glUseProgram would have failed. While
4826 // glLinkProgram could later mark the program as invalid the previous
4827 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:144828 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:504829 // The program does not exist.
4830 // But GL says no ERROR.
4831 return false;
4832 }
[email protected]f39f4b3f2010-05-12 17:04:084833 // Validate all attribs currently enabled. If they are used by the current
4834 // program then check that they have enough elements to handle the draw call.
4835 // If they are not used by the current program check that they have a buffer
4836 // assigned.
4837 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:444838 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]f39f4b3f2010-05-12 17:04:084839 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:404840 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:084841 const VertexAttribManager::VertexAttribInfo* info = *it;
4842 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4843 current_program_->GetAttribInfoByLocation(info->index());
4844 if (attrib_info) {
4845 // This attrib is used in the current program.
4846 if (!info->CanAccess(max_vertex_accessed)) {
4847 SetGLError(GL_INVALID_OPERATION,
4848 "glDrawXXX: attempt to access out of range vertices");
4849 return false;
4850 }
4851 } else {
4852 // This attrib is not used in the current program.
[email protected]a0b78dc2011-11-11 10:43:104853 if (!info->buffer()) {
[email protected]f39f4b3f2010-05-12 17:04:084854 SetGLError(
4855 GL_INVALID_OPERATION,
4856 "glDrawXXX: attempt to render with no buffer attached to enabled "
4857 "attrib");
4858 return false;
4859 }
[email protected]1d32bc82010-01-13 22:06:464860 }
[email protected]07f54fcc2009-12-22 02:46:304861 }
[email protected]3916c97e2010-02-25 03:20:504862 return true;
[email protected]b1122982010-05-17 23:04:244863}
4864
[email protected]c13e1da62011-09-09 21:48:304865bool GLES2DecoderImpl::SimulateAttrib0(
4866 GLuint max_vertex_accessed, bool* simulated) {
4867 DCHECK(simulated);
4868 *simulated = false;
4869
[email protected]876f6fee2010-08-02 23:10:324870 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
[email protected]c13e1da62011-09-09 21:48:304871 return true;
[email protected]876f6fee2010-08-02 23:10:324872
[email protected]b1122982010-05-17 23:04:244873 const VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:444874 vertex_attrib_manager_->GetVertexAttribInfo(0);
[email protected]b1122982010-05-17 23:04:244875 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:494876 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
4877 if (info->enabled() && attrib_0_used) {
[email protected]c13e1da62011-09-09 21:48:304878 return true;
[email protected]b1122982010-05-17 23:04:244879 }
4880
[email protected]b1122982010-05-17 23:04:244881 // Make a buffer with a single repeated vec4 value enough to
4882 // simulate the constant value that is supposed to be here.
4883 // This is required to emulate GLES2 on GL.
[email protected]c13e1da62011-09-09 21:48:304884 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
4885
4886 GLuint num_vertices = max_vertex_accessed + 1;
4887 GLuint size_needed = 0;
4888
4889 if (num_vertices == 0 ||
4890 !SafeMultiply(num_vertices, static_cast<GLuint>(sizeof(Vec4)),
4891 &size_needed) ||
4892 size_needed > 0x7FFFFFFFU) {
4893 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
4894 return false;
4895 }
4896
4897 CopyRealGLErrorsToWrapper();
4898 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
4899
4900 if (static_cast<GLsizei>(size_needed) > attrib_0_size_) {
[email protected]fc753442011-02-04 19:49:494901 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:304902 GLenum error = glGetError();
4903 if (error != GL_NO_ERROR) {
4904 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
4905 return false;
4906 }
[email protected]fc753442011-02-04 19:49:494907 attrib_0_buffer_matches_value_ = false;
4908 }
4909 if (attrib_0_used &&
4910 (!attrib_0_buffer_matches_value_ ||
4911 (info->value().v[0] != attrib_0_value_.v[0] ||
4912 info->value().v[1] != attrib_0_value_.v[1] ||
4913 info->value().v[2] != attrib_0_value_.v[2] ||
4914 info->value().v[3] != attrib_0_value_.v[3]))) {
4915 std::vector<Vec4> temp(num_vertices, info->value());
4916 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
4917 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:244918 attrib_0_value_ = info->value();
4919 attrib_0_size_ = size_needed;
4920 }
4921
4922 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4923
[email protected]c13e1da62011-09-09 21:48:304924 *simulated = true;
[email protected]b1122982010-05-17 23:04:244925 return true;
[email protected]b1122982010-05-17 23:04:244926}
4927
4928void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
4929 const VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:444930 vertex_attrib_manager_->GetVertexAttribInfo(0);
[email protected]b1122982010-05-17 23:04:244931 const void* ptr = reinterpret_cast<const void*>(info->offset());
4932 BufferManager::BufferInfo* buffer_info = info->buffer();
4933 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
4934 glVertexAttribPointer(
4935 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
4936 ptr);
4937 glBindBuffer(GL_ARRAY_BUFFER,
4938 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4939}
[email protected]07f54fcc2009-12-22 02:46:304940
[email protected]8fbedc02010-11-18 18:43:404941bool GLES2DecoderImpl::SimulateFixedAttribs(
4942 GLuint max_vertex_accessed, bool* simulated) {
4943 DCHECK(simulated);
4944 *simulated = false;
4945 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4946 return true;
4947
[email protected]3757a372012-01-19 05:20:444948 if (!vertex_attrib_manager_->HaveFixedAttribs()) {
[email protected]8fbedc02010-11-18 18:43:404949 return true;
4950 }
4951
4952 // NOTE: we could be smart and try to check if a buffer is used
4953 // twice in 2 different attribs, find the overlapping parts and therefore
4954 // duplicate the minimum amount of data but this whole code path is not meant
4955 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
4956 // tests so we just add to the buffer attrib used.
4957
4958 // Compute the number of elements needed.
[email protected]c13e1da62011-09-09 21:48:304959 GLuint num_vertices = max_vertex_accessed + 1;
4960 if (num_vertices == 0) {
4961 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
4962 return false;
4963 }
4964
4965 GLuint elements_needed = 0;
[email protected]8fbedc02010-11-18 18:43:404966 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:444967 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]8fbedc02010-11-18 18:43:404968 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4969 infos.begin(); it != infos.end(); ++it) {
4970 const VertexAttribManager::VertexAttribInfo* info = *it;
4971 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4972 current_program_->GetAttribInfoByLocation(info->index());
4973 if (attrib_info &&
4974 info->CanAccess(max_vertex_accessed) &&
4975 info->type() == GL_FIXED) {
[email protected]c13e1da62011-09-09 21:48:304976 GLuint elements_used = 0;
4977 if (!SafeMultiply(num_vertices,
4978 static_cast<GLuint>(info->size()), &elements_used) ||
[email protected]8fbedc02010-11-18 18:43:404979 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
4980 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4981 return false;
4982 }
4983 }
4984 }
4985
[email protected]c13e1da62011-09-09 21:48:304986 const GLuint kSizeOfFloat = sizeof(float); // NOLINT
4987 GLuint size_needed = 0;
4988 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed) ||
4989 size_needed > 0x7FFFFFFFU) {
[email protected]8fbedc02010-11-18 18:43:404990 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4991 return false;
4992 }
4993
[email protected]c13e1da62011-09-09 21:48:304994 CopyRealGLErrorsToWrapper();
[email protected]8fbedc02010-11-18 18:43:404995
4996 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
[email protected]c13e1da62011-09-09 21:48:304997 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
[email protected]8fbedc02010-11-18 18:43:404998 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:304999 GLenum error = glGetError();
5000 if (error != GL_NO_ERROR) {
5001 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5002 return false;
5003 }
[email protected]8fbedc02010-11-18 18:43:405004 }
5005
5006 // Copy the elements and convert to float
5007 GLintptr offset = 0;
5008 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5009 infos.begin(); it != infos.end(); ++it) {
5010 const VertexAttribManager::VertexAttribInfo* info = *it;
5011 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5012 current_program_->GetAttribInfoByLocation(info->index());
5013 if (attrib_info &&
5014 info->CanAccess(max_vertex_accessed) &&
5015 info->type() == GL_FIXED) {
5016 int num_elements = info->size() * kSizeOfFloat;
5017 int size = num_elements * num_vertices;
5018 scoped_array<float> data(new float[size]);
5019 const int32* src = reinterpret_cast<const int32 *>(
5020 info->buffer()->GetRange(info->offset(), size));
5021 const int32* end = src + num_elements;
5022 float* dst = data.get();
5023 while (src != end) {
5024 *dst++ = static_cast<float>(*src++) / 65536.0f;
5025 }
5026 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
5027 glVertexAttribPointer(
5028 info->index(), info->size(), GL_FLOAT, false, 0,
5029 reinterpret_cast<GLvoid*>(offset));
5030 offset += size;
5031 }
5032 }
5033 *simulated = true;
5034 return true;
5035}
5036
5037void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
5038 // There's no need to call glVertexAttribPointer because we shadow all the
5039 // settings and passing GL_FIXED to it will not work.
5040 glBindBuffer(GL_ARRAY_BUFFER,
5041 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
5042}
5043
[email protected]38d139d2011-07-14 00:38:435044error::Error GLES2DecoderImpl::HandleDrawArrays(
5045 uint32 immediate_data_size, const gles2::DrawArrays& c) {
5046 GLenum mode = static_cast<GLenum>(c.mode);
5047 GLint first = static_cast<GLint>(c.first);
5048 GLsizei count = static_cast<GLsizei>(c.count);
5049 if (!validators_->draw_mode.IsValid(mode)) {
5050 SetGLError(GL_INVALID_ENUM, "glDrawArrays: mode GL_INVALID_ENUM");
5051 return error::kNoError;
5052 }
5053 if (count < 0) {
5054 SetGLError(GL_INVALID_VALUE, "glDrawArrays: count < 0");
5055 return error::kNoError;
5056 }
[email protected]0d6bfdc2011-11-02 01:32:205057 if (!CheckBoundFramebuffersValid("glDrawArrays")) {
[email protected]38d139d2011-07-14 00:38:435058 return error::kNoError;
5059 }
5060 // We have to check this here because the prototype for glDrawArrays
5061 // is GLint not GLsizei.
5062 if (first < 0) {
5063 SetGLError(GL_INVALID_VALUE, "glDrawArrays: first < 0");
5064 return error::kNoError;
5065 }
5066
5067 if (count == 0) {
5068 return error::kNoError;
5069 }
5070
5071 GLuint max_vertex_accessed = first + count - 1;
5072 if (IsDrawValid(max_vertex_accessed)) {
[email protected]0d6bfdc2011-11-02 01:32:205073 if (!ClearUnclearedTextures()) {
5074 SetGLError(GL_INVALID_VALUE, "glDrawArrays: out of memory");
5075 return error::kNoError;
5076 }
[email protected]c13e1da62011-09-09 21:48:305077 bool simulated_attrib_0 = false;
5078 if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
5079 return error::kNoError;
5080 }
[email protected]38d139d2011-07-14 00:38:435081 bool simulated_fixed_attribs = false;
5082 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
5083 bool textures_set = SetBlackTextureForNonRenderableTextures();
5084 ApplyDirtyState();
5085 glDrawArrays(mode, first, count);
5086 if (textures_set) {
5087 RestoreStateForNonRenderableTextures();
5088 }
5089 if (simulated_fixed_attribs) {
5090 RestoreStateForSimulatedFixedAttribs();
5091 }
5092 }
5093 if (simulated_attrib_0) {
5094 RestoreStateForSimulatedAttrib0();
5095 }
5096 if (WasContextLost()) {
5097 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawArrays.";
5098 return error::kLostContext;
5099 }
5100 }
5101 return error::kNoError;
5102}
5103
[email protected]f7a64ee2010-02-01 22:24:145104error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:195105 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]a0b78dc2011-11-11 10:43:105106 if (!bound_element_array_buffer_) {
[email protected]8eee29c2010-04-29 03:38:295107 SetGLError(GL_INVALID_OPERATION,
5108 "glDrawElements: No element array buffer bound");
5109 return error::kNoError;
5110 }
5111
5112 GLenum mode = c.mode;
5113 GLsizei count = c.count;
5114 GLenum type = c.type;
5115 int32 offset = c.index_offset;
5116 if (count < 0) {
5117 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
5118 return error::kNoError;
5119 }
5120 if (offset < 0) {
5121 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
5122 return error::kNoError;
5123 }
[email protected]9438b012010-06-15 22:55:055124 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:295125 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
5126 return error::kNoError;
5127 }
[email protected]9438b012010-06-15 22:55:055128 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295129 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
5130 return error::kNoError;
5131 }
5132
[email protected]0d6bfdc2011-11-02 01:32:205133 if (!CheckBoundFramebuffersValid("glDrawElements")) {
[email protected]3a03a8f2011-03-19 00:51:275134 return error::kNoError;
5135 }
5136
[email protected]6c788fb72010-08-26 02:16:315137 if (count == 0) {
5138 return error::kNoError;
5139 }
5140
[email protected]8eee29c2010-04-29 03:38:295141 GLuint max_vertex_accessed;
5142 if (!bound_element_array_buffer_->GetMaxValueForRange(
5143 offset, count, type, &max_vertex_accessed)) {
5144 SetGLError(GL_INVALID_OPERATION,
5145 "glDrawElements: range out of bounds for buffer");
5146 return error::kNoError;
5147 }
5148
5149 if (IsDrawValid(max_vertex_accessed)) {
[email protected]0d6bfdc2011-11-02 01:32:205150 if (!ClearUnclearedTextures()) {
5151 SetGLError(GL_INVALID_VALUE, "glDrawElements: out of memory");
5152 return error::kNoError;
5153 }
[email protected]c13e1da62011-09-09 21:48:305154 bool simulated_attrib_0 = false;
5155 if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
5156 return error::kNoError;
5157 }
[email protected]8fbedc02010-11-18 18:43:405158 bool simulated_fixed_attribs = false;
5159 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
5160 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:465161 ApplyDirtyState();
[email protected]8fbedc02010-11-18 18:43:405162 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
5163 glDrawElements(mode, count, type, indices);
5164 if (textures_set) {
5165 RestoreStateForNonRenderableTextures();
5166 }
5167 if (simulated_fixed_attribs) {
5168 RestoreStateForSimulatedFixedAttribs();
5169 }
[email protected]ba3176a2009-12-16 18:19:465170 }
[email protected]b1122982010-05-17 23:04:245171 if (simulated_attrib_0) {
5172 RestoreStateForSimulatedAttrib0();
5173 }
[email protected]38d139d2011-07-14 00:38:435174 if (WasContextLost()) {
5175 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawElements.";
5176 return error::kLostContext;
5177 }
[email protected]96449d2c2009-11-25 00:01:325178 }
[email protected]f7a64ee2010-02-01 22:24:145179 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325180}
5181
[email protected]269200b12010-11-18 22:53:065182GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:235183 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
5184 GLuint max_vertex_accessed = 0;
5185 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:295186 if (!info) {
[email protected]ae51d192010-04-27 00:48:035187 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:295188 SetGLError(GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:065189 "GetMaxValueInBufferCHROMIUM: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:235190 } else {
5191 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:035192 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:065193 SetGLError(
5194 GL_INVALID_OPERATION,
5195 "GetMaxValueInBufferCHROMIUM: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:235196 }
5197 }
5198 return max_vertex_accessed;
5199}
5200
[email protected]96449d2c2009-11-25 00:01:325201// Calls glShaderSource for the various versions of the ShaderSource command.
5202// Assumes that data / data_size points to a piece of memory that is in range
5203// of whatever context it came from (shared memory, immediate memory, bucket
5204// memory.)
[email protected]45bf5152010-02-12 00:11:315205error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035206 GLuint client_id, const char* data, uint32 data_size) {
[email protected]258a3313f2011-10-18 20:13:575207 std::string str(data, data + data_size);
[email protected]6b8cf1a2010-05-06 16:13:585208 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5209 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:315210 if (!info) {
[email protected]45bf5152010-02-12 00:11:315211 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325212 }
[email protected]45bf5152010-02-12 00:11:315213 // Note: We don't actually call glShaderSource here. We wait until
5214 // the call to glCompileShader.
[email protected]258a3313f2011-10-18 20:13:575215 info->UpdateSource(str.c_str());
[email protected]f7a64ee2010-02-01 22:24:145216 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325217}
5218
[email protected]f7a64ee2010-02-01 22:24:145219error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:195220 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:325221 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315222 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:325223 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:465224 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145225 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325226 }
[email protected]ae51d192010-04-27 00:48:035227 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:325228}
5229
[email protected]f7a64ee2010-02-01 22:24:145230error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:195231 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:325232 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315233 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:305234 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465235 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145236 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325237 }
[email protected]ae51d192010-04-27 00:48:035238 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:315239}
5240
[email protected]558847a2010-03-24 07:02:545241error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
5242 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:545243 Bucket* bucket = GetBucket(c.data_bucket_id);
5244 if (!bucket || bucket->size() == 0) {
5245 return error::kInvalidArguments;
5246 }
5247 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035248 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:545249 bucket->size() - 1);
5250}
5251
[email protected]ae51d192010-04-27 00:48:035252void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]0c8fabf2011-06-14 19:35:225253 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]6b8cf1a2010-05-06 16:13:585254 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5255 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:315256 if (!info) {
[email protected]45bf5152010-02-12 00:11:315257 return;
5258 }
[email protected]de17df392010-04-23 21:09:415259 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
5260 // glShaderSource and then glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:525261 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:345262 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:185263 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:345264 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:455265 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:235266
[email protected]a550584e2010-09-17 18:01:455267 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:345268 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:185269 return;
5270 }
[email protected]a550584e2010-09-17 18:01:455271 shader_src = translator->translated_shader();
[email protected]93297702011-11-05 05:09:465272 if (!feature_info_->feature_flags().angle_translated_shader_source)
[email protected]d6a53e42011-10-05 00:09:365273 info->UpdateTranslatedSource(shader_src);
[email protected]de17df392010-04-23 21:09:415274 }
[email protected]de17df392010-04-23 21:09:415275
[email protected]ae51d192010-04-27 00:48:035276 glShaderSource(info->service_id(), 1, &shader_src, NULL);
5277 glCompileShader(info->service_id());
[email protected]93297702011-11-05 05:09:465278 if (feature_info_->feature_flags().angle_translated_shader_source) {
[email protected]d6a53e42011-10-05 00:09:365279 GLint max_len = 0;
5280 glGetShaderiv(info->service_id(),
5281 GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
5282 &max_len);
5283 scoped_array<char> temp(new char[max_len]);
5284 GLint len = 0;
5285 glGetTranslatedShaderSourceANGLE(
5286 info->service_id(), max_len, &len, temp.get());
5287 DCHECK(max_len == 0 || len < max_len);
5288 DCHECK(len == 0 || temp[len] == '\0');
5289 info->UpdateTranslatedSource(temp.get());
5290 }
5291
[email protected]e5186162010-06-14 18:54:415292 GLint status = GL_FALSE;
5293 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
5294 if (status) {
[email protected]f57bb282010-11-12 00:51:345295 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:415296 } else {
[email protected]d9977d42010-09-01 20:27:025297 // We cannot reach here if we are using the shader translator.
5298 // All invalid shaders must be rejected by the translator.
5299 // All translated shaders must compile.
5300 LOG_IF(ERROR, use_shader_translator_)
5301 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:335302 GLint max_len = 0;
5303 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
5304 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:415305 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:335306 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
5307 DCHECK(max_len == 0 || len < max_len);
[email protected]d6a53e42011-10-05 00:09:365308 DCHECK(len == 0 || temp[len] == '\0');
[email protected]df6cf1ad2011-01-29 01:20:525309 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
[email protected]e5186162010-06-14 18:54:415310 }
[email protected]45bf5152010-02-12 00:11:315311};
5312
[email protected]ddd968b82010-03-02 00:44:295313void GLES2DecoderImpl::DoGetShaderiv(
5314 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:585315 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5316 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:295317 if (!info) {
[email protected]ddd968b82010-03-02 00:44:295318 return;
5319 }
[email protected]8f1ccdac2010-05-19 21:01:485320 switch (pname) {
5321 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525322 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:485323 return;
5324 case GL_COMPILE_STATUS:
[email protected]062c38b2012-01-18 03:25:105325 *params = compile_shader_always_succeeds_ ? true : info->IsValid();
[email protected]e5186162010-06-14 18:54:415326 return;
[email protected]8f1ccdac2010-05-19 21:01:485327 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525328 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:415329 return;
[email protected]d6a53e42011-10-05 00:09:365330 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5331 *params = info->translated_source() ?
5332 info->translated_source()->size() + 1 : 0;
5333 return;
[email protected]8f1ccdac2010-05-19 21:01:485334 default:
5335 break;
[email protected]ddd968b82010-03-02 00:44:295336 }
[email protected]8f1ccdac2010-05-19 21:01:485337 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:295338}
5339
[email protected]ae51d192010-04-27 00:48:035340error::Error GLES2DecoderImpl::HandleGetShaderSource(
5341 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
5342 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:035343 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5344 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:585345 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5346 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:525347 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:295348 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:295349 return error::kNoError;
5350 }
[email protected]df6cf1ad2011-01-29 01:20:525351 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:035352 return error::kNoError;
5353}
5354
[email protected]d6a53e42011-10-05 00:09:365355error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
5356 uint32 immediate_data_size,
5357 const gles2::GetTranslatedShaderSourceANGLE& c) {
5358 GLuint shader = c.shader;
5359
5360 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5361 Bucket* bucket = CreateBucket(bucket_id);
5362 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5363 shader, "glTranslatedGetShaderSourceANGLE");
5364 if (!info) {
5365 bucket->SetSize(0);
5366 return error::kNoError;
5367 }
5368
5369 bucket->SetFromString(info->translated_source() ?
5370 info->translated_source()->c_str() : NULL);
5371 return error::kNoError;
5372}
5373
[email protected]ae51d192010-04-27 00:48:035374error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
5375 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
5376 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:585377 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5378 Bucket* bucket = CreateBucket(bucket_id);
5379 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5380 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525381 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465382 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035383 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:315384 }
[email protected]df6cf1ad2011-01-29 01:20:525385 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035386 return error::kNoError;
5387}
5388
5389error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
5390 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
5391 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:585392 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5393 Bucket* bucket = CreateBucket(bucket_id);
5394 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5395 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525396 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465397 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035398 return error::kNoError;
5399 }
[email protected]df6cf1ad2011-01-29 01:20:525400 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035401 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325402}
5403
[email protected]1958e0e2010-04-22 05:17:155404bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105405 const BufferManager::BufferInfo* buffer = GetBufferInfo(client_id);
5406 return buffer && buffer->IsValid() && !buffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155407}
5408
5409bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105410 const FramebufferManager::FramebufferInfo* framebuffer =
[email protected]06c8b082011-01-05 18:00:365411 GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105412 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155413}
5414
5415bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365416 // IsProgram is true for programs as soon as they are created, until they are
5417 // deleted and no longer in use.
[email protected]a0b78dc2011-11-11 10:43:105418 const ProgramManager::ProgramInfo* program = GetProgramInfo(client_id);
5419 return program != NULL && !program->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155420}
5421
5422bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105423 const RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]06c8b082011-01-05 18:00:365424 GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105425 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155426}
5427
5428bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365429 // IsShader is true for shaders as soon as they are created, until they
5430 // are deleted and not attached to any programs.
[email protected]a0b78dc2011-11-11 10:43:105431 const ShaderManager::ShaderInfo* shader = GetShaderInfo(client_id);
5432 return shader != NULL && !shader->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155433}
5434
5435bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105436 const TextureManager::TextureInfo* texture = GetTextureInfo(client_id);
5437 return texture && texture->IsValid() && !texture->IsDeleted();
[email protected]ae51d192010-04-27 00:48:035438}
5439
5440void GLES2DecoderImpl::DoAttachShader(
5441 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585442 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5443 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035444 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035445 return;
[email protected]1958e0e2010-04-22 05:17:155446 }
[email protected]6b8cf1a2010-05-06 16:13:585447 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5448 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035449 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035450 return;
5451 }
[email protected]ca488e12010-12-13 20:06:145452 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:315453 SetGLError(GL_INVALID_OPERATION,
5454 "glAttachShader: can not attach more than"
5455 " one shader of the same type.");
5456 return;
5457 }
[email protected]ae51d192010-04-27 00:48:035458 glAttachShader(program_info->service_id(), shader_info->service_id());
5459}
5460
5461void GLES2DecoderImpl::DoDetachShader(
5462 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585463 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5464 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035465 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035466 return;
5467 }
[email protected]6b8cf1a2010-05-06 16:13:585468 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5469 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035470 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035471 return;
5472 }
[email protected]9a0ccd42011-03-16 23:58:225473 if (!program_info->DetachShader(shader_manager(), shader_info)) {
5474 SetGLError(GL_INVALID_OPERATION,
5475 "glDetachShader: shader not attached to program");
5476 return;
5477 }
[email protected]ae51d192010-04-27 00:48:035478 glDetachShader(program_info->service_id(), shader_info->service_id());
5479}
5480
5481void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585482 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5483 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:035484 if (!info) {
[email protected]ae51d192010-04-27 00:48:035485 return;
5486 }
[email protected]d685a682011-04-29 16:19:575487 info->Validate();
[email protected]1958e0e2010-04-22 05:17:155488}
5489
[email protected]b1122982010-05-17 23:04:245490void GLES2DecoderImpl::DoGetVertexAttribfv(
5491 GLuint index, GLenum pname, GLfloat* params) {
5492 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445493 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245494 if (!info) {
5495 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
5496 return;
5497 }
5498 switch (pname) {
5499 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5500 BufferManager::BufferInfo* buffer = info->buffer();
5501 if (buffer && !buffer->IsDeleted()) {
5502 GLuint client_id;
5503 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5504 *params = static_cast<GLfloat>(client_id);
5505 }
5506 break;
5507 }
5508 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5509 *params = static_cast<GLfloat>(info->enabled());
5510 break;
5511 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5512 *params = static_cast<GLfloat>(info->size());
5513 break;
5514 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5515 *params = static_cast<GLfloat>(info->gl_stride());
5516 break;
5517 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5518 *params = static_cast<GLfloat>(info->type());
5519 break;
5520 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5521 *params = static_cast<GLfloat>(info->normalized());
5522 break;
5523 case GL_CURRENT_VERTEX_ATTRIB:
5524 params[0] = info->value().v[0];
5525 params[1] = info->value().v[1];
5526 params[2] = info->value().v[2];
5527 params[3] = info->value().v[3];
5528 break;
5529 default:
5530 NOTREACHED();
5531 break;
5532 }
5533}
5534
5535void GLES2DecoderImpl::DoGetVertexAttribiv(
5536 GLuint index, GLenum pname, GLint* params) {
5537 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445538 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245539 if (!info) {
5540 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
5541 return;
5542 }
5543 switch (pname) {
5544 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5545 BufferManager::BufferInfo* buffer = info->buffer();
5546 if (buffer && !buffer->IsDeleted()) {
5547 GLuint client_id;
5548 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5549 *params = client_id;
5550 }
5551 break;
5552 }
5553 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5554 *params = info->enabled();
5555 break;
5556 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5557 *params = info->size();
5558 break;
5559 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5560 *params = info->gl_stride();
5561 break;
5562 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5563 *params = info->type();
5564 break;
5565 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5566 *params = static_cast<GLint>(info->normalized());
5567 break;
5568 case GL_CURRENT_VERTEX_ATTRIB:
5569 params[0] = static_cast<GLint>(info->value().v[0]);
5570 params[1] = static_cast<GLint>(info->value().v[1]);
5571 params[2] = static_cast<GLint>(info->value().v[2]);
5572 params[3] = static_cast<GLint>(info->value().v[3]);
5573 break;
5574 default:
5575 NOTREACHED();
5576 break;
5577 }
5578}
5579
5580void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
5581 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445582 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245583 if (!info) {
5584 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
5585 return;
5586 }
5587 VertexAttribManager::VertexAttribInfo::Vec4 value;
5588 value.v[0] = v0;
5589 value.v[1] = 0.0f;
5590 value.v[2] = 0.0f;
5591 value.v[3] = 1.0f;
5592 info->set_value(value);
5593 glVertexAttrib1f(index, v0);
5594}
5595
5596void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
5597 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445598 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245599 if (!info) {
5600 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
5601 return;
5602 }
5603 VertexAttribManager::VertexAttribInfo::Vec4 value;
5604 value.v[0] = v0;
5605 value.v[1] = v1;
5606 value.v[2] = 0.0f;
5607 value.v[3] = 1.0f;
5608 info->set_value(value);
5609 glVertexAttrib2f(index, v0, v1);
5610}
5611
5612void GLES2DecoderImpl::DoVertexAttrib3f(
5613 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
5614 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445615 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245616 if (!info) {
5617 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
5618 return;
5619 }
5620 VertexAttribManager::VertexAttribInfo::Vec4 value;
5621 value.v[0] = v0;
5622 value.v[1] = v1;
5623 value.v[2] = v2;
5624 value.v[3] = 1.0f;
5625 info->set_value(value);
5626 glVertexAttrib3f(index, v0, v1, v2);
5627}
5628
5629void GLES2DecoderImpl::DoVertexAttrib4f(
5630 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
5631 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445632 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245633 if (!info) {
5634 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
5635 return;
5636 }
5637 VertexAttribManager::VertexAttribInfo::Vec4 value;
5638 value.v[0] = v0;
5639 value.v[1] = v1;
5640 value.v[2] = v2;
5641 value.v[3] = v3;
5642 info->set_value(value);
5643 glVertexAttrib4f(index, v0, v1, v2, v3);
5644}
5645
5646void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
5647 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445648 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245649 if (!info) {
5650 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
5651 return;
5652 }
5653 VertexAttribManager::VertexAttribInfo::Vec4 value;
5654 value.v[0] = v[0];
5655 value.v[1] = 0.0f;
5656 value.v[2] = 0.0f;
5657 value.v[3] = 1.0f;
5658 info->set_value(value);
5659 glVertexAttrib1fv(index, v);
5660}
5661
5662void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
5663 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445664 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245665 if (!info) {
5666 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
5667 return;
5668 }
5669 VertexAttribManager::VertexAttribInfo::Vec4 value;
5670 value.v[0] = v[0];
5671 value.v[1] = v[1];
5672 value.v[2] = 0.0f;
5673 value.v[3] = 1.0f;
5674 info->set_value(value);
5675 glVertexAttrib2fv(index, v);
5676}
5677
5678void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
5679 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445680 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245681 if (!info) {
5682 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
5683 return;
5684 }
5685 VertexAttribManager::VertexAttribInfo::Vec4 value;
5686 value.v[0] = v[0];
5687 value.v[1] = v[1];
5688 value.v[2] = v[2];
5689 value.v[3] = 1.0f;
5690 info->set_value(value);
5691 glVertexAttrib3fv(index, v);
5692}
5693
5694void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
5695 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445696 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245697 if (!info) {
5698 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
5699 return;
5700 }
5701 VertexAttribManager::VertexAttribInfo::Vec4 value;
5702 value.v[0] = v[0];
5703 value.v[1] = v[1];
5704 value.v[2] = v[2];
5705 value.v[3] = v[3];
5706 info->set_value(value);
5707 glVertexAttrib4fv(index, v);
5708}
5709
[email protected]f7a64ee2010-02-01 22:24:145710error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:195711 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:295712 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
5713 SetGLError(GL_INVALID_VALUE,
5714 "glVertexAttribPointer: no array buffer bound");
5715 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325716 }
[email protected]8eee29c2010-04-29 03:38:295717
5718 GLuint indx = c.indx;
5719 GLint size = c.size;
5720 GLenum type = c.type;
5721 GLboolean normalized = c.normalized;
5722 GLsizei stride = c.stride;
5723 GLsizei offset = c.offset;
5724 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:055725 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295726 SetGLError(GL_INVALID_ENUM,
5727 "glVertexAttribPointer: type GL_INVALID_ENUM");
5728 return error::kNoError;
5729 }
[email protected]9438b012010-06-15 22:55:055730 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:315731 SetGLError(GL_INVALID_VALUE,
[email protected]8eee29c2010-04-29 03:38:295732 "glVertexAttribPointer: size GL_INVALID_VALUE");
5733 return error::kNoError;
5734 }
5735 if (indx >= group_->max_vertex_attribs()) {
5736 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
5737 return error::kNoError;
5738 }
5739 if (stride < 0) {
5740 SetGLError(GL_INVALID_VALUE,
5741 "glVertexAttribPointer: stride < 0");
5742 return error::kNoError;
5743 }
5744 if (stride > 255) {
5745 SetGLError(GL_INVALID_VALUE,
5746 "glVertexAttribPointer: stride > 255");
5747 return error::kNoError;
5748 }
5749 if (offset < 0) {
5750 SetGLError(GL_INVALID_VALUE,
5751 "glVertexAttribPointer: offset < 0");
5752 return error::kNoError;
5753 }
5754 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:315755 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:295756 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:315757 SetGLError(GL_INVALID_OPERATION,
5758 "glVertexAttribPointer: offset not valid for type");
5759 return error::kNoError;
5760 }
5761 if (stride % component_size > 0) {
5762 SetGLError(GL_INVALID_OPERATION,
[email protected]8eee29c2010-04-29 03:38:295763 "glVertexAttribPointer: stride not valid for type");
5764 return error::kNoError;
5765 }
[email protected]3757a372012-01-19 05:20:445766 vertex_attrib_manager_->SetAttribInfo(
[email protected]8fbedc02010-11-18 18:43:405767 indx,
[email protected]8eee29c2010-04-29 03:38:295768 bound_array_buffer_,
5769 size,
5770 type,
[email protected]b1122982010-05-17 23:04:245771 normalized,
5772 stride,
5773 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:295774 offset);
[email protected]8fbedc02010-11-18 18:43:405775 if (type != GL_FIXED) {
5776 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
5777 }
[email protected]f7a64ee2010-02-01 22:24:145778 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325779}
5780
[email protected]f7a64ee2010-02-01 22:24:145781error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:195782 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:315783 GLint x = c.x;
5784 GLint y = c.y;
5785 GLsizei width = c.width;
5786 GLsizei height = c.height;
5787 GLenum format = c.format;
5788 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:565789 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:295790 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:565791 return error::kNoError;
5792 }
[email protected]a51788e2010-02-24 21:54:255793 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:185794 uint32 pixels_size;
5795 if (!GLES2Util::ComputeImageDataSize(
5796 width, height, format, type, pack_alignment_, &pixels_size)) {
5797 return error::kOutOfBounds;
5798 }
[email protected]612d2f82009-12-08 20:49:315799 void* pixels = GetSharedMemoryAs<void*>(
5800 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:255801 Result* result = GetSharedMemoryAs<Result*>(
5802 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5803 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:145804 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465805 }
[email protected]a51788e2010-02-24 21:54:255806
[email protected]9438b012010-06-15 22:55:055807 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295808 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
5809 return error::kNoError;
5810 }
[email protected]9438b012010-06-15 22:55:055811 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295812 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125813 return error::kNoError;
5814 }
[email protected]57f223832010-03-19 01:57:565815 if (width == 0 || height == 0) {
5816 return error::kNoError;
5817 }
5818
[email protected]57f223832010-03-19 01:57:565819 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:305820 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:565821
5822 GLint max_x;
5823 GLint max_y;
5824 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:295825 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:145826 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:315827 }
[email protected]57f223832010-03-19 01:57:565828
[email protected]0d6bfdc2011-11-02 01:32:205829 if (!CheckBoundFramebuffersValid("glReadPixels")) {
5830 return error::kNoError;
5831 }
5832
[email protected]a0b78dc2011-11-11 10:43:105833 CopyRealGLErrorsToWrapper();
5834
5835 ScopedResolvedFrameBufferBinder binder(this, false, true);
5836
[email protected]d37231fa2010-04-09 21:16:025837 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:565838 // The user requested an out of range area. Get the results 1 line
5839 // at a time.
5840 uint32 temp_size;
5841 if (!GLES2Util::ComputeImageDataSize(
5842 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295843 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565844 return error::kNoError;
5845 }
5846 GLsizei unpadded_row_size = temp_size;
5847 if (!GLES2Util::ComputeImageDataSize(
5848 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295849 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565850 return error::kNoError;
5851 }
5852 GLsizei padded_row_size = temp_size - unpadded_row_size;
5853 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:295854 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565855 return error::kNoError;
5856 }
5857
5858 GLint dest_x_offset = std::max(-x, 0);
5859 uint32 dest_row_offset;
5860 if (!GLES2Util::ComputeImageDataSize(
5861 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:295862 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565863 return error::kNoError;
5864 }
5865
5866 // Copy each row into the larger dest rect.
5867 int8* dst = static_cast<int8*>(pixels);
5868 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:025869 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:565870 GLint read_width = read_end_x - read_x;
5871 for (GLint yy = 0; yy < height; ++yy) {
5872 GLint ry = y + yy;
5873
5874 // Clear the row.
5875 memset(dst, 0, unpadded_row_size);
5876
5877 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:025878 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:565879 glReadPixels(
5880 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
5881 }
5882 dst += padded_row_size;
5883 }
5884 } else {
5885 glReadPixels(x, y, width, height, format, type, pixels);
5886 }
[email protected]1002c2d2011-06-28 22:39:045887 GLenum error = PeekGLError();
[email protected]a51788e2010-02-24 21:54:255888 if (error == GL_NO_ERROR) {
5889 *result = true;
[email protected]4848b9f82011-03-10 18:37:565890
5891 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5892 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5893 if ((channels_exist & 0x0008) == 0) {
5894 // Set the alpha to 255 because some drivers are buggy in this regard.
5895 uint32 temp_size;
5896 if (!GLES2Util::ComputeImageDataSize(
5897 width, 1, format, type, pack_alignment_, &temp_size)) {
5898 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5899 return error::kNoError;
5900 }
5901 GLsizei unpadded_row_size = temp_size;
5902 if (!GLES2Util::ComputeImageDataSize(
5903 width, 2, format, type, pack_alignment_, &temp_size)) {
5904 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5905 return error::kNoError;
5906 }
5907 GLsizei padded_row_size = temp_size - unpadded_row_size;
5908 if (padded_row_size < 0 || unpadded_row_size < 0) {
5909 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5910 return error::kNoError;
5911 }
5912 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
5913 // of this implementation.
5914 if (type != GL_UNSIGNED_BYTE) {
5915 SetGLError(GL_INVALID_OPERATION, "unsupported readPixel format");
5916 return error::kNoError;
5917 }
5918 switch (format) {
5919 case GL_RGBA:
[email protected]297ca1c2011-06-20 23:08:465920 case GL_BGRA_EXT:
[email protected]4848b9f82011-03-10 18:37:565921 case GL_ALPHA: {
5922 int offset = (format == GL_ALPHA) ? 0 : 3;
5923 int step = (format == GL_ALPHA) ? 1 : 4;
5924 uint8* dst = static_cast<uint8*>(pixels) + offset;
5925 for (GLint yy = 0; yy < height; ++yy) {
5926 uint8* end = dst + unpadded_row_size;
5927 for (uint8* d = dst; d < end; d += step) {
5928 *d = 255;
5929 }
5930 dst += padded_row_size;
5931 }
5932 break;
5933 }
5934 default:
5935 break;
5936 }
5937 }
[email protected]a51788e2010-02-24 21:54:255938 }
[email protected]4848b9f82011-03-10 18:37:565939
[email protected]f7a64ee2010-02-01 22:24:145940 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325941}
5942
[email protected]f7a64ee2010-02-01 22:24:145943error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:195944 uint32 immediate_data_size, const gles2::PixelStorei& c) {
5945 GLenum pname = c.pname;
5946 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:055947 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:295948 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125949 return error::kNoError;
5950 }
[email protected]222471d2011-11-30 18:06:395951 switch (pname) {
5952 case GL_PACK_ALIGNMENT:
5953 case GL_UNPACK_ALIGNMENT:
5954 if (!validators_->pixel_store_alignment.IsValid(param)) {
5955 SetGLError(GL_INVALID_VALUE,
5956 "glPixelSTore: param GL_INVALID_VALUE");
5957 return error::kNoError;
5958 }
5959 default:
5960 break;
[email protected]b9849abf2009-11-25 19:13:195961 }
5962 glPixelStorei(pname, param);
5963 switch (pname) {
5964 case GL_PACK_ALIGNMENT:
5965 pack_alignment_ = param;
5966 break;
[email protected]222471d2011-11-30 18:06:395967 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
5968 break;
[email protected]b9849abf2009-11-25 19:13:195969 case GL_UNPACK_ALIGNMENT:
5970 unpack_alignment_ = param;
5971 break;
5972 default:
5973 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:375974 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:195975 break;
5976 }
[email protected]f7a64ee2010-02-01 22:24:145977 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195978}
5979
[email protected]1c75a3702011-11-11 14:15:285980error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
5981 uint32 immediate_data_size, const gles2::PostSubBufferCHROMIUM& c) {
5982 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
[email protected]aa258822011-11-22 13:52:255983 if (!context_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
[email protected]1c75a3702011-11-11 14:15:285984 SetGLError(GL_INVALID_OPERATION,
5985 "glPostSubBufferCHROMIUM: command not supported by surface");
5986 return error::kNoError;
5987 }
5988 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height))
5989 return error::kNoError;
5990 else
5991 return error::kLostContext;
5992}
5993
[email protected]558847a2010-03-24 07:02:545994error::Error GLES2DecoderImpl::GetAttribLocationHelper(
5995 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5996 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:575997 if (!StringIsValidForGLES(name_str.c_str())) {
5998 SetGLError(GL_INVALID_VALUE, "glGetAttribLocation: Invalid character");
5999 return error::kNoError;
6000 }
[email protected]6b8cf1a2010-05-06 16:13:586001 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6002 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:036003 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146004 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196005 }
[email protected]ae51d192010-04-27 00:48:036006 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:296007 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:256008 return error::kNoError;
6009 }
[email protected]b9849abf2009-11-25 19:13:196010 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546011 location_shm_id, location_shm_offset, sizeof(GLint));
6012 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146013 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196014 }
[email protected]558847a2010-03-24 07:02:546015 // Require the client to init this incase the context is lost and we are no
6016 // longer executing commands.
6017 if (*location != -1) {
6018 return error::kGenericError;
6019 }
[email protected]0bfd9882010-02-05 23:02:256020 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:146021 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196022}
6023
[email protected]558847a2010-03-24 07:02:546024error::Error GLES2DecoderImpl::HandleGetAttribLocation(
6025 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
6026 uint32 name_size = c.data_size;
6027 const char* name = GetSharedMemoryAs<const char*>(
6028 c.name_shm_id, c.name_shm_offset, name_size);
6029 if (!name) {
6030 return error::kOutOfBounds;
6031 }
6032 String name_str(name, name_size);
6033 return GetAttribLocationHelper(
6034 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6035}
6036
[email protected]f7a64ee2010-02-01 22:24:146037error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196038 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:546039 uint32 name_size = c.data_size;
6040 const char* name = GetImmediateDataAs<const char*>(
6041 c, name_size, immediate_data_size);
6042 if (!name) {
6043 return error::kOutOfBounds;
6044 }
6045 String name_str(name, name_size);
6046 return GetAttribLocationHelper(
6047 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6048}
6049
6050error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
6051 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
6052 Bucket* bucket = GetBucket(c.name_bucket_id);
6053 if (!bucket) {
6054 return error::kInvalidArguments;
6055 }
6056 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186057 if (!bucket->GetAsString(&name_str)) {
6058 return error::kInvalidArguments;
6059 }
[email protected]558847a2010-03-24 07:02:546060 return GetAttribLocationHelper(
6061 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6062}
6063
6064error::Error GLES2DecoderImpl::GetUniformLocationHelper(
6065 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6066 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576067 if (!StringIsValidForGLES(name_str.c_str())) {
6068 SetGLError(GL_INVALID_VALUE, "glGetUniformLocation: Invalid character");
6069 return error::kNoError;
6070 }
[email protected]6b8cf1a2010-05-06 16:13:586071 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6072 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:036073 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146074 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196075 }
[email protected]ae51d192010-04-27 00:48:036076 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:296077 SetGLError(GL_INVALID_OPERATION,
6078 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:256079 return error::kNoError;
6080 }
[email protected]b9849abf2009-11-25 19:13:196081 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546082 location_shm_id, location_shm_offset, sizeof(GLint));
6083 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146084 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196085 }
[email protected]558847a2010-03-24 07:02:546086 // Require the client to init this incase the context is lost an we are no
6087 // longer executing commands.
6088 if (*location != -1) {
6089 return error::kGenericError;
6090 }
6091 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:146092 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196093}
6094
[email protected]f7a64ee2010-02-01 22:24:146095error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:196096 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:196097 uint32 name_size = c.data_size;
6098 const char* name = GetSharedMemoryAs<const char*>(
6099 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:546100 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146101 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196102 }
6103 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546104 return GetUniformLocationHelper(
6105 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196106}
6107
[email protected]f7a64ee2010-02-01 22:24:146108error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196109 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:196110 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:306111 const char* name = GetImmediateDataAs<const char*>(
6112 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:546113 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146114 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196115 }
6116 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546117 return GetUniformLocationHelper(
6118 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6119}
6120
6121error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
6122 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
6123 Bucket* bucket = GetBucket(c.name_bucket_id);
6124 if (!bucket) {
6125 return error::kInvalidArguments;
6126 }
6127 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186128 if (!bucket->GetAsString(&name_str)) {
6129 return error::kInvalidArguments;
6130 }
[email protected]558847a2010-03-24 07:02:546131 return GetUniformLocationHelper(
6132 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196133}
6134
[email protected]ddd968b82010-03-02 00:44:296135error::Error GLES2DecoderImpl::HandleGetString(
6136 uint32 immediate_data_size, const gles2::GetString& c) {
6137 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:056138 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:296139 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:296140 return error::kNoError;
6141 }
[email protected]1958e0e2010-04-22 05:17:156142 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
6143 const char* str = NULL;
[email protected]f0d74742011-10-03 16:31:046144 std::string extensions;
[email protected]1958e0e2010-04-22 05:17:156145 switch (name) {
6146 case GL_VERSION:
6147 str = "OpenGL ES 2.0 Chromium";
6148 break;
6149 case GL_SHADING_LANGUAGE_VERSION:
6150 str = "OpenGL ES GLSL ES 1.0 Chromium";
6151 break;
6152 case GL_EXTENSIONS:
[email protected]f0d74742011-10-03 16:31:046153 {
6154 // For WebGL contexts, strip out the OES derivatives extension if it has
6155 // not been enabled.
6156 if (force_webgl_glsl_validation_ &&
6157 !derivatives_explicitly_enabled_) {
6158 extensions = feature_info_->extensions();
6159 size_t offset = extensions.find(kOESDerivativeExtension);
6160 if (std::string::npos != offset) {
6161 extensions.replace(offset,
6162 offset + arraysize(kOESDerivativeExtension),
6163 std::string());
6164 }
6165 str = extensions.c_str();
6166 } else {
6167 str = feature_info_->extensions().c_str();
6168 }
[email protected]f0d74742011-10-03 16:31:046169 }
[email protected]1958e0e2010-04-22 05:17:156170 break;
6171 default:
6172 str = gl_str;
6173 break;
6174 }
[email protected]ddd968b82010-03-02 00:44:296175 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:156176 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:296177 return error::kNoError;
6178}
6179
[email protected]0c86dbf2010-03-05 08:14:116180void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:156181 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:056182 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296183 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
6184 return;
6185 }
[email protected]9438b012010-06-15 22:55:056186 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:296187 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:116188 return;
[email protected]3b6ec202010-03-05 05:16:236189 }
6190 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:296191 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:286192 return;
[email protected]3b6ec202010-03-05 05:16:236193 }
6194 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
6195 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296196 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:286197 return;
[email protected]3b6ec202010-03-05 05:16:236198 }
6199 // Clear the buffer to 0 if no initial data was passed in.
6200 scoped_array<int8> zero;
6201 if (!data) {
6202 zero.reset(new int8[size]);
6203 memset(zero.get(), 0, size);
6204 data = zero.get();
6205 }
[email protected]473c01ccb2011-06-07 01:33:306206
6207 if (!bufferdata_faster_than_buffersubdata_ &&
6208 size == info->size() && usage == info->usage()) {
6209 glBufferSubData(target, 0, size, data);
6210 info->SetRange(0, size, data);
6211 return;
6212 }
6213
[email protected]3b6ec202010-03-05 05:16:236214 CopyRealGLErrorsToWrapper();
6215 glBufferData(target, size, data, usage);
[email protected]1002c2d2011-06-28 22:39:046216 GLenum error = PeekGLError();
6217 if (error == GL_NO_ERROR) {
[email protected]473c01ccb2011-06-07 01:33:306218 buffer_manager()->SetInfo(info, size, usage);
[email protected]0c86dbf2010-03-05 08:14:116219 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:236220 }
[email protected]0c86dbf2010-03-05 08:14:116221}
6222
6223error::Error GLES2DecoderImpl::HandleBufferData(
6224 uint32 immediate_data_size, const gles2::BufferData& c) {
6225 GLenum target = static_cast<GLenum>(c.target);
6226 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
6227 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6228 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6229 GLenum usage = static_cast<GLenum>(c.usage);
6230 const void* data = NULL;
6231 if (data_shm_id != 0 || data_shm_offset != 0) {
6232 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
6233 if (!data) {
6234 return error::kOutOfBounds;
6235 }
6236 }
6237 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:146238 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196239}
6240
[email protected]f7a64ee2010-02-01 22:24:146241error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:196242 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
6243 GLenum target = static_cast<GLenum>(c.target);
6244 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:306245 const void* data = GetImmediateDataAs<const void*>(
6246 c, size, immediate_data_size);
6247 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146248 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:306249 }
[email protected]b9849abf2009-11-25 19:13:196250 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:116251 DoBufferData(target, size, data, usage);
6252 return error::kNoError;
6253}
6254
6255void GLES2DecoderImpl::DoBufferSubData(
6256 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:506257 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476258 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296259 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:286260 return;
[email protected]a93bb842010-02-16 23:03:476261 }
[email protected]0c86dbf2010-03-05 08:14:116262 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:296263 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]473c01ccb2011-06-07 01:33:306264 return;
[email protected]07f54fcc2009-12-22 02:46:306265 }
[email protected]473c01ccb2011-06-07 01:33:306266 if (bufferdata_faster_than_buffersubdata_ &&
6267 offset == 0 && size == info->size()) {
6268 glBufferData(target, size, data, info->usage());
6269 return;
6270 }
6271 glBufferSubData(target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:196272}
6273
[email protected]0d6bfdc2011-11-02 01:32:206274bool GLES2DecoderImpl::ClearLevel(
6275 unsigned service_id,
6276 unsigned bind_target,
6277 unsigned target,
6278 int level,
6279 unsigned format,
6280 unsigned type,
6281 int width,
[email protected]4502e6492011-12-14 19:39:156282 int height,
6283 bool is_texture_immutable) {
[email protected]0d6bfdc2011-11-02 01:32:206284 // Assumes the size has already been checked.
6285 uint32 pixels_size = 0;
6286 if (!GLES2Util::ComputeImageDataSize(
6287 width, height, format, type, unpack_alignment_, &pixels_size)) {
6288 return false;
6289 }
6290 scoped_array<char> zero(new char[pixels_size]);
6291 memset(zero.get(), 0, pixels_size);
6292 glBindTexture(bind_target, service_id);
[email protected]4502e6492011-12-14 19:39:156293 if (is_texture_immutable) {
6294 glTexSubImage2D(
6295 target, level, 0, 0, width, height, format, type, zero.get());
6296 } else {
6297 WrappedTexImage2D(
6298 target, level, format, width, height, 0, format, type, zero.get());
6299 }
[email protected]0d6bfdc2011-11-02 01:32:206300 TextureManager::TextureInfo* info = GetTextureInfoForTarget(bind_target);
6301 glBindTexture(bind_target, info ? info->service_id() : 0);
6302 return true;
6303}
6304
[email protected]a93bb842010-02-16 23:03:476305error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
6306 GLenum target,
6307 GLint level,
6308 GLenum internal_format,
6309 GLsizei width,
6310 GLsizei height,
6311 GLint border,
6312 GLsizei image_size,
6313 const void* data) {
[email protected]a93bb842010-02-16 23:03:476314 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:056315 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296316 SetGLError(GL_INVALID_ENUM,
6317 "glCompressedTexImage2D: target GL_INVALID_ENUM");
6318 return error::kNoError;
6319 }
[email protected]9438b012010-06-15 22:55:056320 if (!validators_->compressed_texture_format.IsValid(
6321 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296322 SetGLError(GL_INVALID_ENUM,
6323 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:476324 return error::kNoError;
6325 }
[email protected]80eb6b52012-01-19 00:14:416326 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476327 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296328 SetGLError(GL_INVALID_VALUE,
6329 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476330 return error::kNoError;
6331 }
[email protected]3916c97e2010-02-25 03:20:506332 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476333 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296334 SetGLError(GL_INVALID_VALUE,
6335 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:476336 return error::kNoError;
6337 }
[email protected]97dc7cbe2011-12-06 17:26:176338 if (info->IsImmutable()) {
6339 SetGLError(GL_INVALID_OPERATION,
6340 "glCompressedTexImage2D: texture is immutable");
6341 return error::kNoError;
6342 }
[email protected]968351b2011-12-20 08:26:516343
6344 if (info->IsAttachedToFramebuffer()) {
6345 state_dirty_ = true;
6346 // TODO(gman): If textures tracked which framebuffers they were attached to
6347 // we could just mark those framebuffers as not complete.
6348 framebuffer_manager()->IncFramebufferStateChangeCount();
6349 }
6350
[email protected]a93bb842010-02-16 23:03:476351 scoped_array<int8> zero;
6352 if (!data) {
6353 zero.reset(new int8[image_size]);
6354 memset(zero.get(), 0, image_size);
6355 data = zero.get();
6356 }
[email protected]cadde4a2010-07-31 17:10:436357 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:476358 glCompressedTexImage2D(
6359 target, level, internal_format, width, height, border, image_size, data);
[email protected]1002c2d2011-06-28 22:39:046360 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436361 if (error == GL_NO_ERROR) {
6362 texture_manager()->SetLevelInfo(
[email protected]0d6bfdc2011-11-02 01:32:206363 info, target, level, internal_format, width, height, 1, border, 0, 0,
6364 true);
[email protected]cadde4a2010-07-31 17:10:436365 }
[email protected]a93bb842010-02-16 23:03:476366 return error::kNoError;
6367}
6368
[email protected]f7a64ee2010-02-01 22:24:146369error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196370 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
6371 GLenum target = static_cast<GLenum>(c.target);
6372 GLint level = static_cast<GLint>(c.level);
6373 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6374 GLsizei width = static_cast<GLsizei>(c.width);
6375 GLsizei height = static_cast<GLsizei>(c.height);
6376 GLint border = static_cast<GLint>(c.border);
6377 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
6378 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6379 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6380 const void* data = NULL;
6381 if (data_shm_id != 0 || data_shm_offset != 0) {
6382 data = GetSharedMemoryAs<const void*>(
6383 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:466384 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146385 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196386 }
6387 }
[email protected]a93bb842010-02-16 23:03:476388 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196389 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:196390}
6391
[email protected]f7a64ee2010-02-01 22:24:146392error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:196393 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
6394 GLenum target = static_cast<GLenum>(c.target);
6395 GLint level = static_cast<GLint>(c.level);
6396 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6397 GLsizei width = static_cast<GLsizei>(c.width);
6398 GLsizei height = static_cast<GLsizei>(c.height);
6399 GLint border = static_cast<GLint>(c.border);
6400 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:306401 const void* data = GetImmediateDataAs<const void*>(
6402 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466403 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146404 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466405 }
[email protected]a93bb842010-02-16 23:03:476406 return DoCompressedTexImage2D(
6407 target, level, internal_format, width, height, border, image_size, data);
6408}
6409
[email protected]b6140d02010-05-17 14:47:166410error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
6411 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
6412 GLenum target = static_cast<GLenum>(c.target);
6413 GLint level = static_cast<GLint>(c.level);
6414 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6415 GLsizei width = static_cast<GLsizei>(c.width);
6416 GLsizei height = static_cast<GLsizei>(c.height);
6417 GLint border = static_cast<GLint>(c.border);
6418 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:286419 if (!bucket) {
6420 return error::kInvalidArguments;
6421 }
6422 uint32 data_size = bucket->size();
6423 GLsizei imageSize = data_size;
6424 const void* data = bucket->GetData(0, data_size);
6425 if (!data) {
6426 return error::kInvalidArguments;
6427 }
[email protected]b6140d02010-05-17 14:47:166428 return DoCompressedTexImage2D(
6429 target, level, internal_format, width, height, border,
[email protected]12f93d82011-10-17 21:16:286430 imageSize, data);
[email protected]b6140d02010-05-17 14:47:166431}
6432
6433error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
6434 uint32 immediate_data_size,
6435 const gles2::CompressedTexSubImage2DBucket& c) {
6436 GLenum target = static_cast<GLenum>(c.target);
6437 GLint level = static_cast<GLint>(c.level);
6438 GLint xoffset = static_cast<GLint>(c.xoffset);
6439 GLint yoffset = static_cast<GLint>(c.yoffset);
6440 GLsizei width = static_cast<GLsizei>(c.width);
6441 GLsizei height = static_cast<GLsizei>(c.height);
6442 GLenum format = static_cast<GLenum>(c.format);
6443 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:286444 if (!bucket) {
6445 return error::kInvalidArguments;
6446 }
[email protected]b6140d02010-05-17 14:47:166447 uint32 data_size = bucket->size();
6448 GLsizei imageSize = data_size;
6449 const void* data = bucket->GetData(0, data_size);
[email protected]12f93d82011-10-17 21:16:286450 if (!data) {
6451 return error::kInvalidArguments;
6452 }
[email protected]9438b012010-06-15 22:55:056453 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:166454 SetGLError(
6455 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
6456 return error::kNoError;
6457 }
[email protected]9438b012010-06-15 22:55:056458 if (!validators_->compressed_texture_format.IsValid(format)) {
6459 SetGLError(GL_INVALID_ENUM,
6460 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
6461 return error::kNoError;
6462 }
[email protected]b6140d02010-05-17 14:47:166463 if (width < 0) {
6464 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
6465 return error::kNoError;
6466 }
6467 if (height < 0) {
6468 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
6469 return error::kNoError;
6470 }
6471 if (imageSize < 0) {
6472 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
6473 return error::kNoError;
6474 }
[email protected]cadde4a2010-07-31 17:10:436475 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:166476 target, level, xoffset, yoffset, width, height, format, imageSize, data);
6477 return error::kNoError;
6478}
6479
[email protected]a93bb842010-02-16 23:03:476480error::Error GLES2DecoderImpl::DoTexImage2D(
6481 GLenum target,
6482 GLint level,
6483 GLenum internal_format,
6484 GLsizei width,
6485 GLsizei height,
6486 GLint border,
6487 GLenum format,
6488 GLenum type,
6489 const void* pixels,
6490 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:056491 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296492 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
6493 return error::kNoError;
6494 }
[email protected]9438b012010-06-15 22:55:056495 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296496 SetGLError(GL_INVALID_ENUM,
6497 "glTexImage2D: internal_format GL_INVALID_ENUM");
6498 return error::kNoError;
6499 }
[email protected]9438b012010-06-15 22:55:056500 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:296501 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
6502 return error::kNoError;
6503 }
[email protected]9438b012010-06-15 22:55:056504 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:296505 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:146506 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196507 }
[email protected]7b92c412010-07-20 17:48:256508 if (format != internal_format) {
6509 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
6510 return error::kNoError;
6511 }
[email protected]80eb6b52012-01-19 00:14:416512 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476513 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296514 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476515 return error::kNoError;
6516 }
[email protected]3916c97e2010-02-25 03:20:506517 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476518 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296519 SetGLError(GL_INVALID_OPERATION,
6520 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:476521 return error::kNoError;
6522 }
[email protected]0226c112011-07-22 03:25:076523
[email protected]97dc7cbe2011-12-06 17:26:176524 if (info->IsImmutable()) {
6525 SetGLError(GL_INVALID_OPERATION,
6526 "glTexImage2D: texture is immutable");
6527 return error::kNoError;
6528 }
6529
[email protected]0226c112011-07-22 03:25:076530 GLsizei tex_width = 0;
6531 GLsizei tex_height = 0;
6532 GLenum tex_type = 0;
6533 GLenum tex_format = 0;
6534 bool level_is_same =
6535 info->GetLevelSize(target, level, &tex_width, &tex_height) &&
6536 info->GetLevelType(target, level, &tex_type, &tex_format) &&
6537 width == tex_width && height == tex_height &&
6538 type == tex_type && format == tex_format;
6539
6540 if (level_is_same && !pixels) {
[email protected]1bed6222011-12-21 11:21:396541 // Just set the level info but mark the texture as uncleared.
6542 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416543 info,
[email protected]1bed6222011-12-21 11:21:396544 target, level, internal_format, width, height, 1, border, format, type,
6545 false);
[email protected]ea72ed222011-08-17 18:58:436546 tex_image_2d_failed_ = false;
[email protected]0226c112011-07-22 03:25:076547 return error::kNoError;
6548 }
6549
[email protected]297ca1c2011-06-20 23:08:466550 if (info->IsAttachedToFramebuffer()) {
6551 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:516552 // TODO(gman): If textures tracked which framebuffers they were attached to
6553 // we could just mark those framebuffers as not complete.
6554 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:466555 }
6556
[email protected]1bed6222011-12-21 11:21:396557 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same && pixels) {
[email protected]0226c112011-07-22 03:25:076558 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
6559 tex_image_2d_failed_ = false;
6560 return error::kNoError;
[email protected]7488d962010-07-16 02:41:586561 }
[email protected]876f6fee2010-08-02 23:10:326562
[email protected]cadde4a2010-07-31 17:10:436563 CopyRealGLErrorsToWrapper();
[email protected]473c01ccb2011-06-07 01:33:306564 WrappedTexImage2D(
6565 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476566 pixels);
[email protected]1002c2d2011-06-28 22:39:046567 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436568 if (error == GL_NO_ERROR) {
[email protected]0d6bfdc2011-11-02 01:32:206569 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416570 info,
[email protected]0d6bfdc2011-11-02 01:32:206571 target, level, internal_format, width, height, 1, border, format, type,
6572 pixels != NULL);
[email protected]b493ee622011-04-13 23:52:006573 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:436574 }
[email protected]f7a64ee2010-02-01 22:24:146575 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196576}
6577
[email protected]f7a64ee2010-02-01 22:24:146578error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196579 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]366ae242011-05-10 02:23:586580 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:006581 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:196582 GLenum target = static_cast<GLenum>(c.target);
6583 GLint level = static_cast<GLint>(c.level);
6584 GLint internal_format = static_cast<GLint>(c.internalformat);
6585 GLsizei width = static_cast<GLsizei>(c.width);
6586 GLsizei height = static_cast<GLsizei>(c.height);
6587 GLint border = static_cast<GLint>(c.border);
6588 GLenum format = static_cast<GLenum>(c.format);
6589 GLenum type = static_cast<GLenum>(c.type);
6590 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
6591 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:186592 uint32 pixels_size;
6593 if (!GLES2Util::ComputeImageDataSize(
6594 width, height, format, type, unpack_alignment_, &pixels_size)) {
6595 return error::kOutOfBounds;
6596 }
[email protected]b9849abf2009-11-25 19:13:196597 const void* pixels = NULL;
6598 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
6599 pixels = GetSharedMemoryAs<const void*>(
6600 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:466601 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146602 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196603 }
6604 }
[email protected]a93bb842010-02-16 23:03:476605 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196606 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476607 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:196608}
6609
[email protected]f7a64ee2010-02-01 22:24:146610error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:196611 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
6612 GLenum target = static_cast<GLenum>(c.target);
6613 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:466614 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:196615 GLsizei width = static_cast<GLsizei>(c.width);
6616 GLsizei height = static_cast<GLsizei>(c.height);
6617 GLint border = static_cast<GLint>(c.border);
6618 GLenum format = static_cast<GLenum>(c.format);
6619 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:186620 uint32 size;
6621 if (!GLES2Util::ComputeImageDataSize(
6622 width, height, format, type, unpack_alignment_, &size)) {
6623 return error::kOutOfBounds;
6624 }
[email protected]07f54fcc2009-12-22 02:46:306625 const void* pixels = GetImmediateDataAs<const void*>(
6626 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466627 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146628 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466629 }
[email protected]a93bb842010-02-16 23:03:476630 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:466631 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476632 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:146633 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326634}
6635
[email protected]cadde4a2010-07-31 17:10:436636void GLES2DecoderImpl::DoCompressedTexSubImage2D(
6637 GLenum target,
6638 GLint level,
6639 GLint xoffset,
6640 GLint yoffset,
6641 GLsizei width,
6642 GLsizei height,
6643 GLenum format,
6644 GLsizei image_size,
6645 const void * data) {
6646 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6647 if (!info) {
6648 SetGLError(GL_INVALID_OPERATION,
6649 "glCompressedTexSubImage2D: unknown texture for target");
6650 return;
6651 }
6652 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:526653 GLenum internal_format = 0;
6654 if (!info->GetLevelType(target, level, &type, &internal_format)) {
6655 SetGLError(
6656 GL_INVALID_OPERATION,
[email protected]4502e6492011-12-14 19:39:156657 "glCompressedTexSubImage2D: level does not exist.");
[email protected]df6cf1ad2011-01-29 01:20:526658 return;
6659 }
6660 if (internal_format != format) {
6661 SetGLError(
6662 GL_INVALID_OPERATION,
[email protected]4502e6492011-12-14 19:39:156663 "glCompressedTexSubImage2D: format does not match internal format.");
[email protected]df6cf1ad2011-01-29 01:20:526664 return;
6665 }
6666 if (!info->ValidForTexture(
6667 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:436668 SetGLError(GL_INVALID_VALUE,
[email protected]4502e6492011-12-14 19:39:156669 "glCompressedTexSubImage2D: bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:436670 return;
6671 }
[email protected]0d6bfdc2011-11-02 01:32:206672 // Note: There is no need to deal with texture cleared tracking here
6673 // because the validation above means you can only get here if the level
6674 // is already a matching compressed format and in that case
6675 // CompressedTexImage2D already cleared the texture.
[email protected]cadde4a2010-07-31 17:10:436676 glCompressedTexSubImage2D(
6677 target, level, xoffset, yoffset, width, height, format, image_size, data);
6678}
6679
[email protected]6e288612010-12-21 20:45:036680static void Clip(
6681 GLint start, GLint range, GLint sourceRange,
6682 GLint* out_start, GLint* out_range) {
6683 DCHECK(out_start);
6684 DCHECK(out_range);
6685 if (start < 0) {
6686 range += start;
6687 start = 0;
6688 }
6689 GLint end = start + range;
6690 if (end > sourceRange) {
6691 range -= end - sourceRange;
6692 }
6693 *out_start = start;
6694 *out_range = range;
6695}
6696
[email protected]cadde4a2010-07-31 17:10:436697void GLES2DecoderImpl::DoCopyTexImage2D(
6698 GLenum target,
6699 GLint level,
6700 GLenum internal_format,
6701 GLint x,
6702 GLint y,
6703 GLsizei width,
6704 GLsizei height,
6705 GLint border) {
6706 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6707 if (!info) {
6708 SetGLError(GL_INVALID_OPERATION,
6709 "glCopyTexImage2D: unknown texture for target");
6710 return;
6711 }
[email protected]97dc7cbe2011-12-06 17:26:176712 if (info->IsImmutable()) {
6713 SetGLError(GL_INVALID_OPERATION,
6714 "glCopyTexImage2D: texture is immutable");
6715 }
[email protected]80eb6b52012-01-19 00:14:416716 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:186717 border != 0) {
6718 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
6719 return;
6720 }
6721
[email protected]9edc6b22010-12-23 02:00:266722 // Check we have compatible formats.
6723 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6724 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6725 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
6726
6727 if ((channels_needed & channels_exist) != channels_needed) {
6728 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
6729 return;
6730 }
6731
[email protected]a0b78dc2011-11-11 10:43:106732 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
6733 return;
6734 }
6735
[email protected]cadde4a2010-07-31 17:10:436736 CopyRealGLErrorsToWrapper();
[email protected]de26b3c2011-08-03 21:54:276737 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:036738 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:266739
[email protected]297ca1c2011-06-20 23:08:466740 if (info->IsAttachedToFramebuffer()) {
6741 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:516742 // TODO(gman): If textures tracked which framebuffers they were attached to
6743 // we could just mark those framebuffers as not complete.
6744 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:466745 }
6746
[email protected]9edc6b22010-12-23 02:00:266747 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:036748 GLint copyX = 0;
6749 GLint copyY = 0;
6750 GLint copyWidth = 0;
6751 GLint copyHeight = 0;
6752 Clip(x, width, size.width(), &copyX, &copyWidth);
6753 Clip(y, height, size.height(), &copyY, &copyHeight);
6754
6755 if (copyX != x ||
6756 copyY != y ||
6757 copyWidth != width ||
6758 copyHeight != height) {
6759 // some part was clipped so clear the texture.
[email protected]0d6bfdc2011-11-02 01:32:206760 if (!ClearLevel(
6761 info->service_id(), info->target(),
[email protected]4502e6492011-12-14 19:39:156762 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
6763 info->IsImmutable())) {
[email protected]0d6bfdc2011-11-02 01:32:206764 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexImage2D: dimensions too big");
[email protected]6e288612010-12-21 20:45:036765 return;
6766 }
[email protected]6e288612010-12-21 20:45:036767 if (copyHeight > 0 && copyWidth > 0) {
6768 GLint dx = copyX - x;
6769 GLint dy = copyY - y;
6770 GLint destX = dx;
6771 GLint destY = dy;
6772 glCopyTexSubImage2D(target, level,
6773 destX, destY, copyX, copyY,
6774 copyWidth, copyHeight);
6775 }
6776 } else {
6777 glCopyTexImage2D(target, level, internal_format,
6778 copyX, copyY, copyWidth, copyHeight, border);
6779 }
[email protected]1002c2d2011-06-28 22:39:046780 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436781 if (error == GL_NO_ERROR) {
6782 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416783 info, target, level, internal_format, width, height, 1,
[email protected]0d6bfdc2011-11-02 01:32:206784 border, internal_format, GL_UNSIGNED_BYTE, true);
[email protected]cadde4a2010-07-31 17:10:436785 }
6786}
6787
6788void GLES2DecoderImpl::DoCopyTexSubImage2D(
6789 GLenum target,
6790 GLint level,
6791 GLint xoffset,
6792 GLint yoffset,
6793 GLint x,
6794 GLint y,
6795 GLsizei width,
6796 GLsizei height) {
6797 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6798 if (!info) {
6799 SetGLError(GL_INVALID_OPERATION,
6800 "glCopyTexSubImage2D: unknown texture for target");
6801 return;
6802 }
6803 GLenum type = 0;
6804 GLenum format = 0;
6805 if (!info->GetLevelType(target, level, &type, &format) ||
6806 !info->ValidForTexture(
6807 target, level, xoffset, yoffset, width, height, format, type)) {
6808 SetGLError(GL_INVALID_VALUE,
6809 "glCopyTexSubImage2D: bad dimensions.");
6810 return;
6811 }
[email protected]9edc6b22010-12-23 02:00:266812
6813 // Check we have compatible formats.
6814 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6815 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6816 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
6817
6818 if ((channels_needed & channels_exist) != channels_needed) {
6819 SetGLError(
6820 GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
6821 return;
6822 }
6823
[email protected]a0b78dc2011-11-11 10:43:106824 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
6825 return;
6826 }
6827
[email protected]de26b3c2011-08-03 21:54:276828 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:036829 gfx::Size size = GetBoundReadFrameBufferSize();
6830 GLint copyX = 0;
6831 GLint copyY = 0;
6832 GLint copyWidth = 0;
6833 GLint copyHeight = 0;
6834 Clip(x, width, size.width(), &copyX, &copyWidth);
6835 Clip(y, height, size.height(), &copyY, &copyHeight);
[email protected]0d6bfdc2011-11-02 01:32:206836
6837 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
6838 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D: dimensions too big");
6839 return;
6840 }
6841
[email protected]6e288612010-12-21 20:45:036842 if (copyX != x ||
6843 copyY != y ||
6844 copyWidth != width ||
6845 copyHeight != height) {
[email protected]0d6bfdc2011-11-02 01:32:206846 // some part was clipped so clear the sub rect.
[email protected]6e288612010-12-21 20:45:036847 uint32 pixels_size = 0;
6848 if (!GLES2Util::ComputeImageDataSize(
6849 width, height, format, type, unpack_alignment_, &pixels_size)) {
6850 SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large");
6851 return;
6852 }
6853 scoped_array<char> zero(new char[pixels_size]);
6854 memset(zero.get(), 0, pixels_size);
6855 glTexSubImage2D(
6856 target, level, xoffset, yoffset, width, height,
6857 format, type, zero.get());
6858 }
[email protected]0d6bfdc2011-11-02 01:32:206859
[email protected]6e288612010-12-21 20:45:036860 if (copyHeight > 0 && copyWidth > 0) {
6861 GLint dx = copyX - x;
6862 GLint dy = copyY - y;
6863 GLint destX = xoffset + dx;
6864 GLint destY = yoffset + dy;
6865 glCopyTexSubImage2D(target, level,
6866 destX, destY, copyX, copyY,
6867 copyWidth, copyHeight);
6868 }
[email protected]cadde4a2010-07-31 17:10:436869}
6870
6871void GLES2DecoderImpl::DoTexSubImage2D(
6872 GLenum target,
6873 GLint level,
6874 GLint xoffset,
6875 GLint yoffset,
6876 GLsizei width,
6877 GLsizei height,
6878 GLenum format,
6879 GLenum type,
6880 const void * data) {
6881 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6882 if (!info) {
6883 SetGLError(GL_INVALID_OPERATION,
6884 "glTexSubImage2D: unknown texture for target");
6885 return;
6886 }
[email protected]df6cf1ad2011-01-29 01:20:526887 GLenum current_type = 0;
6888 GLenum internal_format = 0;
6889 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
6890 SetGLError(
6891 GL_INVALID_OPERATION,
6892 "glTexSubImage2D: level does not exist.");
6893 return;
6894 }
6895 if (format != internal_format) {
6896 SetGLError(GL_INVALID_OPERATION,
6897 "glTexSubImage2D: format does not match internal format.");
6898 return;
6899 }
6900 if (type != current_type) {
6901 SetGLError(GL_INVALID_OPERATION,
6902 "glTexSubImage2D: type does not match type of texture.");
6903 return;
6904 }
6905
[email protected]cadde4a2010-07-31 17:10:436906 if (!info->ValidForTexture(
6907 target, level, xoffset, yoffset, width, height, format, type)) {
6908 SetGLError(GL_INVALID_VALUE,
6909 "glTexSubImage2D: bad dimensions.");
6910 return;
6911 }
[email protected]473c01ccb2011-06-07 01:33:306912
[email protected]4502e6492011-12-14 19:39:156913 GLsizei tex_width = 0;
6914 GLsizei tex_height = 0;
6915 bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height);
6916 DCHECK(ok);
6917 if (xoffset != 0 || yoffset != 0 ||
6918 width != tex_width || height != tex_height) {
6919 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
6920 SetGLError(GL_OUT_OF_MEMORY, "glTexSubImage2D: dimensions too big");
[email protected]473c01ccb2011-06-07 01:33:306921 return;
6922 }
[email protected]4502e6492011-12-14 19:39:156923 glTexSubImage2D(
6924 target, level, xoffset, yoffset, width, height, format, type, data);
[email protected]0d6bfdc2011-11-02 01:32:206925 return;
6926 }
[email protected]4502e6492011-12-14 19:39:156927
6928 if (teximage2d_faster_than_texsubimage2d_ && !info->IsImmutable()) {
6929 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
6930 // same as internal_foramt. If that changes we'll need to look them up.
6931 WrappedTexImage2D(
6932 target, level, format, width, height, 0, format, type, data);
6933 } else {
6934 glTexSubImage2D(
6935 target, level, xoffset, yoffset, width, height, format, type, data);
6936 }
6937 texture_manager()->SetLevelCleared(info, target, level);
[email protected]cadde4a2010-07-31 17:10:436938}
6939
[email protected]b493ee622011-04-13 23:52:006940error::Error GLES2DecoderImpl::HandleTexSubImage2D(
6941 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]366ae242011-05-10 02:23:586942 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:006943 GLboolean internal = static_cast<GLboolean>(c.internal);
6944 if (internal == GL_TRUE && tex_image_2d_failed_)
6945 return error::kNoError;
6946
6947 GLenum target = static_cast<GLenum>(c.target);
6948 GLint level = static_cast<GLint>(c.level);
6949 GLint xoffset = static_cast<GLint>(c.xoffset);
6950 GLint yoffset = static_cast<GLint>(c.yoffset);
6951 GLsizei width = static_cast<GLsizei>(c.width);
6952 GLsizei height = static_cast<GLsizei>(c.height);
6953 GLenum format = static_cast<GLenum>(c.format);
6954 GLenum type = static_cast<GLenum>(c.type);
6955 uint32 data_size;
6956 if (!GLES2Util::ComputeImageDataSize(
6957 width, height, format, type, unpack_alignment_, &data_size)) {
6958 return error::kOutOfBounds;
6959 }
6960 const void* pixels = GetSharedMemoryAs<const void*>(
6961 c.pixels_shm_id, c.pixels_shm_offset, data_size);
6962 if (!validators_->texture_target.IsValid(target)) {
6963 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
6964 return error::kNoError;
6965 }
6966 if (width < 0) {
6967 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
6968 return error::kNoError;
6969 }
6970 if (height < 0) {
6971 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
6972 return error::kNoError;
6973 }
6974 if (!validators_->texture_format.IsValid(format)) {
6975 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
6976 return error::kNoError;
6977 }
6978 if (!validators_->pixel_type.IsValid(type)) {
6979 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
6980 return error::kNoError;
6981 }
6982 if (pixels == NULL) {
6983 return error::kOutOfBounds;
6984 }
6985 DoTexSubImage2D(
6986 target, level, xoffset, yoffset, width, height, format, type, pixels);
6987 return error::kNoError;
6988}
6989
6990error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
6991 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
6992 GLboolean internal = static_cast<GLboolean>(c.internal);
6993 if (internal == GL_TRUE && tex_image_2d_failed_)
6994 return error::kNoError;
6995
6996 GLenum target = static_cast<GLenum>(c.target);
6997 GLint level = static_cast<GLint>(c.level);
6998 GLint xoffset = static_cast<GLint>(c.xoffset);
6999 GLint yoffset = static_cast<GLint>(c.yoffset);
7000 GLsizei width = static_cast<GLsizei>(c.width);
7001 GLsizei height = static_cast<GLsizei>(c.height);
7002 GLenum format = static_cast<GLenum>(c.format);
7003 GLenum type = static_cast<GLenum>(c.type);
7004 uint32 data_size;
7005 if (!GLES2Util::ComputeImageDataSize(
7006 width, height, format, type, unpack_alignment_, &data_size)) {
7007 return error::kOutOfBounds;
7008 }
7009 const void* pixels = GetImmediateDataAs<const void*>(
7010 c, data_size, immediate_data_size);
7011 if (!validators_->texture_target.IsValid(target)) {
7012 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
7013 return error::kNoError;
7014 }
7015 if (width < 0) {
7016 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
7017 return error::kNoError;
7018 }
7019 if (height < 0) {
7020 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
7021 return error::kNoError;
7022 }
7023 if (!validators_->texture_format.IsValid(format)) {
7024 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
7025 return error::kNoError;
7026 }
7027 if (!validators_->pixel_type.IsValid(type)) {
7028 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
7029 return error::kNoError;
7030 }
7031 if (pixels == NULL) {
7032 return error::kOutOfBounds;
7033 }
7034 DoTexSubImage2D(
7035 target, level, xoffset, yoffset, width, height, format, type, pixels);
7036 return error::kNoError;
7037}
7038
[email protected]f7a64ee2010-02-01 22:24:147039error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:197040 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:367041 GLuint index = static_cast<GLuint>(c.index);
7042 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:257043 typedef gles2::GetVertexAttribPointerv::Result Result;
7044 Result* result = GetSharedMemoryAs<Result*>(
7045 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:367046 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:147047 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:367048 }
[email protected]07d0cc82010-02-17 04:51:407049 // Check that the client initialized the result.
7050 if (result->size != 0) {
7051 return error::kInvalidArguments;
7052 }
[email protected]9438b012010-06-15 22:55:057053 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:297054 SetGLError(GL_INVALID_ENUM,
7055 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:147056 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367057 }
[email protected]3916c97e2010-02-25 03:20:507058 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:297059 SetGLError(GL_INVALID_VALUE,
7060 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:147061 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367062 }
[email protected]0bfd9882010-02-05 23:02:257063 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:087064 *result->GetData() =
[email protected]3757a372012-01-19 05:20:447065 vertex_attrib_manager_->GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:147066 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327067}
7068
[email protected]f7b85372010-02-03 01:11:377069bool GLES2DecoderImpl::GetUniformSetup(
7070 GLuint program, GLint location,
7071 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:107072 error::Error* error, GLuint* service_id, void** result_pointer,
7073 GLenum* result_type) {
7074 DCHECK(error);
7075 DCHECK(service_id);
7076 DCHECK(result_pointer);
7077 DCHECK(result_type);
[email protected]f7b85372010-02-03 01:11:377078 *error = error::kNoError;
7079 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:257080 SizedResult<GLint>* result;
7081 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7082 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
7083 if (!result) {
[email protected]f7b85372010-02-03 01:11:377084 *error = error::kOutOfBounds;
7085 return false;
7086 }
[email protected]0bfd9882010-02-05 23:02:257087 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:377088 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:257089 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:587090 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7091 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:377092 if (!info) {
[email protected]ae51d192010-04-27 00:48:037093 return false;
7094 }
7095 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:377096 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:297097 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:377098 return false;
7099 }
[email protected]ae51d192010-04-27 00:48:037100 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:367101 GLint array_index = -1;
7102 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
7103 info->GetUniformInfoByLocation(location, &array_index);
7104 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:377105 // No such location.
[email protected]8eee29c2010-04-29 03:38:297106 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:377107 return false;
7108 }
[email protected]43c2f1f2011-03-25 18:35:367109 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:507110 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:377111 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:297112 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:377113 return false;
7114 }
[email protected]0bfd9882010-02-05 23:02:257115 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7116 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
7117 if (!result) {
[email protected]f7b85372010-02-03 01:11:377118 *error = error::kOutOfBounds;
7119 return false;
7120 }
[email protected]0bfd9882010-02-05 23:02:257121 result->size = size;
[email protected]939e7362010-05-13 20:49:107122 *result_type = type;
[email protected]f7b85372010-02-03 01:11:377123 return true;
7124}
7125
[email protected]f7a64ee2010-02-01 22:24:147126error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:197127 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:377128 GLuint program = c.program;
7129 GLint location = c.location;
7130 GLuint service_id;
[email protected]939e7362010-05-13 20:49:107131 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:377132 Error error;
[email protected]0bfd9882010-02-05 23:02:257133 void* result;
[email protected]f7b85372010-02-03 01:11:377134 if (GetUniformSetup(
7135 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:107136 &error, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:257137 glGetUniformiv(
7138 service_id, location,
7139 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:377140 }
7141 return error;
[email protected]96449d2c2009-11-25 00:01:327142}
7143
[email protected]f7a64ee2010-02-01 22:24:147144error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:197145 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:377146 GLuint program = c.program;
7147 GLint location = c.location;
7148 GLuint service_id;
7149 Error error;
[email protected]0bfd9882010-02-05 23:02:257150 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:107151 Result* result;
7152 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:377153 if (GetUniformSetup(
7154 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:107155 &error, &service_id, reinterpret_cast<void**>(&result), &result_type)) {
7156 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
7157 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
7158 GLsizei num_values = result->GetNumResults();
7159 scoped_array<GLint> temp(new GLint[num_values]);
7160 glGetUniformiv(service_id, location, temp.get());
7161 GLfloat* dst = result->GetData();
7162 for (GLsizei ii = 0; ii < num_values; ++ii) {
7163 dst[ii] = (temp[ii] != 0);
7164 }
7165 } else {
7166 glGetUniformfv(service_id, location, result->GetData());
7167 }
[email protected]f7b85372010-02-03 01:11:377168 }
7169 return error;
[email protected]96449d2c2009-11-25 00:01:327170}
7171
[email protected]f7a64ee2010-02-01 22:24:147172error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:197173 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:257174 GLenum shader_type = static_cast<GLenum>(c.shadertype);
7175 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
7176 typedef gles2::GetShaderPrecisionFormat::Result Result;
7177 Result* result = GetSharedMemoryAs<Result*>(
7178 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7179 if (!result) {
7180 return error::kOutOfBounds;
7181 }
[email protected]07d0cc82010-02-17 04:51:407182 // Check that the client initialized the result.
7183 if (result->success != 0) {
7184 return error::kInvalidArguments;
7185 }
[email protected]9438b012010-06-15 22:55:057186 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:297187 SetGLError(GL_INVALID_ENUM,
7188 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
7189 return error::kNoError;
7190 }
[email protected]9438b012010-06-15 22:55:057191 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:297192 SetGLError(GL_INVALID_ENUM,
7193 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
7194 return error::kNoError;
7195 }
7196
7197 result->success = 1; // true
7198 switch (precision_type) {
7199 case GL_LOW_INT:
7200 case GL_MEDIUM_INT:
7201 case GL_HIGH_INT:
7202 result->min_range = -31;
7203 result->max_range = 31;
7204 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:107205 break;
[email protected]8eee29c2010-04-29 03:38:297206 case GL_LOW_FLOAT:
7207 case GL_MEDIUM_FLOAT:
7208 case GL_HIGH_FLOAT:
7209 result->min_range = -62;
7210 result->max_range = 62;
7211 result->precision = -16;
7212 break;
7213 default:
7214 NOTREACHED();
7215 break;
[email protected]0bfd9882010-02-05 23:02:257216 }
[email protected]f7a64ee2010-02-01 22:24:147217 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327218}
7219
[email protected]f7a64ee2010-02-01 22:24:147220error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:197221 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:257222 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:587223 GLuint program = static_cast<GLuint>(c.program);
7224 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7225 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:037226 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257227 return error::kNoError;
7228 }
7229 typedef gles2::GetAttachedShaders::Result Result;
7230 uint32 max_count = Result::ComputeMaxResults(result_size);
7231 Result* result = GetSharedMemoryAs<Result*>(
7232 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
7233 if (!result) {
7234 return error::kOutOfBounds;
7235 }
[email protected]07d0cc82010-02-17 04:51:407236 // Check that the client initialized the result.
7237 if (result->size != 0) {
7238 return error::kInvalidArguments;
7239 }
[email protected]0bfd9882010-02-05 23:02:257240 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:037241 glGetAttachedShaders(
7242 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:257243 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:037244 if (!shader_manager()->GetClientId(result->GetData()[ii],
7245 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:257246 NOTREACHED();
7247 return error::kGenericError;
7248 }
7249 }
7250 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:147251 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327252}
7253
[email protected]f7a64ee2010-02-01 22:24:147254error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:197255 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:257256 GLuint program = c.program;
7257 GLuint index = c.index;
7258 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:257259 typedef gles2::GetActiveUniform::Result Result;
7260 Result* result = GetSharedMemoryAs<Result*>(
7261 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7262 if (!result) {
7263 return error::kOutOfBounds;
7264 }
[email protected]07d0cc82010-02-17 04:51:407265 // Check that the client initialized the result.
7266 if (result->success != 0) {
7267 return error::kInvalidArguments;
7268 }
[email protected]6b8cf1a2010-05-06 16:13:587269 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7270 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:037271 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257272 return error::kNoError;
7273 }
7274 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
7275 info->GetUniformInfo(index);
7276 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:297277 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:257278 return error::kNoError;
7279 }
7280 result->success = 1; // true.
7281 result->size = uniform_info->size;
7282 result->type = uniform_info->type;
7283 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297284 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:147285 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327286}
7287
[email protected]f7a64ee2010-02-01 22:24:147288error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:197289 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:257290 GLuint program = c.program;
7291 GLuint index = c.index;
7292 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:257293 typedef gles2::GetActiveAttrib::Result Result;
7294 Result* result = GetSharedMemoryAs<Result*>(
7295 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7296 if (!result) {
7297 return error::kOutOfBounds;
7298 }
[email protected]07d0cc82010-02-17 04:51:407299 // Check that the client initialized the result.
7300 if (result->success != 0) {
7301 return error::kInvalidArguments;
7302 }
[email protected]6b8cf1a2010-05-06 16:13:587303 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7304 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:037305 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257306 return error::kNoError;
7307 }
7308 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
7309 info->GetAttribInfo(index);
7310 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:297311 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:257312 return error::kNoError;
7313 }
7314 result->success = 1; // true.
7315 result->size = attrib_info->size;
7316 result->type = attrib_info->type;
7317 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297318 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:147319 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327320}
7321
[email protected]b273e432010-04-12 17:23:587322error::Error GLES2DecoderImpl::HandleShaderBinary(
7323 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
7324#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:297325 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:587326 return error::kNoError;
7327#else
7328 GLsizei n = static_cast<GLsizei>(c.n);
7329 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:297330 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:587331 return error::kNoError;
7332 }
7333 GLsizei length = static_cast<GLsizei>(c.length);
7334 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:297335 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:587336 return error::kNoError;
7337 }
7338 uint32 data_size;
7339 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
7340 return error::kOutOfBounds;
7341 }
7342 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
7343 c.shaders_shm_id, c.shaders_shm_offset, data_size);
7344 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
7345 const void* binary = GetSharedMemoryAs<const void*>(
7346 c.binary_shm_id, c.binary_shm_offset, length);
7347 if (shaders == NULL || binary == NULL) {
7348 return error::kOutOfBounds;
7349 }
7350 scoped_array<GLuint> service_ids(new GLuint[n]);
7351 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:037352 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
7353 if (!info) {
[email protected]8eee29c2010-04-29 03:38:297354 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:587355 return error::kNoError;
7356 }
[email protected]ae51d192010-04-27 00:48:037357 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:587358 }
7359 // TODO(gman): call glShaderBinary
7360 return error::kNoError;
7361#endif
7362}
7363
[email protected]6217d392010-03-25 22:08:357364error::Error GLES2DecoderImpl::HandleSwapBuffers(
7365 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:497366 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7367 int this_frame_number = frame_number_++;
[email protected]da151512011-11-11 23:27:387368 // TRACE_EVENT for gpu tests:
[email protected]529c6672012-01-04 02:18:267369 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers",
7370 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
7371 "width", (is_offscreen ? offscreen_size_.width() :
7372 surface_->GetSize().width()));
[email protected]64ace852011-05-19 21:49:497373 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
7374 "offscreen", is_offscreen,
7375 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:357376 // If offscreen then don't actually SwapBuffers to the display. Just copy
7377 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:497378 if (is_offscreen) {
[email protected]1fb8c482011-08-31 01:01:537379 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
7380 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
7381 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
7382 // fix this.
7383 if (needs_mac_nvidia_driver_workaround_) {
7384 offscreen_saved_frame_buffer_->Create();
7385 glFinish();
7386 }
7387
7388 // Allocate the offscreen saved color texture.
7389 DCHECK(offscreen_saved_color_format_);
7390 offscreen_saved_color_texture_->AllocateStorage(
7391 offscreen_size_, offscreen_saved_color_format_);
[email protected]1078f912011-12-23 13:12:147392 UpdateBackbufferMemoryAccounting();
[email protected]1fb8c482011-08-31 01:01:537393
7394 offscreen_saved_frame_buffer_->AttachRenderTexture(
7395 offscreen_saved_color_texture_.get());
7396 if (offscreen_saved_frame_buffer_->CheckStatus() !=
7397 GL_FRAMEBUFFER_COMPLETE) {
7398 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
7399 << "because offscreen saved FBO was incomplete.";
7400 return error::kLostContext;
7401 }
7402
[email protected]1fb8c482011-08-31 01:01:537403 // Clear the offscreen color texture.
7404 // TODO(piman): Is this still necessary?
7405 {
7406 ScopedFrameBufferBinder binder(this,
7407 offscreen_saved_frame_buffer_->id());
7408 glClearColor(0, 0, 0, 0);
7409 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
7410 glDisable(GL_SCISSOR_TEST);
7411 glClear(GL_COLOR_BUFFER_BIT);
7412 RestoreClearState();
7413 }
7414
7415 UpdateParentTextureInfo();
7416 }
7417
[email protected]6217d392010-03-25 22:08:357418 ScopedGLErrorSuppressor suppressor(this);
7419
[email protected]34ff8b0c2010-10-01 20:06:027420 if (IsOffscreenBufferMultisampled()) {
[email protected]51411e32012-01-19 20:21:137421 // For multisampled buffers, resolve the frame buffer.
[email protected]de26b3c2011-08-03 21:54:277422 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]89d6ed02011-04-20 00:23:237423 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:487424 } else {
[email protected]9a5afa432011-07-22 18:16:397425 if (surface_->IsOffscreen()) {
[email protected]51411e32012-01-19 20:21:137426 ScopedFrameBufferBinder binder(this,
7427 offscreen_target_frame_buffer_->id());
7428
[email protected]8a61d872012-01-20 12:43:567429 if (offscreen_target_buffer_preserved_) {
7430 // Copy the target frame buffer to the saved offscreen texture.
7431 offscreen_saved_color_texture_->Copy(
7432 offscreen_saved_color_texture_->size(),
7433 offscreen_saved_color_format_);
7434 } else {
7435 // Flip the textures in the parent context via the texture manager.
7436 if (!!offscreen_saved_color_texture_info_.get())
7437 offscreen_saved_color_texture_info_->
7438 SetServiceId(offscreen_target_color_texture_->id());
7439
7440 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
7441 offscreen_target_frame_buffer_->AttachRenderTexture(
7442 offscreen_target_color_texture_.get());
7443 }
[email protected]b86b14982010-10-11 18:45:487444
[email protected]a3ded6d2010-10-19 06:44:397445 // Ensure the side effects of the copy are visible to the parent
7446 // context. There is no need to do this for ANGLE because it uses a
7447 // single D3D device for all contexts.
[email protected]b86b14982010-10-11 18:45:487448 if (!IsAngle())
7449 glFlush();
7450 }
[email protected]89d6ed02011-04-20 00:23:237451 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:397452 }
[email protected]6217d392010-03-25 22:08:357453 } else {
[email protected]64ace852011-05-19 21:49:497454 TRACE_EVENT1("gpu", "GLContext::SwapBuffers", "frame", this_frame_number);
[email protected]f62a5ab2011-05-23 20:34:157455 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:017456 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:027457 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:017458 }
[email protected]6217d392010-03-25 22:08:357459 }
7460
[email protected]89d6ed02011-04-20 00:23:237461 return error::kNoError;
[email protected]6217d392010-03-25 22:08:357462}
7463
[email protected]d4239852011-08-12 04:51:227464error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
7465 uint32 immediate_data_size, const gles2::EnableFeatureCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:187466 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287467 if (!bucket || bucket->size() == 0) {
7468 return error::kInvalidArguments;
7469 }
[email protected]d4239852011-08-12 04:51:227470 typedef gles2::EnableFeatureCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:187471 Result* result = GetSharedMemoryAs<Result*>(
7472 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7473 if (!result) {
7474 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:107475 }
[email protected]b1d2dcb2010-05-17 19:24:187476 // Check that the client initialized the result.
7477 if (*result != 0) {
7478 return error::kInvalidArguments;
7479 }
7480 std::string feature_str;
7481 if (!bucket->GetAsString(&feature_str)) {
7482 return error::kInvalidArguments;
7483 }
7484
7485 // TODO(gman): make this some kind of table to function pointer thingy.
[email protected]d4239852011-08-12 04:51:227486 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
[email protected]b1d2dcb2010-05-17 19:24:187487 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]d4239852011-08-12 04:51:227488 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
[email protected]8fbedc02010-11-18 18:43:407489 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
7490 // TODO(gman): decide how to remove the need for this const_cast.
7491 // I could make validators_ non const but that seems bad as this is the only
7492 // place it is needed. I could make some special friend class of validators
7493 // just to allow this to set them. That seems silly. I could refactor this
7494 // code to use the extension mechanism or the initialization attributes to
7495 // turn this feature on. Given that the only real point of this is to make
7496 // the conformance tests pass and given that there is lots of real work that
7497 // needs to be done it seems like refactoring for one to one of those
7498 // methods is a very low priority.
7499 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]f0d74742011-10-03 16:31:047500 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
7501 force_webgl_glsl_validation_ = true;
7502 InitializeShaderTranslator();
[email protected]b1d2dcb2010-05-17 19:24:187503 } else {
7504 return error::kNoError;
7505 }
7506
7507 *result = 1; // true.
7508 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:107509}
7510
[email protected]c2f8c8402010-12-06 18:07:247511error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
7512 uint32 immediate_data_size,
7513 const gles2::GetRequestableExtensionsCHROMIUM& c) {
7514 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]80eb6b52012-01-19 00:14:417515 FeatureInfo::Ref info(new FeatureInfo());
[email protected]e82fb792011-09-22 00:33:297516 info->Initialize(disallowed_features_, NULL);
[email protected]c2f8c8402010-12-06 18:07:247517 bucket->SetFromString(info->extensions().c_str());
7518 return error::kNoError;
7519}
7520
7521error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
7522 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
7523 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287524 if (!bucket || bucket->size() == 0) {
7525 return error::kInvalidArguments;
7526 }
[email protected]c2f8c8402010-12-06 18:07:247527 std::string feature_str;
7528 if (!bucket->GetAsString(&feature_str)) {
7529 return error::kInvalidArguments;
7530 }
7531
7532 bool std_derivatives_enabled =
7533 feature_info_->feature_flags().oes_standard_derivatives;
7534 bool webglsl_enabled =
7535 feature_info_->feature_flags().chromium_webglsl;
7536
7537 feature_info_->AddFeatures(feature_str.c_str());
7538
[email protected]f0d74742011-10-03 16:31:047539 bool initialization_required = false;
7540 if (force_webgl_glsl_validation_ && !derivatives_explicitly_enabled_) {
7541 size_t derivatives_offset = feature_str.find(kOESDerivativeExtension);
7542 if (std::string::npos != derivatives_offset) {
7543 derivatives_explicitly_enabled_ = true;
7544 initialization_required = true;
7545 }
7546 }
7547
[email protected]c2f8c8402010-12-06 18:07:247548 // If we just enabled a feature which affects the shader translator,
7549 // we may need to re-initialize it.
7550 if (std_derivatives_enabled !=
7551 feature_info_->feature_flags().oes_standard_derivatives ||
7552 webglsl_enabled !=
[email protected]f0d74742011-10-03 16:31:047553 feature_info_->feature_flags().chromium_webglsl ||
7554 initialization_required) {
[email protected]c2f8c8402010-12-06 18:07:247555 InitializeShaderTranslator();
7556 }
7557
[email protected]302ce6d2011-07-07 23:28:117558 UpdateCapabilities();
7559
[email protected]c2f8c8402010-12-06 18:07:247560 return error::kNoError;
7561}
7562
[email protected]372e0412011-06-28 16:08:567563error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
7564 uint32 immediate_data_size, const gles2::GetMultipleIntegervCHROMIUM& c) {
7565 GLuint count = c.count;
7566 uint32 pnames_size;
7567 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
7568 return error::kOutOfBounds;
7569 }
7570 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
7571 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
7572 if (pnames == NULL) {
7573 return error::kOutOfBounds;
7574 }
7575
7576 // We have to copy them since we use them twice so the client
7577 // can't change them between the time we validate them and the time we use
7578 // them.
7579 scoped_array<GLenum> enums(new GLenum[count]);
7580 memcpy(enums.get(), pnames, pnames_size);
7581
7582 // Count up the space needed for the result.
7583 uint32 num_results = 0;
7584 for (GLuint ii = 0; ii < count; ++ii) {
7585 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
7586 if (num == 0) {
7587 SetGLError(GL_INVALID_ENUM,
7588 "glGetMulitpleCHROMIUM: pname GL_INVALID_ENUM");
7589 return error::kNoError;
7590 }
7591 // Num will never be more than 4.
7592 DCHECK_LE(num, 4u);
7593 if (!SafeAdd(num_results, num, &num_results)) {
7594 return error::kOutOfBounds;
7595 }
7596 }
7597
7598 uint32 result_size = 0;
7599 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
7600 return error::kOutOfBounds;
7601 }
7602
7603 if (result_size != static_cast<uint32>(c.size)) {
7604 SetGLError(GL_INVALID_VALUE,
7605 "glGetMulitpleCHROMIUM: bad size GL_INVALID_VALUE");
7606 return error::kNoError;
7607 }
7608
7609 GLint* results = GetSharedMemoryAs<GLint*>(
7610 c.results_shm_id, c.results_shm_offset, result_size);
7611 if (results == NULL) {
7612 return error::kOutOfBounds;
7613 }
7614
7615 // Check the results have been cleared in case the context was lost.
7616 for (uint32 ii = 0; ii < num_results; ++ii) {
7617 if (results[ii]) {
7618 return error::kInvalidArguments;
7619 }
7620 }
7621
7622 // Get each result.
7623 GLint* start = results;
7624 for (GLuint ii = 0; ii < count; ++ii) {
7625 GLsizei num_written = 0;
7626 if (!GetHelper(enums[ii], results, &num_written)) {
7627 glGetIntegerv(enums[ii], results);
7628 }
7629 results += num_written;
7630 }
7631
7632 // Just to verify. Should this be a DCHECK?
7633 if (static_cast<uint32>(results - start) != num_results) {
7634 return error::kOutOfBounds;
7635 }
7636
7637 return error::kNoError;
7638}
7639
[email protected]2318d342011-07-11 22:27:427640error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
7641 uint32 immediate_data_size, const gles2::GetProgramInfoCHROMIUM& c) {
7642 GLuint program = static_cast<GLuint>(c.program);
7643 uint32 bucket_id = c.bucket_id;
7644 Bucket* bucket = CreateBucket(bucket_id);
7645 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
7646 ProgramManager::ProgramInfo* info = NULL;
[email protected]9a14ae612011-08-08 17:51:467647 info = GetProgramInfo(program);
7648 if (!info || !info->IsValid()) {
7649 return error::kNoError;
[email protected]2318d342011-07-11 22:27:427650 }
7651 info->GetProgramInfo(bucket);
7652 return error::kNoError;
7653}
7654
[email protected]38d139d2011-07-14 00:38:437655error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
7656 switch (reset_status_) {
7657 case GL_NO_ERROR:
7658 // TODO(kbr): improve the precision of the error code in this case.
7659 // Consider delegating to context for error code if MakeCurrent fails.
7660 return error::kUnknown;
7661 case GL_GUILTY_CONTEXT_RESET_ARB:
7662 return error::kGuilty;
7663 case GL_INNOCENT_CONTEXT_RESET_ARB:
7664 return error::kInnocent;
7665 case GL_UNKNOWN_CONTEXT_RESET_ARB:
7666 return error::kUnknown;
7667 }
7668
7669 NOTREACHED();
7670 return error::kUnknown;
7671}
7672
7673bool GLES2DecoderImpl::WasContextLost() {
7674 if (context_->WasAllocatedUsingARBRobustness() && has_arb_robustness_) {
7675 GLenum status = glGetGraphicsResetStatusARB();
7676 if (status != GL_NO_ERROR) {
7677 // The graphics card was reset. Signal a lost context to the application.
7678 reset_status_ = status;
7679 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
7680 << " context lost via ARB_robustness. Reset status = 0x"
7681 << std::hex << status << std::dec;
7682 return true;
7683 }
7684 }
7685 return false;
7686}
7687
[email protected]b0af4f52011-09-28 22:04:427688error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
7689 uint32 immediate_data_size,
7690 const gles2::CreateStreamTextureCHROMIUM& c) {
7691 if (!feature_info_->feature_flags().chromium_stream_texture) {
7692 SetGLError(GL_INVALID_OPERATION,
7693 "glOpenStreamTextureCHROMIUM: "
7694 "not supported.");
7695 return error::kNoError;
7696 }
7697
7698 uint32 client_id = c.client_id;
7699 typedef gles2::CreateStreamTextureCHROMIUM::Result Result;
7700 Result* result = GetSharedMemoryAs<Result*>(
7701 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7702
[email protected]e5081262012-01-05 23:09:037703 if (!result)
7704 return error::kOutOfBounds;
[email protected]b0af4f52011-09-28 22:04:427705 *result = GL_ZERO;
7706 TextureManager::TextureInfo* info =
7707 texture_manager()->GetTextureInfo(client_id);
7708 if (!info) {
7709 SetGLError(GL_INVALID_VALUE,
7710 "glCreateStreamTextureCHROMIUM: "
7711 "bad texture id.");
7712 return error::kNoError;
7713 }
7714
7715 if (info->IsStreamTexture()) {
7716 SetGLError(GL_INVALID_OPERATION,
7717 "glCreateStreamTextureCHROMIUM: "
7718 "is already a stream texture.");
7719 return error::kNoError;
7720 }
7721
7722 if (info->target() && info->target() != GL_TEXTURE_EXTERNAL_OES) {
7723 SetGLError(GL_INVALID_OPERATION,
7724 "glCreateStreamTextureCHROMIUM: "
7725 "is already bound to incompatible target.");
7726 return error::kNoError;
7727 }
7728
7729 if (!stream_texture_manager_)
7730 return error::kInvalidArguments;
7731
7732 GLuint object_id = stream_texture_manager_->CreateStreamTexture(
7733 info->service_id(), client_id);
7734
7735 if (object_id) {
7736 info->SetStreamTexture(true);
7737 } else {
7738 SetGLError(GL_OUT_OF_MEMORY,
7739 "glCreateStreamTextureCHROMIUM: "
7740 "failed to create platform texture.");
7741 }
7742
7743 *result = object_id;
7744 return error::kNoError;
7745}
7746
7747error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
7748 uint32 immediate_data_size,
7749 const gles2::DestroyStreamTextureCHROMIUM& c) {
7750 GLuint client_id = c.texture;
7751 TextureManager::TextureInfo* info =
7752 texture_manager()->GetTextureInfo(client_id);
7753 if (info && info->IsStreamTexture()) {
7754 if (!stream_texture_manager_)
7755 return error::kInvalidArguments;
7756
7757 stream_texture_manager_->DestroyStreamTexture(info->service_id());
7758 info->SetStreamTexture(false);
[email protected]80eb6b52012-01-19 00:14:417759 texture_manager()->SetInfoTarget(info, 0);
[email protected]b0af4f52011-09-28 22:04:427760 } else {
7761 SetGLError(GL_INVALID_VALUE,
7762 "glDestroyStreamTextureCHROMIUM: bad texture id.");
7763 }
7764
7765 return error::kNoError;
7766}
7767
[email protected]e51bdf32011-11-23 22:21:467768#if defined(OS_MACOSX)
7769void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
7770 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
7771 texture_id);
7772 if (it != texture_to_io_surface_map_.end()) {
7773 // Found a previous IOSurface bound to this texture; release it.
7774 CFTypeRef surface = it->second;
7775 CFRelease(surface);
7776 texture_to_io_surface_map_.erase(it);
7777 }
7778}
7779#endif
7780
7781void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
7782 GLenum target, GLsizei width, GLsizei height,
7783 GLuint io_surface_id, GLuint plane) {
7784#if defined(OS_MACOSX)
7785 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
7786 SetGLError(GL_INVALID_OPERATION,
7787 "glTexImageIOSurface2DCHROMIUM: only supported on desktop GL.");
7788 return;
7789 }
7790
7791 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
7792 if (!surface_support) {
7793 SetGLError(GL_INVALID_OPERATION,
7794 "glTexImageIOSurface2DCHROMIUM: only supported on 10.6.");
7795 return;
7796 }
7797
7798 if (target != GL_TEXTURE_RECTANGLE_ARB) {
7799 // This might be supported in the future, and if we could require
7800 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
7801 // could delete a lot of code. For now, perform strict validation so we
7802 // know what's going on.
7803 SetGLError(
7804 GL_INVALID_OPERATION,
7805 "glTexImageIOSurface2DCHROMIUM: requires TEXTURE_RECTANGLE_ARB target");
7806 return;
7807 }
7808
7809 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7810 if (!info) {
7811 SetGLError(GL_INVALID_OPERATION,
7812 "glTexImageIOSurface2DCHROMIUM: no rectangle texture bound");
7813 return;
7814 }
7815 if (info == texture_manager()->GetDefaultTextureInfo(target)) {
7816 // Maybe this is conceptually valid, but disallow it to avoid accidents.
7817 SetGLError(GL_INVALID_OPERATION,
7818 "glTexImageIOSurface2DCHROMIUM: can't bind default texture");
7819 return;
7820 }
7821
7822 // Look up the new IOSurface. Note that because of asynchrony
7823 // between processes this might fail; during live resizing the
7824 // plugin process might allocate and release an IOSurface before
7825 // this process gets a chance to look it up. Hold on to any old
7826 // IOSurface in this case.
7827 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
7828 if (!surface) {
7829 SetGLError(GL_INVALID_OPERATION,
7830 "glTexImageIOSurface2DCHROMIUM: no IOSurface with the given ID");
7831 return;
7832 }
7833
7834 // Release any IOSurface previously bound to this texture.
7835 ReleaseIOSurfaceForTexture(info->service_id());
7836
7837 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
7838 texture_to_io_surface_map_.insert(
7839 std::make_pair(info->service_id(), surface));
7840
7841 CGLContextObj context =
7842 static_cast<CGLContextObj>(context_->GetHandle());
7843
7844 CGLError err = surface_support->CGLTexImageIOSurface2D(
7845 context,
7846 target,
7847 GL_RGBA,
7848 width,
7849 height,
7850 GL_BGRA,
7851 GL_UNSIGNED_INT_8_8_8_8_REV,
7852 surface,
7853 plane);
7854
7855 if (err != kCGLNoError) {
7856 SetGLError(
7857 GL_INVALID_OPERATION,
7858 "glTexImageIOSurface2DCHROMIUM: error in CGLTexImageIOSurface2D");
7859 return;
7860 }
7861
7862 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:417863 info, target, 0, GL_RGBA, width, height, 1, 0,
[email protected]e51bdf32011-11-23 22:21:467864 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
7865
7866#else
7867 SetGLError(GL_INVALID_OPERATION,
7868 "glTexImageIOSurface2DCHROMIUM: not supported.");
7869#endif
7870}
7871
[email protected]97dc7cbe2011-12-06 17:26:177872static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
7873 switch (internalformat) {
7874 case GL_RGB565:
7875 return GL_RGB;
7876 case GL_RGBA4:
7877 return GL_RGBA;
7878 case GL_RGB5_A1:
7879 return GL_RGBA;
7880 case GL_RGB8_OES:
7881 return GL_RGB;
7882 case GL_RGBA8_OES:
7883 return GL_RGBA;
7884 case GL_LUMINANCE8_ALPHA8_EXT:
7885 return GL_LUMINANCE_ALPHA;
7886 case GL_LUMINANCE8_EXT:
7887 return GL_LUMINANCE;
7888 case GL_ALPHA8_EXT:
7889 return GL_ALPHA;
7890 case GL_RGBA32F_EXT:
7891 return GL_RGBA;
7892 case GL_RGB32F_EXT:
7893 return GL_RGB;
7894 case GL_ALPHA32F_EXT:
7895 return GL_ALPHA;
7896 case GL_LUMINANCE32F_EXT:
7897 return GL_LUMINANCE;
7898 case GL_LUMINANCE_ALPHA32F_EXT:
7899 return GL_LUMINANCE_ALPHA;
7900 case GL_RGBA16F_EXT:
7901 return GL_RGBA;
7902 case GL_RGB16F_EXT:
7903 return GL_RGB;
7904 case GL_ALPHA16F_EXT:
7905 return GL_ALPHA;
7906 case GL_LUMINANCE16F_EXT:
7907 return GL_LUMINANCE;
7908 case GL_LUMINANCE_ALPHA16F_EXT:
7909 return GL_LUMINANCE_ALPHA;
7910 case GL_BGRA8_EXT:
7911 return GL_BGRA_EXT;
7912 default:
7913 return GL_NONE;
7914 }
7915}
7916
7917static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
7918 switch (internalformat) {
7919 case GL_RGB565:
7920 return GL_UNSIGNED_SHORT_5_6_5;
7921 case GL_RGBA4:
7922 return GL_UNSIGNED_SHORT_4_4_4_4;
7923 case GL_RGB5_A1:
7924 return GL_UNSIGNED_SHORT_5_5_5_1;
7925 case GL_RGB8_OES:
7926 return GL_UNSIGNED_BYTE;
7927 case GL_RGBA8_OES:
7928 return GL_UNSIGNED_BYTE;
7929 case GL_LUMINANCE8_ALPHA8_EXT:
7930 return GL_UNSIGNED_BYTE;
7931 case GL_LUMINANCE8_EXT:
7932 return GL_UNSIGNED_BYTE;
7933 case GL_ALPHA8_EXT:
7934 return GL_UNSIGNED_BYTE;
7935 case GL_RGBA32F_EXT:
7936 return GL_FLOAT;
7937 case GL_RGB32F_EXT:
7938 return GL_FLOAT;
7939 case GL_ALPHA32F_EXT:
7940 return GL_FLOAT;
7941 case GL_LUMINANCE32F_EXT:
7942 return GL_FLOAT;
7943 case GL_LUMINANCE_ALPHA32F_EXT:
7944 return GL_FLOAT;
7945 case GL_RGBA16F_EXT:
7946 return GL_HALF_FLOAT_OES;
7947 case GL_RGB16F_EXT:
7948 return GL_HALF_FLOAT_OES;
7949 case GL_ALPHA16F_EXT:
7950 return GL_HALF_FLOAT_OES;
7951 case GL_LUMINANCE16F_EXT:
7952 return GL_HALF_FLOAT_OES;
7953 case GL_LUMINANCE_ALPHA16F_EXT:
7954 return GL_HALF_FLOAT_OES;
7955 case GL_BGRA8_EXT:
7956 return GL_UNSIGNED_BYTE;
7957 default:
7958 return GL_NONE;
7959 }
7960}
7961
7962void GLES2DecoderImpl::DoTexStorage2DEXT(
7963 GLenum target,
7964 GLint levels,
7965 GLenum internal_format,
7966 GLsizei width,
7967 GLsizei height) {
[email protected]80eb6b52012-01-19 00:14:417968 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
[email protected]97dc7cbe2011-12-06 17:26:177969 TextureManager::ComputeMipMapCount(width, height, 1) < levels) {
7970 SetGLError(GL_INVALID_VALUE, "glTexStorage2DEXT: dimensions out of range");
7971 return;
7972 }
7973 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7974 if (!info) {
7975 SetGLError(GL_INVALID_OPERATION,
7976 "glTexStorage2DEXT: unknown texture for target");
7977 return;
7978 }
7979 if (info->IsAttachedToFramebuffer()) {
7980 state_dirty_ = true;
7981 }
7982 if (info->IsImmutable()) {
7983 SetGLError(GL_INVALID_OPERATION,
7984 "glTexStorage2DEXT: texture is immutable");
7985 return;
7986 }
7987 CopyRealGLErrorsToWrapper();
[email protected]f0e6a34f2012-01-04 20:53:407988 glTexStorage2DEXT(target, levels, GetTexInternalFormat(internal_format),
7989 width, height);
[email protected]97dc7cbe2011-12-06 17:26:177990 GLenum error = PeekGLError();
7991 if (error == GL_NO_ERROR) {
7992 GLenum format = ExtractFormatFromStorageFormat(internal_format);
7993 GLenum type = ExtractTypeFromStorageFormat(internal_format);
[email protected]4502e6492011-12-14 19:39:157994 GLsizei level_width = width;
7995 GLsizei level_height = height;
7996 for (int ii = 0; ii < levels; ++ii) {
7997 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:417998 info, target, 0, format, level_width, level_height, 1, 0, format,
7999 type, false);
[email protected]4502e6492011-12-14 19:39:158000 level_width = std::max(1, level_width >> 1);
8001 level_height = std::max(1, level_height >> 1);
8002 }
[email protected]97dc7cbe2011-12-06 17:26:178003 info->SetImmutable(true);
8004 }
[email protected]97dc7cbe2011-12-06 17:26:178005}
[email protected]e51bdf32011-11-23 22:21:468006
[email protected]96449d2c2009-11-25 00:01:328007// Include the auto-generated part of this file. We split this because it means
8008// we can easily edit the non-auto generated parts right here in this file
8009// instead of having to edit some template or the code generator.
8010#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
8011
8012} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:258013} // namespace gpu