blob: 89d608bfa31b44c7a8b73864360cd5abd8695aa9 [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_;
415};
416
417ContextCreationAttribParser::ContextCreationAttribParser()
418 : alpha_size_(-1),
419 blue_size_(-1),
420 green_size_(-1),
421 red_size_(-1),
422 depth_size_(-1),
423 stencil_size_(-1),
424 samples_(-1),
425 sample_buffers_(-1) {
426}
427
428bool ContextCreationAttribParser::Parse(const std::vector<int32>& attribs) {
429 // From <EGL/egl.h>.
430 const int32 EGL_ALPHA_SIZE = 0x3021;
431 const int32 EGL_BLUE_SIZE = 0x3022;
432 const int32 EGL_GREEN_SIZE = 0x3023;
433 const int32 EGL_RED_SIZE = 0x3024;
434 const int32 EGL_DEPTH_SIZE = 0x3025;
435 const int32 EGL_STENCIL_SIZE = 0x3026;
436 const int32 EGL_SAMPLES = 0x3031;
437 const int32 EGL_SAMPLE_BUFFERS = 0x3032;
438 const int32 EGL_NONE = 0x3038;
439
440 for (size_t i = 0; i < attribs.size(); i += 2) {
441 const int32 attrib = attribs[i];
442 if (i + 1 >= attribs.size()) {
443 if (attrib == EGL_NONE)
444 return true;
445
446 DLOG(ERROR) << "Missing value after context creation attribute: "
447 << attrib;
448 return false;
449 }
450
451 const int32 value = attribs[i+1];
452 switch (attrib) {
453 case EGL_ALPHA_SIZE:
454 alpha_size_ = value;
455 break;
456 case EGL_BLUE_SIZE:
457 blue_size_ = value;
458 break;
459 case EGL_GREEN_SIZE:
460 green_size_ = value;
461 break;
462 case EGL_RED_SIZE:
463 red_size_ = value;
464 break;
465 case EGL_DEPTH_SIZE:
466 depth_size_ = value;
467 break;
468 case EGL_STENCIL_SIZE:
469 stencil_size_ = value;
470 break;
471 case EGL_SAMPLES:
472 samples_ = value;
473 break;
474 case EGL_SAMPLE_BUFFERS:
475 sample_buffers_ = value;
476 break;
477 case EGL_NONE:
478 // Terminate list, even if more attributes.
479 return true;
480 default:
481 DLOG(ERROR) << "Invalid context creation attribute: " << attrib;
482 return false;
483 }
484 }
485
486 return true;
487}
488
[email protected]43f28f832010-02-03 02:28:48489// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32490
[email protected]ddb1e5a2010-12-13 20:10:45491bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
492 uint32* service_texture_id) {
493 return false;
494}
495
[email protected]a3ded6d2010-10-19 06:44:39496GLES2Decoder::GLES2Decoder()
[email protected]e844ae22012-01-14 03:36:26497 : debug_(false),
498 log_commands_(false) {
[email protected]96449d2c2009-11-25 00:01:32499}
500
[email protected]3916c97e2010-02-25 03:20:50501GLES2Decoder::~GLES2Decoder() {
502}
503
[email protected]f39f4b3f2010-05-12 17:04:08504// This class implements GLES2Decoder so we don't have to expose all the GLES2
505// cmd stuff to outside this class.
506class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
507 public GLES2Decoder {
508 public:
[email protected]aa7666122011-09-02 19:45:52509 explicit GLES2DecoderImpl(ContextGroup* group);
[email protected]80eb6b52012-01-19 00:14:41510 ~GLES2DecoderImpl();
[email protected]f39f4b3f2010-05-12 17:04:08511
[email protected]96449d2c2009-11-25 00:01:32512 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14513 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50514 unsigned int arg_count,
515 const void* args);
[email protected]96449d2c2009-11-25 00:01:32516
517 // Overridden from AsyncAPIInterface.
518 virtual const char* GetCommandName(unsigned int command_id) const;
519
520 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38521 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
522 const scoped_refptr<gfx::GLContext>& context,
[email protected]6217d392010-03-25 22:08:35523 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:29524 const DisallowedFeatures& disallowed_features,
[email protected]a3ded6d2010-10-19 06:44:39525 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:24526 const std::vector<int32>& attribs);
[email protected]96449d2c2009-11-25 00:01:32527 virtual void Destroy();
[email protected]3c644d82011-06-20 19:58:24528 virtual bool SetParent(GLES2Decoder* parent_decoder,
529 uint32 parent_texture_id);
[email protected]799b4b22011-08-22 17:09:59530 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]9a5afa432011-07-22 18:16:39531 void UpdateParentTextureInfo();
[email protected]eb54a562010-01-20 21:55:18532 virtual bool MakeCurrent();
[email protected]a96a6022011-11-04 00:58:12533 virtual void ReleaseCurrent();
[email protected]56ac89b2010-03-17 21:16:55534 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30535 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]f62a5ab2011-05-23 20:34:15536 virtual gfx::GLSurface* GetGLSurface() { return surface_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39537 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]43f28f832010-02-03 02:28:48538
[email protected]0d6bfdc2011-11-02 01:32:20539 virtual void SetGLError(GLenum error, const char* msg);
[email protected]9d37f062011-11-22 01:24:52540 virtual void SetResizeCallback(
541 const base::Callback<void(gfx::Size)>& callback);
[email protected]22f320a2011-08-30 01:17:00542
[email protected]6b6e7ee2011-12-13 08:04:52543 virtual void SetMsgCallback(const MsgCallback& callback);
[email protected]22f320a2011-08-30 01:17:00544
[email protected]b0af4f52011-09-28 22:04:42545 virtual void SetStreamTextureManager(StreamTextureManager* manager);
[email protected]1318e922010-09-17 22:03:16546 virtual bool GetServiceTextureId(uint32 client_texture_id,
547 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48548
[email protected]8e3e0662010-08-23 18:46:30549 // Restores the current state to the user's settings.
550 void RestoreCurrentFramebufferBindings();
551 void RestoreCurrentRenderbufferBindings();
552 void RestoreCurrentTexture2DBindings();
553
[email protected]297ca1c2011-06-20 23:08:46554 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
555 void ApplyDirtyState();
556
557 // These check the state of the currently bound framebuffer or the
558 // backbuffer if no framebuffer is bound.
559 bool BoundFramebufferHasColorAttachmentWithAlpha();
560 bool BoundFramebufferHasDepthAttachment();
561 bool BoundFramebufferHasStencilAttachment();
562
[email protected]38d139d2011-07-14 00:38:43563 virtual error::ContextLostReason GetContextLostReason();
564
[email protected]96449d2c2009-11-25 00:01:32565 private:
[email protected]6217d392010-03-25 22:08:35566 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02567 friend class ScopedResolvedFrameBufferBinder;
[email protected]1078f912011-12-23 13:12:14568 friend class Texture;
[email protected]6217d392010-03-25 22:08:35569 friend class RenderBuffer;
570 friend class FrameBuffer;
571
[email protected]3916c97e2010-02-25 03:20:50572 // State associated with each texture unit.
573 struct TextureUnit {
574 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
575
576 // The last target that was bound to this texture unit.
577 GLenum bind_target;
578
579 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
580 TextureManager::TextureInfo::Ref bound_texture_2d;
581
582 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
583 // glBindTexture
584 TextureManager::TextureInfo::Ref bound_texture_cube_map;
[email protected]61eeb33f2011-07-26 15:30:31585
586 // texture currently bound to this unit's GL_TEXTURE_EXTERNAL_OES with
587 // glBindTexture
588 TextureManager::TextureInfo::Ref bound_texture_external_oes;
589
[email protected]e51bdf32011-11-23 22:21:46590 // texture currently bound to this unit's GL_TEXTURE_RECTANGLE_ARB with
591 // glBindTexture
592 TextureManager::TextureInfo::Ref bound_texture_rectangle_arb;
593
[email protected]61eeb33f2011-07-26 15:30:31594 TextureManager::TextureInfo::Ref GetInfoForSamplerType(GLenum type) {
595 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:46596 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
597 switch (type) {
598 case GL_SAMPLER_2D:
599 return bound_texture_2d;
600 case GL_SAMPLER_CUBE:
601 return bound_texture_cube_map;
602 case GL_SAMPLER_EXTERNAL_OES:
603 return bound_texture_external_oes;
604 case GL_SAMPLER_2D_RECT_ARB:
605 return bound_texture_rectangle_arb;
606 }
607
608 NOTREACHED();
609 return NULL;
[email protected]61eeb33f2011-07-26 15:30:31610 }
[email protected]a0b78dc2011-11-11 10:43:10611
612 void Unbind(TextureManager::TextureInfo* texture) {
613 if (bound_texture_2d == texture) {
614 bound_texture_2d = NULL;
615 }
616 if (bound_texture_cube_map == texture) {
617 bound_texture_cube_map = NULL;
618 }
619 if (bound_texture_external_oes == texture) {
620 bound_texture_external_oes = NULL;
621 }
622 }
[email protected]3916c97e2010-02-25 03:20:50623 };
624
[email protected]c2f8c8402010-12-06 18:07:24625 // Initialize or re-initialize the shader translator.
626 bool InitializeShaderTranslator();
627
[email protected]302ce6d2011-07-07 23:28:11628 void UpdateCapabilities();
629
[email protected]ae51d192010-04-27 00:48:03630 // Helpers for the glGen and glDelete functions.
631 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
632 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
633 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
634 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
635 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
636 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
637 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
638 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47639
[email protected]3916c97e2010-02-25 03:20:50640 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50641 BufferManager* buffer_manager() {
642 return group_->buffer_manager();
643 }
644
[email protected]a25fa872010-03-25 02:57:58645 RenderbufferManager* renderbuffer_manager() {
646 return group_->renderbuffer_manager();
647 }
648
649 FramebufferManager* framebuffer_manager() {
650 return group_->framebuffer_manager();
651 }
652
[email protected]3916c97e2010-02-25 03:20:50653 ProgramManager* program_manager() {
654 return group_->program_manager();
655 }
656
657 ShaderManager* shader_manager() {
658 return group_->shader_manager();
659 }
660
661 TextureManager* texture_manager() {
662 return group_->texture_manager();
663 }
664
[email protected]34ff8b0c2010-10-01 20:06:02665 bool IsOffscreenBufferMultisampled() const {
666 return offscreen_target_samples_ > 1;
667 }
668
[email protected]a93bb842010-02-16 23:03:47669 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03670 TextureManager::TextureInfo* CreateTextureInfo(
671 GLuint client_id, GLuint service_id) {
[email protected]80eb6b52012-01-19 00:14:41672 return texture_manager()->CreateTextureInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47673 }
674
675 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03676 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50677 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03678 texture_manager()->GetTextureInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10679 return info;
[email protected]a93bb842010-02-16 23:03:47680 }
681
682 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03683 void RemoveTextureInfo(GLuint client_id) {
[email protected]80eb6b52012-01-19 00:14:41684 texture_manager()->RemoveTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50685 }
[email protected]a93bb842010-02-16 23:03:47686
[email protected]d37231fa2010-04-09 21:16:02687 // Get the size (in pixels) of the currently bound frame buffer (either FBO
688 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30689 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02690
[email protected]9edc6b22010-12-23 02:00:26691 // Get the format of the currently bound frame buffer (either FBO or regular
692 // back buffer)
693 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46694 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26695
[email protected]a93bb842010-02-16 23:03:47696 // Wrapper for CompressedTexImage2D commands.
697 error::Error DoCompressedTexImage2D(
698 GLenum target,
699 GLint level,
700 GLenum internal_format,
701 GLsizei width,
702 GLsizei height,
703 GLint border,
704 GLsizei image_size,
705 const void* data);
706
[email protected]cadde4a2010-07-31 17:10:43707 // Wrapper for CompressedTexSubImage2D.
708 void DoCompressedTexSubImage2D(
709 GLenum target,
710 GLint level,
711 GLint xoffset,
712 GLint yoffset,
713 GLsizei width,
714 GLsizei height,
715 GLenum format,
716 GLsizei imageSize,
717 const void * data);
718
719 // Wrapper for CopyTexImage2D.
720 void DoCopyTexImage2D(
721 GLenum target,
722 GLint level,
723 GLenum internal_format,
724 GLint x,
725 GLint y,
726 GLsizei width,
727 GLsizei height,
728 GLint border);
729
730 // Wrapper for CopyTexSubImage2D.
731 void DoCopyTexSubImage2D(
732 GLenum target,
733 GLint level,
734 GLint xoffset,
735 GLint yoffset,
736 GLint x,
737 GLint y,
738 GLsizei width,
739 GLsizei height);
740
[email protected]a93bb842010-02-16 23:03:47741 // Wrapper for TexImage2D commands.
742 error::Error DoTexImage2D(
743 GLenum target,
744 GLint level,
745 GLenum internal_format,
746 GLsizei width,
747 GLsizei height,
748 GLint border,
749 GLenum format,
750 GLenum type,
751 const void* pixels,
752 uint32 pixels_size);
753
[email protected]cadde4a2010-07-31 17:10:43754 // Wrapper for TexSubImage2D.
755 void DoTexSubImage2D(
756 GLenum target,
757 GLint level,
758 GLint xoffset,
759 GLint yoffset,
760 GLsizei width,
761 GLsizei height,
762 GLenum format,
763 GLenum type,
764 const void * data);
765
[email protected]e51bdf32011-11-23 22:21:46766 // Wrapper for TexImageIOSurface2DCHROMIUM.
767 void DoTexImageIOSurface2DCHROMIUM(
768 GLenum target,
769 GLsizei width,
770 GLsizei height,
771 GLuint io_surface_id,
772 GLuint plane);
773
[email protected]97dc7cbe2011-12-06 17:26:17774 // Wrapper for TexStorage2DEXT.
775 void DoTexStorage2DEXT(
776 GLenum target,
777 GLint levels,
778 GLenum internal_format,
779 GLsizei width,
780 GLsizei height);
781
[email protected]a93bb842010-02-16 23:03:47782 // Creates a ProgramInfo for the given program.
[email protected]d685a682011-04-29 16:19:57783 ProgramManager::ProgramInfo* CreateProgramInfo(
784 GLuint client_id, GLuint service_id) {
785 return program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47786 }
787
[email protected]07f54fcc2009-12-22 02:46:30788 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03789 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14790 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46791 }
[email protected]07f54fcc2009-12-22 02:46:30792
[email protected]6b8cf1a2010-05-06 16:13:58793 // Gets the program info for the given program. If it's not a program
794 // generates a GL error. Returns NULL if not program.
795 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
796 GLuint client_id, const char* function_name) {
797 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
798 if (!info) {
799 if (GetShaderInfo(client_id)) {
800 SetGLError(GL_INVALID_OPERATION,
801 (std::string(function_name) +
802 ": shader passed for program").c_str());
803 } else {
804 SetGLError(GL_INVALID_VALUE,
805 (std::string(function_name) + ": unknown program").c_str());
806 }
807 }
808 return info;
809 }
810
811
[email protected]45bf5152010-02-12 00:11:31812 // Creates a ShaderInfo for the given shader.
[email protected]d685a682011-04-29 16:19:57813 ShaderManager::ShaderInfo* CreateShaderInfo(
814 GLuint client_id,
815 GLuint service_id,
816 GLenum shader_type) {
817 return shader_manager()->CreateShaderInfo(
818 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31819 }
820
821 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03822 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14823 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31824 }
825
[email protected]6b8cf1a2010-05-06 16:13:58826 // Gets the shader info for the given shader. If it's not a shader generates a
827 // GL error. Returns NULL if not shader.
828 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
829 GLuint client_id, const char* function_name) {
830 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
831 if (!info) {
832 if (GetProgramInfo(client_id)) {
833 SetGLError(
834 GL_INVALID_OPERATION,
835 (std::string(function_name) +
836 ": program passed for shader").c_str());
837 } else {
838 SetGLError(GL_INVALID_VALUE,
839 (std::string(function_name) + ": unknown shader").c_str());
840 }
841 }
842 return info;
843 }
844
[email protected]a93bb842010-02-16 23:03:47845 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03846 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
847 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47848 }
849
[email protected]07f54fcc2009-12-22 02:46:30850 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03851 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
852 BufferManager::BufferInfo* info =
853 buffer_manager()->GetBufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10854 return info;
[email protected]1d32bc82010-01-13 22:06:46855 }
[email protected]07f54fcc2009-12-22 02:46:30856
[email protected]a93bb842010-02-16 23:03:47857 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
858 // on glDeleteBuffers so we can make sure the user does not try to render
859 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03860 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47861
[email protected]a25fa872010-03-25 02:57:58862 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03863 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
864 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58865 }
866
867 // Gets the framebuffer info for the given framebuffer.
868 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03869 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58870 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03871 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10872 return info;
[email protected]a25fa872010-03-25 02:57:58873 }
874
875 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03876 void RemoveFramebufferInfo(GLuint client_id) {
877 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58878 }
879
880 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03881 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
882 return renderbuffer_manager()->CreateRenderbufferInfo(
883 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58884 }
885
886 // Gets the renderbuffer info for the given renderbuffer.
887 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03888 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58889 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03890 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10891 return info;
[email protected]a25fa872010-03-25 02:57:58892 }
893
894 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03895 void RemoveRenderbufferInfo(GLuint client_id) {
896 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58897 }
898
[email protected]258a3313f2011-10-18 20:13:57899 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
900
[email protected]558847a2010-03-24 07:02:54901 error::Error GetAttribLocationHelper(
902 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
903 const std::string& name_str);
904
905 error::Error GetUniformLocationHelper(
906 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
907 const std::string& name_str);
908
[email protected]3916c97e2010-02-25 03:20:50909 // Helper for glShaderSource.
910 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03911 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30912
[email protected]0d6bfdc2011-11-02 01:32:20913 // Clear any textures used by the current program.
914 bool ClearUnclearedTextures();
915
916 // Clear any uncleared level in texture.
917 // Returns false if there was a generated GL error.
918 bool ClearTexture(TextureManager::TextureInfo* info);
919
920 // Clears any uncleared attachments attached to the given frame buffer.
921 // Returns false if there was a generated GL error.
922 void ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:30923 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28924
[email protected]0d6bfdc2011-11-02 01:32:20925 // overridden from GLES2Decoder
926 virtual bool ClearLevel(
927 unsigned service_id,
928 unsigned bind_target,
929 unsigned target,
930 int level,
931 unsigned format,
932 unsigned type,
933 int width,
[email protected]4502e6492011-12-14 19:39:15934 int height,
935 bool is_texture_immutable);
[email protected]0d6bfdc2011-11-02 01:32:20936
[email protected]c007aa02010-09-02 22:22:40937 // Restore all GL state that affects clearing.
938 void RestoreClearState();
939
[email protected]3a2e7c7b2010-08-06 01:12:28940 // Remembers the state of some capabilities.
[email protected]297ca1c2011-06-20 23:08:46941 // Returns: true if glEnable/glDisable should actually be called.
942 bool SetCapabilityState(GLenum cap, bool enabled);
[email protected]3a2e7c7b2010-08-06 01:12:28943
[email protected]0d6bfdc2011-11-02 01:32:20944 // Check that the currently bound framebuffers are valid.
945 // Generates GL error if not.
946 bool CheckBoundFramebuffersValid(const char* func_name);
947
948 // Check if a framebuffer meets our requirements.
949 bool CheckFramebufferValid(
950 FramebufferManager::FramebufferInfo* framebuffer,
951 GLenum target,
952 const char* func_name);
[email protected]3a03a8f2011-03-19 00:51:27953
[email protected]939e7362010-05-13 20:49:10954 // Checks if the current program exists and is valid. If not generates the
955 // appropriate GL error. Returns true if the current program is in a usable
956 // state.
957 bool CheckCurrentProgram(const char* function_name);
958
959 // Checks if the current program exists and is valid and that location is not
960 // -1. If the current program is not valid generates the appropriate GL
961 // error. Returns true if the current program is in a usable state and
962 // location is not -1.
963 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
964
965 // Gets the type of a uniform for a location in the current program. Sets GL
966 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:36967 // program is valid and the location exists. Adjusts count so it
968 // does not overflow the uniform.
969 bool PrepForSetUniformByLocation(
970 GLint location, const char* function_name, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:10971
[email protected]b177ae22011-11-01 03:29:11972 // Gets the service id for any simulated backbuffer fbo.
973 GLuint GetBackbufferServiceId();
974
[email protected]b273e432010-04-12 17:23:58975 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
976 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
977
[email protected]96449d2c2009-11-25 00:01:32978 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03979 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32980
981 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03982 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32983
[email protected]3916c97e2010-02-25 03:20:50984 // Wrapper for glActiveTexture
985 void DoActiveTexture(GLenum texture_unit);
986
[email protected]ae51d192010-04-27 00:48:03987 // Wrapper for glAttachShader
988 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
989
[email protected]96449d2c2009-11-25 00:01:32990 // Wrapper for glBindBuffer since we need to track the current targets.
991 void DoBindBuffer(GLenum target, GLuint buffer);
992
[email protected]86093972010-03-11 00:13:56993 // Wrapper for glBindFramebuffer since we need to track the current targets.
994 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
995
996 // Wrapper for glBindRenderbuffer since we need to track the current targets.
997 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
998
[email protected]a93bb842010-02-16 23:03:47999 // Wrapper for glBindTexture since we need to track the current targets.
1000 void DoBindTexture(GLenum target, GLuint texture);
1001
[email protected]8e3e0662010-08-23 18:46:301002 // Wrapper for glBlitFramebufferEXT.
1003 void DoBlitFramebufferEXT(
1004 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1005 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1006 GLbitfield mask, GLenum filter);
1007
[email protected]36cef8ce2010-03-16 07:34:451008 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:111009 void DoBufferData(
1010 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
1011
[email protected]36cef8ce2010-03-16 07:34:451012 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:111013 void DoBufferSubData(
1014 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1015
[email protected]36cef8ce2010-03-16 07:34:451016 // Wrapper for glCheckFramebufferStatus
1017 GLenum DoCheckFramebufferStatus(GLenum target);
1018
[email protected]3a03a8f2011-03-19 00:51:271019 // Wrapper for glClear
1020 void DoClear(GLbitfield mask);
1021
[email protected]3a2e7c7b2010-08-06 01:12:281022 // Wrappers for clear and mask settings functions.
1023 void DoClearColor(
1024 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
1025 void DoClearDepthf(GLclampf depth);
1026 void DoClearStencil(GLint s);
1027 void DoColorMask(
1028 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
1029 void DoDepthMask(GLboolean depth);
1030 void DoStencilMask(GLuint mask);
1031 void DoStencilMaskSeparate(GLenum face, GLuint mask);
1032
[email protected]45bf5152010-02-12 00:11:311033 // Wrapper for glCompileShader.
1034 void DoCompileShader(GLuint shader);
1035
[email protected]269200b12010-11-18 22:53:061036 // Helper for DeleteSharedIdsCHROMIUM commands.
1037 void DoDeleteSharedIdsCHROMIUM(
1038 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101039
[email protected]ae51d192010-04-27 00:48:031040 // Wrapper for glDetachShader
1041 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1042
[email protected]3a2e7c7b2010-08-06 01:12:281043 // Wrapper for glDisable
1044 void DoDisable(GLenum cap);
1045
[email protected]07f54fcc2009-12-22 02:46:301046 // Wrapper for glDisableVertexAttribArray.
1047 void DoDisableVertexAttribArray(GLuint index);
1048
[email protected]3a2e7c7b2010-08-06 01:12:281049 // Wrapper for glEnable
1050 void DoEnable(GLenum cap);
1051
[email protected]07f54fcc2009-12-22 02:46:301052 // Wrapper for glEnableVertexAttribArray.
1053 void DoEnableVertexAttribArray(GLuint index);
1054
[email protected]36cef8ce2010-03-16 07:34:451055 // Wrapper for glFramebufferRenderbufffer.
1056 void DoFramebufferRenderbuffer(
1057 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1058 GLuint renderbuffer);
1059
1060 // Wrapper for glFramebufferTexture2D.
1061 void DoFramebufferTexture2D(
1062 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1063 GLint level);
1064
[email protected]a93bb842010-02-16 23:03:471065 // Wrapper for glGenerateMipmap
1066 void DoGenerateMipmap(GLenum target);
1067
[email protected]269200b12010-11-18 22:53:061068 // Helper for GenSharedIdsCHROMIUM commands.
1069 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:101070 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1071
[email protected]b273e432010-04-12 17:23:581072 // Wrapper for DoGetBooleanv.
1073 void DoGetBooleanv(GLenum pname, GLboolean* params);
1074
1075 // Wrapper for DoGetFloatv.
1076 void DoGetFloatv(GLenum pname, GLfloat* params);
1077
[email protected]36cef8ce2010-03-16 07:34:451078 // Wrapper for glGetFramebufferAttachmentParameteriv.
1079 void DoGetFramebufferAttachmentParameteriv(
1080 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1081
[email protected]a0c3e972010-04-21 00:49:131082 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581083 void DoGetIntegerv(GLenum pname, GLint* params);
1084
[email protected]29a9eb52010-04-13 09:04:231085 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:061086 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:231087 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1088
[email protected]a0c3e972010-04-21 00:49:131089 // Wrapper for glGetProgramiv.
1090 void DoGetProgramiv(
1091 GLuint program_id, GLenum pname, GLint* params);
1092
[email protected]36cef8ce2010-03-16 07:34:451093 // Wrapper for glRenderbufferParameteriv.
1094 void DoGetRenderbufferParameteriv(
1095 GLenum target, GLenum pname, GLint* params);
1096
[email protected]ddd968b82010-03-02 00:44:291097 // Wrapper for glGetShaderiv
1098 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1099
[email protected]b1122982010-05-17 23:04:241100 // Wrappers for glGetVertexAttrib.
1101 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1102 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1103
[email protected]1958e0e2010-04-22 05:17:151104 // Wrappers for glIsXXX functions.
1105 bool DoIsBuffer(GLuint client_id);
1106 bool DoIsFramebuffer(GLuint client_id);
1107 bool DoIsProgram(GLuint client_id);
1108 bool DoIsRenderbuffer(GLuint client_id);
1109 bool DoIsShader(GLuint client_id);
1110 bool DoIsTexture(GLuint client_id);
1111
[email protected]07f54fcc2009-12-22 02:46:301112 // Wrapper for glLinkProgram
1113 void DoLinkProgram(GLuint program);
1114
[email protected]269200b12010-11-18 22:53:061115 // Helper for RegisterSharedIdsCHROMIUM.
1116 void DoRegisterSharedIdsCHROMIUM(
1117 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101118
[email protected]36cef8ce2010-03-16 07:34:451119 // Wrapper for glRenderbufferStorage.
1120 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031121 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451122
[email protected]8e3e0662010-08-23 18:46:301123 // Wrapper for glRenderbufferStorageMultisampleEXT.
1124 void DoRenderbufferStorageMultisample(
1125 GLenum target, GLsizei samples, GLenum internalformat,
1126 GLsizei width, GLsizei height);
1127
[email protected]b273e432010-04-12 17:23:581128 // Wrapper for glReleaseShaderCompiler.
1129 void DoReleaseShaderCompiler() { }
1130
[email protected]3916c97e2010-02-25 03:20:501131 // Wrappers for glTexParameter functions.
1132 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1133 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1134 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1135 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1136
1137 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1138 // spec only these 2 functions can be used to set sampler uniforms.
1139 void DoUniform1i(GLint location, GLint v0);
[email protected]939e7362010-05-13 20:49:101140 void DoUniform1iv(GLint location, GLsizei count, const GLint* value);
[email protected]43c2f1f2011-03-25 18:35:361141 void DoUniform2iv(GLint location, GLsizei count, const GLint* value);
1142 void DoUniform3iv(GLint location, GLsizei count, const GLint* value);
1143 void DoUniform4iv(GLint location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101144
1145 // Wrappers for glUniformfv because some drivers don't correctly accept
1146 // bool uniforms.
1147 void DoUniform1fv(GLint location, GLsizei count, const GLfloat* value);
1148 void DoUniform2fv(GLint location, GLsizei count, const GLfloat* value);
1149 void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value);
1150 void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501151
[email protected]43c2f1f2011-03-25 18:35:361152 void DoUniformMatrix2fv(
1153 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1154 void DoUniformMatrix3fv(
1155 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1156 void DoUniformMatrix4fv(
1157 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1158
[email protected]b1122982010-05-17 23:04:241159 // Wrappers for glVertexAttrib??
1160 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1161 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1162 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1163 void DoVertexAttrib4f(
1164 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1165 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1166 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1167 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1168 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1169
[email protected]07f54fcc2009-12-22 02:46:301170 // Wrapper for glUseProgram
1171 void DoUseProgram(GLuint program);
1172
[email protected]ae51d192010-04-27 00:48:031173 // Wrapper for glValidateProgram.
1174 void DoValidateProgram(GLuint program_client_id);
1175
[email protected]4e8a5b122010-05-08 22:00:101176 // Gets the number of values that will be returned by glGetXXX. Returns
1177 // false if pname is unknown.
1178 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1179
[email protected]96449d2c2009-11-25 00:01:321180 // Gets the GLError through our wrapper.
1181 GLenum GetGLError();
1182
[email protected]1002c2d2011-06-28 22:39:041183 // Gets the GLError and stores it in our wrapper. Effectively
1184 // this lets us peek at the error without losing it.
1185 GLenum PeekGLError();
1186
[email protected]07f54fcc2009-12-22 02:46:301187 // Copies the real GL errors to the wrapper. This is so we can
1188 // make sure there are no native GL errors before calling some GL function
1189 // so that on return we know any error generated was for that specific
1190 // command.
1191 void CopyRealGLErrorsToWrapper();
1192
[email protected]6217d392010-03-25 22:08:351193 // Clear all real GL errors. This is to prevent the client from seeing any
1194 // errors caused by GL calls that it was not responsible for issuing.
1195 void ClearRealGLErrors();
1196
[email protected]07f54fcc2009-12-22 02:46:301197 // Checks if the current program and vertex attributes are valid for drawing.
1198 bool IsDrawValid(GLuint max_vertex_accessed);
1199
[email protected]c13e1da62011-09-09 21:48:301200 // Returns true if successful, simulated will be true if attrib0 was
1201 // simulated.
1202 bool SimulateAttrib0(GLuint max_vertex_accessed, bool* simulated);
[email protected]b1122982010-05-17 23:04:241203 void RestoreStateForSimulatedAttrib0();
1204
[email protected]ef526492010-06-02 23:12:251205 // Returns true if textures were set.
1206 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501207 void RestoreStateForNonRenderableTextures();
1208
[email protected]8fbedc02010-11-18 18:43:401209 // Returns true if GL_FIXED attribs were simulated.
1210 bool SimulateFixedAttribs(GLuint max_vertex_accessed, bool* simulated);
1211 void RestoreStateForSimulatedFixedAttribs();
1212
[email protected]07f54fcc2009-12-22 02:46:301213 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501214 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301215 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501216 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1217 bound_array_buffer_ : bound_element_array_buffer_;
[email protected]a0b78dc2011-11-11 10:43:101218 return info;
[email protected]07f54fcc2009-12-22 02:46:301219 }
1220
[email protected]a93bb842010-02-16 23:03:471221 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501222 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1223 TextureUnit& unit = texture_units_[active_texture_unit_];
1224 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471225 switch (target) {
1226 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501227 info = unit.bound_texture_2d;
1228 break;
[email protected]a93bb842010-02-16 23:03:471229 case GL_TEXTURE_CUBE_MAP:
1230 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1231 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1232 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1233 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1234 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1235 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501236 info = unit.bound_texture_cube_map;
1237 break;
[email protected]61eeb33f2011-07-26 15:30:311238 case GL_TEXTURE_EXTERNAL_OES:
1239 info = unit.bound_texture_external_oes;
1240 break;
[email protected]e51bdf32011-11-23 22:21:461241 case GL_TEXTURE_RECTANGLE_ARB:
1242 info = unit.bound_texture_rectangle_arb;
1243 break;
[email protected]a93bb842010-02-16 23:03:471244 default:
1245 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501246 return NULL;
[email protected]a93bb842010-02-16 23:03:471247 }
[email protected]a0b78dc2011-11-11 10:43:101248 return info;
[email protected]a93bb842010-02-16 23:03:471249 }
1250
[email protected]61eeb33f2011-07-26 15:30:311251 GLenum GetBindTargetForSamplerType(GLenum type) {
1252 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:461253 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1254 switch (type) {
1255 case GL_SAMPLER_2D:
1256 return GL_TEXTURE_2D;
1257 case GL_SAMPLER_CUBE:
1258 return GL_TEXTURE_CUBE_MAP;
1259 case GL_SAMPLER_EXTERNAL_OES:
1260 return GL_TEXTURE_EXTERNAL_OES;
1261 case GL_SAMPLER_2D_RECT_ARB:
1262 return GL_TEXTURE_RECTANGLE_ARB;
1263 }
1264
1265 NOTREACHED();
1266 return 0;
[email protected]61eeb33f2011-07-26 15:30:311267 }
1268
[email protected]8e3e0662010-08-23 18:46:301269 // Gets the framebuffer info for a particular target.
1270 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1271 GLenum target) {
1272 FramebufferManager::FramebufferInfo* info = NULL;
1273 switch (target) {
1274 case GL_FRAMEBUFFER:
1275 case GL_DRAW_FRAMEBUFFER:
1276 info = bound_draw_framebuffer_;
1277 break;
1278 case GL_READ_FRAMEBUFFER:
1279 info = bound_read_framebuffer_;
1280 break;
1281 default:
1282 NOTREACHED();
1283 break;
1284 }
[email protected]a0b78dc2011-11-11 10:43:101285 return info;
[email protected]8e3e0662010-08-23 18:46:301286 }
1287
[email protected]0d6bfdc2011-11-02 01:32:201288 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfoForTarget(
1289 GLenum target) {
1290 RenderbufferManager::RenderbufferInfo* info = NULL;
1291 switch (target) {
1292 case GL_RENDERBUFFER:
1293 info = bound_renderbuffer_;
1294 break;
1295 default:
1296 NOTREACHED();
1297 break;
1298 }
[email protected]a0b78dc2011-11-11 10:43:101299 return info;
[email protected]0d6bfdc2011-11-02 01:32:201300 }
1301
[email protected]f7b85372010-02-03 01:11:371302 // Validates the program and location for a glGetUniform call and returns
1303 // a SizeResult setup to receive the result. Returns true if glGetUniform
1304 // should be called.
1305 bool GetUniformSetup(
1306 GLuint program, GLint location,
1307 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:101308 error::Error* error, GLuint* service_id, void** result,
1309 GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371310
[email protected]1078f912011-12-23 13:12:141311 // Computes the estimated memory used for the backbuffer and passes it to
1312 // the tracing system.
1313 void UpdateBackbufferMemoryAccounting();
1314
[email protected]38d139d2011-07-14 00:38:431315 // Returns true if the context was just lost due to e.g. GL_ARB_robustness.
1316 bool WasContextLost();
1317
[email protected]e51bdf32011-11-23 22:21:461318#if defined(OS_MACOSX)
1319 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1320#endif
1321
[email protected]96449d2c2009-11-25 00:01:321322 // Generate a member function prototype for each command in an automated and
1323 // typesafe way.
1324 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141325 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191326 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321327 const gles2::name& args); \
1328
1329 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1330
1331 #undef GLES2_CMD_OP
1332
[email protected]2f2d7042010-04-14 21:45:581333 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381334 scoped_refptr<gfx::GLSurface> surface_;
1335 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021336
[email protected]a3ded6d2010-10-19 06:44:391337 // The ContextGroup for this decoder uses to track resources.
1338 ContextGroup::Ref group_;
1339
[email protected]6217d392010-03-25 22:08:351340 // A parent decoder can access this decoders saved offscreen frame buffer.
1341 // The parent pointer is reset if the parent is destroyed.
1342 base::WeakPtr<GLES2DecoderImpl> parent_;
1343
[email protected]34ff8b0c2010-10-01 20:06:021344 // Current width and height of the offscreen frame buffer.
1345 gfx::Size offscreen_size_;
1346
[email protected]96449d2c2009-11-25 00:01:321347 // Current GL error bits.
1348 uint32 error_bits_;
1349
[email protected]96449d2c2009-11-25 00:01:321350 // Util to help with GL.
1351 GLES2Util util_;
1352
1353 // pack alignment as last set by glPixelStorei
1354 GLint pack_alignment_;
1355
1356 // unpack alignment as last set by glPixelStorei
1357 GLint unpack_alignment_;
1358
1359 // The currently bound array buffer. If this is 0 it is illegal to call
1360 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501361 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321362
1363 // The currently bound element array buffer. If this is 0 it is illegal
1364 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501365 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301366
[email protected]f39f4b3f2010-05-12 17:04:081367 // Class that manages vertex attribs.
[email protected]3757a372012-01-19 05:20:441368 scoped_ptr<VertexAttribManager> vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301369
[email protected]b1122982010-05-17 23:04:241370 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1371 GLuint attrib_0_buffer_id_;
1372
1373 // The value currently in attrib_0.
1374 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1375
[email protected]fc753442011-02-04 19:49:491376 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1377 bool attrib_0_buffer_matches_value_;
1378
[email protected]b1122982010-05-17 23:04:241379 // The size of attrib 0.
1380 GLsizei attrib_0_size_;
1381
[email protected]8fbedc02010-11-18 18:43:401382 // The buffer used to simulate GL_FIXED attribs.
1383 GLuint fixed_attrib_buffer_id_;
1384
1385 // The size of fiixed attrib buffer.
1386 GLsizei fixed_attrib_buffer_size_;
1387
[email protected]3916c97e2010-02-25 03:20:501388 // Current active texture by 0 - n index.
1389 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1390 // be 2.
1391 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301392
[email protected]3916c97e2010-02-25 03:20:501393 // Which textures are bound to texture units through glActiveTexture.
1394 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471395
[email protected]3a2e7c7b2010-08-06 01:12:281396 // state saved for clearing so we can clear render buffers and then
1397 // restore to these values.
1398 GLclampf clear_red_;
1399 GLclampf clear_green_;
1400 GLclampf clear_blue_;
1401 GLclampf clear_alpha_;
1402 GLboolean mask_red_;
1403 GLboolean mask_green_;
1404 GLboolean mask_blue_;
1405 GLboolean mask_alpha_;
1406 GLint clear_stencil_;
1407 GLuint mask_stencil_front_;
1408 GLuint mask_stencil_back_;
1409 GLclampf clear_depth_;
1410 GLboolean mask_depth_;
1411 bool enable_scissor_test_;
[email protected]297ca1c2011-06-20 23:08:461412 bool enable_depth_test_;
1413 bool enable_stencil_test_;
1414 bool state_dirty_;
[email protected]3a2e7c7b2010-08-06 01:12:281415
[email protected]1d32bc82010-01-13 22:06:461416 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501417 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301418
[email protected]8e3e0662010-08-23 18:46:301419 // The currently bound framebuffers
1420 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1421 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561422
1423 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081424 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561425
[email protected]b9363b22010-06-09 22:06:151426 // The offscreen frame buffer that the client renders to. With EGL, the
1427 // depth and stencil buffers are separate. With regular GL there is a single
1428 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1429 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351430 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1431 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021432 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151433 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1434 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021435 GLenum offscreen_target_color_format_;
1436 GLenum offscreen_target_depth_format_;
1437 GLenum offscreen_target_stencil_format_;
1438 GLsizei offscreen_target_samples_;
[email protected]6217d392010-03-25 22:08:351439
[email protected]de26b3c2011-08-03 21:54:271440 // The copy that is saved when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021441 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351442 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]de26b3c2011-08-03 21:54:271443
1444 // The copy that is used as the destination for multi-sample resolves.
1445 scoped_ptr<FrameBuffer> offscreen_resolved_frame_buffer_;
1446 scoped_ptr<Texture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051447 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351448
[email protected]9d37f062011-11-22 01:24:521449 base::Callback<void(gfx::Size)> resize_callback_;
[email protected]22f320a2011-08-30 01:17:001450
[email protected]6b6e7ee2011-12-13 08:04:521451 MsgCallback msg_callback_;
[email protected]43f28f832010-02-03 02:28:481452
[email protected]b0af4f52011-09-28 22:04:421453 StreamTextureManager* stream_texture_manager_;
1454
[email protected]32fe9aa2011-01-21 23:47:131455 // The format of the back buffer_
1456 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461457 bool back_buffer_has_depth_;
1458 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131459
[email protected]473c01ccb2011-06-07 01:33:301460 bool teximage2d_faster_than_texsubimage2d_;
1461 bool bufferdata_faster_than_buffersubdata_;
1462
[email protected]8eee29c2010-04-29 03:38:291463 // The last error message set.
1464 std::string last_error_;
1465
[email protected]a3a93e7b2010-08-28 00:48:561466 // The current decoder error.
1467 error::Error current_decoder_error_;
1468
[email protected]b1d2dcb2010-05-17 19:24:181469 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451470 scoped_ptr<ShaderTranslator> vertex_translator_;
1471 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181472
[email protected]e82fb792011-09-22 00:33:291473 DisallowedFeatures disallowed_features_;
[email protected]c410da802011-03-14 19:17:411474
[email protected]915a59a12010-09-30 21:29:111475 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051476 const Validators* validators_;
[email protected]80eb6b52012-01-19 00:14:411477 FeatureInfo::Ref feature_info_;
[email protected]9438b012010-06-15 22:55:051478
[email protected]b493ee622011-04-13 23:52:001479 // This indicates all the following texSubImage2D calls that are part of the
1480 // failed texImage2D call should be ignored.
1481 bool tex_image_2d_failed_;
1482
[email protected]65225772011-05-12 21:10:241483 int frame_number_;
1484
[email protected]38d139d2011-07-14 00:38:431485 bool has_arb_robustness_;
1486 GLenum reset_status_;
1487
[email protected]75c023c2011-08-22 23:54:511488 bool needs_mac_nvidia_driver_workaround_;
[email protected]a2a0fe762011-09-20 00:59:121489 bool needs_glsl_built_in_function_emulation_;
[email protected]75c023c2011-08-22 23:54:511490
[email protected]f0d74742011-10-03 16:31:041491 // These flags are used to override the state of the shared feature_info_
1492 // member. Because the same FeatureInfo instance may be shared among many
1493 // contexts, the assumptions on the availablity of extensions in WebGL
1494 // contexts may be broken. These flags override the shared state to preserve
1495 // WebGL semantics.
1496 bool force_webgl_glsl_validation_;
1497 bool derivatives_explicitly_enabled_;
1498
[email protected]062c38b2012-01-18 03:25:101499 bool compile_shader_always_succeeds_;
1500
[email protected]e51bdf32011-11-23 22:21:461501#if defined(OS_MACOSX)
1502 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1503 TextureToIOSurfaceMap texture_to_io_surface_map_;
1504#endif
1505
[email protected]96449d2c2009-11-25 00:01:321506 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1507};
1508
[email protected]6217d392010-03-25 22:08:351509ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1510 : decoder_(decoder) {
1511 decoder_->CopyRealGLErrorsToWrapper();
1512}
1513
1514ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1515 decoder_->ClearRealGLErrors();
1516}
1517
1518ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1519 GLuint id)
1520 : decoder_(decoder) {
1521 ScopedGLErrorSuppressor suppressor(decoder_);
1522
1523 // TODO(apatrick): Check if there are any other states that need to be reset
1524 // before binding a new texture.
1525 glActiveTexture(GL_TEXTURE0);
1526 glBindTexture(GL_TEXTURE_2D, id);
1527}
1528
1529ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1530 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301531 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351532}
1533
1534ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1535 GLuint id)
1536 : decoder_(decoder) {
1537 ScopedGLErrorSuppressor suppressor(decoder_);
1538 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1539}
1540
1541ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1542 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301543 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351544}
1545
1546ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1547 GLuint id)
1548 : decoder_(decoder) {
1549 ScopedGLErrorSuppressor suppressor(decoder_);
1550 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1551}
1552
1553ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1554 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301555 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351556}
1557
[email protected]34ff8b0c2010-10-01 20:06:021558ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271559 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521560 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021561 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1562 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]c0701082011-04-20 00:34:521563 (!decoder_->bound_read_framebuffer_.get() ||
1564 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021565 if (!resolve_and_bind_)
1566 return;
1567
1568 ScopedGLErrorSuppressor suppressor(decoder_);
1569 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1570 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271571 GLuint targetid;
1572 if (internal) {
1573 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1574 decoder_->offscreen_resolved_frame_buffer_.reset(
1575 new FrameBuffer(decoder_));
1576 decoder_->offscreen_resolved_frame_buffer_->Create();
1577 decoder_->offscreen_resolved_color_texture_.reset(new Texture(decoder_));
1578 decoder_->offscreen_resolved_color_texture_->Create();
1579
1580 DCHECK(decoder_->offscreen_saved_color_format_);
1581 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1582 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_);
[email protected]de26b3c2011-08-03 21:54:271583 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1584 decoder_->offscreen_resolved_color_texture_.get());
1585 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1586 GL_FRAMEBUFFER_COMPLETE) {
1587 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1588 << "because offscreen resolved FBO was incomplete.";
1589 return;
1590 }
1591 }
1592 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1593 } else {
1594 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1595 }
1596 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021597 const int width = decoder_->offscreen_size_.width();
1598 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181599 glDisable(GL_SCISSOR_TEST);
[email protected]34ff8b0c2010-10-01 20:06:021600 if (IsAngle()) {
1601 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1602 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1603 } else {
1604 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1605 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1606 }
[email protected]de26b3c2011-08-03 21:54:271607 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021608}
1609
1610ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1611 if (!resolve_and_bind_)
1612 return;
1613
1614 ScopedGLErrorSuppressor suppressor(decoder_);
1615 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181616 if (decoder_->enable_scissor_test_) {
1617 glEnable(GL_SCISSOR_TEST);
1618 }
[email protected]34ff8b0c2010-10-01 20:06:021619}
1620
[email protected]6217d392010-03-25 22:08:351621Texture::Texture(GLES2DecoderImpl* decoder)
1622 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141623 id_(0),
1624 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351625}
1626
1627Texture::~Texture() {
1628 // This does not destroy the render texture because that would require that
1629 // the associated GL context was current. Just check that it was explicitly
1630 // destroyed.
1631 DCHECK_EQ(id_, 0u);
1632}
1633
1634void Texture::Create() {
1635 ScopedGLErrorSuppressor suppressor(decoder_);
1636 Destroy();
1637 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581638 ScopedTexture2DBinder binder(decoder_, id_);
1639 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1640 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1641 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1642 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]62788802011-10-03 17:57:161643
1644 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1645 // never called on an offscreen context, no data will ever be uploaded to the
1646 // saved offscreen color texture (it is deferred until to when SwapBuffers
1647 // is called). My idea is that some nvidia drivers might have a bug where
1648 // deleting a texture that has never been populated might cause a
1649 // crash.
1650 glTexImage2D(
1651 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
[email protected]1078f912011-12-23 13:12:141652 estimated_size_ = 16u * 16u * 4u;
1653 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351654}
1655
[email protected]34ff8b0c2010-10-01 20:06:021656bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351657 DCHECK_NE(id_, 0u);
1658 ScopedGLErrorSuppressor suppressor(decoder_);
1659 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]6217d392010-03-25 22:08:351660
[email protected]f0e6a34f2012-01-04 20:53:401661 WrappedTexImage2D(GL_TEXTURE_2D,
1662 0, // mip level
1663 format,
1664 size.width(),
1665 size.height(),
1666 0, // border
1667 format,
1668 GL_UNSIGNED_BYTE,
1669 NULL);
[email protected]6217d392010-03-25 22:08:351670
[email protected]d37231fa2010-04-09 21:16:021671 size_ = size;
1672
[email protected]1078f912011-12-23 13:12:141673 bool success = glGetError() == GL_NO_ERROR;
1674 if (success) {
1675 uint32 image_size = 0;
1676 GLES2Util::ComputeImageDataSize(
1677 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 4, &image_size);
1678 estimated_size_ = image_size;
1679 decoder_->UpdateBackbufferMemoryAccounting();
1680 }
1681 return success;
[email protected]6217d392010-03-25 22:08:351682}
1683
[email protected]3a4d0c52011-06-29 23:11:581684void Texture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351685 DCHECK_NE(id_, 0u);
1686 ScopedGLErrorSuppressor suppressor(decoder_);
1687 ScopedTexture2DBinder binder(decoder_, id_);
1688 glCopyTexImage2D(GL_TEXTURE_2D,
1689 0, // level
[email protected]3a4d0c52011-06-29 23:11:581690 format,
[email protected]6217d392010-03-25 22:08:351691 0, 0,
1692 size.width(),
1693 size.height(),
1694 0); // border
1695}
1696
1697void Texture::Destroy() {
1698 if (id_ != 0) {
1699 ScopedGLErrorSuppressor suppressor(decoder_);
1700 glDeleteTextures(1, &id_);
1701 id_ = 0;
[email protected]1078f912011-12-23 13:12:141702 estimated_size_ = 0;
1703 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351704 }
1705}
1706
[email protected]97872062010-11-03 19:07:051707void Texture::Invalidate() {
1708 id_ = 0;
1709}
1710
[email protected]6217d392010-03-25 22:08:351711RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1712 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141713 id_(0),
1714 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351715}
1716
1717RenderBuffer::~RenderBuffer() {
1718 // This does not destroy the render buffer because that would require that
1719 // the associated GL context was current. Just check that it was explicitly
1720 // destroyed.
1721 DCHECK_EQ(id_, 0u);
1722}
1723
1724void RenderBuffer::Create() {
1725 ScopedGLErrorSuppressor suppressor(decoder_);
1726 Destroy();
1727 glGenRenderbuffersEXT(1, &id_);
1728}
1729
[email protected]34ff8b0c2010-10-01 20:06:021730bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1731 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351732 ScopedGLErrorSuppressor suppressor(decoder_);
1733 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021734 if (samples <= 1) {
1735 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1736 format,
1737 size.width(),
1738 size.height());
1739 } else {
1740 if (IsAngle()) {
1741 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1742 samples,
1743 format,
1744 size.width(),
1745 size.height());
1746 } else {
1747 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1748 samples,
1749 format,
1750 size.width(),
1751 size.height());
1752 }
1753 }
[email protected]1078f912011-12-23 13:12:141754 bool success = glGetError() == GL_NO_ERROR;
1755 if (success) {
1756 estimated_size_ = size.width() * size.height() * samples *
1757 GLES2Util::RenderbufferBytesPerPixel(format);
1758 decoder_->UpdateBackbufferMemoryAccounting();
1759 }
1760 return success;
[email protected]6217d392010-03-25 22:08:351761}
1762
1763void RenderBuffer::Destroy() {
1764 if (id_ != 0) {
1765 ScopedGLErrorSuppressor suppressor(decoder_);
1766 glDeleteRenderbuffersEXT(1, &id_);
1767 id_ = 0;
[email protected]1078f912011-12-23 13:12:141768 estimated_size_ = 0;
1769 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351770 }
1771}
1772
[email protected]97872062010-11-03 19:07:051773void RenderBuffer::Invalidate() {
1774 id_ = 0;
1775}
1776
[email protected]6217d392010-03-25 22:08:351777FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1778 : decoder_(decoder),
1779 id_(0) {
1780}
1781
1782FrameBuffer::~FrameBuffer() {
1783 // This does not destroy the frame buffer because that would require that
1784 // the associated GL context was current. Just check that it was explicitly
1785 // destroyed.
1786 DCHECK_EQ(id_, 0u);
1787}
1788
1789void FrameBuffer::Create() {
1790 ScopedGLErrorSuppressor suppressor(decoder_);
1791 Destroy();
1792 glGenFramebuffersEXT(1, &id_);
1793}
1794
1795void FrameBuffer::AttachRenderTexture(Texture* texture) {
1796 DCHECK_NE(id_, 0u);
1797 ScopedGLErrorSuppressor suppressor(decoder_);
1798 ScopedFrameBufferBinder binder(decoder_, id_);
1799 GLuint attach_id = texture ? texture->id() : 0;
1800 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1801 GL_COLOR_ATTACHMENT0,
1802 GL_TEXTURE_2D,
1803 attach_id,
1804 0);
1805}
1806
[email protected]b9363b22010-06-09 22:06:151807void FrameBuffer::AttachRenderBuffer(GLenum target,
1808 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351809 DCHECK_NE(id_, 0u);
1810 ScopedGLErrorSuppressor suppressor(decoder_);
1811 ScopedFrameBufferBinder binder(decoder_, id_);
1812 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1813 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151814 target,
[email protected]6217d392010-03-25 22:08:351815 GL_RENDERBUFFER,
1816 attach_id);
1817}
1818
[email protected]6217d392010-03-25 22:08:351819void FrameBuffer::Destroy() {
1820 if (id_ != 0) {
1821 ScopedGLErrorSuppressor suppressor(decoder_);
1822 glDeleteFramebuffersEXT(1, &id_);
1823 id_ = 0;
1824 }
1825}
1826
[email protected]97872062010-11-03 19:07:051827void FrameBuffer::Invalidate() {
1828 id_ = 0;
1829}
1830
[email protected]6217d392010-03-25 22:08:351831GLenum FrameBuffer::CheckStatus() {
1832 DCHECK_NE(id_, 0u);
1833 ScopedGLErrorSuppressor suppressor(decoder_);
1834 ScopedFrameBufferBinder binder(decoder_, id_);
1835 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1836}
1837
[email protected]aa7666122011-09-02 19:45:521838GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1839 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321840}
1841
[email protected]aa7666122011-09-02 19:45:521842GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391843 : GLES2Decoder(),
[email protected]3b1ecc262011-08-03 22:49:571844 group_(group),
[email protected]96449d2c2009-11-25 00:01:321845 error_bits_(0),
[email protected]96449d2c2009-11-25 00:01:321846 pack_alignment_(4),
1847 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241848 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491849 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241850 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401851 fixed_attrib_buffer_id_(0),
1852 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501853 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281854 clear_red_(0),
1855 clear_green_(0),
1856 clear_blue_(0),
1857 clear_alpha_(0),
1858 mask_red_(true),
1859 mask_green_(true),
1860 mask_blue_(true),
1861 mask_alpha_(true),
1862 clear_stencil_(0),
1863 mask_stencil_front_(-1),
1864 mask_stencil_back_(-1),
1865 clear_depth_(1.0f),
1866 mask_depth_(true),
1867 enable_scissor_test_(false),
[email protected]297ca1c2011-06-20 23:08:461868 enable_depth_test_(false),
1869 enable_stencil_test_(false),
1870 state_dirty_(true),
[email protected]34ff8b0c2010-10-01 20:06:021871 offscreen_target_color_format_(0),
1872 offscreen_target_depth_format_(0),
1873 offscreen_target_stencil_format_(0),
1874 offscreen_target_samples_(0),
[email protected]97872062010-11-03 19:07:051875 offscreen_saved_color_format_(0),
[email protected]b0af4f52011-09-28 22:04:421876 stream_texture_manager_(NULL),
[email protected]32fe9aa2011-01-21 23:47:131877 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:461878 back_buffer_has_depth_(false),
1879 back_buffer_has_stencil_(false),
[email protected]473c01ccb2011-06-07 01:33:301880 teximage2d_faster_than_texsubimage2d_(true),
1881 bufferdata_faster_than_buffersubdata_(true),
[email protected]a3a93e7b2010-08-28 00:48:561882 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051883 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111884 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001885 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241886 tex_image_2d_failed_(false),
[email protected]38d139d2011-07-14 00:38:431887 frame_number_(0),
1888 has_arb_robustness_(false),
[email protected]75c023c2011-08-22 23:54:511889 reset_status_(GL_NO_ERROR),
[email protected]a2a0fe762011-09-20 00:59:121890 needs_mac_nvidia_driver_workaround_(false),
[email protected]f0d74742011-10-03 16:31:041891 needs_glsl_built_in_function_emulation_(false),
1892 force_webgl_glsl_validation_(false),
[email protected]062c38b2012-01-18 03:25:101893 derivatives_explicitly_enabled_(false),
1894 compile_shader_always_succeeds_(false) {
[email protected]3b1ecc262011-08-03 22:49:571895 DCHECK(group);
1896
[email protected]b1122982010-05-17 23:04:241897 attrib_0_value_.v[0] = 0.0f;
1898 attrib_0_value_.v[1] = 0.0f;
1899 attrib_0_value_.v[2] = 0.0f;
1900 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151901
[email protected]c2f8c8402010-12-06 18:07:241902 // The shader translator is used for WebGL even when running on EGL
1903 // because additional restrictions are needed (like only enabling
1904 // GL_OES_standard_derivatives on demand). It is used for the unit
1905 // tests because
1906 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1907 // empty string to CompileShader and this is not a valid shader.
1908 // TODO(apatrick): fix this test.
1909 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:041910 !feature_info_->feature_flags().chromium_webglsl &&
1911 !force_webgl_glsl_validation_) ||
[email protected]b9363b22010-06-09 22:06:151912 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) {
1913 use_shader_translator_ = false;
1914 }
[email protected]473c01ccb2011-06-07 01:33:301915
1916 // TODO(gman): Consider setting these based on GPU and/or driver.
1917 if (IsAngle()) {
1918 teximage2d_faster_than_texsubimage2d_ = false;
1919 bufferdata_faster_than_buffersubdata_ = false;
1920 }
[email protected]96449d2c2009-11-25 00:01:321921}
1922
[email protected]80eb6b52012-01-19 00:14:411923GLES2DecoderImpl::~GLES2DecoderImpl() {
1924}
1925
[email protected]c410da802011-03-14 19:17:411926bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:381927 const scoped_refptr<gfx::GLSurface>& surface,
1928 const scoped_refptr<gfx::GLContext>& context,
[email protected]c410da802011-03-14 19:17:411929 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:291930 const DisallowedFeatures& disallowed_features,
[email protected]c410da802011-03-14 19:17:411931 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:241932 const std::vector<int32>& attribs) {
[email protected]4bedba72010-04-20 22:08:541933 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301934 DCHECK(!context_.get());
1935
[email protected]e844ae22012-01-14 03:36:261936 if (CommandLine::ForCurrentProcess()->HasSwitch(
1937 switches::kEnableGPUDebugging)) {
1938 set_debug(true);
1939 }
1940
[email protected]062c38b2012-01-18 03:25:101941 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
1942 switches::kCompileShaderAlwaysSucceeds);
1943
[email protected]fbe20372011-06-01 01:46:381944 // Take ownership of the GLSurface. TODO(apatrick): once the parent / child
1945 // context is retired, the decoder should not take an initial surface as
1946 // an argument to this function.
1947 // Maybe create a short lived offscreen GLSurface for the purpose of
1948 // initializing the decoder's GLContext.
1949 surface_ = surface;
[email protected]f62a5ab2011-05-23 20:34:151950
[email protected]66791e382010-07-14 20:48:301951 // Take ownership of the GLContext.
[email protected]fbe20372011-06-01 01:46:381952 context_ = context;
[email protected]d37231fa2010-04-09 21:16:021953
[email protected]246a70452010-03-05 21:53:501954 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:011955 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
1956 << "MakeCurrent failed.";
[email protected]1871a092011-10-10 21:46:421957 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]246a70452010-03-05 21:53:501958 Destroy();
1959 return false;
[email protected]eb54a562010-01-20 21:55:181960 }
1961
[email protected]e82fb792011-09-22 00:33:291962 if (!group_->Initialize(disallowed_features, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:221963 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:391964 << "failed to initialize.";
[email protected]1871a092011-10-10 21:46:421965 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]a3ded6d2010-10-19 06:44:391966 Destroy();
[email protected]ae1741092010-11-17 19:16:031967 return false;
[email protected]a3ded6d2010-10-19 06:44:391968 }
1969
[email protected]246a70452010-03-05 21:53:501970 CHECK_GL_ERROR();
[email protected]e82fb792011-09-22 00:33:291971 disallowed_features_ = disallowed_features;
[email protected]246a70452010-03-05 21:53:501972
[email protected]3757a372012-01-19 05:20:441973 vertex_attrib_manager_.reset(new VertexAttribManager());
1974 vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:321975
[email protected]302ce6d2011-07-07 23:28:111976 util_.set_num_compressed_texture_formats(
1977 validators_->compressed_texture_format.GetValues().size());
1978
[email protected]1071e572011-02-09 20:00:121979 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1980 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
1981 // OpenGL ES 2.0 does not have this issue.
1982 glEnableVertexAttribArray(0);
1983 }
[email protected]b1122982010-05-17 23:04:241984 glGenBuffersARB(1, &attrib_0_buffer_id_);
1985 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
1986 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
1987 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:401988 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:081989
[email protected]246a70452010-03-05 21:53:501990 texture_units_.reset(
1991 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:151992 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:491993 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:311994 // We want the last bind to be 2D.
1995 TextureManager::TextureInfo* info;
1996 if (feature_info_->feature_flags().oes_egl_image_external) {
1997 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_EXTERNAL_OES);
1998 texture_units_[tt].bound_texture_external_oes = info;
1999 glBindTexture(GL_TEXTURE_EXTERNAL_OES, info->service_id());
2000 }
[email protected]e51bdf32011-11-23 22:21:462001 if (feature_info_->feature_flags().arb_texture_rectangle) {
2002 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_RECTANGLE_ARB);
2003 texture_units_[tt].bound_texture_rectangle_arb = info;
2004 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, info->service_id());
2005 }
[email protected]61eeb33f2011-07-26 15:30:312006 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:492007 texture_units_[tt].bound_texture_cube_map = info;
2008 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
2009 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2010 texture_units_[tt].bound_texture_2d = info;
2011 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:152012 }
[email protected]00f893d2010-08-24 18:55:492013 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:502014 CHECK_GL_ERROR();
2015
[email protected]297ca1c2011-06-20 23:08:462016 ContextCreationAttribParser attrib_parser;
2017 if (!attrib_parser.Parse(attribs))
2018 return false;
[email protected]41c56362011-06-14 16:47:432019
[email protected]297ca1c2011-06-20 23:08:462020 // These are NOT if the back buffer has these proprorties. They are
2021 // if we want the command buffer to enforce them regardless of what
2022 // the real backbuffer is assuming the real back buffer gives us more than
2023 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2024 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2025 // can't do anything about that.
2026
2027 GLint v = 0;
2028 glGetIntegerv(GL_ALPHA_BITS, &v);
2029 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2030 // user requested RGB then RGB. If the user did not specify a preference than
2031 // use whatever we were given. Same for DEPTH and STENCIL.
2032 back_buffer_color_format_ =
2033 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2034 glGetIntegerv(GL_DEPTH_BITS, &v);
2035 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2036 glGetIntegerv(GL_STENCIL_BITS, &v);
2037 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2038
2039 if (surface_->IsOffscreen()) {
[email protected]34ff8b0c2010-10-01 20:06:022040 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:542041 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:022042 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
2043 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:432044 // max_sample_count must be initialized to a sane value. If
2045 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2046 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:022047 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2048 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2049 max_sample_count);
2050 } else {
2051 offscreen_target_samples_ = 1;
2052 }
2053
2054 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2055 const bool rgb8_supported =
2056 context_->HasExtension("GL_OES_rgb8_rgba8");
2057 // The only available default render buffer formats in GLES2 have very
2058 // little precision. Don't enable multisampling unless 8-bit render
2059 // buffer formats are available--instead fall back to 8-bit textures.
2060 if (rgb8_supported && offscreen_target_samples_ > 1) {
2061 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2062 GL_RGBA8 : GL_RGB8;
2063 } else {
2064 offscreen_target_samples_ = 1;
2065 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2066 GL_RGBA : GL_RGB;
2067 }
2068
2069 // ANGLE only supports packed depth/stencil formats, so use it if it is
2070 // available.
2071 const bool depth24_stencil8_supported =
2072 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272073 VLOG(1) << "GL_OES_packed_depth_stencil "
2074 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:002075 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2076 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022077 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2078 offscreen_target_stencil_format_ = 0;
2079 } else {
2080 // It may be the case that this depth/stencil combination is not
2081 // supported, but this will be checked later by CheckFramebufferStatus.
2082 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2083 GL_DEPTH_COMPONENT16 : 0;
2084 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2085 GL_STENCIL_INDEX8 : 0;
2086 }
2087 } else {
2088 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2089 GL_RGBA : GL_RGB;
2090
2091 // If depth is requested at all, use the packed depth stencil format if
2092 // it's available, as some desktop GL drivers don't support any non-packed
2093 // formats for depth attachments.
2094 const bool depth24_stencil8_supported =
2095 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272096 VLOG(1) << "GL_EXT_packed_depth_stencil "
2097 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:022098
[email protected]71ee3642010-10-14 18:08:002099 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2100 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022101 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2102 offscreen_target_stencil_format_ = 0;
2103 } else {
2104 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2105 GL_DEPTH_COMPONENT : 0;
2106 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2107 GL_STENCIL_INDEX : 0;
2108 }
2109 }
2110
[email protected]97872062010-11-03 19:07:052111 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2112 GL_RGBA : GL_RGB;
2113
[email protected]6217d392010-03-25 22:08:352114 // Create the target frame buffer. This is the one that the client renders
2115 // directly to.
2116 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
2117 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022118 // Due to GLES2 format limitations, either the color texture (for
2119 // non-multisampling) or the color render buffer (for multisampling) will be
2120 // attached to the offscreen frame buffer. The render buffer has more
2121 // limited formats available to it, but the texture can't do multisampling.
2122 if (IsOffscreenBufferMultisampled()) {
2123 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
2124 offscreen_target_color_render_buffer_->Create();
2125 } else {
2126 offscreen_target_color_texture_.reset(new Texture(this));
2127 offscreen_target_color_texture_->Create();
2128 }
2129 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152130 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022131 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152132 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:352133
2134 // Create the saved offscreen texture. The target frame buffer is copied
2135 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:022136 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
2137 offscreen_saved_frame_buffer_->Create();
2138 //
[email protected]6217d392010-03-25 22:08:352139 offscreen_saved_color_texture_.reset(new Texture(this));
2140 offscreen_saved_color_texture_->Create();
2141
[email protected]6217d392010-03-25 22:08:352142 // Allocate the render buffers at their initial size and check the status
2143 // of the frame buffers is okay.
[email protected]799b4b22011-08-22 17:09:592144 if (!ResizeOffscreenFrameBuffer(size)) {
[email protected]d0498742010-09-20 20:27:012145 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:352146 Destroy();
2147 return false;
2148 }
2149
2150 // Bind to the new default frame buffer (the offscreen target frame buffer).
2151 // This should now be associated with ID zero.
2152 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2153 }
2154
[email protected]76a0ee102010-04-07 21:03:042155 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2156 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2157 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372158 // mailing list archives. It also implicitly enables the desktop GL
2159 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2160 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152161 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2162 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372163 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152164 }
[email protected]de17df392010-04-23 21:09:412165
[email protected]38d139d2011-07-14 00:38:432166 has_arb_robustness_ = context->HasExtension("GL_ARB_robustness");
2167
[email protected]e82fb792011-09-22 00:33:292168 if (!disallowed_features_.driver_bug_workarounds) {
[email protected]75c023c2011-08-22 23:54:512169#if defined(OS_MACOSX)
[email protected]a2a0fe762011-09-20 00:59:122170 const char* vendor_str = reinterpret_cast<const char*>(
2171 glGetString(GL_VENDOR));
2172 needs_mac_nvidia_driver_workaround_ =
2173 vendor_str && strstr(vendor_str, "NVIDIA");
2174 needs_glsl_built_in_function_emulation_ =
2175 vendor_str && (strstr(vendor_str, "ATI") || strstr(vendor_str, "AMD"));
2176#elif defined(OS_WIN)
2177 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
2178 needs_glsl_built_in_function_emulation_ = true;
[email protected]75c023c2011-08-22 23:54:512179#endif
[email protected]a2a0fe762011-09-20 00:59:122180 }
[email protected]75c023c2011-08-22 23:54:512181
[email protected]c2f8c8402010-12-06 18:07:242182 if (!InitializeShaderTranslator()) {
2183 return false;
[email protected]de17df392010-04-23 21:09:412184 }
[email protected]76a0ee102010-04-07 21:03:042185
[email protected]246a70452010-03-05 21:53:502186 return true;
[email protected]96449d2c2009-11-25 00:01:322187}
2188
[email protected]302ce6d2011-07-07 23:28:112189void GLES2DecoderImpl::UpdateCapabilities() {
2190 util_.set_num_compressed_texture_formats(
2191 validators_->compressed_texture_format.GetValues().size());
2192 util_.set_num_shader_binary_formats(
2193 validators_->shader_binary_format.GetValues().size());
2194}
2195
[email protected]c2f8c8402010-12-06 18:07:242196bool GLES2DecoderImpl::InitializeShaderTranslator() {
2197 // Re-check the state of use_shader_translator_ each time this is called.
2198 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:042199 (feature_info_->feature_flags().chromium_webglsl ||
2200 force_webgl_glsl_validation_) &&
[email protected]c2f8c8402010-12-06 18:07:242201 !use_shader_translator_) {
2202 use_shader_translator_ = true;
2203 }
2204 if (!use_shader_translator_) {
2205 return true;
2206 }
2207 ShBuiltInResources resources;
2208 ShInitBuiltInResources(&resources);
2209 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2210 resources.MaxVertexUniformVectors =
2211 group_->max_vertex_uniform_vectors();
2212 resources.MaxVaryingVectors = group_->max_varying_vectors();
2213 resources.MaxVertexTextureImageUnits =
2214 group_->max_vertex_texture_image_units();
2215 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2216 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2217 resources.MaxFragmentUniformVectors =
2218 group_->max_fragment_uniform_vectors();
2219 resources.MaxDrawBuffers = 1;
[email protected]f0d74742011-10-03 16:31:042220
2221 if (force_webgl_glsl_validation_) {
2222 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2223 } else {
2224 resources.OES_standard_derivatives =
2225 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
[email protected]e51bdf32011-11-23 22:21:462226 resources.ARB_texture_rectangle =
2227 feature_info_->feature_flags().arb_texture_rectangle ? 1 : 0;
[email protected]f0d74742011-10-03 16:31:042228 }
2229
[email protected]c2f8c8402010-12-06 18:07:242230 vertex_translator_.reset(new ShaderTranslator);
[email protected]f0d74742011-10-03 16:31:042231 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ||
2232 feature_info_->feature_flags().chromium_webglsl ?
2233 SH_WEBGL_SPEC : SH_GLES2_SPEC;
[email protected]a2a0fe762011-09-20 00:59:122234 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2235 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2236 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2237 ShaderTranslatorInterface::GlslBuiltInFunctionBehavior function_behavior =
2238 needs_glsl_built_in_function_emulation_ ?
2239 ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated :
2240 ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal;
[email protected]c2f8c8402010-12-06 18:07:242241 if (!vertex_translator_->Init(
[email protected]a2a0fe762011-09-20 00:59:122242 SH_VERTEX_SHADER, shader_spec, &resources,
2243 implementation_type, function_behavior)) {
[email protected]c2f8c8402010-12-06 18:07:242244 LOG(ERROR) << "Could not initialize vertex shader translator.";
2245 Destroy();
2246 return false;
2247 }
2248 fragment_translator_.reset(new ShaderTranslator);
2249 if (!fragment_translator_->Init(
[email protected]a2a0fe762011-09-20 00:59:122250 SH_FRAGMENT_SHADER, shader_spec, &resources,
2251 implementation_type, function_behavior)) {
[email protected]c2f8c8402010-12-06 18:07:242252 LOG(ERROR) << "Could not initialize fragment shader translator.";
2253 Destroy();
2254 return false;
2255 }
2256 return true;
2257}
2258
[email protected]ae51d192010-04-27 00:48:032259bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472260 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032261 if (GetBufferInfo(client_ids[ii])) {
2262 return false;
2263 }
2264 }
2265 scoped_array<GLuint> service_ids(new GLuint[n]);
2266 glGenBuffersARB(n, service_ids.get());
2267 for (GLsizei ii = 0; ii < n; ++ii) {
2268 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2269 }
2270 return true;
2271}
2272
2273bool GLES2DecoderImpl::GenFramebuffersHelper(
2274 GLsizei n, const GLuint* client_ids) {
2275 for (GLsizei ii = 0; ii < n; ++ii) {
2276 if (GetFramebufferInfo(client_ids[ii])) {
2277 return false;
2278 }
2279 }
2280 scoped_array<GLuint> service_ids(new GLuint[n]);
2281 glGenFramebuffersEXT(n, service_ids.get());
2282 for (GLsizei ii = 0; ii < n; ++ii) {
2283 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2284 }
2285 return true;
2286}
2287
2288bool GLES2DecoderImpl::GenRenderbuffersHelper(
2289 GLsizei n, const GLuint* client_ids) {
2290 for (GLsizei ii = 0; ii < n; ++ii) {
2291 if (GetRenderbufferInfo(client_ids[ii])) {
2292 return false;
2293 }
2294 }
2295 scoped_array<GLuint> service_ids(new GLuint[n]);
2296 glGenRenderbuffersEXT(n, service_ids.get());
2297 for (GLsizei ii = 0; ii < n; ++ii) {
2298 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2299 }
2300 return true;
2301}
2302
2303bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2304 for (GLsizei ii = 0; ii < n; ++ii) {
2305 if (GetTextureInfo(client_ids[ii])) {
2306 return false;
2307 }
2308 }
2309 scoped_array<GLuint> service_ids(new GLuint[n]);
2310 glGenTextures(n, service_ids.get());
2311 for (GLsizei ii = 0; ii < n; ++ii) {
2312 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2313 }
2314 return true;
2315}
2316
2317void GLES2DecoderImpl::DeleteBuffersHelper(
2318 GLsizei n, const GLuint* client_ids) {
2319 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102320 BufferManager::BufferInfo* buffer = GetBufferInfo(client_ids[ii]);
2321 if (buffer && !buffer->IsDeleted()) {
[email protected]3757a372012-01-19 05:20:442322 vertex_attrib_manager_->Unbind(buffer);
[email protected]a0b78dc2011-11-11 10:43:102323 if (bound_array_buffer_ == buffer) {
2324 bound_array_buffer_ = NULL;
2325 }
2326 if (bound_element_array_buffer_ == buffer) {
2327 bound_element_array_buffer_ = NULL;
2328 }
2329 GLuint service_id = buffer->service_id();
[email protected]ae51d192010-04-27 00:48:032330 glDeleteBuffersARB(1, &service_id);
2331 RemoveBufferInfo(client_ids[ii]);
2332 }
[email protected]a93bb842010-02-16 23:03:472333 }
[email protected]07f54fcc2009-12-22 02:46:302334}
2335
[email protected]ae51d192010-04-27 00:48:032336void GLES2DecoderImpl::DeleteFramebuffersHelper(
2337 GLsizei n, const GLuint* client_ids) {
[email protected]b177ae22011-11-01 03:29:112338 bool supports_seperate_framebuffer_binds =
2339 feature_info_->feature_flags().chromium_framebuffer_multisample;
2340
[email protected]a25fa872010-03-25 02:57:582341 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102342 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ae51d192010-04-27 00:48:032343 GetFramebufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102344 if (framebuffer && !framebuffer->IsDeleted()) {
2345 if (framebuffer == bound_draw_framebuffer_) {
[email protected]297ca1c2011-06-20 23:08:462346 bound_draw_framebuffer_ = NULL;
2347 state_dirty_ = true;
[email protected]b177ae22011-11-01 03:29:112348 GLenum target = supports_seperate_framebuffer_binds ?
2349 GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER;
2350 glBindFramebufferEXT(target, GetBackbufferServiceId());
2351 }
[email protected]a0b78dc2011-11-11 10:43:102352 if (framebuffer == bound_read_framebuffer_) {
[email protected]b177ae22011-11-01 03:29:112353 bound_read_framebuffer_ = NULL;
2354 GLenum target = supports_seperate_framebuffer_binds ?
2355 GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER;
2356 glBindFramebufferEXT(target, GetBackbufferServiceId());
[email protected]297ca1c2011-06-20 23:08:462357 }
[email protected]a0b78dc2011-11-11 10:43:102358 GLuint service_id = framebuffer->service_id();
[email protected]ae51d192010-04-27 00:48:032359 glDeleteFramebuffersEXT(1, &service_id);
2360 RemoveFramebufferInfo(client_ids[ii]);
2361 }
[email protected]a25fa872010-03-25 02:57:582362 }
[email protected]07f54fcc2009-12-22 02:46:302363}
2364
[email protected]ae51d192010-04-27 00:48:032365void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2366 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102367 bool supports_seperate_framebuffer_binds =
2368 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a25fa872010-03-25 02:57:582369 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102370 RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]ae51d192010-04-27 00:48:032371 GetRenderbufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102372 if (renderbuffer && !renderbuffer->IsDeleted()) {
2373 if (bound_renderbuffer_ == renderbuffer) {
2374 bound_renderbuffer_ = NULL;
2375 }
2376 // Unbind from current framebuffers.
2377 if (supports_seperate_framebuffer_binds) {
2378 if (bound_read_framebuffer_) {
2379 bound_read_framebuffer_->UnbindRenderbuffer(
2380 GL_READ_FRAMEBUFFER, renderbuffer);
2381 }
2382 if (bound_draw_framebuffer_) {
2383 bound_draw_framebuffer_->UnbindRenderbuffer(
2384 GL_DRAW_FRAMEBUFFER, renderbuffer);
2385 }
2386 } else {
2387 if (bound_draw_framebuffer_) {
2388 bound_draw_framebuffer_->UnbindRenderbuffer(
2389 GL_FRAMEBUFFER, renderbuffer);
2390 }
2391 }
[email protected]297ca1c2011-06-20 23:08:462392 state_dirty_ = true;
[email protected]a0b78dc2011-11-11 10:43:102393 GLuint service_id = renderbuffer->service_id();
[email protected]ae51d192010-04-27 00:48:032394 glDeleteRenderbuffersEXT(1, &service_id);
2395 RemoveRenderbufferInfo(client_ids[ii]);
2396 }
[email protected]a25fa872010-03-25 02:57:582397 }
[email protected]07f54fcc2009-12-22 02:46:302398}
2399
[email protected]ae51d192010-04-27 00:48:032400void GLES2DecoderImpl::DeleteTexturesHelper(
2401 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102402 bool supports_seperate_framebuffer_binds =
2403 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a93bb842010-02-16 23:03:472404 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102405 TextureManager::TextureInfo* texture = GetTextureInfo(client_ids[ii]);
2406 if (texture && !texture->IsDeleted()) {
2407 if (texture->IsAttachedToFramebuffer()) {
[email protected]297ca1c2011-06-20 23:08:462408 state_dirty_ = true;
2409 }
[email protected]a0b78dc2011-11-11 10:43:102410 // Unbind texture from texture units.
2411 for (size_t jj = 0; jj < group_->max_texture_units(); ++jj) {
2412 texture_units_[ii].Unbind(texture);
2413 }
2414 // Unbind from current framebuffers.
2415 if (supports_seperate_framebuffer_binds) {
2416 if (bound_read_framebuffer_) {
2417 bound_read_framebuffer_->UnbindTexture(GL_READ_FRAMEBUFFER, texture);
2418 }
2419 if (bound_draw_framebuffer_) {
2420 bound_draw_framebuffer_->UnbindTexture(GL_DRAW_FRAMEBUFFER, texture);
2421 }
2422 } else {
2423 if (bound_draw_framebuffer_) {
2424 bound_draw_framebuffer_->UnbindTexture(GL_FRAMEBUFFER, texture);
2425 }
2426 }
2427 GLuint service_id = texture->service_id();
2428 if (texture->IsStreamTexture() && stream_texture_manager_) {
[email protected]b0af4f52011-09-28 22:04:422429 stream_texture_manager_->DestroyStreamTexture(service_id);
2430 }
[email protected]e51bdf32011-11-23 22:21:462431#if defined(OS_MACOSX)
2432 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2433 ReleaseIOSurfaceForTexture(service_id);
2434 }
2435#endif
[email protected]5f4f2a732011-07-30 00:47:552436 glDeleteTextures(1, &service_id);
[email protected]ae51d192010-04-27 00:48:032437 RemoveTextureInfo(client_ids[ii]);
2438 }
[email protected]a93bb842010-02-16 23:03:472439 }
[email protected]07f54fcc2009-12-22 02:46:302440}
2441
[email protected]43f28f832010-02-03 02:28:482442// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322443
[email protected]eb54a562010-01-20 21:55:182444bool GLES2DecoderImpl::MakeCurrent() {
[email protected]38d139d2011-07-14 00:38:432445 bool result = context_.get() ? context_->MakeCurrent(surface_.get()) : false;
2446 if (result && WasContextLost()) {
2447 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2448 result = false;
2449 }
2450
2451 return result;
[email protected]eb54a562010-01-20 21:55:182452}
2453
[email protected]a96a6022011-11-04 00:58:122454void GLES2DecoderImpl::ReleaseCurrent() {
2455 if (context_.get())
2456 context_->ReleaseCurrent(surface_.get());
2457}
2458
[email protected]8e3e0662010-08-23 18:46:302459void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
[email protected]0d6bfdc2011-11-02 01:32:202460 RenderbufferManager::RenderbufferInfo* renderbuffer =
2461 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
[email protected]8e3e0662010-08-23 18:46:302462 glBindRenderbufferEXT(
[email protected]0d6bfdc2011-11-02 01:32:202463 GL_RENDERBUFFER, renderbuffer ? renderbuffer->service_id() : 0);
[email protected]8e3e0662010-08-23 18:46:302464}
2465
2466static void RebindCurrentFramebuffer(
2467 GLenum target,
2468 FramebufferManager::FramebufferInfo* info,
2469 FrameBuffer* offscreen_frame_buffer) {
2470 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462471
[email protected]8e3e0662010-08-23 18:46:302472 if (framebuffer_id == 0 && offscreen_frame_buffer) {
2473 framebuffer_id = offscreen_frame_buffer->id();
2474 }
[email protected]297ca1c2011-06-20 23:08:462475
[email protected]8e3e0662010-08-23 18:46:302476 glBindFramebufferEXT(target, framebuffer_id);
2477}
2478
2479void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]297ca1c2011-06-20 23:08:462480 state_dirty_ = true;
2481
[email protected]a3ded6d2010-10-19 06:44:392482 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302483 RebindCurrentFramebuffer(
2484 GL_FRAMEBUFFER,
2485 bound_draw_framebuffer_.get(),
2486 offscreen_target_frame_buffer_.get());
2487 } else {
2488 RebindCurrentFramebuffer(
2489 GL_READ_FRAMEBUFFER_EXT,
2490 bound_read_framebuffer_.get(),
2491 offscreen_target_frame_buffer_.get());
2492 RebindCurrentFramebuffer(
2493 GL_DRAW_FRAMEBUFFER_EXT,
2494 bound_draw_framebuffer_.get(),
2495 offscreen_target_frame_buffer_.get());
2496 }
2497}
2498
2499void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2500 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2501 GLuint last_id;
2502 if (info.bound_texture_2d) {
2503 last_id = info.bound_texture_2d->service_id();
2504 } else {
2505 last_id = 0;
2506 }
2507
2508 glBindTexture(GL_TEXTURE_2D, last_id);
2509 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2510}
2511
[email protected]0d6bfdc2011-11-02 01:32:202512bool GLES2DecoderImpl::CheckFramebufferValid(
2513 FramebufferManager::FramebufferInfo* framebuffer,
2514 GLenum target, const char* func_name) {
[email protected]a0b78dc2011-11-11 10:43:102515 if (!framebuffer) {
[email protected]0d6bfdc2011-11-02 01:32:202516 return true;
2517 }
2518
[email protected]968351b2011-12-20 08:26:512519 if (framebuffer_manager()->IsComplete(framebuffer)) {
2520 return true;
2521 }
2522
[email protected]0d6bfdc2011-11-02 01:32:202523 GLenum completeness = framebuffer->IsPossiblyComplete();
2524 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
2525 SetGLError(
2526 GL_INVALID_FRAMEBUFFER_OPERATION,
2527 (std::string(func_name) + " framebuffer incomplete").c_str());
[email protected]3a03a8f2011-03-19 00:51:272528 return false;
2529 }
[email protected]0d6bfdc2011-11-02 01:32:202530
2531 // Are all the attachments cleared?
2532 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2533 texture_manager()->HaveUnclearedMips()) {
2534 if (!framebuffer->IsCleared()) {
2535 // Can we clear them?
2536 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2537 SetGLError(
2538 GL_INVALID_FRAMEBUFFER_OPERATION,
2539 (std::string(func_name) +
2540 " framebuffer incomplete (clear)").c_str());
2541 return false;
2542 }
2543 ClearUnclearedAttachments(target, framebuffer);
2544 }
2545 }
2546
[email protected]968351b2011-12-20 08:26:512547 if (!framebuffer_manager()->IsComplete(framebuffer)) {
2548 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2549 SetGLError(
2550 GL_INVALID_FRAMEBUFFER_OPERATION,
2551 (std::string(func_name) +
2552 " framebuffer incomplete (check)").c_str());
2553 return false;
2554 }
2555 framebuffer_manager()->MarkAsComplete(framebuffer);
2556 }
2557
[email protected]0d6bfdc2011-11-02 01:32:202558 // NOTE: At this point we don't know if the framebuffer is complete but
2559 // we DO know that everything that needs to be cleared has been cleared.
[email protected]3a03a8f2011-03-19 00:51:272560 return true;
2561}
2562
[email protected]0d6bfdc2011-11-02 01:32:202563bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
2564 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
2565 return CheckFramebufferValid(
2566 bound_draw_framebuffer_, GL_FRAMEBUFFER_EXT, func_name);
2567 }
2568 return CheckFramebufferValid(
2569 bound_draw_framebuffer_, GL_DRAW_FRAMEBUFFER_EXT, func_name) &&
2570 CheckFramebufferValid(
2571 bound_read_framebuffer_, GL_READ_FRAMEBUFFER_EXT, func_name);
2572}
2573
[email protected]8e3e0662010-08-23 18:46:302574gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
[email protected]0d6bfdc2011-11-02 01:32:202575 FramebufferManager::FramebufferInfo* framebuffer =
2576 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2577 if (framebuffer != NULL) {
[email protected]9edc6b22010-12-23 02:00:262578 const FramebufferManager::FramebufferInfo::Attachment* attachment =
[email protected]0d6bfdc2011-11-02 01:32:202579 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
[email protected]9edc6b22010-12-23 02:00:262580 if (attachment) {
2581 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502582 }
[email protected]9edc6b22010-12-23 02:00:262583 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022584 } else if (offscreen_target_frame_buffer_.get()) {
2585 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352586 } else {
[email protected]f62a5ab2011-05-23 20:34:152587 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022588 }
[email protected]246a70452010-03-05 21:53:502589}
2590
[email protected]9edc6b22010-12-23 02:00:262591GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202592 FramebufferManager::FramebufferInfo* framebuffer =
2593 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2594 if (framebuffer != NULL) {
2595 return framebuffer->GetColorAttachmentFormat();
[email protected]297ca1c2011-06-20 23:08:462596 } else if (offscreen_target_frame_buffer_.get()) {
2597 return offscreen_target_color_format_;
2598 } else {
2599 return back_buffer_color_format_;
2600 }
2601}
2602
2603GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202604 FramebufferManager::FramebufferInfo* framebuffer =
2605 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
2606 if (framebuffer != NULL) {
2607 return framebuffer->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262608 } else if (offscreen_target_frame_buffer_.get()) {
2609 return offscreen_target_color_format_;
2610 } else {
[email protected]32fe9aa2011-01-21 23:47:132611 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262612 }
2613}
2614
[email protected]9a5afa432011-07-22 18:16:392615void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]34ff8b0c2010-10-01 20:06:022616 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582617 // Update the info about the offscreen saved color texture in the parent.
2618 // The reference to the parent is a weak pointer and will become null if the
2619 // parent is later destroyed.
[email protected]6217d392010-03-25 22:08:352620 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]8d25d042010-06-16 19:48:142621 GLuint client_id;
[email protected]262d7aa2010-12-03 22:07:292622 TextureManager* parent_texture_manager = parent_->texture_manager();
2623 CHECK(parent_texture_manager->GetClientId(service_id, &client_id));
[email protected]8d25d042010-06-16 19:48:142624 TextureManager::TextureInfo* info = parent_->GetTextureInfo(client_id);
[email protected]6217d392010-03-25 22:08:352625 DCHECK(info);
2626
[email protected]262d7aa2010-12-03 22:07:292627 parent_texture_manager->SetLevelInfo(
[email protected]ef526492010-06-02 23:12:252628 info,
2629 GL_TEXTURE_2D,
2630 0, // level
2631 GL_RGBA,
[email protected]799b4b22011-08-22 17:09:592632 offscreen_size_.width(),
2633 offscreen_size_.height(),
[email protected]ef526492010-06-02 23:12:252634 1, // depth
2635 0, // border
2636 GL_RGBA,
[email protected]0d6bfdc2011-11-02 01:32:202637 GL_UNSIGNED_BYTE,
2638 true);
[email protected]262d7aa2010-12-03 22:07:292639 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042640 info,
2641 GL_TEXTURE_MAG_FILTER,
2642 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292643 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042644 info,
2645 GL_TEXTURE_MIN_FILTER,
2646 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292647 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042648 info,
2649 GL_TEXTURE_WRAP_S,
2650 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292651 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042652 info,
2653 GL_TEXTURE_WRAP_T,
2654 GL_CLAMP_TO_EDGE);
[email protected]0c8c9d22010-06-25 17:36:392655 }
[email protected]6217d392010-03-25 22:08:352656}
2657
[email protected]799b4b22011-08-22 17:09:592658void GLES2DecoderImpl::SetResizeCallback(
[email protected]9d37f062011-11-22 01:24:522659 const base::Callback<void(gfx::Size)>& callback) {
2660 resize_callback_ = callback;
[email protected]7ff86b92010-11-25 17:50:002661}
2662
[email protected]6b6e7ee2011-12-13 08:04:522663void GLES2DecoderImpl::SetMsgCallback(const MsgCallback& callback) {
2664 msg_callback_ = callback;
2665}
2666
[email protected]b0af4f52011-09-28 22:04:422667void GLES2DecoderImpl::SetStreamTextureManager(StreamTextureManager* manager) {
2668 stream_texture_manager_ = manager;
2669}
2670
[email protected]1318e922010-09-17 22:03:162671bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2672 uint32* service_texture_id) {
2673 TextureManager::TextureInfo* texture =
2674 texture_manager()->GetTextureInfo(client_texture_id);
2675 if (texture) {
2676 *service_texture_id = texture->service_id();
2677 return true;
2678 }
2679 return false;
2680}
2681
[email protected]96449d2c2009-11-25 00:01:322682void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392683 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052684
[email protected]3c644d82011-06-20 19:58:242685 SetParent(NULL, 0);
2686
[email protected]80eb6b52012-01-19 00:14:412687 // Unbind everything.
[email protected]3757a372012-01-19 05:20:442688 vertex_attrib_manager_.reset();
[email protected]80eb6b52012-01-19 00:14:412689 texture_units_.reset();
2690 bound_array_buffer_ = NULL;
2691 bound_element_array_buffer_ = NULL;
2692 current_program_ = NULL;
2693 bound_read_framebuffer_ = NULL;
2694 bound_draw_framebuffer_ = NULL;
2695 bound_renderbuffer_ = NULL;
2696
[email protected]eadc96792010-10-27 19:39:392697 if (have_context) {
[email protected]ca488e12010-12-13 20:06:142698 if (current_program_) {
2699 program_manager()->UnuseProgram(shader_manager(), current_program_);
2700 current_program_ = NULL;
2701 }
2702
[email protected]b1122982010-05-17 23:04:242703 if (attrib_0_buffer_id_) {
2704 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2705 }
[email protected]8fbedc02010-11-18 18:43:402706 if (fixed_attrib_buffer_id_) {
2707 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2708 }
[email protected]b1122982010-05-17 23:04:242709
[email protected]97872062010-11-03 19:07:052710 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542711 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052712 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542713 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052714 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022715 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052716 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152717 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052718 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152719 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052720 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022721 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052722 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542723 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:272724 if (offscreen_resolved_frame_buffer_.get())
2725 offscreen_resolved_frame_buffer_->Destroy();
2726 if (offscreen_resolved_color_texture_.get())
2727 offscreen_resolved_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052728 } else {
2729 if (offscreen_target_frame_buffer_.get())
2730 offscreen_target_frame_buffer_->Invalidate();
2731 if (offscreen_target_color_texture_.get())
2732 offscreen_target_color_texture_->Invalidate();
2733 if (offscreen_target_color_render_buffer_.get())
2734 offscreen_target_color_render_buffer_->Invalidate();
2735 if (offscreen_target_depth_render_buffer_.get())
2736 offscreen_target_depth_render_buffer_->Invalidate();
2737 if (offscreen_target_stencil_render_buffer_.get())
2738 offscreen_target_stencil_render_buffer_->Invalidate();
2739 if (offscreen_saved_frame_buffer_.get())
2740 offscreen_saved_frame_buffer_->Invalidate();
2741 if (offscreen_saved_color_texture_.get())
2742 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:272743 if (offscreen_resolved_frame_buffer_.get())
2744 offscreen_resolved_frame_buffer_->Invalidate();
2745 if (offscreen_resolved_color_texture_.get())
2746 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022747 }
[email protected]97872062010-11-03 19:07:052748
[email protected]1871a092011-10-10 21:46:422749 if (group_) {
2750 group_->Destroy(have_context);
2751 group_ = NULL;
2752 }
[email protected]3ae019382011-10-05 19:42:412753
[email protected]fe871662011-06-16 20:43:052754 if (context_.get()) {
2755 context_->ReleaseCurrent(NULL);
[email protected]79311e82011-09-20 00:40:502756 context_ = NULL;
[email protected]fe871662011-06-16 20:43:052757 }
[email protected]0fc35742011-04-13 17:57:542758
[email protected]97872062010-11-03 19:07:052759 offscreen_target_frame_buffer_.reset();
2760 offscreen_target_color_texture_.reset();
2761 offscreen_target_color_render_buffer_.reset();
2762 offscreen_target_depth_render_buffer_.reset();
2763 offscreen_target_stencil_render_buffer_.reset();
2764 offscreen_saved_frame_buffer_.reset();
2765 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:272766 offscreen_resolved_frame_buffer_.reset();
2767 offscreen_resolved_color_texture_.reset();
[email protected]e51bdf32011-11-23 22:21:462768
2769#if defined(OS_MACOSX)
2770 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
2771 it != texture_to_io_surface_map_.end(); ++it) {
2772 CFRelease(it->second);
2773 }
2774 texture_to_io_surface_map_.clear();
2775#endif
[email protected]96449d2c2009-11-25 00:01:322776}
2777
[email protected]3c644d82011-06-20 19:58:242778bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
2779 uint32 new_parent_texture_id) {
[email protected]9a5afa432011-07-22 18:16:392780 if (!offscreen_saved_color_texture_.get())
2781 return false;
2782
[email protected]3c644d82011-06-20 19:58:242783 // Remove the saved frame buffer mapping from the parent decoder. The
2784 // parent pointer is a weak pointer so it will be null if the parent has
2785 // already been destroyed.
2786 if (parent_) {
2787 // First check the texture has been mapped into the parent. This might not
2788 // be the case if initialization failed midway through.
2789 GLuint service_id = offscreen_saved_color_texture_->id();
2790 GLuint client_id = 0;
2791 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
[email protected]80eb6b52012-01-19 00:14:412792 parent_->texture_manager()->RemoveTextureInfo(client_id);
[email protected]3c644d82011-06-20 19:58:242793 }
2794 }
2795
2796 GLES2DecoderImpl* new_parent_impl = static_cast<GLES2DecoderImpl*>(
2797 new_parent);
2798 if (new_parent_impl) {
2799 // Map the ID of the saved offscreen texture into the parent so that
2800 // it can reference it.
2801 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]98687862011-07-11 23:31:302802
2803 // Replace texture info when ID is already in use by parent.
2804 if (new_parent_impl->texture_manager()->GetTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412805 new_parent_texture_id))
[email protected]98687862011-07-11 23:31:302806 new_parent_impl->texture_manager()->RemoveTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412807 new_parent_texture_id);
[email protected]98687862011-07-11 23:31:302808
[email protected]3c644d82011-06-20 19:58:242809 TextureManager::TextureInfo* info =
[email protected]5f4f2a732011-07-30 00:47:552810 new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id);
2811 info->SetNotOwned();
[email protected]80eb6b52012-01-19 00:14:412812 new_parent_impl->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
[email protected]3c644d82011-06-20 19:58:242813
2814 parent_ = new_parent_impl->AsWeakPtr();
[email protected]9a5afa432011-07-22 18:16:392815
2816 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:242817 } else {
2818 parent_.reset();
2819 }
2820
2821 return true;
2822}
2823
[email protected]1078f912011-12-23 13:12:142824void GLES2DecoderImpl::UpdateBackbufferMemoryAccounting() {
2825 size_t total = 0;
2826 if (offscreen_target_frame_buffer_.get()) {
2827 if (offscreen_target_color_texture_.get()) {
2828 total += offscreen_target_color_texture_->estimated_size();
2829 }
2830 if (offscreen_target_color_render_buffer_.get()) {
2831 total += offscreen_target_color_render_buffer_->estimated_size();
2832 }
2833 if (offscreen_target_depth_render_buffer_.get()) {
2834 total += offscreen_target_depth_render_buffer_->estimated_size();
2835 }
2836 if (offscreen_target_stencil_render_buffer_.get()) {
2837 total += offscreen_target_stencil_render_buffer_->estimated_size();
2838 }
2839 if (offscreen_saved_color_texture_.get()) {
2840 total += offscreen_saved_color_texture_->estimated_size();
2841 }
2842 if (offscreen_resolved_color_texture_.get()) {
2843 total += offscreen_resolved_color_texture_->estimated_size();
2844 }
2845 } else {
2846 gfx::Size size = surface_->GetSize();
2847 total += size.width() * size.height() *
2848 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_);
2849 }
2850 TRACE_COUNTER_ID1(
2851 "GLES2DecoderImpl", "BackbufferMemory", this, total);
2852}
2853
[email protected]799b4b22011-08-22 17:09:592854bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2855 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
2856 if (!is_offscreen) {
2857 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
2858 << " with an onscreen framebuffer.";
2859 return false;
2860 }
2861
2862 if (offscreen_size_ == size)
2863 return true;
2864
2865 offscreen_size_ = size;
2866 int w = offscreen_size_.width();
2867 int h = offscreen_size_.height();
2868 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
2869 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2870 << "to allocate storage due to excessive dimensions.";
2871 return false;
2872 }
2873
2874 // Reallocate the offscreen target buffers.
2875 DCHECK(offscreen_target_color_format_);
2876 if (IsOffscreenBufferMultisampled()) {
2877 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2878 offscreen_size_, offscreen_target_color_format_,
2879 offscreen_target_samples_)) {
2880 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2881 << "to allocate storage for offscreen target color buffer.";
2882 return false;
2883 }
2884 } else {
2885 if (!offscreen_target_color_texture_->AllocateStorage(
2886 offscreen_size_, offscreen_target_color_format_)) {
2887 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2888 << "to allocate storage for offscreen target color texture.";
2889 return false;
2890 }
2891 }
2892 if (offscreen_target_depth_format_ &&
2893 !offscreen_target_depth_render_buffer_->AllocateStorage(
2894 offscreen_size_, offscreen_target_depth_format_,
2895 offscreen_target_samples_)) {
2896 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2897 << "to allocate storage for offscreen target depth buffer.";
2898 return false;
2899 }
2900 if (offscreen_target_stencil_format_ &&
2901 !offscreen_target_stencil_render_buffer_->AllocateStorage(
2902 offscreen_size_, offscreen_target_stencil_format_,
2903 offscreen_target_samples_)) {
2904 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2905 << "to allocate storage for offscreen target stencil buffer.";
2906 return false;
2907 }
[email protected]1078f912011-12-23 13:12:142908 UpdateBackbufferMemoryAccounting();
[email protected]799b4b22011-08-22 17:09:592909
2910 // Attach the offscreen target buffers to the target frame buffer.
2911 if (IsOffscreenBufferMultisampled()) {
2912 offscreen_target_frame_buffer_->AttachRenderBuffer(
2913 GL_COLOR_ATTACHMENT0,
2914 offscreen_target_color_render_buffer_.get());
2915 } else {
2916 offscreen_target_frame_buffer_->AttachRenderTexture(
2917 offscreen_target_color_texture_.get());
2918 }
2919 if (offscreen_target_depth_format_) {
2920 offscreen_target_frame_buffer_->AttachRenderBuffer(
2921 GL_DEPTH_ATTACHMENT,
2922 offscreen_target_depth_render_buffer_.get());
2923 }
2924 const bool packed_depth_stencil =
2925 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2926 if (packed_depth_stencil) {
2927 offscreen_target_frame_buffer_->AttachRenderBuffer(
2928 GL_STENCIL_ATTACHMENT,
2929 offscreen_target_depth_render_buffer_.get());
2930 } else if (offscreen_target_stencil_format_) {
2931 offscreen_target_frame_buffer_->AttachRenderBuffer(
2932 GL_STENCIL_ATTACHMENT,
2933 offscreen_target_stencil_render_buffer_.get());
2934 }
2935
2936 if (offscreen_target_frame_buffer_->CheckStatus() !=
2937 GL_FRAMEBUFFER_COMPLETE) {
2938 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2939 << "because offscreen FBO was incomplete.";
2940 return false;
2941 }
2942
2943 // Clear the target frame buffer.
2944 {
2945 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
2946 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2947 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
2948 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2949 glClearStencil(0);
2950 glStencilMaskSeparate(GL_FRONT, -1);
2951 glStencilMaskSeparate(GL_BACK, -1);
2952 glClearDepth(0);
2953 glDepthMask(GL_TRUE);
2954 glDisable(GL_SCISSOR_TEST);
2955 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2956 RestoreClearState();
2957 }
[email protected]d85ef76d2011-09-08 22:21:432958
2959 // Destroy the offscreen resolved framebuffers.
2960 if (offscreen_resolved_frame_buffer_.get())
2961 offscreen_resolved_frame_buffer_->Destroy();
2962 if (offscreen_resolved_color_texture_.get())
2963 offscreen_resolved_color_texture_->Destroy();
2964 offscreen_resolved_color_texture_.reset();
2965 offscreen_resolved_frame_buffer_.reset();
2966
[email protected]799b4b22011-08-22 17:09:592967 return true;
[email protected]6217d392010-03-25 22:08:352968}
2969
[email protected]799b4b22011-08-22 17:09:592970error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
2971 uint32 immediate_data_size, const gles2::ResizeCHROMIUM& c) {
2972 GLuint width = static_cast<GLuint>(c.width);
2973 GLuint height = static_cast<GLuint>(c.height);
2974 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
[email protected]a0d989162011-11-22 13:15:072975#if defined(OS_POSIX) && !defined(OS_MACOSX) && \
2976 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
[email protected]7ff86b92010-11-25 17:50:002977 // Make sure that we are done drawing to the back buffer before resizing.
2978 glFinish();
2979#endif
[email protected]799b4b22011-08-22 17:09:592980 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
2981 if (is_offscreen) {
2982 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height)))
2983 return error::kLostContext;
[email protected]7ff86b92010-11-25 17:50:002984 }
[email protected]799b4b22011-08-22 17:09:592985
[email protected]9d37f062011-11-22 01:24:522986 if (!resize_callback_.is_null()) {
2987 resize_callback_.Run(gfx::Size(width, height));
[email protected]c777de52011-09-09 23:08:562988 DCHECK(context_->IsCurrent(surface_.get()));
2989 if (!context_->IsCurrent(surface_.get()))
[email protected]658f7562011-09-09 05:24:052990 return error::kLostContext;
[email protected]658f7562011-09-09 05:24:052991 }
[email protected]799b4b22011-08-22 17:09:592992
[email protected]1078f912011-12-23 13:12:142993 UpdateBackbufferMemoryAccounting();
2994
[email protected]799b4b22011-08-22 17:09:592995 return error::kNoError;
[email protected]43ecf372010-11-16 19:19:392996}
2997
[email protected]96449d2c2009-11-25 00:01:322998const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
2999 if (command_id > kStartPoint && command_id < kNumCommands) {
3000 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3001 }
3002 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3003}
3004
3005// Decode command with its arguments, and call the corresponding GL function.
3006// Note: args is a pointer to the command buffer. As such, it could be changed
3007// by a (malicious) client at any time, so if validation has to happen, it
3008// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:143009error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:323010 unsigned int command,
3011 unsigned int arg_count,
3012 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:143013 error::Error result = error::kNoError;
[email protected]e844ae22012-01-14 03:36:263014 if (log_commands()) {
[email protected]4297cbe2011-11-03 18:04:003015 LOG(INFO) << "[" << this << "]" << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193016 }
[email protected]96449d2c2009-11-25 00:01:323017 unsigned int command_index = command - kStartPoint - 1;
3018 if (command_index < arraysize(g_command_info)) {
3019 const CommandInfo& info = g_command_info[command_index];
3020 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3021 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3022 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:193023 uint32 immediate_data_size =
3024 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:323025 switch (command) {
3026 #define GLES2_CMD_OP(name) \
3027 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:193028 result = Handle ## name( \
3029 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:323030 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:193031 break; \
[email protected]96449d2c2009-11-25 00:01:323032
3033 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:323034 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:383035 }
3036 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:303037 GLenum error;
3038 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]e844ae22012-01-14 03:36:263039 SetGLError(error, "GL error from driver");
3040 LOG(INFO) << "[" << this << "]"
3041 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3042 << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193043 }
[email protected]96449d2c2009-11-25 00:01:323044 }
3045 } else {
[email protected]f7a64ee2010-02-01 22:24:143046 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:323047 }
[email protected]b9849abf2009-11-25 19:13:193048 } else {
3049 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:323050 }
[email protected]a3a93e7b2010-08-28 00:48:563051 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3052 result = current_decoder_error_;
3053 current_decoder_error_ = error::kNoError;
3054 }
[email protected]b9849abf2009-11-25 19:13:193055 return result;
[email protected]96449d2c2009-11-25 00:01:323056}
3057
[email protected]ae51d192010-04-27 00:48:033058void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
3059 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:503060}
3061
[email protected]ae51d192010-04-27 00:48:033062bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3063 if (GetProgramInfo(client_id)) {
3064 return false;
3065 }
[email protected]96449d2c2009-11-25 00:01:323066 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:033067 if (service_id != 0) {
3068 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:323069 }
[email protected]ae51d192010-04-27 00:48:033070 return true;
[email protected]96449d2c2009-11-25 00:01:323071}
3072
[email protected]ae51d192010-04-27 00:48:033073bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3074 if (GetShaderInfo(client_id)) {
3075 return false;
[email protected]96449d2c2009-11-25 00:01:323076 }
[email protected]ae51d192010-04-27 00:48:033077 GLuint service_id = glCreateShader(type);
3078 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:383079 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:033080 }
3081 return true;
[email protected]96449d2c2009-11-25 00:01:323082}
3083
[email protected]3916c97e2010-02-25 03:20:503084void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:453085 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]660858b2011-07-13 23:16:143086 if (texture_index >= group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:293087 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:503088 return;
3089 }
[email protected]36cef8ce2010-03-16 07:34:453090 active_texture_unit_ = texture_index;
3091 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:503092}
3093
[email protected]051b1372010-04-12 02:42:083094void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:503095 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083096 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033097 if (client_id != 0) {
3098 info = GetBufferInfo(client_id);
3099 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353100 if (!group_->bind_generates_resource()) {
3101 SetGLError(GL_INVALID_VALUE,
3102 "glBindBuffer: id not generated by glGenBuffers");
3103 return;
3104 }
3105
[email protected]ae51d192010-04-27 00:48:033106 // It's a new id so make a buffer info for it.
3107 glGenBuffersARB(1, &service_id);
3108 CreateBufferInfo(client_id, service_id);
3109 info = GetBufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573110 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103111 group_->GetIdAllocator(id_namespaces::kBuffers);
3112 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033113 }
[email protected]051b1372010-04-12 02:42:083114 }
[email protected]ae51d192010-04-27 00:48:033115 if (info) {
[email protected]4e8a5b122010-05-08 22:00:103116 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:293117 SetGLError(GL_INVALID_OPERATION,
3118 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:473119 return;
3120 }
[email protected]ae51d192010-04-27 00:48:033121 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:473122 }
[email protected]96449d2c2009-11-25 00:01:323123 switch (target) {
3124 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503125 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323126 break;
3127 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503128 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323129 break;
3130 default:
[email protected]a93bb842010-02-16 23:03:473131 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:323132 break;
3133 }
[email protected]051b1372010-04-12 02:42:083134 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:323135}
3136
[email protected]297ca1c2011-06-20 23:08:463137bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
3138 return (GLES2Util::GetChannelsForFormat(
3139 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3140}
3141
3142bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203143 FramebufferManager::FramebufferInfo* framebuffer =
3144 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3145 if (framebuffer) {
3146 return framebuffer->HasDepthAttachment();
[email protected]297ca1c2011-06-20 23:08:463147 }
3148 if (offscreen_target_frame_buffer_.get()) {
3149 return offscreen_target_depth_format_ != 0;
3150 }
3151 return back_buffer_has_depth_;
3152}
3153
3154bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203155 FramebufferManager::FramebufferInfo* framebuffer =
3156 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3157 if (framebuffer) {
3158 return framebuffer->HasStencilAttachment();
[email protected]297ca1c2011-06-20 23:08:463159 }
3160 if (offscreen_target_frame_buffer_.get()) {
3161 return offscreen_target_stencil_format_ != 0 ||
3162 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3163 }
3164 return back_buffer_has_stencil_;
3165}
3166
3167void GLES2DecoderImpl::ApplyDirtyState() {
3168 if (state_dirty_) {
3169 glColorMask(
3170 mask_red_, mask_green_, mask_blue_,
3171 mask_alpha_ && BoundFramebufferHasColorAttachmentWithAlpha());
3172 bool have_depth = BoundFramebufferHasDepthAttachment();
3173 glDepthMask(mask_depth_ && have_depth);
3174 EnableDisable(GL_DEPTH_TEST, enable_depth_test_ && have_depth);
3175 bool have_stencil = BoundFramebufferHasStencilAttachment();
3176 glStencilMaskSeparate(GL_FRONT, have_stencil ? mask_stencil_front_ : 0);
3177 glStencilMaskSeparate(GL_BACK, have_stencil ? mask_stencil_back_ : 0);
3178 EnableDisable(GL_STENCIL_TEST, enable_stencil_test_ && have_stencil);
3179 state_dirty_ = false;
3180 }
3181}
3182
[email protected]b177ae22011-11-01 03:29:113183GLuint GLES2DecoderImpl::GetBackbufferServiceId() {
3184 return (offscreen_target_frame_buffer_.get()) ?
3185 offscreen_target_frame_buffer_->id() :
3186 surface_->GetBackingFrameBufferObject();
3187}
3188
[email protected]051b1372010-04-12 02:42:083189void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3190 FramebufferManager::FramebufferInfo* info = NULL;
3191 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033192 if (client_id != 0) {
3193 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083194 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353195 if (!group_->bind_generates_resource()) {
3196 SetGLError(GL_INVALID_VALUE,
3197 "glBindFramebuffer: id not generated by glGenFramebuffers");
3198 return;
3199 }
3200
[email protected]ae51d192010-04-27 00:48:033201 // It's a new id so make a framebuffer info for it.
3202 glGenFramebuffersEXT(1, &service_id);
3203 CreateFramebufferInfo(client_id, service_id);
3204 info = GetFramebufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573205 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103206 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3207 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033208 } else {
3209 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083210 }
[email protected]06c8b082011-01-05 18:00:363211 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083212 }
[email protected]8e3e0662010-08-23 18:46:303213
3214 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
3215 bound_draw_framebuffer_ = info;
3216 }
3217 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
3218 bound_read_framebuffer_ = info;
3219 }
[email protected]6217d392010-03-25 22:08:353220
[email protected]297ca1c2011-06-20 23:08:463221 state_dirty_ = true;
3222
[email protected]b177ae22011-11-01 03:29:113223 // If we are rendering to the backbuffer get the FBO id for any simulated
3224 // backbuffer.
3225 if (info == NULL) {
3226 service_id = GetBackbufferServiceId();
[email protected]297ca1c2011-06-20 23:08:463227 }
[email protected]6217d392010-03-25 22:08:353228
[email protected]051b1372010-04-12 02:42:083229 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563230}
3231
[email protected]051b1372010-04-12 02:42:083232void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
3233 RenderbufferManager::RenderbufferInfo* info = NULL;
3234 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033235 if (client_id != 0) {
3236 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083237 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353238 if (!group_->bind_generates_resource()) {
3239 SetGLError(
3240 GL_INVALID_VALUE,
3241 "glBindRenderbuffer: id not generated by glGenRenderbuffers");
3242 return;
3243 }
3244
[email protected]ae51d192010-04-27 00:48:033245 // It's a new id so make a renderbuffer info for it.
3246 glGenRenderbuffersEXT(1, &service_id);
3247 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:103248 info = GetRenderbufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573249 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103250 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3251 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033252 } else {
3253 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083254 }
[email protected]06c8b082011-01-05 18:00:363255 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083256 }
3257 bound_renderbuffer_ = info;
3258 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563259}
3260
[email protected]051b1372010-04-12 02:42:083261void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033262 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083263 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033264 if (client_id != 0) {
3265 info = GetTextureInfo(client_id);
3266 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353267 if (!group_->bind_generates_resource()) {
3268 SetGLError(GL_INVALID_VALUE,
3269 "glBindTexture: id not generated by glGenTextures");
3270 return;
3271 }
3272
[email protected]ae51d192010-04-27 00:48:033273 // It's a new id so make a texture info for it.
3274 glGenTextures(1, &service_id);
[email protected]80eb6b52012-01-19 00:14:413275 DCHECK_NE(0u, service_id);
[email protected]ae51d192010-04-27 00:48:033276 CreateTextureInfo(client_id, service_id);
3277 info = GetTextureInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573278 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103279 group_->GetIdAllocator(id_namespaces::kTextures);
3280 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033281 }
3282 } else {
3283 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:083284 }
[email protected]ae51d192010-04-27 00:48:033285
[email protected]1958e0e2010-04-22 05:17:153286 // Check the texture exists
3287 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:033288 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:293289 SetGLError(GL_INVALID_OPERATION,
3290 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:153291 return;
3292 }
[email protected]b0af4f52011-09-28 22:04:423293 if (info->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
3294 SetGLError(GL_INVALID_OPERATION,
3295 "glBindTexture: illegal target for stream texture.");
3296 return;
3297 }
[email protected]1958e0e2010-04-22 05:17:153298 if (info->target() == 0) {
[email protected]80eb6b52012-01-19 00:14:413299 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:473300 }
[email protected]ae51d192010-04-27 00:48:033301 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:503302 TextureUnit& unit = texture_units_[active_texture_unit_];
3303 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:473304 switch (target) {
3305 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:503306 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:473307 break;
3308 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:503309 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:473310 break;
[email protected]61eeb33f2011-07-26 15:30:313311 case GL_TEXTURE_EXTERNAL_OES:
3312 unit.bound_texture_external_oes = info;
[email protected]b0af4f52011-09-28 22:04:423313 if (info->IsStreamTexture()) {
3314 DCHECK(stream_texture_manager_);
3315 StreamTexture* stream_tex =
3316 stream_texture_manager_->LookupStreamTexture(info->service_id());
3317 if (stream_tex)
3318 stream_tex->Update();
3319 }
[email protected]61eeb33f2011-07-26 15:30:313320 break;
[email protected]e51bdf32011-11-23 22:21:463321 case GL_TEXTURE_RECTANGLE_ARB:
3322 unit.bound_texture_rectangle_arb = info;
3323 break;
[email protected]a93bb842010-02-16 23:03:473324 default:
3325 NOTREACHED(); // Validation should prevent us getting here.
3326 break;
3327 }
3328}
3329
[email protected]07f54fcc2009-12-22 02:46:303330void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443331 if (vertex_attrib_manager_->Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:123332 if (index != 0 ||
3333 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:243334 glDisableVertexAttribArray(index);
3335 }
[email protected]07f54fcc2009-12-22 02:46:303336 } else {
[email protected]8eee29c2010-04-29 03:38:293337 SetGLError(GL_INVALID_VALUE,
3338 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:303339 }
3340}
3341
3342void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443343 if (vertex_attrib_manager_->Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:303344 glEnableVertexAttribArray(index);
3345 } else {
[email protected]8eee29c2010-04-29 03:38:293346 SetGLError(GL_INVALID_VALUE,
3347 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:303348 }
3349}
3350
[email protected]a93bb842010-02-16 23:03:473351void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:503352 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]97dc7cbe2011-12-06 17:26:173353 if (!info ||
[email protected]80eb6b52012-01-19 00:14:413354 !texture_manager()->MarkMipmapsGenerated(info)) {
[email protected]8eee29c2010-04-29 03:38:293355 SetGLError(GL_INVALID_OPERATION,
3356 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:473357 return;
3358 }
[email protected]59f3ca02011-03-26 22:24:193359 // Workaround for Mac driver bug. In the large scheme of things setting
3360 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
[email protected]a8bad262011-10-21 18:28:563361 // hit so there's probably no need to make this conditional. The bug appears
3362 // to be that if the filtering mode is set to something that doesn't require
3363 // mipmaps for rendering, or is never set to something other than the default,
3364 // then glGenerateMipmap misbehaves.
3365 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
[email protected]a93bb842010-02-16 23:03:473366 glGenerateMipmapEXT(target);
[email protected]59f3ca02011-03-26 22:24:193367 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
[email protected]a93bb842010-02-16 23:03:473368}
3369
[email protected]b273e432010-04-12 17:23:583370bool GLES2DecoderImpl::GetHelper(
3371 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:583372 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:153373 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
3374 switch (pname) {
[email protected]b273e432010-04-12 17:23:583375 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
3376 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103377 if (params) {
[email protected]5094b0f2010-11-09 19:45:243378 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:103379 }
[email protected]b273e432010-04-12 17:23:583380 return true;
3381 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3382 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103383 if (params) {
[email protected]5094b0f2010-11-09 19:45:243384 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:103385 }
[email protected]b273e432010-04-12 17:23:583386 return true;
3387 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
3388 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103389 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483390 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:103391 }
[email protected]b273e432010-04-12 17:23:583392 return true;
3393 case GL_MAX_VARYING_VECTORS:
3394 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103395 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483396 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:103397 }
[email protected]b273e432010-04-12 17:23:583398 return true;
3399 case GL_MAX_VERTEX_UNIFORM_VECTORS:
3400 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103401 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483402 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:103403 }
[email protected]b273e432010-04-12 17:23:583404 return true;
[email protected]5cb735d2011-10-13 01:37:233405 }
3406 }
3407 switch (pname) {
[email protected]5094b0f2010-11-09 19:45:243408 case GL_MAX_VIEWPORT_DIMS:
3409 if (offscreen_target_frame_buffer_.get()) {
3410 *num_written = 2;
3411 if (params) {
3412 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3413 params[1] = renderbuffer_manager()->max_renderbuffer_size();
3414 }
3415 return true;
3416 }
[email protected]5cb735d2011-10-13 01:37:233417 return false;
[email protected]84afefa2011-10-19 21:45:533418 case GL_MAX_SAMPLES:
3419 *num_written = 1;
3420 if (params) {
3421 params[0] = renderbuffer_manager()->max_samples();
3422 }
3423 return true;
3424 case GL_MAX_RENDERBUFFER_SIZE:
3425 *num_written = 1;
3426 if (params) {
3427 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3428 }
3429 return true;
[email protected]5cb735d2011-10-13 01:37:233430 case GL_MAX_TEXTURE_SIZE:
3431 *num_written = 1;
3432 if (params) {
3433 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
3434 }
3435 return true;
3436 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
3437 *num_written = 1;
3438 if (params) {
3439 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
3440 }
3441 return true;
[email protected]297ca1c2011-06-20 23:08:463442 case GL_COLOR_WRITEMASK:
3443 *num_written = 4;
3444 if (params) {
3445 params[0] = mask_red_;
3446 params[1] = mask_green_;
3447 params[2] = mask_blue_;
3448 params[3] = mask_alpha_;
3449 }
3450 return true;
3451 case GL_DEPTH_WRITEMASK:
3452 *num_written = 1;
3453 if (params) {
3454 params[0] = mask_depth_;
3455 }
3456 return true;
3457 case GL_STENCIL_BACK_WRITEMASK:
3458 *num_written = 1;
3459 if (params) {
3460 params[0] = mask_stencil_back_;
3461 }
3462 return true;
3463 case GL_STENCIL_WRITEMASK:
3464 *num_written = 1;
3465 if (params) {
3466 params[0] = mask_stencil_front_;
3467 }
3468 return true;
3469 case GL_DEPTH_TEST:
3470 *num_written = 1;
3471 if (params) {
3472 params[0] = enable_depth_test_;
3473 }
3474 return true;
3475 case GL_STENCIL_TEST:
3476 *num_written = 1;
3477 if (params) {
3478 params[0] = enable_stencil_test_;
3479 }
3480 return true;
3481 case GL_ALPHA_BITS:
3482 *num_written = 1;
3483 if (params) {
3484 GLint v = 0;
3485 glGetIntegerv(GL_ALPHA_BITS, &v);
3486 params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0;
3487 }
3488 return true;
3489 case GL_DEPTH_BITS:
3490 *num_written = 1;
3491 if (params) {
3492 GLint v = 0;
3493 glGetIntegerv(GL_DEPTH_BITS, &v);
3494 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
3495 }
3496 return true;
3497 case GL_STENCIL_BITS:
3498 *num_written = 1;
3499 if (params) {
3500 GLint v = 0;
3501 glGetIntegerv(GL_STENCIL_BITS, &v);
3502 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
3503 }
3504 return true;
[email protected]656dcaad2010-05-07 17:18:373505 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113506 *num_written = validators_->compressed_texture_format.GetValues().size();
3507 if (params) {
3508 for (GLint ii = 0; ii < *num_written; ++ii) {
3509 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
3510 }
3511 }
[email protected]656dcaad2010-05-07 17:18:373512 return true;
[email protected]b273e432010-04-12 17:23:583513 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
3514 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103515 if (params) {
[email protected]302ce6d2011-07-07 23:28:113516 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103517 }
[email protected]b273e432010-04-12 17:23:583518 return true;
3519 case GL_NUM_SHADER_BINARY_FORMATS:
3520 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103521 if (params) {
[email protected]302ce6d2011-07-07 23:28:113522 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103523 }
[email protected]b273e432010-04-12 17:23:583524 return true;
3525 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113526 *num_written = validators_->shader_binary_format.GetValues().size();
3527 if (params) {
3528 for (GLint ii = 0; ii < *num_written; ++ii) {
3529 params[ii] = validators_->shader_binary_format.GetValues()[ii];
3530 }
3531 }
3532 return true;
[email protected]b273e432010-04-12 17:23:583533 case GL_SHADER_COMPILER:
3534 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103535 if (params) {
3536 *params = GL_TRUE;
3537 }
[email protected]b273e432010-04-12 17:23:583538 return true;
[email protected]6b8cf1a2010-05-06 16:13:583539 case GL_ARRAY_BUFFER_BINDING:
3540 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103541 if (params) {
3542 if (bound_array_buffer_) {
3543 GLuint client_id = 0;
3544 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
3545 &client_id);
3546 *params = client_id;
3547 } else {
3548 *params = 0;
3549 }
[email protected]6b8cf1a2010-05-06 16:13:583550 }
3551 return true;
3552 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3553 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103554 if (params) {
3555 if (bound_element_array_buffer_) {
3556 GLuint client_id = 0;
3557 buffer_manager()->GetClientId(
3558 bound_element_array_buffer_->service_id(),
3559 &client_id);
3560 *params = client_id;
3561 } else {
3562 *params = 0;
3563 }
[email protected]6b8cf1a2010-05-06 16:13:583564 }
3565 return true;
3566 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:303567 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:583568 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103569 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203570 FramebufferManager::FramebufferInfo* framebuffer =
3571 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3572 if (framebuffer) {
[email protected]4e8a5b122010-05-08 22:00:103573 GLuint client_id = 0;
3574 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203575 framebuffer->service_id(), &client_id);
[email protected]8e3e0662010-08-23 18:46:303576 *params = client_id;
3577 } else {
3578 *params = 0;
3579 }
3580 }
3581 return true;
3582 case GL_READ_FRAMEBUFFER_BINDING:
3583 *num_written = 1;
3584 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203585 FramebufferManager::FramebufferInfo* framebuffer =
3586 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
3587 if (framebuffer) {
[email protected]8e3e0662010-08-23 18:46:303588 GLuint client_id = 0;
3589 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203590 framebuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103591 *params = client_id;
3592 } else {
3593 *params = 0;
3594 }
[email protected]6b8cf1a2010-05-06 16:13:583595 }
3596 return true;
3597 case GL_RENDERBUFFER_BINDING:
3598 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103599 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203600 RenderbufferManager::RenderbufferInfo* renderbuffer =
3601 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
3602 if (renderbuffer) {
[email protected]4e8a5b122010-05-08 22:00:103603 GLuint client_id = 0;
3604 renderbuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203605 renderbuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103606 *params = client_id;
3607 } else {
3608 *params = 0;
3609 }
[email protected]6b8cf1a2010-05-06 16:13:583610 }
3611 return true;
3612 case GL_CURRENT_PROGRAM:
3613 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103614 if (params) {
3615 if (current_program_) {
3616 GLuint client_id = 0;
3617 program_manager()->GetClientId(
3618 current_program_->service_id(), &client_id);
3619 *params = client_id;
3620 } else {
3621 *params = 0;
3622 }
[email protected]6b8cf1a2010-05-06 16:13:583623 }
3624 return true;
[email protected]4e8a5b122010-05-08 22:00:103625 case GL_TEXTURE_BINDING_2D:
3626 *num_written = 1;
3627 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583628 TextureUnit& unit = texture_units_[active_texture_unit_];
3629 if (unit.bound_texture_2d) {
3630 GLuint client_id = 0;
3631 texture_manager()->GetClientId(
3632 unit.bound_texture_2d->service_id(), &client_id);
3633 *params = client_id;
3634 } else {
3635 *params = 0;
3636 }
[email protected]6b8cf1a2010-05-06 16:13:583637 }
[email protected]4e8a5b122010-05-08 22:00:103638 return true;
3639 case GL_TEXTURE_BINDING_CUBE_MAP:
3640 *num_written = 1;
3641 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583642 TextureUnit& unit = texture_units_[active_texture_unit_];
3643 if (unit.bound_texture_cube_map) {
3644 GLuint client_id = 0;
3645 texture_manager()->GetClientId(
3646 unit.bound_texture_cube_map->service_id(), &client_id);
3647 *params = client_id;
3648 } else {
3649 *params = 0;
3650 }
[email protected]6b8cf1a2010-05-06 16:13:583651 }
[email protected]4e8a5b122010-05-08 22:00:103652 return true;
[email protected]61eeb33f2011-07-26 15:30:313653 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3654 *num_written = 1;
3655 if (params) {
3656 TextureUnit& unit = texture_units_[active_texture_unit_];
3657 if (unit.bound_texture_external_oes) {
3658 GLuint client_id = 0;
3659 texture_manager()->GetClientId(
3660 unit.bound_texture_external_oes->service_id(), &client_id);
3661 *params = client_id;
3662 } else {
3663 *params = 0;
3664 }
3665 }
3666 return true;
[email protected]e51bdf32011-11-23 22:21:463667 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
3668 *num_written = 1;
3669 if (params) {
3670 TextureUnit& unit = texture_units_[active_texture_unit_];
3671 if (unit.bound_texture_rectangle_arb) {
3672 GLuint client_id = 0;
3673 texture_manager()->GetClientId(
3674 unit.bound_texture_rectangle_arb->service_id(), &client_id);
3675 *params = client_id;
3676 } else {
3677 *params = 0;
3678 }
3679 }
3680 return true;
[email protected]b273e432010-04-12 17:23:583681 default:
[email protected]4e8a5b122010-05-08 22:00:103682 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533683 return false;
[email protected]b273e432010-04-12 17:23:583684 }
3685}
3686
[email protected]4e8a5b122010-05-08 22:00:103687bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3688 GLenum pname, GLsizei* num_values) {
3689 return GetHelper(pname, NULL, num_values);
3690}
3691
[email protected]b273e432010-04-12 17:23:583692void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3693 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103694 GLsizei num_written = 0;
3695 if (GetHelper(pname, NULL, &num_written)) {
3696 scoped_array<GLint> values(new GLint[num_written]);
3697 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583698 for (GLsizei ii = 0; ii < num_written; ++ii) {
3699 params[ii] = static_cast<GLboolean>(values[ii]);
3700 }
3701 } else {
3702 glGetBooleanv(pname, params);
3703 }
3704}
3705
3706void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3707 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103708 GLsizei num_written = 0;
3709 if (GetHelper(pname, NULL, &num_written)) {
3710 scoped_array<GLint> values(new GLint[num_written]);
3711 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583712 for (GLsizei ii = 0; ii < num_written; ++ii) {
3713 params[ii] = static_cast<GLfloat>(values[ii]);
3714 }
3715 } else {
3716 glGetFloatv(pname, params);
3717 }
3718}
3719
3720void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3721 DCHECK(params);
3722 GLsizei num_written;
3723 if (!GetHelper(pname, params, &num_written)) {
3724 glGetIntegerv(pname, params);
3725 }
3726}
3727
[email protected]a0c3e972010-04-21 00:49:133728void GLES2DecoderImpl::DoGetProgramiv(
3729 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583730 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3731 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133732 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133733 return;
3734 }
3735 info->GetProgramiv(pname, params);
3736}
3737
[email protected]258a3313f2011-10-18 20:13:573738void GLES2DecoderImpl::DoBindAttribLocation(
3739 GLuint program, GLuint index, const char* name) {
3740 if (!StringIsValidForGLES(name)) {
3741 SetGLError(GL_INVALID_VALUE, "glBindAttribLocation: Invalid character");
3742 return;
3743 }
[email protected]6b8cf1a2010-05-06 16:13:583744 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3745 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033746 if (!info) {
[email protected]258a3313f2011-10-18 20:13:573747 return;
[email protected]558847a2010-03-24 07:02:543748 }
[email protected]258a3313f2011-10-18 20:13:573749 glBindAttribLocation(info->service_id(), index, name);
3750}
3751
3752error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3753 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
3754 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543755 GLuint index = static_cast<GLuint>(c.index);
3756 uint32 name_size = c.data_size;
3757 const char* name = GetSharedMemoryAs<const char*>(
3758 c.name_shm_id, c.name_shm_offset, name_size);
3759 if (name == NULL) {
3760 return error::kOutOfBounds;
3761 }
3762 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573763 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543764 return error::kNoError;
3765}
3766
3767error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3768 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583769 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543770 GLuint index = static_cast<GLuint>(c.index);
3771 uint32 name_size = c.data_size;
3772 const char* name = GetImmediateDataAs<const char*>(
3773 c, name_size, immediate_data_size);
3774 if (name == NULL) {
3775 return error::kOutOfBounds;
3776 }
3777 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573778 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543779 return error::kNoError;
3780}
3781
3782error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3783 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583784 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543785 GLuint index = static_cast<GLuint>(c.index);
3786 Bucket* bucket = GetBucket(c.name_bucket_id);
3787 if (!bucket || bucket->size() == 0) {
3788 return error::kInvalidArguments;
3789 }
3790 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183791 if (!bucket->GetAsString(&name_str)) {
3792 return error::kInvalidArguments;
3793 }
[email protected]258a3313f2011-10-18 20:13:573794 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543795 return error::kNoError;
3796}
3797
[email protected]f7a64ee2010-02-01 22:24:143798error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463799 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033800 GLuint client_id = c.shader;
3801 if (client_id) {
3802 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3803 if (info) {
[email protected]ca488e12010-12-13 20:06:143804 if (!info->IsDeleted()) {
3805 glDeleteShader(info->service_id());
3806 shader_manager()->MarkAsDeleted(info);
3807 }
[email protected]ae51d192010-04-27 00:48:033808 } else {
[email protected]8eee29c2010-04-29 03:38:293809 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033810 }
[email protected]96449d2c2009-11-25 00:01:323811 }
[email protected]f7a64ee2010-02-01 22:24:143812 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323813}
3814
[email protected]f7a64ee2010-02-01 22:24:143815error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463816 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033817 GLuint client_id = c.program;
3818 if (client_id) {
3819 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3820 if (info) {
[email protected]ca488e12010-12-13 20:06:143821 if (!info->IsDeleted()) {
3822 glDeleteProgram(info->service_id());
3823 program_manager()->MarkAsDeleted(shader_manager(), info);
3824 }
[email protected]ae51d192010-04-27 00:48:033825 } else {
[email protected]8eee29c2010-04-29 03:38:293826 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033827 }
[email protected]96449d2c2009-11-25 00:01:323828 }
[email protected]f7a64ee2010-02-01 22:24:143829 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323830}
3831
[email protected]269200b12010-11-18 22:53:063832void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103833 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573834 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103835 for (GLsizei ii = 0; ii < n; ++ii) {
3836 id_allocator->FreeID(ids[ii]);
3837 }
3838}
3839
[email protected]269200b12010-11-18 22:53:063840error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
3841 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103842 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3843 GLsizei n = static_cast<GLsizei>(c.n);
3844 uint32 data_size;
3845 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3846 return error::kOutOfBounds;
3847 }
3848 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3849 c.ids_shm_id, c.ids_shm_offset, data_size);
3850 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063851 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103852 return error::kNoError;
3853 }
3854 if (ids == NULL) {
3855 return error::kOutOfBounds;
3856 }
[email protected]269200b12010-11-18 22:53:063857 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103858 return error::kNoError;
3859}
3860
[email protected]269200b12010-11-18 22:53:063861void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103862 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573863 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103864 if (id_offset == 0) {
3865 for (GLsizei ii = 0; ii < n; ++ii) {
3866 ids[ii] = id_allocator->AllocateID();
3867 }
3868 } else {
3869 for (GLsizei ii = 0; ii < n; ++ii) {
3870 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
3871 id_offset = ids[ii] + 1;
3872 }
3873 }
3874}
3875
[email protected]269200b12010-11-18 22:53:063876error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
3877 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103878 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3879 GLuint id_offset = static_cast<GLuint>(c.id_offset);
3880 GLsizei n = static_cast<GLsizei>(c.n);
3881 uint32 data_size;
3882 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3883 return error::kOutOfBounds;
3884 }
3885 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3886 c.ids_shm_id, c.ids_shm_offset, data_size);
3887 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063888 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103889 return error::kNoError;
3890 }
3891 if (ids == NULL) {
3892 return error::kOutOfBounds;
3893 }
[email protected]269200b12010-11-18 22:53:063894 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:103895 return error::kNoError;
3896}
3897
[email protected]269200b12010-11-18 22:53:063898void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103899 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573900 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103901 for (GLsizei ii = 0; ii < n; ++ii) {
3902 if (!id_allocator->MarkAsUsed(ids[ii])) {
3903 for (GLsizei jj = 0; jj < ii; ++jj) {
3904 id_allocator->FreeID(ids[jj]);
3905 }
3906 SetGLError(
3907 GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:063908 "RegisterSharedIdsCHROMIUM: attempt to register "
3909 "id that already exists");
[email protected]066849e32010-05-03 19:14:103910 return;
3911 }
3912 }
3913}
3914
[email protected]269200b12010-11-18 22:53:063915error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
3916 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103917 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3918 GLsizei n = static_cast<GLsizei>(c.n);
3919 uint32 data_size;
3920 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3921 return error::kOutOfBounds;
3922 }
3923 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3924 c.ids_shm_id, c.ids_shm_offset, data_size);
3925 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063926 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103927 return error::kNoError;
3928 }
3929 if (ids == NULL) {
3930 return error::kOutOfBounds;
3931 }
[email protected]269200b12010-11-18 22:53:063932 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103933 return error::kNoError;
3934}
3935
[email protected]3a03a8f2011-03-19 00:51:273936void GLES2DecoderImpl::DoClear(GLbitfield mask) {
[email protected]0d6bfdc2011-11-02 01:32:203937 if (CheckBoundFramebuffersValid("glClear")) {
[email protected]529c6672012-01-04 02:18:263938 UNSHIPPED_TRACE_EVENT_INSTANT2("test_gpu", "DoClear", "red", clear_red_,
3939 "green", clear_green_);
[email protected]297ca1c2011-06-20 23:08:463940 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:273941 glClear(mask);
3942 }
3943}
3944
[email protected]36cef8ce2010-03-16 07:34:453945void GLES2DecoderImpl::DoFramebufferRenderbuffer(
3946 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:033947 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:303948 FramebufferManager::FramebufferInfo* framebuffer_info =
3949 GetFramebufferInfoForTarget(target);
3950 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293951 SetGLError(GL_INVALID_OPERATION,
3952 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453953 return;
3954 }
[email protected]ae51d192010-04-27 00:48:033955 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283956 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033957 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283958 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:033959 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293960 SetGLError(GL_INVALID_OPERATION,
3961 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:033962 return;
3963 }
3964 service_id = info->service_id();
3965 }
[email protected]9edc6b22010-12-23 02:00:263966 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033967 glFramebufferRenderbufferEXT(
3968 target, attachment, renderbuffertarget, service_id);
[email protected]1002c2d2011-06-28 22:39:043969 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263970 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:303971 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]3a2e7c7b2010-08-06 01:12:283972 }
[email protected]297ca1c2011-06-20 23:08:463973 if (framebuffer_info == bound_draw_framebuffer_) {
3974 state_dirty_ = true;
3975 }
[email protected]3a2e7c7b2010-08-06 01:12:283976}
3977
[email protected]297ca1c2011-06-20 23:08:463978bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
[email protected]3a2e7c7b2010-08-06 01:12:283979 switch (cap) {
3980 case GL_SCISSOR_TEST:
3981 enable_scissor_test_ = enabled;
[email protected]297ca1c2011-06-20 23:08:463982 return true;
3983 case GL_DEPTH_TEST: {
3984 if (enable_depth_test_ != enabled) {
3985 enable_depth_test_ = enabled;
3986 state_dirty_ = true;
3987 }
3988 return false;
3989 }
3990 case GL_STENCIL_TEST:
3991 if (enable_stencil_test_ != enabled) {
3992 enable_stencil_test_ = enabled;
3993 state_dirty_ = true;
3994 }
3995 return false;
[email protected]3a2e7c7b2010-08-06 01:12:283996 default:
[email protected]297ca1c2011-06-20 23:08:463997 return true;
[email protected]3a2e7c7b2010-08-06 01:12:283998 }
3999}
4000
4001void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464002 if (SetCapabilityState(cap, false)) {
4003 glDisable(cap);
4004 }
[email protected]3a2e7c7b2010-08-06 01:12:284005}
4006
4007void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464008 if (SetCapabilityState(cap, true)) {
4009 glEnable(cap);
4010 }
[email protected]3a2e7c7b2010-08-06 01:12:284011}
4012
4013void GLES2DecoderImpl::DoClearColor(
4014 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
4015 clear_red_ = red;
4016 clear_green_ = green;
4017 clear_blue_ = blue;
4018 clear_alpha_ = alpha;
4019 glClearColor(red, green, blue, alpha);
4020}
4021
4022void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
4023 clear_depth_ = depth;
4024 glClearDepth(depth);
4025}
4026
4027void GLES2DecoderImpl::DoClearStencil(GLint s) {
4028 clear_stencil_ = s;
4029 glClearStencil(s);
4030}
4031
4032void GLES2DecoderImpl::DoColorMask(
4033 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
4034 mask_red_ = red;
4035 mask_green_ = green;
4036 mask_blue_ = blue;
4037 mask_alpha_ = alpha;
[email protected]297ca1c2011-06-20 23:08:464038 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284039}
4040
4041void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
4042 mask_depth_ = depth;
[email protected]297ca1c2011-06-20 23:08:464043 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284044}
4045
4046void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
4047 mask_stencil_front_ = mask;
4048 mask_stencil_back_ = mask;
[email protected]297ca1c2011-06-20 23:08:464049 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284050}
4051
4052void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
[email protected]297ca1c2011-06-20 23:08:464053 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284054 mask_stencil_front_ = mask;
[email protected]297ca1c2011-06-20 23:08:464055 }
4056 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284057 mask_stencil_back_ = mask;
4058 }
[email protected]297ca1c2011-06-20 23:08:464059 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284060}
4061
[email protected]0d6bfdc2011-11-02 01:32:204062// Assumes framebuffer is complete.
4063void GLES2DecoderImpl::ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:304064 GLenum target, FramebufferManager::FramebufferInfo* info) {
4065 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204066 // bind this to the DRAW point, clear then bind back to READ
4067 // TODO(gman): I don't think there is any guarantee that an FBO that
4068 // is complete on the READ attachment will be complete as a DRAW
4069 // attachment.
4070 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
4071 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, info->service_id());
[email protected]8e3e0662010-08-23 18:46:304072 }
[email protected]3a2e7c7b2010-08-06 01:12:284073 GLbitfield clear_bits = 0;
4074 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:464075 glClearColor(
[email protected]0d6bfdc2011-11-02 01:32:204076 0.0f, 0.0f, 0.0f,
[email protected]297ca1c2011-06-20 23:08:464077 (GLES2Util::GetChannelsForFormat(
[email protected]0d6bfdc2011-11-02 01:32:204078 info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f : 1.0f);
[email protected]3a2e7c7b2010-08-06 01:12:284079 glColorMask(true, true, true, true);
4080 clear_bits |= GL_COLOR_BUFFER_BIT;
4081 }
4082
4083 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4084 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4085 glClearStencil(0);
4086 glStencilMask(-1);
4087 clear_bits |= GL_STENCIL_BUFFER_BIT;
4088 }
4089
4090 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4091 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4092 glClearDepth(1.0f);
4093 glDepthMask(true);
4094 clear_bits |= GL_DEPTH_BUFFER_BIT;
4095 }
4096
4097 glDisable(GL_SCISSOR_TEST);
4098 glClear(clear_bits);
4099
[email protected]968351b2011-12-20 08:26:514100 framebuffer_manager()->MarkAttachmentsAsCleared(
4101 info, renderbuffer_manager(), texture_manager());
[email protected]3a2e7c7b2010-08-06 01:12:284102
[email protected]c007aa02010-09-02 22:22:404103 RestoreClearState();
4104
4105 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204106 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, info->service_id());
[email protected]87d1a3fe2011-12-01 04:25:484107 FramebufferManager::FramebufferInfo* framebuffer =
4108 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4109 GLuint service_id =
4110 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
4111 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
[email protected]c007aa02010-09-02 22:22:404112 }
4113}
4114
4115void GLES2DecoderImpl::RestoreClearState() {
[email protected]297ca1c2011-06-20 23:08:464116 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284117 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
[email protected]3a2e7c7b2010-08-06 01:12:284118 glClearStencil(clear_stencil_);
[email protected]3a2e7c7b2010-08-06 01:12:284119 glClearDepth(clear_depth_);
[email protected]3a2e7c7b2010-08-06 01:12:284120 if (enable_scissor_test_) {
4121 glEnable(GL_SCISSOR_TEST);
4122 }
[email protected]36cef8ce2010-03-16 07:34:454123}
4124
4125GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]0d6bfdc2011-11-02 01:32:204126 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]8e3e0662010-08-23 18:46:304127 GetFramebufferInfoForTarget(target);
[email protected]0d6bfdc2011-11-02 01:32:204128 if (!framebuffer) {
[email protected]36cef8ce2010-03-16 07:34:454129 return GL_FRAMEBUFFER_COMPLETE;
4130 }
[email protected]0d6bfdc2011-11-02 01:32:204131 GLenum completeness = framebuffer->IsPossiblyComplete();
4132 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4133 return completeness;
4134 }
[email protected]36cef8ce2010-03-16 07:34:454135 return glCheckFramebufferStatusEXT(target);
4136}
4137
4138void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:034139 GLenum target, GLenum attachment, GLenum textarget,
4140 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:304141 FramebufferManager::FramebufferInfo* framebuffer_info =
4142 GetFramebufferInfoForTarget(target);
4143 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294144 SetGLError(GL_INVALID_OPERATION,
4145 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:454146 return;
4147 }
[email protected]ae51d192010-04-27 00:48:034148 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:284149 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:034150 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:284151 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:034152 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294153 SetGLError(GL_INVALID_OPERATION,
4154 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:034155 return;
4156 }
4157 service_id = info->service_id();
4158 }
[email protected]0d6bfdc2011-11-02 01:32:204159
[email protected]80eb6b52012-01-19 00:14:414160 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
[email protected]0d6bfdc2011-11-02 01:32:204161 SetGLError(GL_INVALID_VALUE,
4162 "glFramebufferTexture2D: level out of range");
4163 return;
4164 }
4165
[email protected]9edc6b22010-12-23 02:00:264166 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034167 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]1002c2d2011-06-28 22:39:044168 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264169 if (error == GL_NO_ERROR) {
4170 framebuffer_info->AttachTexture(attachment, info, textarget, level);
[email protected]3a2e7c7b2010-08-06 01:12:284171 }
[email protected]297ca1c2011-06-20 23:08:464172 if (framebuffer_info == bound_draw_framebuffer_) {
4173 state_dirty_ = true;
4174 }
[email protected]36cef8ce2010-03-16 07:34:454175}
4176
4177void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4178 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:304179 FramebufferManager::FramebufferInfo* framebuffer_info =
4180 GetFramebufferInfoForTarget(target);
4181 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294182 SetGLError(GL_INVALID_OPERATION,
4183 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454184 return;
4185 }
4186 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:574187 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4188 GLint type = 0;
4189 GLuint client_id = 0;
4190 glGetFramebufferAttachmentParameterivEXT(
4191 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
4192 switch (type) {
4193 case GL_RENDERBUFFER: {
4194 renderbuffer_manager()->GetClientId(*params, &client_id);
4195 break;
4196 }
4197 case GL_TEXTURE: {
4198 texture_manager()->GetClientId(*params, &client_id);
4199 break;
4200 }
4201 default:
4202 break;
4203 }
4204 *params = client_id;
4205 }
[email protected]36cef8ce2010-03-16 07:34:454206}
4207
4208void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4209 GLenum target, GLenum pname, GLint* params) {
[email protected]0d6bfdc2011-11-02 01:32:204210 RenderbufferManager::RenderbufferInfo* renderbuffer =
4211 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4212 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294213 SetGLError(GL_INVALID_OPERATION,
4214 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454215 return;
4216 }
[email protected]3a03a8f2011-03-19 00:51:274217 switch (pname) {
4218 case GL_RENDERBUFFER_INTERNAL_FORMAT:
[email protected]0d6bfdc2011-11-02 01:32:204219 *params = renderbuffer->internal_format();
[email protected]3a03a8f2011-03-19 00:51:274220 break;
4221 case GL_RENDERBUFFER_WIDTH:
[email protected]0d6bfdc2011-11-02 01:32:204222 *params = renderbuffer->width();
[email protected]3a03a8f2011-03-19 00:51:274223 break;
4224 case GL_RENDERBUFFER_HEIGHT:
[email protected]0d6bfdc2011-11-02 01:32:204225 *params = renderbuffer->height();
[email protected]3a03a8f2011-03-19 00:51:274226 break;
4227 default:
4228 glGetRenderbufferParameterivEXT(target, pname, params);
4229 break;
[email protected]b71f52c2010-06-18 22:20:204230 }
[email protected]36cef8ce2010-03-16 07:34:454231}
4232
[email protected]8e3e0662010-08-23 18:46:304233void GLES2DecoderImpl::DoBlitFramebufferEXT(
4234 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
4235 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
4236 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:394237 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304238 SetGLError(GL_INVALID_OPERATION,
4239 "glBlitFramebufferEXT: function not available");
4240 }
[email protected]5094b0f2010-11-09 19:45:244241 if (IsAngle()) {
4242 glBlitFramebufferANGLE(
4243 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4244 } else {
4245 glBlitFramebufferEXT(
4246 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4247 }
[email protected]529c6672012-01-04 02:18:264248 UNSHIPPED_TRACE_EVENT_INSTANT1("test_gpu", "DoBlit", "width", srcX1 - srcX0);
[email protected]8e3e0662010-08-23 18:46:304249}
4250
4251void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
4252 GLenum target, GLsizei samples, GLenum internalformat,
4253 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:394254 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304255 SetGLError(GL_INVALID_OPERATION,
4256 "glRenderbufferStorageMultisampleEXT: function not available");
4257 return;
4258 }
[email protected]8e3e0662010-08-23 18:46:304259
[email protected]0d6bfdc2011-11-02 01:32:204260 RenderbufferManager::RenderbufferInfo* renderbuffer =
4261 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4262 if (!renderbuffer) {
4263 SetGLError(GL_INVALID_OPERATION,
4264 "glGetRenderbufferStorageMultisample: no renderbuffer bound");
4265 return;
4266 }
4267
[email protected]84afefa2011-10-19 21:45:534268 if (samples > renderbuffer_manager()->max_samples()) {
4269 SetGLError(GL_INVALID_VALUE,
4270 "glGetRenderbufferStorageMultisample: samples too large");
4271 return;
4272 }
4273
4274 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4275 height > renderbuffer_manager()->max_renderbuffer_size()) {
4276 SetGLError(GL_INVALID_VALUE,
4277 "glGetRenderbufferStorageMultisample: size too large");
4278 return;
4279 }
4280
[email protected]9edc6b22010-12-23 02:00:264281 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:304282 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264283 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:304284 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264285 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:304286 break;
4287 case GL_RGBA4:
4288 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264289 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:304290 break;
4291 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264292 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:304293 break;
4294 }
4295 }
4296
[email protected]9edc6b22010-12-23 02:00:264297 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:084298 if (IsAngle()) {
4299 glRenderbufferStorageMultisampleANGLE(
4300 target, samples, impl_format, width, height);
4301 } else {
4302 glRenderbufferStorageMultisampleEXT(
4303 target, samples, impl_format, width, height);
4304 }
[email protected]1002c2d2011-06-28 22:39:044305 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264306 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514307 // TODO(gman): If renderbuffers tracked which framebuffers they were
4308 // attached to we could just mark those framebuffers as not complete.
4309 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204310 renderbuffer_manager()->SetInfo(
4311 renderbuffer, samples, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264312 }
[email protected]8e3e0662010-08-23 18:46:304313}
4314
[email protected]36cef8ce2010-03-16 07:34:454315void GLES2DecoderImpl::DoRenderbufferStorage(
4316 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]0d6bfdc2011-11-02 01:32:204317 RenderbufferManager::RenderbufferInfo* renderbuffer =
4318 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4319 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294320 SetGLError(GL_INVALID_OPERATION,
4321 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454322 return;
4323 }
[email protected]876f6fee2010-08-02 23:10:324324
[email protected]84afefa2011-10-19 21:45:534325 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4326 height > renderbuffer_manager()->max_renderbuffer_size()) {
4327 SetGLError(GL_INVALID_VALUE,
4328 "glGetRenderbufferStorage: size too large");
4329 return;
4330 }
4331
[email protected]9edc6b22010-12-23 02:00:264332 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:324333 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264334 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:324335 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264336 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:324337 break;
4338 case GL_RGBA4:
4339 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264340 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:324341 break;
4342 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264343 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:324344 break;
4345 }
[email protected]b71f52c2010-06-18 22:20:204346 }
[email protected]876f6fee2010-08-02 23:10:324347
[email protected]9edc6b22010-12-23 02:00:264348 CopyRealGLErrorsToWrapper();
4349 glRenderbufferStorageEXT(target, impl_format, width, height);
[email protected]1002c2d2011-06-28 22:39:044350 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264351 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514352 // TODO(gman): If tetxures tracked which framebuffers they were attached to
4353 // we could just mark those framebuffers as not complete.
4354 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204355 renderbuffer_manager()->SetInfo(
4356 renderbuffer, 0, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264357 }
[email protected]36cef8ce2010-03-16 07:34:454358}
4359
[email protected]07f54fcc2009-12-22 02:46:304360void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]0c8fabf2011-06-14 19:35:224361 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]6b8cf1a2010-05-06 16:13:584362 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4363 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:474364 if (!info) {
[email protected]a93bb842010-02-16 23:03:474365 return;
4366 }
[email protected]05afda12011-01-20 00:17:344367
[email protected]d685a682011-04-29 16:19:574368 info->Link();
[email protected]07f54fcc2009-12-22 02:46:304369};
4370
[email protected]3916c97e2010-02-25 03:20:504371void GLES2DecoderImpl::DoTexParameterf(
4372 GLenum target, GLenum pname, GLfloat param) {
4373 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:304374 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294375 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244376 return;
[email protected]07f54fcc2009-12-22 02:46:304377 }
[email protected]cbb22e42011-05-12 23:36:244378
4379 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414380 info, pname, static_cast<GLint>(param))) {
[email protected]cbb22e42011-05-12 23:36:244381 SetGLError(GL_INVALID_ENUM, "glTexParameterf: param GL_INVALID_ENUM");
4382 return;
4383 }
4384 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:304385}
4386
[email protected]3916c97e2010-02-25 03:20:504387void GLES2DecoderImpl::DoTexParameteri(
4388 GLenum target, GLenum pname, GLint param) {
4389 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4390 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294391 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244392 return;
[email protected]3916c97e2010-02-25 03:20:504393 }
[email protected]cbb22e42011-05-12 23:36:244394
[email protected]80eb6b52012-01-19 00:14:414395 if (!texture_manager()->SetParameter(info, pname, param)) {
[email protected]cbb22e42011-05-12 23:36:244396 SetGLError(GL_INVALID_ENUM, "glTexParameteri: param GL_INVALID_ENUM");
4397 return;
4398 }
4399 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:504400}
4401
4402void GLES2DecoderImpl::DoTexParameterfv(
4403 GLenum target, GLenum pname, const GLfloat* params) {
4404 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4405 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294406 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244407 return;
[email protected]3916c97e2010-02-25 03:20:504408 }
[email protected]cbb22e42011-05-12 23:36:244409
4410 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414411 info, pname, static_cast<GLint>(params[0]))) {
[email protected]cbb22e42011-05-12 23:36:244412 SetGLError(GL_INVALID_ENUM, "glTexParameterfv: param GL_INVALID_ENUM");
4413 return;
4414 }
4415 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504416}
4417
4418void GLES2DecoderImpl::DoTexParameteriv(
4419 GLenum target, GLenum pname, const GLint* params) {
4420 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4421 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294422 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244423 return;
[email protected]3916c97e2010-02-25 03:20:504424 }
[email protected]cbb22e42011-05-12 23:36:244425
[email protected]80eb6b52012-01-19 00:14:414426 if (!texture_manager()->SetParameter(info, pname, *params)) {
[email protected]cbb22e42011-05-12 23:36:244427 SetGLError(GL_INVALID_ENUM, "glTexParameteriv: param GL_INVALID_ENUM");
4428 return;
4429 }
4430 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504431}
4432
[email protected]939e7362010-05-13 20:49:104433bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:144434 if (!current_program_) {
[email protected]939e7362010-05-13 20:49:104435 // The program does not exist.
4436 SetGLError(GL_INVALID_OPERATION,
4437 (std::string(function_name) + ": no program in use").c_str());
4438 return false;
4439 }
[email protected]ca488e12010-12-13 20:06:144440 if (!current_program_->InUse()) {
[email protected]939e7362010-05-13 20:49:104441 SetGLError(GL_INVALID_OPERATION,
4442 (std::string(function_name) + ": program not linked").c_str());
4443 return false;
4444 }
4445 return true;
4446}
4447
4448bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
4449 GLint location, const char* function_name) {
4450 if (!CheckCurrentProgram(function_name)) {
4451 return false;
4452 }
4453 return location != -1;
4454}
4455
[email protected]43c2f1f2011-03-25 18:35:364456bool GLES2DecoderImpl::PrepForSetUniformByLocation(
4457 GLint location, const char* function_name, GLenum* type, GLsizei* count) {
4458 DCHECK(type);
4459 DCHECK(count);
[email protected]939e7362010-05-13 20:49:104460 if (!CheckCurrentProgramForUniform(location, function_name)) {
4461 return false;
4462 }
[email protected]43c2f1f2011-03-25 18:35:364463 GLint array_index = -1;
4464 const ProgramManager::ProgramInfo::UniformInfo* info =
4465 current_program_->GetUniformInfoByLocation(location, &array_index);
4466 if (!info) {
[email protected]939e7362010-05-13 20:49:104467 SetGLError(GL_INVALID_OPERATION,
[email protected]43c2f1f2011-03-25 18:35:364468 (std::string(function_name) + ": unknown location").c_str());
[email protected]939e7362010-05-13 20:49:104469 return false;
4470 }
[email protected]43c2f1f2011-03-25 18:35:364471 if (*count > 1 && !info->is_array) {
4472 SetGLError(
4473 GL_INVALID_OPERATION,
4474 (std::string(function_name) + ": count > 1 for non-array").c_str());
4475 return false;
4476 }
4477 *count = std::min(info->size - array_index, *count);
4478 if (*count <= 0) {
4479 return false;
4480 }
4481 *type = info->type;
[email protected]939e7362010-05-13 20:49:104482 return true;
4483}
4484
[email protected]939e7362010-05-13 20:49:104485void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
4486 if (!CheckCurrentProgramForUniform(location, "glUniform1i")) {
[email protected]3916c97e2010-02-25 03:20:504487 return;
4488 }
4489 current_program_->SetSamplers(location, 1, &v0);
4490 glUniform1i(location, v0);
4491}
4492
4493void GLES2DecoderImpl::DoUniform1iv(
4494 GLint location, GLsizei count, const GLint *value) {
[email protected]939e7362010-05-13 20:49:104495 if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) {
[email protected]3916c97e2010-02-25 03:20:504496 return;
4497 }
[email protected]43c2f1f2011-03-25 18:35:364498 GLenum type = 0;
4499 if (!PrepForSetUniformByLocation(location, "glUniform1iv", &type, &count)) {
4500 return;
4501 }
[email protected]61eeb33f2011-07-26 15:30:314502 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
4503 type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]43c2f1f2011-03-25 18:35:364504 current_program_->SetSamplers(location, count, value);
4505 }
[email protected]3916c97e2010-02-25 03:20:504506 glUniform1iv(location, count, value);
4507}
4508
[email protected]939e7362010-05-13 20:49:104509void GLES2DecoderImpl::DoUniform1fv(
4510 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364511 GLenum type = 0;
4512 if (!PrepForSetUniformByLocation(location, "glUniform1fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104513 return;
4514 }
4515 if (type == GL_BOOL) {
4516 scoped_array<GLint> temp(new GLint[count]);
4517 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:534518 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104519 }
4520 DoUniform1iv(location, count, temp.get());
4521 } else {
4522 glUniform1fv(location, count, value);
4523 }
4524}
4525
4526void GLES2DecoderImpl::DoUniform2fv(
4527 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364528 GLenum type = 0;
4529 if (!PrepForSetUniformByLocation(location, "glUniform2fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104530 return;
4531 }
4532 if (type == GL_BOOL_VEC2) {
4533 GLsizei num_values = count * 2;
4534 scoped_array<GLint> temp(new GLint[num_values]);
4535 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534536 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104537 }
4538 glUniform2iv(location, count, temp.get());
4539 } else {
4540 glUniform2fv(location, count, value);
4541 }
4542}
4543
4544void GLES2DecoderImpl::DoUniform3fv(
4545 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364546 GLenum type = 0;
4547 if (!PrepForSetUniformByLocation(location, "glUniform3fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104548 return;
4549 }
4550 if (type == GL_BOOL_VEC3) {
4551 GLsizei num_values = count * 3;
4552 scoped_array<GLint> temp(new GLint[num_values]);
4553 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534554 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104555 }
4556 glUniform3iv(location, count, temp.get());
4557 } else {
4558 glUniform3fv(location, count, value);
4559 }
4560}
4561
4562void GLES2DecoderImpl::DoUniform4fv(
4563 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364564 GLenum type = 0;
4565 if (!PrepForSetUniformByLocation(location, "glUniform4fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104566 return;
4567 }
4568 if (type == GL_BOOL_VEC4) {
4569 GLsizei num_values = count * 4;
4570 scoped_array<GLint> temp(new GLint[num_values]);
4571 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534572 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104573 }
4574 glUniform4iv(location, count, temp.get());
4575 } else {
4576 glUniform4fv(location, count, value);
4577 }
4578}
4579
[email protected]43c2f1f2011-03-25 18:35:364580void GLES2DecoderImpl::DoUniform2iv(
4581 GLint location, GLsizei count, const GLint* value) {
4582 GLenum type = 0;
4583 if (!PrepForSetUniformByLocation(location, "glUniform2iv", &type, &count)) {
4584 return;
4585 }
4586 glUniform2iv(location, count, value);
4587}
4588
4589void GLES2DecoderImpl::DoUniform3iv(
4590 GLint location, GLsizei count, const GLint* value) {
4591 GLenum type = 0;
4592 if (!PrepForSetUniformByLocation(location, "glUniform3iv", &type, &count)) {
4593 return;
4594 }
4595 glUniform3iv(location, count, value);
4596}
4597
4598void GLES2DecoderImpl::DoUniform4iv(
4599 GLint location, GLsizei count, const GLint* value) {
4600 GLenum type = 0;
4601 if (!PrepForSetUniformByLocation(location, "glUniform4iv", &type, &count)) {
4602 return;
4603 }
4604 glUniform4iv(location, count, value);
4605}
4606
4607void GLES2DecoderImpl::DoUniformMatrix2fv(
4608 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4609 GLenum type = 0;
4610 if (!PrepForSetUniformByLocation(
4611 location, "glUniformMatrix2fv", &type, &count)) {
4612 return;
4613 }
[email protected]e5081262012-01-05 23:09:034614 glUniformMatrix2fv(location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364615}
4616
4617void GLES2DecoderImpl::DoUniformMatrix3fv(
4618 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4619 GLenum type = 0;
4620 if (!PrepForSetUniformByLocation(
4621 location, "glUniformMatrix3fv", &type, &count)) {
4622 return;
4623 }
[email protected]e5081262012-01-05 23:09:034624 glUniformMatrix3fv(location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364625}
4626
4627void GLES2DecoderImpl::DoUniformMatrix4fv(
4628 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4629 GLenum type = 0;
4630 if (!PrepForSetUniformByLocation(
4631 location, "glUniformMatrix4fv", &type, &count)) {
4632 return;
4633 }
[email protected]e5081262012-01-05 23:09:034634 glUniformMatrix4fv(location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364635}
4636
[email protected]3916c97e2010-02-25 03:20:504637void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:034638 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:504639 ProgramManager::ProgramInfo* info = NULL;
4640 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:584641 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:504642 if (!info) {
[email protected]ae51d192010-04-27 00:48:034643 return;
4644 }
4645 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:504646 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:294647 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:504648 return;
4649 }
[email protected]ae51d192010-04-27 00:48:034650 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:504651 }
[email protected]ca488e12010-12-13 20:06:144652 if (current_program_) {
4653 program_manager()->UnuseProgram(shader_manager(), current_program_);
4654 }
[email protected]3916c97e2010-02-25 03:20:504655 current_program_ = info;
[email protected]ca488e12010-12-13 20:06:144656 if (current_program_) {
4657 program_manager()->UseProgram(current_program_);
4658 }
[email protected]ae51d192010-04-27 00:48:034659 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:504660}
4661
[email protected]96449d2c2009-11-25 00:01:324662GLenum GLES2DecoderImpl::GetGLError() {
4663 // Check the GL error first, then our wrapped error.
4664 GLenum error = glGetError();
4665 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:374666 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:324667 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:294668 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:324669 break;
4670 }
4671 }
4672 }
4673
4674 if (error != GL_NO_ERROR) {
4675 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:294676 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324677 }
4678 return error;
4679}
4680
[email protected]1002c2d2011-06-28 22:39:044681GLenum GLES2DecoderImpl::PeekGLError() {
4682 GLenum error = glGetError();
4683 if (error != GL_NO_ERROR) {
4684 SetGLError(error, "");
4685 }
4686 return error;
4687}
4688
[email protected]8eee29c2010-04-29 03:38:294689void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
4690 if (msg) {
4691 last_error_ = msg;
[email protected]d0498742010-09-20 20:27:014692 LOG(ERROR) << last_error_;
[email protected]6b6e7ee2011-12-13 08:04:524693 if (!msg_callback_.is_null()) {
4694 msg_callback_.Run(0, GLES2Util::GetStringEnum(error) + " : " + msg);
4695 }
[email protected]8eee29c2010-04-29 03:38:294696 }
[email protected]ddd968b82010-03-02 00:44:294697 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324698}
4699
[email protected]07f54fcc2009-12-22 02:46:304700void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
4701 GLenum error;
4702 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294703 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:304704 }
4705}
4706
[email protected]6217d392010-03-25 22:08:354707void GLES2DecoderImpl::ClearRealGLErrors() {
4708 GLenum error;
4709 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]3ed14d112011-12-13 22:05:514710 if (error != GL_OUT_OF_MEMORY) {
4711 // GL_OUT_OF_MEMORY can legally happen on lost device.
4712 NOTREACHED() << "GL error " << error << " was unhandled.";
4713 }
[email protected]6217d392010-03-25 22:08:354714 }
4715}
4716
[email protected]ef526492010-06-02 23:12:254717bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:504718 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:254719 // Only check if there are some unrenderable textures.
4720 if (!texture_manager()->HaveUnrenderableTextures()) {
4721 return false;
4722 }
4723 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:504724 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4725 current_program_->sampler_indices();
4726 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4727 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4728 current_program_->GetUniformInfo(sampler_indices[ii]);
4729 DCHECK(uniform_info);
4730 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4731 GLuint texture_unit_index = uniform_info->texture_units[jj];
4732 if (texture_unit_index < group_->max_texture_units()) {
4733 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4734 TextureManager::TextureInfo* texture_info =
[email protected]61eeb33f2011-07-26 15:30:314735 texture_unit.GetInfoForSamplerType(uniform_info->type);
[email protected]80eb6b52012-01-19 00:14:414736 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]ef526492010-06-02 23:12:254737 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:504738 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4739 glBindTexture(
[email protected]61eeb33f2011-07-26 15:30:314740 GetBindTargetForSamplerType(uniform_info->type),
[email protected]00f893d2010-08-24 18:55:494741 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:504742 }
4743 }
4744 // else: should this be an error?
4745 }
4746 }
[email protected]ef526492010-06-02 23:12:254747 return textures_set;
[email protected]3916c97e2010-02-25 03:20:504748}
4749
4750void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
4751 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:504752 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4753 current_program_->sampler_indices();
4754 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4755 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4756 current_program_->GetUniformInfo(sampler_indices[ii]);
4757 DCHECK(uniform_info);
4758 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4759 GLuint texture_unit_index = uniform_info->texture_units[jj];
4760 if (texture_unit_index < group_->max_texture_units()) {
4761 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4762 TextureManager::TextureInfo* texture_info =
4763 uniform_info->type == GL_SAMPLER_2D ?
4764 texture_unit.bound_texture_2d :
4765 texture_unit.bound_texture_cube_map;
[email protected]80eb6b52012-01-19 00:14:414766 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]3916c97e2010-02-25 03:20:504767 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4768 // Get the texture info that was previously bound here.
4769 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
4770 texture_unit.bound_texture_2d :
4771 texture_unit.bound_texture_cube_map;
4772 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:034773 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:504774 }
4775 }
4776 }
4777 }
4778 // Set the active texture back to whatever the user had it as.
4779 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:304780}
4781
[email protected]0d6bfdc2011-11-02 01:32:204782bool GLES2DecoderImpl::ClearUnclearedTextures() {
4783 // Only check if there are some uncleared textures.
4784 if (!texture_manager()->HaveUnsafeTextures()) {
4785 return true;
4786 }
4787
4788 // 1: Check all textures we are about to render with.
4789 if (current_program_) {
4790 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4791 current_program_->sampler_indices();
4792 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4793 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4794 current_program_->GetUniformInfo(sampler_indices[ii]);
4795 DCHECK(uniform_info);
4796 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4797 GLuint texture_unit_index = uniform_info->texture_units[jj];
4798 if (texture_unit_index < group_->max_texture_units()) {
4799 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4800 TextureManager::TextureInfo* texture_info =
4801 texture_unit.GetInfoForSamplerType(uniform_info->type);
4802 if (texture_info && !texture_info->SafeToRenderFrom()) {
4803 if (!texture_manager()->ClearRenderableLevels(this, texture_info)) {
4804 return false;
4805 }
4806 }
4807 }
4808 }
4809 }
4810 }
4811 return true;
4812}
4813
[email protected]07f54fcc2009-12-22 02:46:304814bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]689fa1c52010-06-09 18:35:034815 // NOTE: We specifically do not check current_program->IsValid() because
4816 // it could never be invalid since glUseProgram would have failed. While
4817 // glLinkProgram could later mark the program as invalid the previous
4818 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:144819 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:504820 // The program does not exist.
4821 // But GL says no ERROR.
4822 return false;
4823 }
[email protected]f39f4b3f2010-05-12 17:04:084824 // Validate all attribs currently enabled. If they are used by the current
4825 // program then check that they have enough elements to handle the draw call.
4826 // If they are not used by the current program check that they have a buffer
4827 // assigned.
4828 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:444829 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]f39f4b3f2010-05-12 17:04:084830 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:404831 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:084832 const VertexAttribManager::VertexAttribInfo* info = *it;
4833 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4834 current_program_->GetAttribInfoByLocation(info->index());
4835 if (attrib_info) {
4836 // This attrib is used in the current program.
4837 if (!info->CanAccess(max_vertex_accessed)) {
4838 SetGLError(GL_INVALID_OPERATION,
4839 "glDrawXXX: attempt to access out of range vertices");
4840 return false;
4841 }
4842 } else {
4843 // This attrib is not used in the current program.
[email protected]a0b78dc2011-11-11 10:43:104844 if (!info->buffer()) {
[email protected]f39f4b3f2010-05-12 17:04:084845 SetGLError(
4846 GL_INVALID_OPERATION,
4847 "glDrawXXX: attempt to render with no buffer attached to enabled "
4848 "attrib");
4849 return false;
4850 }
[email protected]1d32bc82010-01-13 22:06:464851 }
[email protected]07f54fcc2009-12-22 02:46:304852 }
[email protected]3916c97e2010-02-25 03:20:504853 return true;
[email protected]b1122982010-05-17 23:04:244854}
4855
[email protected]c13e1da62011-09-09 21:48:304856bool GLES2DecoderImpl::SimulateAttrib0(
4857 GLuint max_vertex_accessed, bool* simulated) {
4858 DCHECK(simulated);
4859 *simulated = false;
4860
[email protected]876f6fee2010-08-02 23:10:324861 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
[email protected]c13e1da62011-09-09 21:48:304862 return true;
[email protected]876f6fee2010-08-02 23:10:324863
[email protected]b1122982010-05-17 23:04:244864 const VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:444865 vertex_attrib_manager_->GetVertexAttribInfo(0);
[email protected]b1122982010-05-17 23:04:244866 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:494867 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
4868 if (info->enabled() && attrib_0_used) {
[email protected]c13e1da62011-09-09 21:48:304869 return true;
[email protected]b1122982010-05-17 23:04:244870 }
4871
[email protected]b1122982010-05-17 23:04:244872 // Make a buffer with a single repeated vec4 value enough to
4873 // simulate the constant value that is supposed to be here.
4874 // This is required to emulate GLES2 on GL.
[email protected]c13e1da62011-09-09 21:48:304875 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
4876
4877 GLuint num_vertices = max_vertex_accessed + 1;
4878 GLuint size_needed = 0;
4879
4880 if (num_vertices == 0 ||
4881 !SafeMultiply(num_vertices, static_cast<GLuint>(sizeof(Vec4)),
4882 &size_needed) ||
4883 size_needed > 0x7FFFFFFFU) {
4884 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
4885 return false;
4886 }
4887
4888 CopyRealGLErrorsToWrapper();
4889 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
4890
4891 if (static_cast<GLsizei>(size_needed) > attrib_0_size_) {
[email protected]fc753442011-02-04 19:49:494892 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:304893 GLenum error = glGetError();
4894 if (error != GL_NO_ERROR) {
4895 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
4896 return false;
4897 }
[email protected]fc753442011-02-04 19:49:494898 attrib_0_buffer_matches_value_ = false;
4899 }
4900 if (attrib_0_used &&
4901 (!attrib_0_buffer_matches_value_ ||
4902 (info->value().v[0] != attrib_0_value_.v[0] ||
4903 info->value().v[1] != attrib_0_value_.v[1] ||
4904 info->value().v[2] != attrib_0_value_.v[2] ||
4905 info->value().v[3] != attrib_0_value_.v[3]))) {
4906 std::vector<Vec4> temp(num_vertices, info->value());
4907 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
4908 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:244909 attrib_0_value_ = info->value();
4910 attrib_0_size_ = size_needed;
4911 }
4912
4913 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4914
[email protected]c13e1da62011-09-09 21:48:304915 *simulated = true;
[email protected]b1122982010-05-17 23:04:244916 return true;
[email protected]b1122982010-05-17 23:04:244917}
4918
4919void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
4920 const VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:444921 vertex_attrib_manager_->GetVertexAttribInfo(0);
[email protected]b1122982010-05-17 23:04:244922 const void* ptr = reinterpret_cast<const void*>(info->offset());
4923 BufferManager::BufferInfo* buffer_info = info->buffer();
4924 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
4925 glVertexAttribPointer(
4926 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
4927 ptr);
4928 glBindBuffer(GL_ARRAY_BUFFER,
4929 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4930}
[email protected]07f54fcc2009-12-22 02:46:304931
[email protected]8fbedc02010-11-18 18:43:404932bool GLES2DecoderImpl::SimulateFixedAttribs(
4933 GLuint max_vertex_accessed, bool* simulated) {
4934 DCHECK(simulated);
4935 *simulated = false;
4936 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4937 return true;
4938
[email protected]3757a372012-01-19 05:20:444939 if (!vertex_attrib_manager_->HaveFixedAttribs()) {
[email protected]8fbedc02010-11-18 18:43:404940 return true;
4941 }
4942
4943 // NOTE: we could be smart and try to check if a buffer is used
4944 // twice in 2 different attribs, find the overlapping parts and therefore
4945 // duplicate the minimum amount of data but this whole code path is not meant
4946 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
4947 // tests so we just add to the buffer attrib used.
4948
4949 // Compute the number of elements needed.
[email protected]c13e1da62011-09-09 21:48:304950 GLuint num_vertices = max_vertex_accessed + 1;
4951 if (num_vertices == 0) {
4952 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
4953 return false;
4954 }
4955
4956 GLuint elements_needed = 0;
[email protected]8fbedc02010-11-18 18:43:404957 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:444958 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]8fbedc02010-11-18 18:43:404959 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4960 infos.begin(); it != infos.end(); ++it) {
4961 const VertexAttribManager::VertexAttribInfo* info = *it;
4962 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4963 current_program_->GetAttribInfoByLocation(info->index());
4964 if (attrib_info &&
4965 info->CanAccess(max_vertex_accessed) &&
4966 info->type() == GL_FIXED) {
[email protected]c13e1da62011-09-09 21:48:304967 GLuint elements_used = 0;
4968 if (!SafeMultiply(num_vertices,
4969 static_cast<GLuint>(info->size()), &elements_used) ||
[email protected]8fbedc02010-11-18 18:43:404970 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
4971 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4972 return false;
4973 }
4974 }
4975 }
4976
[email protected]c13e1da62011-09-09 21:48:304977 const GLuint kSizeOfFloat = sizeof(float); // NOLINT
4978 GLuint size_needed = 0;
4979 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed) ||
4980 size_needed > 0x7FFFFFFFU) {
[email protected]8fbedc02010-11-18 18:43:404981 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4982 return false;
4983 }
4984
[email protected]c13e1da62011-09-09 21:48:304985 CopyRealGLErrorsToWrapper();
[email protected]8fbedc02010-11-18 18:43:404986
4987 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
[email protected]c13e1da62011-09-09 21:48:304988 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
[email protected]8fbedc02010-11-18 18:43:404989 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:304990 GLenum error = glGetError();
4991 if (error != GL_NO_ERROR) {
4992 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4993 return false;
4994 }
[email protected]8fbedc02010-11-18 18:43:404995 }
4996
4997 // Copy the elements and convert to float
4998 GLintptr offset = 0;
4999 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5000 infos.begin(); it != infos.end(); ++it) {
5001 const VertexAttribManager::VertexAttribInfo* info = *it;
5002 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5003 current_program_->GetAttribInfoByLocation(info->index());
5004 if (attrib_info &&
5005 info->CanAccess(max_vertex_accessed) &&
5006 info->type() == GL_FIXED) {
5007 int num_elements = info->size() * kSizeOfFloat;
5008 int size = num_elements * num_vertices;
5009 scoped_array<float> data(new float[size]);
5010 const int32* src = reinterpret_cast<const int32 *>(
5011 info->buffer()->GetRange(info->offset(), size));
5012 const int32* end = src + num_elements;
5013 float* dst = data.get();
5014 while (src != end) {
5015 *dst++ = static_cast<float>(*src++) / 65536.0f;
5016 }
5017 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
5018 glVertexAttribPointer(
5019 info->index(), info->size(), GL_FLOAT, false, 0,
5020 reinterpret_cast<GLvoid*>(offset));
5021 offset += size;
5022 }
5023 }
5024 *simulated = true;
5025 return true;
5026}
5027
5028void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
5029 // There's no need to call glVertexAttribPointer because we shadow all the
5030 // settings and passing GL_FIXED to it will not work.
5031 glBindBuffer(GL_ARRAY_BUFFER,
5032 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
5033}
5034
[email protected]38d139d2011-07-14 00:38:435035error::Error GLES2DecoderImpl::HandleDrawArrays(
5036 uint32 immediate_data_size, const gles2::DrawArrays& c) {
5037 GLenum mode = static_cast<GLenum>(c.mode);
5038 GLint first = static_cast<GLint>(c.first);
5039 GLsizei count = static_cast<GLsizei>(c.count);
5040 if (!validators_->draw_mode.IsValid(mode)) {
5041 SetGLError(GL_INVALID_ENUM, "glDrawArrays: mode GL_INVALID_ENUM");
5042 return error::kNoError;
5043 }
5044 if (count < 0) {
5045 SetGLError(GL_INVALID_VALUE, "glDrawArrays: count < 0");
5046 return error::kNoError;
5047 }
[email protected]0d6bfdc2011-11-02 01:32:205048 if (!CheckBoundFramebuffersValid("glDrawArrays")) {
[email protected]38d139d2011-07-14 00:38:435049 return error::kNoError;
5050 }
5051 // We have to check this here because the prototype for glDrawArrays
5052 // is GLint not GLsizei.
5053 if (first < 0) {
5054 SetGLError(GL_INVALID_VALUE, "glDrawArrays: first < 0");
5055 return error::kNoError;
5056 }
5057
5058 if (count == 0) {
5059 return error::kNoError;
5060 }
5061
5062 GLuint max_vertex_accessed = first + count - 1;
5063 if (IsDrawValid(max_vertex_accessed)) {
[email protected]0d6bfdc2011-11-02 01:32:205064 if (!ClearUnclearedTextures()) {
5065 SetGLError(GL_INVALID_VALUE, "glDrawArrays: out of memory");
5066 return error::kNoError;
5067 }
[email protected]c13e1da62011-09-09 21:48:305068 bool simulated_attrib_0 = false;
5069 if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
5070 return error::kNoError;
5071 }
[email protected]38d139d2011-07-14 00:38:435072 bool simulated_fixed_attribs = false;
5073 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
5074 bool textures_set = SetBlackTextureForNonRenderableTextures();
5075 ApplyDirtyState();
5076 glDrawArrays(mode, first, count);
5077 if (textures_set) {
5078 RestoreStateForNonRenderableTextures();
5079 }
5080 if (simulated_fixed_attribs) {
5081 RestoreStateForSimulatedFixedAttribs();
5082 }
5083 }
5084 if (simulated_attrib_0) {
5085 RestoreStateForSimulatedAttrib0();
5086 }
5087 if (WasContextLost()) {
5088 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawArrays.";
5089 return error::kLostContext;
5090 }
5091 }
5092 return error::kNoError;
5093}
5094
[email protected]f7a64ee2010-02-01 22:24:145095error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:195096 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]a0b78dc2011-11-11 10:43:105097 if (!bound_element_array_buffer_) {
[email protected]8eee29c2010-04-29 03:38:295098 SetGLError(GL_INVALID_OPERATION,
5099 "glDrawElements: No element array buffer bound");
5100 return error::kNoError;
5101 }
5102
5103 GLenum mode = c.mode;
5104 GLsizei count = c.count;
5105 GLenum type = c.type;
5106 int32 offset = c.index_offset;
5107 if (count < 0) {
5108 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
5109 return error::kNoError;
5110 }
5111 if (offset < 0) {
5112 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
5113 return error::kNoError;
5114 }
[email protected]9438b012010-06-15 22:55:055115 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:295116 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
5117 return error::kNoError;
5118 }
[email protected]9438b012010-06-15 22:55:055119 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295120 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
5121 return error::kNoError;
5122 }
5123
[email protected]0d6bfdc2011-11-02 01:32:205124 if (!CheckBoundFramebuffersValid("glDrawElements")) {
[email protected]3a03a8f2011-03-19 00:51:275125 return error::kNoError;
5126 }
5127
[email protected]6c788fb72010-08-26 02:16:315128 if (count == 0) {
5129 return error::kNoError;
5130 }
5131
[email protected]8eee29c2010-04-29 03:38:295132 GLuint max_vertex_accessed;
5133 if (!bound_element_array_buffer_->GetMaxValueForRange(
5134 offset, count, type, &max_vertex_accessed)) {
5135 SetGLError(GL_INVALID_OPERATION,
5136 "glDrawElements: range out of bounds for buffer");
5137 return error::kNoError;
5138 }
5139
5140 if (IsDrawValid(max_vertex_accessed)) {
[email protected]0d6bfdc2011-11-02 01:32:205141 if (!ClearUnclearedTextures()) {
5142 SetGLError(GL_INVALID_VALUE, "glDrawElements: out of memory");
5143 return error::kNoError;
5144 }
[email protected]c13e1da62011-09-09 21:48:305145 bool simulated_attrib_0 = false;
5146 if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
5147 return error::kNoError;
5148 }
[email protected]8fbedc02010-11-18 18:43:405149 bool simulated_fixed_attribs = false;
5150 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
5151 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:465152 ApplyDirtyState();
[email protected]8fbedc02010-11-18 18:43:405153 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
5154 glDrawElements(mode, count, type, indices);
5155 if (textures_set) {
5156 RestoreStateForNonRenderableTextures();
5157 }
5158 if (simulated_fixed_attribs) {
5159 RestoreStateForSimulatedFixedAttribs();
5160 }
[email protected]ba3176a2009-12-16 18:19:465161 }
[email protected]b1122982010-05-17 23:04:245162 if (simulated_attrib_0) {
5163 RestoreStateForSimulatedAttrib0();
5164 }
[email protected]38d139d2011-07-14 00:38:435165 if (WasContextLost()) {
5166 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawElements.";
5167 return error::kLostContext;
5168 }
[email protected]96449d2c2009-11-25 00:01:325169 }
[email protected]f7a64ee2010-02-01 22:24:145170 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325171}
5172
[email protected]269200b12010-11-18 22:53:065173GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:235174 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
5175 GLuint max_vertex_accessed = 0;
5176 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:295177 if (!info) {
[email protected]ae51d192010-04-27 00:48:035178 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:295179 SetGLError(GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:065180 "GetMaxValueInBufferCHROMIUM: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:235181 } else {
5182 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:035183 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:065184 SetGLError(
5185 GL_INVALID_OPERATION,
5186 "GetMaxValueInBufferCHROMIUM: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:235187 }
5188 }
5189 return max_vertex_accessed;
5190}
5191
[email protected]96449d2c2009-11-25 00:01:325192// Calls glShaderSource for the various versions of the ShaderSource command.
5193// Assumes that data / data_size points to a piece of memory that is in range
5194// of whatever context it came from (shared memory, immediate memory, bucket
5195// memory.)
[email protected]45bf5152010-02-12 00:11:315196error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035197 GLuint client_id, const char* data, uint32 data_size) {
[email protected]258a3313f2011-10-18 20:13:575198 std::string str(data, data + data_size);
[email protected]6b8cf1a2010-05-06 16:13:585199 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5200 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:315201 if (!info) {
[email protected]45bf5152010-02-12 00:11:315202 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325203 }
[email protected]45bf5152010-02-12 00:11:315204 // Note: We don't actually call glShaderSource here. We wait until
5205 // the call to glCompileShader.
[email protected]258a3313f2011-10-18 20:13:575206 info->UpdateSource(str.c_str());
[email protected]f7a64ee2010-02-01 22:24:145207 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325208}
5209
[email protected]f7a64ee2010-02-01 22:24:145210error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:195211 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:325212 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315213 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:325214 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:465215 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145216 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325217 }
[email protected]ae51d192010-04-27 00:48:035218 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:325219}
5220
[email protected]f7a64ee2010-02-01 22:24:145221error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:195222 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:325223 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315224 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:305225 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465226 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145227 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325228 }
[email protected]ae51d192010-04-27 00:48:035229 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:315230}
5231
[email protected]558847a2010-03-24 07:02:545232error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
5233 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:545234 Bucket* bucket = GetBucket(c.data_bucket_id);
5235 if (!bucket || bucket->size() == 0) {
5236 return error::kInvalidArguments;
5237 }
5238 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035239 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:545240 bucket->size() - 1);
5241}
5242
[email protected]ae51d192010-04-27 00:48:035243void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]0c8fabf2011-06-14 19:35:225244 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]6b8cf1a2010-05-06 16:13:585245 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5246 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:315247 if (!info) {
[email protected]45bf5152010-02-12 00:11:315248 return;
5249 }
[email protected]de17df392010-04-23 21:09:415250 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
5251 // glShaderSource and then glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:525252 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:345253 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:185254 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:345255 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:455256 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:235257
[email protected]a550584e2010-09-17 18:01:455258 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:345259 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:185260 return;
5261 }
[email protected]a550584e2010-09-17 18:01:455262 shader_src = translator->translated_shader();
[email protected]93297702011-11-05 05:09:465263 if (!feature_info_->feature_flags().angle_translated_shader_source)
[email protected]d6a53e42011-10-05 00:09:365264 info->UpdateTranslatedSource(shader_src);
[email protected]de17df392010-04-23 21:09:415265 }
[email protected]de17df392010-04-23 21:09:415266
[email protected]ae51d192010-04-27 00:48:035267 glShaderSource(info->service_id(), 1, &shader_src, NULL);
5268 glCompileShader(info->service_id());
[email protected]93297702011-11-05 05:09:465269 if (feature_info_->feature_flags().angle_translated_shader_source) {
[email protected]d6a53e42011-10-05 00:09:365270 GLint max_len = 0;
5271 glGetShaderiv(info->service_id(),
5272 GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
5273 &max_len);
5274 scoped_array<char> temp(new char[max_len]);
5275 GLint len = 0;
5276 glGetTranslatedShaderSourceANGLE(
5277 info->service_id(), max_len, &len, temp.get());
5278 DCHECK(max_len == 0 || len < max_len);
5279 DCHECK(len == 0 || temp[len] == '\0');
5280 info->UpdateTranslatedSource(temp.get());
5281 }
5282
[email protected]e5186162010-06-14 18:54:415283 GLint status = GL_FALSE;
5284 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
5285 if (status) {
[email protected]f57bb282010-11-12 00:51:345286 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:415287 } else {
[email protected]d9977d42010-09-01 20:27:025288 // We cannot reach here if we are using the shader translator.
5289 // All invalid shaders must be rejected by the translator.
5290 // All translated shaders must compile.
5291 LOG_IF(ERROR, use_shader_translator_)
5292 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:335293 GLint max_len = 0;
5294 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
5295 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:415296 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:335297 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
5298 DCHECK(max_len == 0 || len < max_len);
[email protected]d6a53e42011-10-05 00:09:365299 DCHECK(len == 0 || temp[len] == '\0');
[email protected]df6cf1ad2011-01-29 01:20:525300 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
[email protected]e5186162010-06-14 18:54:415301 }
[email protected]45bf5152010-02-12 00:11:315302};
5303
[email protected]ddd968b82010-03-02 00:44:295304void GLES2DecoderImpl::DoGetShaderiv(
5305 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:585306 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5307 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:295308 if (!info) {
[email protected]ddd968b82010-03-02 00:44:295309 return;
5310 }
[email protected]8f1ccdac2010-05-19 21:01:485311 switch (pname) {
5312 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525313 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:485314 return;
5315 case GL_COMPILE_STATUS:
[email protected]062c38b2012-01-18 03:25:105316 *params = compile_shader_always_succeeds_ ? true : info->IsValid();
[email protected]e5186162010-06-14 18:54:415317 return;
[email protected]8f1ccdac2010-05-19 21:01:485318 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525319 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:415320 return;
[email protected]d6a53e42011-10-05 00:09:365321 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5322 *params = info->translated_source() ?
5323 info->translated_source()->size() + 1 : 0;
5324 return;
[email protected]8f1ccdac2010-05-19 21:01:485325 default:
5326 break;
[email protected]ddd968b82010-03-02 00:44:295327 }
[email protected]8f1ccdac2010-05-19 21:01:485328 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:295329}
5330
[email protected]ae51d192010-04-27 00:48:035331error::Error GLES2DecoderImpl::HandleGetShaderSource(
5332 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
5333 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:035334 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5335 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:585336 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5337 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:525338 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:295339 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:295340 return error::kNoError;
5341 }
[email protected]df6cf1ad2011-01-29 01:20:525342 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:035343 return error::kNoError;
5344}
5345
[email protected]d6a53e42011-10-05 00:09:365346error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
5347 uint32 immediate_data_size,
5348 const gles2::GetTranslatedShaderSourceANGLE& c) {
5349 GLuint shader = c.shader;
5350
5351 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5352 Bucket* bucket = CreateBucket(bucket_id);
5353 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5354 shader, "glTranslatedGetShaderSourceANGLE");
5355 if (!info) {
5356 bucket->SetSize(0);
5357 return error::kNoError;
5358 }
5359
5360 bucket->SetFromString(info->translated_source() ?
5361 info->translated_source()->c_str() : NULL);
5362 return error::kNoError;
5363}
5364
[email protected]ae51d192010-04-27 00:48:035365error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
5366 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
5367 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:585368 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5369 Bucket* bucket = CreateBucket(bucket_id);
5370 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5371 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525372 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465373 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035374 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:315375 }
[email protected]df6cf1ad2011-01-29 01:20:525376 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035377 return error::kNoError;
5378}
5379
5380error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
5381 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
5382 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:585383 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5384 Bucket* bucket = CreateBucket(bucket_id);
5385 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5386 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525387 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465388 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035389 return error::kNoError;
5390 }
[email protected]df6cf1ad2011-01-29 01:20:525391 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035392 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325393}
5394
[email protected]1958e0e2010-04-22 05:17:155395bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105396 const BufferManager::BufferInfo* buffer = GetBufferInfo(client_id);
5397 return buffer && buffer->IsValid() && !buffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155398}
5399
5400bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105401 const FramebufferManager::FramebufferInfo* framebuffer =
[email protected]06c8b082011-01-05 18:00:365402 GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105403 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155404}
5405
5406bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365407 // IsProgram is true for programs as soon as they are created, until they are
5408 // deleted and no longer in use.
[email protected]a0b78dc2011-11-11 10:43:105409 const ProgramManager::ProgramInfo* program = GetProgramInfo(client_id);
5410 return program != NULL && !program->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155411}
5412
5413bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105414 const RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]06c8b082011-01-05 18:00:365415 GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105416 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155417}
5418
5419bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365420 // IsShader is true for shaders as soon as they are created, until they
5421 // are deleted and not attached to any programs.
[email protected]a0b78dc2011-11-11 10:43:105422 const ShaderManager::ShaderInfo* shader = GetShaderInfo(client_id);
5423 return shader != NULL && !shader->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155424}
5425
5426bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105427 const TextureManager::TextureInfo* texture = GetTextureInfo(client_id);
5428 return texture && texture->IsValid() && !texture->IsDeleted();
[email protected]ae51d192010-04-27 00:48:035429}
5430
5431void GLES2DecoderImpl::DoAttachShader(
5432 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585433 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5434 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035435 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035436 return;
[email protected]1958e0e2010-04-22 05:17:155437 }
[email protected]6b8cf1a2010-05-06 16:13:585438 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5439 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035440 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035441 return;
5442 }
[email protected]ca488e12010-12-13 20:06:145443 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:315444 SetGLError(GL_INVALID_OPERATION,
5445 "glAttachShader: can not attach more than"
5446 " one shader of the same type.");
5447 return;
5448 }
[email protected]ae51d192010-04-27 00:48:035449 glAttachShader(program_info->service_id(), shader_info->service_id());
5450}
5451
5452void GLES2DecoderImpl::DoDetachShader(
5453 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585454 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5455 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035456 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035457 return;
5458 }
[email protected]6b8cf1a2010-05-06 16:13:585459 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5460 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035461 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035462 return;
5463 }
[email protected]9a0ccd42011-03-16 23:58:225464 if (!program_info->DetachShader(shader_manager(), shader_info)) {
5465 SetGLError(GL_INVALID_OPERATION,
5466 "glDetachShader: shader not attached to program");
5467 return;
5468 }
[email protected]ae51d192010-04-27 00:48:035469 glDetachShader(program_info->service_id(), shader_info->service_id());
5470}
5471
5472void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585473 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5474 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:035475 if (!info) {
[email protected]ae51d192010-04-27 00:48:035476 return;
5477 }
[email protected]d685a682011-04-29 16:19:575478 info->Validate();
[email protected]1958e0e2010-04-22 05:17:155479}
5480
[email protected]b1122982010-05-17 23:04:245481void GLES2DecoderImpl::DoGetVertexAttribfv(
5482 GLuint index, GLenum pname, GLfloat* params) {
5483 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445484 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245485 if (!info) {
5486 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
5487 return;
5488 }
5489 switch (pname) {
5490 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5491 BufferManager::BufferInfo* buffer = info->buffer();
5492 if (buffer && !buffer->IsDeleted()) {
5493 GLuint client_id;
5494 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5495 *params = static_cast<GLfloat>(client_id);
5496 }
5497 break;
5498 }
5499 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5500 *params = static_cast<GLfloat>(info->enabled());
5501 break;
5502 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5503 *params = static_cast<GLfloat>(info->size());
5504 break;
5505 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5506 *params = static_cast<GLfloat>(info->gl_stride());
5507 break;
5508 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5509 *params = static_cast<GLfloat>(info->type());
5510 break;
5511 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5512 *params = static_cast<GLfloat>(info->normalized());
5513 break;
5514 case GL_CURRENT_VERTEX_ATTRIB:
5515 params[0] = info->value().v[0];
5516 params[1] = info->value().v[1];
5517 params[2] = info->value().v[2];
5518 params[3] = info->value().v[3];
5519 break;
5520 default:
5521 NOTREACHED();
5522 break;
5523 }
5524}
5525
5526void GLES2DecoderImpl::DoGetVertexAttribiv(
5527 GLuint index, GLenum pname, GLint* params) {
5528 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445529 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245530 if (!info) {
5531 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
5532 return;
5533 }
5534 switch (pname) {
5535 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5536 BufferManager::BufferInfo* buffer = info->buffer();
5537 if (buffer && !buffer->IsDeleted()) {
5538 GLuint client_id;
5539 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5540 *params = client_id;
5541 }
5542 break;
5543 }
5544 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5545 *params = info->enabled();
5546 break;
5547 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5548 *params = info->size();
5549 break;
5550 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5551 *params = info->gl_stride();
5552 break;
5553 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5554 *params = info->type();
5555 break;
5556 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5557 *params = static_cast<GLint>(info->normalized());
5558 break;
5559 case GL_CURRENT_VERTEX_ATTRIB:
5560 params[0] = static_cast<GLint>(info->value().v[0]);
5561 params[1] = static_cast<GLint>(info->value().v[1]);
5562 params[2] = static_cast<GLint>(info->value().v[2]);
5563 params[3] = static_cast<GLint>(info->value().v[3]);
5564 break;
5565 default:
5566 NOTREACHED();
5567 break;
5568 }
5569}
5570
5571void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
5572 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445573 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245574 if (!info) {
5575 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
5576 return;
5577 }
5578 VertexAttribManager::VertexAttribInfo::Vec4 value;
5579 value.v[0] = v0;
5580 value.v[1] = 0.0f;
5581 value.v[2] = 0.0f;
5582 value.v[3] = 1.0f;
5583 info->set_value(value);
5584 glVertexAttrib1f(index, v0);
5585}
5586
5587void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
5588 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445589 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245590 if (!info) {
5591 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
5592 return;
5593 }
5594 VertexAttribManager::VertexAttribInfo::Vec4 value;
5595 value.v[0] = v0;
5596 value.v[1] = v1;
5597 value.v[2] = 0.0f;
5598 value.v[3] = 1.0f;
5599 info->set_value(value);
5600 glVertexAttrib2f(index, v0, v1);
5601}
5602
5603void GLES2DecoderImpl::DoVertexAttrib3f(
5604 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
5605 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445606 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245607 if (!info) {
5608 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
5609 return;
5610 }
5611 VertexAttribManager::VertexAttribInfo::Vec4 value;
5612 value.v[0] = v0;
5613 value.v[1] = v1;
5614 value.v[2] = v2;
5615 value.v[3] = 1.0f;
5616 info->set_value(value);
5617 glVertexAttrib3f(index, v0, v1, v2);
5618}
5619
5620void GLES2DecoderImpl::DoVertexAttrib4f(
5621 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
5622 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445623 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245624 if (!info) {
5625 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
5626 return;
5627 }
5628 VertexAttribManager::VertexAttribInfo::Vec4 value;
5629 value.v[0] = v0;
5630 value.v[1] = v1;
5631 value.v[2] = v2;
5632 value.v[3] = v3;
5633 info->set_value(value);
5634 glVertexAttrib4f(index, v0, v1, v2, v3);
5635}
5636
5637void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
5638 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445639 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245640 if (!info) {
5641 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
5642 return;
5643 }
5644 VertexAttribManager::VertexAttribInfo::Vec4 value;
5645 value.v[0] = v[0];
5646 value.v[1] = 0.0f;
5647 value.v[2] = 0.0f;
5648 value.v[3] = 1.0f;
5649 info->set_value(value);
5650 glVertexAttrib1fv(index, v);
5651}
5652
5653void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
5654 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445655 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245656 if (!info) {
5657 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
5658 return;
5659 }
5660 VertexAttribManager::VertexAttribInfo::Vec4 value;
5661 value.v[0] = v[0];
5662 value.v[1] = v[1];
5663 value.v[2] = 0.0f;
5664 value.v[3] = 1.0f;
5665 info->set_value(value);
5666 glVertexAttrib2fv(index, v);
5667}
5668
5669void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
5670 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445671 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245672 if (!info) {
5673 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
5674 return;
5675 }
5676 VertexAttribManager::VertexAttribInfo::Vec4 value;
5677 value.v[0] = v[0];
5678 value.v[1] = v[1];
5679 value.v[2] = v[2];
5680 value.v[3] = 1.0f;
5681 info->set_value(value);
5682 glVertexAttrib3fv(index, v);
5683}
5684
5685void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
5686 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445687 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245688 if (!info) {
5689 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
5690 return;
5691 }
5692 VertexAttribManager::VertexAttribInfo::Vec4 value;
5693 value.v[0] = v[0];
5694 value.v[1] = v[1];
5695 value.v[2] = v[2];
5696 value.v[3] = v[3];
5697 info->set_value(value);
5698 glVertexAttrib4fv(index, v);
5699}
5700
[email protected]f7a64ee2010-02-01 22:24:145701error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:195702 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:295703 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
5704 SetGLError(GL_INVALID_VALUE,
5705 "glVertexAttribPointer: no array buffer bound");
5706 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325707 }
[email protected]8eee29c2010-04-29 03:38:295708
5709 GLuint indx = c.indx;
5710 GLint size = c.size;
5711 GLenum type = c.type;
5712 GLboolean normalized = c.normalized;
5713 GLsizei stride = c.stride;
5714 GLsizei offset = c.offset;
5715 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:055716 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295717 SetGLError(GL_INVALID_ENUM,
5718 "glVertexAttribPointer: type GL_INVALID_ENUM");
5719 return error::kNoError;
5720 }
[email protected]9438b012010-06-15 22:55:055721 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:315722 SetGLError(GL_INVALID_VALUE,
[email protected]8eee29c2010-04-29 03:38:295723 "glVertexAttribPointer: size GL_INVALID_VALUE");
5724 return error::kNoError;
5725 }
5726 if (indx >= group_->max_vertex_attribs()) {
5727 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
5728 return error::kNoError;
5729 }
5730 if (stride < 0) {
5731 SetGLError(GL_INVALID_VALUE,
5732 "glVertexAttribPointer: stride < 0");
5733 return error::kNoError;
5734 }
5735 if (stride > 255) {
5736 SetGLError(GL_INVALID_VALUE,
5737 "glVertexAttribPointer: stride > 255");
5738 return error::kNoError;
5739 }
5740 if (offset < 0) {
5741 SetGLError(GL_INVALID_VALUE,
5742 "glVertexAttribPointer: offset < 0");
5743 return error::kNoError;
5744 }
5745 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:315746 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:295747 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:315748 SetGLError(GL_INVALID_OPERATION,
5749 "glVertexAttribPointer: offset not valid for type");
5750 return error::kNoError;
5751 }
5752 if (stride % component_size > 0) {
5753 SetGLError(GL_INVALID_OPERATION,
[email protected]8eee29c2010-04-29 03:38:295754 "glVertexAttribPointer: stride not valid for type");
5755 return error::kNoError;
5756 }
[email protected]3757a372012-01-19 05:20:445757 vertex_attrib_manager_->SetAttribInfo(
[email protected]8fbedc02010-11-18 18:43:405758 indx,
[email protected]8eee29c2010-04-29 03:38:295759 bound_array_buffer_,
5760 size,
5761 type,
[email protected]b1122982010-05-17 23:04:245762 normalized,
5763 stride,
5764 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:295765 offset);
[email protected]8fbedc02010-11-18 18:43:405766 if (type != GL_FIXED) {
5767 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
5768 }
[email protected]f7a64ee2010-02-01 22:24:145769 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325770}
5771
[email protected]f7a64ee2010-02-01 22:24:145772error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:195773 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:315774 GLint x = c.x;
5775 GLint y = c.y;
5776 GLsizei width = c.width;
5777 GLsizei height = c.height;
5778 GLenum format = c.format;
5779 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:565780 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:295781 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:565782 return error::kNoError;
5783 }
[email protected]a51788e2010-02-24 21:54:255784 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:185785 uint32 pixels_size;
5786 if (!GLES2Util::ComputeImageDataSize(
5787 width, height, format, type, pack_alignment_, &pixels_size)) {
5788 return error::kOutOfBounds;
5789 }
[email protected]612d2f82009-12-08 20:49:315790 void* pixels = GetSharedMemoryAs<void*>(
5791 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:255792 Result* result = GetSharedMemoryAs<Result*>(
5793 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5794 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:145795 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465796 }
[email protected]a51788e2010-02-24 21:54:255797
[email protected]9438b012010-06-15 22:55:055798 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295799 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
5800 return error::kNoError;
5801 }
[email protected]9438b012010-06-15 22:55:055802 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295803 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125804 return error::kNoError;
5805 }
[email protected]57f223832010-03-19 01:57:565806 if (width == 0 || height == 0) {
5807 return error::kNoError;
5808 }
5809
[email protected]57f223832010-03-19 01:57:565810 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:305811 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:565812
5813 GLint max_x;
5814 GLint max_y;
5815 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:295816 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:145817 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:315818 }
[email protected]57f223832010-03-19 01:57:565819
[email protected]0d6bfdc2011-11-02 01:32:205820 if (!CheckBoundFramebuffersValid("glReadPixels")) {
5821 return error::kNoError;
5822 }
5823
[email protected]a0b78dc2011-11-11 10:43:105824 CopyRealGLErrorsToWrapper();
5825
5826 ScopedResolvedFrameBufferBinder binder(this, false, true);
5827
[email protected]d37231fa2010-04-09 21:16:025828 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:565829 // The user requested an out of range area. Get the results 1 line
5830 // at a time.
5831 uint32 temp_size;
5832 if (!GLES2Util::ComputeImageDataSize(
5833 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295834 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565835 return error::kNoError;
5836 }
5837 GLsizei unpadded_row_size = temp_size;
5838 if (!GLES2Util::ComputeImageDataSize(
5839 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295840 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565841 return error::kNoError;
5842 }
5843 GLsizei padded_row_size = temp_size - unpadded_row_size;
5844 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:295845 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565846 return error::kNoError;
5847 }
5848
5849 GLint dest_x_offset = std::max(-x, 0);
5850 uint32 dest_row_offset;
5851 if (!GLES2Util::ComputeImageDataSize(
5852 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:295853 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565854 return error::kNoError;
5855 }
5856
5857 // Copy each row into the larger dest rect.
5858 int8* dst = static_cast<int8*>(pixels);
5859 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:025860 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:565861 GLint read_width = read_end_x - read_x;
5862 for (GLint yy = 0; yy < height; ++yy) {
5863 GLint ry = y + yy;
5864
5865 // Clear the row.
5866 memset(dst, 0, unpadded_row_size);
5867
5868 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:025869 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:565870 glReadPixels(
5871 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
5872 }
5873 dst += padded_row_size;
5874 }
5875 } else {
5876 glReadPixels(x, y, width, height, format, type, pixels);
5877 }
[email protected]1002c2d2011-06-28 22:39:045878 GLenum error = PeekGLError();
[email protected]a51788e2010-02-24 21:54:255879 if (error == GL_NO_ERROR) {
5880 *result = true;
[email protected]4848b9f82011-03-10 18:37:565881
5882 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5883 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5884 if ((channels_exist & 0x0008) == 0) {
5885 // Set the alpha to 255 because some drivers are buggy in this regard.
5886 uint32 temp_size;
5887 if (!GLES2Util::ComputeImageDataSize(
5888 width, 1, format, type, pack_alignment_, &temp_size)) {
5889 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5890 return error::kNoError;
5891 }
5892 GLsizei unpadded_row_size = temp_size;
5893 if (!GLES2Util::ComputeImageDataSize(
5894 width, 2, format, type, pack_alignment_, &temp_size)) {
5895 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5896 return error::kNoError;
5897 }
5898 GLsizei padded_row_size = temp_size - unpadded_row_size;
5899 if (padded_row_size < 0 || unpadded_row_size < 0) {
5900 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5901 return error::kNoError;
5902 }
5903 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
5904 // of this implementation.
5905 if (type != GL_UNSIGNED_BYTE) {
5906 SetGLError(GL_INVALID_OPERATION, "unsupported readPixel format");
5907 return error::kNoError;
5908 }
5909 switch (format) {
5910 case GL_RGBA:
[email protected]297ca1c2011-06-20 23:08:465911 case GL_BGRA_EXT:
[email protected]4848b9f82011-03-10 18:37:565912 case GL_ALPHA: {
5913 int offset = (format == GL_ALPHA) ? 0 : 3;
5914 int step = (format == GL_ALPHA) ? 1 : 4;
5915 uint8* dst = static_cast<uint8*>(pixels) + offset;
5916 for (GLint yy = 0; yy < height; ++yy) {
5917 uint8* end = dst + unpadded_row_size;
5918 for (uint8* d = dst; d < end; d += step) {
5919 *d = 255;
5920 }
5921 dst += padded_row_size;
5922 }
5923 break;
5924 }
5925 default:
5926 break;
5927 }
5928 }
[email protected]a51788e2010-02-24 21:54:255929 }
[email protected]4848b9f82011-03-10 18:37:565930
[email protected]f7a64ee2010-02-01 22:24:145931 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325932}
5933
[email protected]f7a64ee2010-02-01 22:24:145934error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:195935 uint32 immediate_data_size, const gles2::PixelStorei& c) {
5936 GLenum pname = c.pname;
5937 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:055938 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:295939 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125940 return error::kNoError;
5941 }
[email protected]222471d2011-11-30 18:06:395942 switch (pname) {
5943 case GL_PACK_ALIGNMENT:
5944 case GL_UNPACK_ALIGNMENT:
5945 if (!validators_->pixel_store_alignment.IsValid(param)) {
5946 SetGLError(GL_INVALID_VALUE,
5947 "glPixelSTore: param GL_INVALID_VALUE");
5948 return error::kNoError;
5949 }
5950 default:
5951 break;
[email protected]b9849abf2009-11-25 19:13:195952 }
5953 glPixelStorei(pname, param);
5954 switch (pname) {
5955 case GL_PACK_ALIGNMENT:
5956 pack_alignment_ = param;
5957 break;
[email protected]222471d2011-11-30 18:06:395958 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
5959 break;
[email protected]b9849abf2009-11-25 19:13:195960 case GL_UNPACK_ALIGNMENT:
5961 unpack_alignment_ = param;
5962 break;
5963 default:
5964 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:375965 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:195966 break;
5967 }
[email protected]f7a64ee2010-02-01 22:24:145968 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195969}
5970
[email protected]1c75a3702011-11-11 14:15:285971error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
5972 uint32 immediate_data_size, const gles2::PostSubBufferCHROMIUM& c) {
5973 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
[email protected]aa258822011-11-22 13:52:255974 if (!context_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
[email protected]1c75a3702011-11-11 14:15:285975 SetGLError(GL_INVALID_OPERATION,
5976 "glPostSubBufferCHROMIUM: command not supported by surface");
5977 return error::kNoError;
5978 }
5979 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height))
5980 return error::kNoError;
5981 else
5982 return error::kLostContext;
5983}
5984
[email protected]558847a2010-03-24 07:02:545985error::Error GLES2DecoderImpl::GetAttribLocationHelper(
5986 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5987 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:575988 if (!StringIsValidForGLES(name_str.c_str())) {
5989 SetGLError(GL_INVALID_VALUE, "glGetAttribLocation: Invalid character");
5990 return error::kNoError;
5991 }
[email protected]6b8cf1a2010-05-06 16:13:585992 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5993 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:035994 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145995 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195996 }
[email protected]ae51d192010-04-27 00:48:035997 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295998 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255999 return error::kNoError;
6000 }
[email protected]b9849abf2009-11-25 19:13:196001 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546002 location_shm_id, location_shm_offset, sizeof(GLint));
6003 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146004 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196005 }
[email protected]558847a2010-03-24 07:02:546006 // Require the client to init this incase the context is lost and we are no
6007 // longer executing commands.
6008 if (*location != -1) {
6009 return error::kGenericError;
6010 }
[email protected]0bfd9882010-02-05 23:02:256011 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:146012 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196013}
6014
[email protected]558847a2010-03-24 07:02:546015error::Error GLES2DecoderImpl::HandleGetAttribLocation(
6016 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
6017 uint32 name_size = c.data_size;
6018 const char* name = GetSharedMemoryAs<const char*>(
6019 c.name_shm_id, c.name_shm_offset, name_size);
6020 if (!name) {
6021 return error::kOutOfBounds;
6022 }
6023 String name_str(name, name_size);
6024 return GetAttribLocationHelper(
6025 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6026}
6027
[email protected]f7a64ee2010-02-01 22:24:146028error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196029 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:546030 uint32 name_size = c.data_size;
6031 const char* name = GetImmediateDataAs<const char*>(
6032 c, name_size, immediate_data_size);
6033 if (!name) {
6034 return error::kOutOfBounds;
6035 }
6036 String name_str(name, name_size);
6037 return GetAttribLocationHelper(
6038 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6039}
6040
6041error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
6042 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
6043 Bucket* bucket = GetBucket(c.name_bucket_id);
6044 if (!bucket) {
6045 return error::kInvalidArguments;
6046 }
6047 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186048 if (!bucket->GetAsString(&name_str)) {
6049 return error::kInvalidArguments;
6050 }
[email protected]558847a2010-03-24 07:02:546051 return GetAttribLocationHelper(
6052 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6053}
6054
6055error::Error GLES2DecoderImpl::GetUniformLocationHelper(
6056 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6057 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576058 if (!StringIsValidForGLES(name_str.c_str())) {
6059 SetGLError(GL_INVALID_VALUE, "glGetUniformLocation: Invalid character");
6060 return error::kNoError;
6061 }
[email protected]6b8cf1a2010-05-06 16:13:586062 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6063 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:036064 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146065 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196066 }
[email protected]ae51d192010-04-27 00:48:036067 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:296068 SetGLError(GL_INVALID_OPERATION,
6069 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:256070 return error::kNoError;
6071 }
[email protected]b9849abf2009-11-25 19:13:196072 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546073 location_shm_id, location_shm_offset, sizeof(GLint));
6074 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146075 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196076 }
[email protected]558847a2010-03-24 07:02:546077 // Require the client to init this incase the context is lost an we are no
6078 // longer executing commands.
6079 if (*location != -1) {
6080 return error::kGenericError;
6081 }
6082 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:146083 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196084}
6085
[email protected]f7a64ee2010-02-01 22:24:146086error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:196087 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:196088 uint32 name_size = c.data_size;
6089 const char* name = GetSharedMemoryAs<const char*>(
6090 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:546091 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146092 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196093 }
6094 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546095 return GetUniformLocationHelper(
6096 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196097}
6098
[email protected]f7a64ee2010-02-01 22:24:146099error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196100 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:196101 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:306102 const char* name = GetImmediateDataAs<const char*>(
6103 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:546104 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146105 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196106 }
6107 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546108 return GetUniformLocationHelper(
6109 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6110}
6111
6112error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
6113 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
6114 Bucket* bucket = GetBucket(c.name_bucket_id);
6115 if (!bucket) {
6116 return error::kInvalidArguments;
6117 }
6118 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186119 if (!bucket->GetAsString(&name_str)) {
6120 return error::kInvalidArguments;
6121 }
[email protected]558847a2010-03-24 07:02:546122 return GetUniformLocationHelper(
6123 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196124}
6125
[email protected]ddd968b82010-03-02 00:44:296126error::Error GLES2DecoderImpl::HandleGetString(
6127 uint32 immediate_data_size, const gles2::GetString& c) {
6128 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:056129 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:296130 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:296131 return error::kNoError;
6132 }
[email protected]1958e0e2010-04-22 05:17:156133 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
6134 const char* str = NULL;
[email protected]f0d74742011-10-03 16:31:046135 std::string extensions;
[email protected]1958e0e2010-04-22 05:17:156136 switch (name) {
6137 case GL_VERSION:
6138 str = "OpenGL ES 2.0 Chromium";
6139 break;
6140 case GL_SHADING_LANGUAGE_VERSION:
6141 str = "OpenGL ES GLSL ES 1.0 Chromium";
6142 break;
6143 case GL_EXTENSIONS:
[email protected]f0d74742011-10-03 16:31:046144 {
6145 // For WebGL contexts, strip out the OES derivatives extension if it has
6146 // not been enabled.
6147 if (force_webgl_glsl_validation_ &&
6148 !derivatives_explicitly_enabled_) {
6149 extensions = feature_info_->extensions();
6150 size_t offset = extensions.find(kOESDerivativeExtension);
6151 if (std::string::npos != offset) {
6152 extensions.replace(offset,
6153 offset + arraysize(kOESDerivativeExtension),
6154 std::string());
6155 }
6156 str = extensions.c_str();
6157 } else {
6158 str = feature_info_->extensions().c_str();
6159 }
[email protected]f0d74742011-10-03 16:31:046160 }
[email protected]1958e0e2010-04-22 05:17:156161 break;
6162 default:
6163 str = gl_str;
6164 break;
6165 }
[email protected]ddd968b82010-03-02 00:44:296166 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:156167 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:296168 return error::kNoError;
6169}
6170
[email protected]0c86dbf2010-03-05 08:14:116171void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:156172 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:056173 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296174 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
6175 return;
6176 }
[email protected]9438b012010-06-15 22:55:056177 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:296178 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:116179 return;
[email protected]3b6ec202010-03-05 05:16:236180 }
6181 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:296182 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:286183 return;
[email protected]3b6ec202010-03-05 05:16:236184 }
6185 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
6186 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296187 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:286188 return;
[email protected]3b6ec202010-03-05 05:16:236189 }
6190 // Clear the buffer to 0 if no initial data was passed in.
6191 scoped_array<int8> zero;
6192 if (!data) {
6193 zero.reset(new int8[size]);
6194 memset(zero.get(), 0, size);
6195 data = zero.get();
6196 }
[email protected]473c01ccb2011-06-07 01:33:306197
6198 if (!bufferdata_faster_than_buffersubdata_ &&
6199 size == info->size() && usage == info->usage()) {
6200 glBufferSubData(target, 0, size, data);
6201 info->SetRange(0, size, data);
6202 return;
6203 }
6204
[email protected]3b6ec202010-03-05 05:16:236205 CopyRealGLErrorsToWrapper();
6206 glBufferData(target, size, data, usage);
[email protected]1002c2d2011-06-28 22:39:046207 GLenum error = PeekGLError();
6208 if (error == GL_NO_ERROR) {
[email protected]473c01ccb2011-06-07 01:33:306209 buffer_manager()->SetInfo(info, size, usage);
[email protected]0c86dbf2010-03-05 08:14:116210 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:236211 }
[email protected]0c86dbf2010-03-05 08:14:116212}
6213
6214error::Error GLES2DecoderImpl::HandleBufferData(
6215 uint32 immediate_data_size, const gles2::BufferData& c) {
6216 GLenum target = static_cast<GLenum>(c.target);
6217 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
6218 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6219 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6220 GLenum usage = static_cast<GLenum>(c.usage);
6221 const void* data = NULL;
6222 if (data_shm_id != 0 || data_shm_offset != 0) {
6223 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
6224 if (!data) {
6225 return error::kOutOfBounds;
6226 }
6227 }
6228 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:146229 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196230}
6231
[email protected]f7a64ee2010-02-01 22:24:146232error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:196233 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
6234 GLenum target = static_cast<GLenum>(c.target);
6235 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:306236 const void* data = GetImmediateDataAs<const void*>(
6237 c, size, immediate_data_size);
6238 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146239 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:306240 }
[email protected]b9849abf2009-11-25 19:13:196241 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:116242 DoBufferData(target, size, data, usage);
6243 return error::kNoError;
6244}
6245
6246void GLES2DecoderImpl::DoBufferSubData(
6247 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:506248 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476249 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296250 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:286251 return;
[email protected]a93bb842010-02-16 23:03:476252 }
[email protected]0c86dbf2010-03-05 08:14:116253 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:296254 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]473c01ccb2011-06-07 01:33:306255 return;
[email protected]07f54fcc2009-12-22 02:46:306256 }
[email protected]473c01ccb2011-06-07 01:33:306257 if (bufferdata_faster_than_buffersubdata_ &&
6258 offset == 0 && size == info->size()) {
6259 glBufferData(target, size, data, info->usage());
6260 return;
6261 }
6262 glBufferSubData(target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:196263}
6264
[email protected]0d6bfdc2011-11-02 01:32:206265bool GLES2DecoderImpl::ClearLevel(
6266 unsigned service_id,
6267 unsigned bind_target,
6268 unsigned target,
6269 int level,
6270 unsigned format,
6271 unsigned type,
6272 int width,
[email protected]4502e6492011-12-14 19:39:156273 int height,
6274 bool is_texture_immutable) {
[email protected]0d6bfdc2011-11-02 01:32:206275 // Assumes the size has already been checked.
6276 uint32 pixels_size = 0;
6277 if (!GLES2Util::ComputeImageDataSize(
6278 width, height, format, type, unpack_alignment_, &pixels_size)) {
6279 return false;
6280 }
6281 scoped_array<char> zero(new char[pixels_size]);
6282 memset(zero.get(), 0, pixels_size);
6283 glBindTexture(bind_target, service_id);
[email protected]4502e6492011-12-14 19:39:156284 if (is_texture_immutable) {
6285 glTexSubImage2D(
6286 target, level, 0, 0, width, height, format, type, zero.get());
6287 } else {
6288 WrappedTexImage2D(
6289 target, level, format, width, height, 0, format, type, zero.get());
6290 }
[email protected]0d6bfdc2011-11-02 01:32:206291 TextureManager::TextureInfo* info = GetTextureInfoForTarget(bind_target);
6292 glBindTexture(bind_target, info ? info->service_id() : 0);
6293 return true;
6294}
6295
[email protected]a93bb842010-02-16 23:03:476296error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
6297 GLenum target,
6298 GLint level,
6299 GLenum internal_format,
6300 GLsizei width,
6301 GLsizei height,
6302 GLint border,
6303 GLsizei image_size,
6304 const void* data) {
[email protected]a93bb842010-02-16 23:03:476305 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:056306 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296307 SetGLError(GL_INVALID_ENUM,
6308 "glCompressedTexImage2D: target GL_INVALID_ENUM");
6309 return error::kNoError;
6310 }
[email protected]9438b012010-06-15 22:55:056311 if (!validators_->compressed_texture_format.IsValid(
6312 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296313 SetGLError(GL_INVALID_ENUM,
6314 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:476315 return error::kNoError;
6316 }
[email protected]80eb6b52012-01-19 00:14:416317 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476318 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296319 SetGLError(GL_INVALID_VALUE,
6320 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476321 return error::kNoError;
6322 }
[email protected]3916c97e2010-02-25 03:20:506323 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476324 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296325 SetGLError(GL_INVALID_VALUE,
6326 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:476327 return error::kNoError;
6328 }
[email protected]97dc7cbe2011-12-06 17:26:176329 if (info->IsImmutable()) {
6330 SetGLError(GL_INVALID_OPERATION,
6331 "glCompressedTexImage2D: texture is immutable");
6332 return error::kNoError;
6333 }
[email protected]968351b2011-12-20 08:26:516334
6335 if (info->IsAttachedToFramebuffer()) {
6336 state_dirty_ = true;
6337 // TODO(gman): If textures tracked which framebuffers they were attached to
6338 // we could just mark those framebuffers as not complete.
6339 framebuffer_manager()->IncFramebufferStateChangeCount();
6340 }
6341
[email protected]a93bb842010-02-16 23:03:476342 scoped_array<int8> zero;
6343 if (!data) {
6344 zero.reset(new int8[image_size]);
6345 memset(zero.get(), 0, image_size);
6346 data = zero.get();
6347 }
[email protected]cadde4a2010-07-31 17:10:436348 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:476349 glCompressedTexImage2D(
6350 target, level, internal_format, width, height, border, image_size, data);
[email protected]1002c2d2011-06-28 22:39:046351 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436352 if (error == GL_NO_ERROR) {
6353 texture_manager()->SetLevelInfo(
[email protected]0d6bfdc2011-11-02 01:32:206354 info, target, level, internal_format, width, height, 1, border, 0, 0,
6355 true);
[email protected]cadde4a2010-07-31 17:10:436356 }
[email protected]a93bb842010-02-16 23:03:476357 return error::kNoError;
6358}
6359
[email protected]f7a64ee2010-02-01 22:24:146360error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196361 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
6362 GLenum target = static_cast<GLenum>(c.target);
6363 GLint level = static_cast<GLint>(c.level);
6364 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6365 GLsizei width = static_cast<GLsizei>(c.width);
6366 GLsizei height = static_cast<GLsizei>(c.height);
6367 GLint border = static_cast<GLint>(c.border);
6368 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
6369 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6370 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6371 const void* data = NULL;
6372 if (data_shm_id != 0 || data_shm_offset != 0) {
6373 data = GetSharedMemoryAs<const void*>(
6374 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:466375 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146376 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196377 }
6378 }
[email protected]a93bb842010-02-16 23:03:476379 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196380 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:196381}
6382
[email protected]f7a64ee2010-02-01 22:24:146383error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:196384 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
6385 GLenum target = static_cast<GLenum>(c.target);
6386 GLint level = static_cast<GLint>(c.level);
6387 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6388 GLsizei width = static_cast<GLsizei>(c.width);
6389 GLsizei height = static_cast<GLsizei>(c.height);
6390 GLint border = static_cast<GLint>(c.border);
6391 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:306392 const void* data = GetImmediateDataAs<const void*>(
6393 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466394 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146395 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466396 }
[email protected]a93bb842010-02-16 23:03:476397 return DoCompressedTexImage2D(
6398 target, level, internal_format, width, height, border, image_size, data);
6399}
6400
[email protected]b6140d02010-05-17 14:47:166401error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
6402 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
6403 GLenum target = static_cast<GLenum>(c.target);
6404 GLint level = static_cast<GLint>(c.level);
6405 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6406 GLsizei width = static_cast<GLsizei>(c.width);
6407 GLsizei height = static_cast<GLsizei>(c.height);
6408 GLint border = static_cast<GLint>(c.border);
6409 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:286410 if (!bucket) {
6411 return error::kInvalidArguments;
6412 }
6413 uint32 data_size = bucket->size();
6414 GLsizei imageSize = data_size;
6415 const void* data = bucket->GetData(0, data_size);
6416 if (!data) {
6417 return error::kInvalidArguments;
6418 }
[email protected]b6140d02010-05-17 14:47:166419 return DoCompressedTexImage2D(
6420 target, level, internal_format, width, height, border,
[email protected]12f93d82011-10-17 21:16:286421 imageSize, data);
[email protected]b6140d02010-05-17 14:47:166422}
6423
6424error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
6425 uint32 immediate_data_size,
6426 const gles2::CompressedTexSubImage2DBucket& c) {
6427 GLenum target = static_cast<GLenum>(c.target);
6428 GLint level = static_cast<GLint>(c.level);
6429 GLint xoffset = static_cast<GLint>(c.xoffset);
6430 GLint yoffset = static_cast<GLint>(c.yoffset);
6431 GLsizei width = static_cast<GLsizei>(c.width);
6432 GLsizei height = static_cast<GLsizei>(c.height);
6433 GLenum format = static_cast<GLenum>(c.format);
6434 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:286435 if (!bucket) {
6436 return error::kInvalidArguments;
6437 }
[email protected]b6140d02010-05-17 14:47:166438 uint32 data_size = bucket->size();
6439 GLsizei imageSize = data_size;
6440 const void* data = bucket->GetData(0, data_size);
[email protected]12f93d82011-10-17 21:16:286441 if (!data) {
6442 return error::kInvalidArguments;
6443 }
[email protected]9438b012010-06-15 22:55:056444 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:166445 SetGLError(
6446 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
6447 return error::kNoError;
6448 }
[email protected]9438b012010-06-15 22:55:056449 if (!validators_->compressed_texture_format.IsValid(format)) {
6450 SetGLError(GL_INVALID_ENUM,
6451 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
6452 return error::kNoError;
6453 }
[email protected]b6140d02010-05-17 14:47:166454 if (width < 0) {
6455 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
6456 return error::kNoError;
6457 }
6458 if (height < 0) {
6459 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
6460 return error::kNoError;
6461 }
6462 if (imageSize < 0) {
6463 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
6464 return error::kNoError;
6465 }
[email protected]cadde4a2010-07-31 17:10:436466 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:166467 target, level, xoffset, yoffset, width, height, format, imageSize, data);
6468 return error::kNoError;
6469}
6470
[email protected]a93bb842010-02-16 23:03:476471error::Error GLES2DecoderImpl::DoTexImage2D(
6472 GLenum target,
6473 GLint level,
6474 GLenum internal_format,
6475 GLsizei width,
6476 GLsizei height,
6477 GLint border,
6478 GLenum format,
6479 GLenum type,
6480 const void* pixels,
6481 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:056482 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296483 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
6484 return error::kNoError;
6485 }
[email protected]9438b012010-06-15 22:55:056486 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296487 SetGLError(GL_INVALID_ENUM,
6488 "glTexImage2D: internal_format GL_INVALID_ENUM");
6489 return error::kNoError;
6490 }
[email protected]9438b012010-06-15 22:55:056491 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:296492 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
6493 return error::kNoError;
6494 }
[email protected]9438b012010-06-15 22:55:056495 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:296496 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:146497 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196498 }
[email protected]7b92c412010-07-20 17:48:256499 if (format != internal_format) {
6500 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
6501 return error::kNoError;
6502 }
[email protected]80eb6b52012-01-19 00:14:416503 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476504 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296505 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476506 return error::kNoError;
6507 }
[email protected]3916c97e2010-02-25 03:20:506508 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476509 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296510 SetGLError(GL_INVALID_OPERATION,
6511 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:476512 return error::kNoError;
6513 }
[email protected]0226c112011-07-22 03:25:076514
[email protected]97dc7cbe2011-12-06 17:26:176515 if (info->IsImmutable()) {
6516 SetGLError(GL_INVALID_OPERATION,
6517 "glTexImage2D: texture is immutable");
6518 return error::kNoError;
6519 }
6520
[email protected]0226c112011-07-22 03:25:076521 GLsizei tex_width = 0;
6522 GLsizei tex_height = 0;
6523 GLenum tex_type = 0;
6524 GLenum tex_format = 0;
6525 bool level_is_same =
6526 info->GetLevelSize(target, level, &tex_width, &tex_height) &&
6527 info->GetLevelType(target, level, &tex_type, &tex_format) &&
6528 width == tex_width && height == tex_height &&
6529 type == tex_type && format == tex_format;
6530
6531 if (level_is_same && !pixels) {
[email protected]1bed6222011-12-21 11:21:396532 // Just set the level info but mark the texture as uncleared.
6533 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416534 info,
[email protected]1bed6222011-12-21 11:21:396535 target, level, internal_format, width, height, 1, border, format, type,
6536 false);
[email protected]ea72ed222011-08-17 18:58:436537 tex_image_2d_failed_ = false;
[email protected]0226c112011-07-22 03:25:076538 return error::kNoError;
6539 }
6540
[email protected]297ca1c2011-06-20 23:08:466541 if (info->IsAttachedToFramebuffer()) {
6542 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:516543 // TODO(gman): If textures tracked which framebuffers they were attached to
6544 // we could just mark those framebuffers as not complete.
6545 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:466546 }
6547
[email protected]1bed6222011-12-21 11:21:396548 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same && pixels) {
[email protected]0226c112011-07-22 03:25:076549 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
6550 tex_image_2d_failed_ = false;
6551 return error::kNoError;
[email protected]7488d962010-07-16 02:41:586552 }
[email protected]876f6fee2010-08-02 23:10:326553
[email protected]cadde4a2010-07-31 17:10:436554 CopyRealGLErrorsToWrapper();
[email protected]473c01ccb2011-06-07 01:33:306555 WrappedTexImage2D(
6556 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476557 pixels);
[email protected]1002c2d2011-06-28 22:39:046558 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436559 if (error == GL_NO_ERROR) {
[email protected]0d6bfdc2011-11-02 01:32:206560 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416561 info,
[email protected]0d6bfdc2011-11-02 01:32:206562 target, level, internal_format, width, height, 1, border, format, type,
6563 pixels != NULL);
[email protected]b493ee622011-04-13 23:52:006564 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:436565 }
[email protected]f7a64ee2010-02-01 22:24:146566 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196567}
6568
[email protected]f7a64ee2010-02-01 22:24:146569error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196570 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]366ae242011-05-10 02:23:586571 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:006572 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:196573 GLenum target = static_cast<GLenum>(c.target);
6574 GLint level = static_cast<GLint>(c.level);
6575 GLint internal_format = static_cast<GLint>(c.internalformat);
6576 GLsizei width = static_cast<GLsizei>(c.width);
6577 GLsizei height = static_cast<GLsizei>(c.height);
6578 GLint border = static_cast<GLint>(c.border);
6579 GLenum format = static_cast<GLenum>(c.format);
6580 GLenum type = static_cast<GLenum>(c.type);
6581 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
6582 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:186583 uint32 pixels_size;
6584 if (!GLES2Util::ComputeImageDataSize(
6585 width, height, format, type, unpack_alignment_, &pixels_size)) {
6586 return error::kOutOfBounds;
6587 }
[email protected]b9849abf2009-11-25 19:13:196588 const void* pixels = NULL;
6589 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
6590 pixels = GetSharedMemoryAs<const void*>(
6591 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:466592 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146593 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196594 }
6595 }
[email protected]a93bb842010-02-16 23:03:476596 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196597 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476598 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:196599}
6600
[email protected]f7a64ee2010-02-01 22:24:146601error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:196602 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
6603 GLenum target = static_cast<GLenum>(c.target);
6604 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:466605 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:196606 GLsizei width = static_cast<GLsizei>(c.width);
6607 GLsizei height = static_cast<GLsizei>(c.height);
6608 GLint border = static_cast<GLint>(c.border);
6609 GLenum format = static_cast<GLenum>(c.format);
6610 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:186611 uint32 size;
6612 if (!GLES2Util::ComputeImageDataSize(
6613 width, height, format, type, unpack_alignment_, &size)) {
6614 return error::kOutOfBounds;
6615 }
[email protected]07f54fcc2009-12-22 02:46:306616 const void* pixels = GetImmediateDataAs<const void*>(
6617 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466618 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146619 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466620 }
[email protected]a93bb842010-02-16 23:03:476621 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:466622 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476623 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:146624 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326625}
6626
[email protected]cadde4a2010-07-31 17:10:436627void GLES2DecoderImpl::DoCompressedTexSubImage2D(
6628 GLenum target,
6629 GLint level,
6630 GLint xoffset,
6631 GLint yoffset,
6632 GLsizei width,
6633 GLsizei height,
6634 GLenum format,
6635 GLsizei image_size,
6636 const void * data) {
6637 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6638 if (!info) {
6639 SetGLError(GL_INVALID_OPERATION,
6640 "glCompressedTexSubImage2D: unknown texture for target");
6641 return;
6642 }
6643 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:526644 GLenum internal_format = 0;
6645 if (!info->GetLevelType(target, level, &type, &internal_format)) {
6646 SetGLError(
6647 GL_INVALID_OPERATION,
[email protected]4502e6492011-12-14 19:39:156648 "glCompressedTexSubImage2D: level does not exist.");
[email protected]df6cf1ad2011-01-29 01:20:526649 return;
6650 }
6651 if (internal_format != format) {
6652 SetGLError(
6653 GL_INVALID_OPERATION,
[email protected]4502e6492011-12-14 19:39:156654 "glCompressedTexSubImage2D: format does not match internal format.");
[email protected]df6cf1ad2011-01-29 01:20:526655 return;
6656 }
6657 if (!info->ValidForTexture(
6658 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:436659 SetGLError(GL_INVALID_VALUE,
[email protected]4502e6492011-12-14 19:39:156660 "glCompressedTexSubImage2D: bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:436661 return;
6662 }
[email protected]0d6bfdc2011-11-02 01:32:206663 // Note: There is no need to deal with texture cleared tracking here
6664 // because the validation above means you can only get here if the level
6665 // is already a matching compressed format and in that case
6666 // CompressedTexImage2D already cleared the texture.
[email protected]cadde4a2010-07-31 17:10:436667 glCompressedTexSubImage2D(
6668 target, level, xoffset, yoffset, width, height, format, image_size, data);
6669}
6670
[email protected]6e288612010-12-21 20:45:036671static void Clip(
6672 GLint start, GLint range, GLint sourceRange,
6673 GLint* out_start, GLint* out_range) {
6674 DCHECK(out_start);
6675 DCHECK(out_range);
6676 if (start < 0) {
6677 range += start;
6678 start = 0;
6679 }
6680 GLint end = start + range;
6681 if (end > sourceRange) {
6682 range -= end - sourceRange;
6683 }
6684 *out_start = start;
6685 *out_range = range;
6686}
6687
[email protected]cadde4a2010-07-31 17:10:436688void GLES2DecoderImpl::DoCopyTexImage2D(
6689 GLenum target,
6690 GLint level,
6691 GLenum internal_format,
6692 GLint x,
6693 GLint y,
6694 GLsizei width,
6695 GLsizei height,
6696 GLint border) {
6697 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6698 if (!info) {
6699 SetGLError(GL_INVALID_OPERATION,
6700 "glCopyTexImage2D: unknown texture for target");
6701 return;
6702 }
[email protected]97dc7cbe2011-12-06 17:26:176703 if (info->IsImmutable()) {
6704 SetGLError(GL_INVALID_OPERATION,
6705 "glCopyTexImage2D: texture is immutable");
6706 }
[email protected]80eb6b52012-01-19 00:14:416707 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:186708 border != 0) {
6709 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
6710 return;
6711 }
6712
[email protected]9edc6b22010-12-23 02:00:266713 // Check we have compatible formats.
6714 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6715 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6716 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
6717
6718 if ((channels_needed & channels_exist) != channels_needed) {
6719 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
6720 return;
6721 }
6722
[email protected]a0b78dc2011-11-11 10:43:106723 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
6724 return;
6725 }
6726
[email protected]cadde4a2010-07-31 17:10:436727 CopyRealGLErrorsToWrapper();
[email protected]de26b3c2011-08-03 21:54:276728 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:036729 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:266730
[email protected]297ca1c2011-06-20 23:08:466731 if (info->IsAttachedToFramebuffer()) {
6732 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:516733 // TODO(gman): If textures tracked which framebuffers they were attached to
6734 // we could just mark those framebuffers as not complete.
6735 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:466736 }
6737
[email protected]9edc6b22010-12-23 02:00:266738 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:036739 GLint copyX = 0;
6740 GLint copyY = 0;
6741 GLint copyWidth = 0;
6742 GLint copyHeight = 0;
6743 Clip(x, width, size.width(), &copyX, &copyWidth);
6744 Clip(y, height, size.height(), &copyY, &copyHeight);
6745
6746 if (copyX != x ||
6747 copyY != y ||
6748 copyWidth != width ||
6749 copyHeight != height) {
6750 // some part was clipped so clear the texture.
[email protected]0d6bfdc2011-11-02 01:32:206751 if (!ClearLevel(
6752 info->service_id(), info->target(),
[email protected]4502e6492011-12-14 19:39:156753 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
6754 info->IsImmutable())) {
[email protected]0d6bfdc2011-11-02 01:32:206755 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexImage2D: dimensions too big");
[email protected]6e288612010-12-21 20:45:036756 return;
6757 }
[email protected]6e288612010-12-21 20:45:036758 if (copyHeight > 0 && copyWidth > 0) {
6759 GLint dx = copyX - x;
6760 GLint dy = copyY - y;
6761 GLint destX = dx;
6762 GLint destY = dy;
6763 glCopyTexSubImage2D(target, level,
6764 destX, destY, copyX, copyY,
6765 copyWidth, copyHeight);
6766 }
6767 } else {
6768 glCopyTexImage2D(target, level, internal_format,
6769 copyX, copyY, copyWidth, copyHeight, border);
6770 }
[email protected]1002c2d2011-06-28 22:39:046771 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436772 if (error == GL_NO_ERROR) {
6773 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416774 info, target, level, internal_format, width, height, 1,
[email protected]0d6bfdc2011-11-02 01:32:206775 border, internal_format, GL_UNSIGNED_BYTE, true);
[email protected]cadde4a2010-07-31 17:10:436776 }
6777}
6778
6779void GLES2DecoderImpl::DoCopyTexSubImage2D(
6780 GLenum target,
6781 GLint level,
6782 GLint xoffset,
6783 GLint yoffset,
6784 GLint x,
6785 GLint y,
6786 GLsizei width,
6787 GLsizei height) {
6788 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6789 if (!info) {
6790 SetGLError(GL_INVALID_OPERATION,
6791 "glCopyTexSubImage2D: unknown texture for target");
6792 return;
6793 }
6794 GLenum type = 0;
6795 GLenum format = 0;
6796 if (!info->GetLevelType(target, level, &type, &format) ||
6797 !info->ValidForTexture(
6798 target, level, xoffset, yoffset, width, height, format, type)) {
6799 SetGLError(GL_INVALID_VALUE,
6800 "glCopyTexSubImage2D: bad dimensions.");
6801 return;
6802 }
[email protected]9edc6b22010-12-23 02:00:266803
6804 // Check we have compatible formats.
6805 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6806 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6807 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
6808
6809 if ((channels_needed & channels_exist) != channels_needed) {
6810 SetGLError(
6811 GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
6812 return;
6813 }
6814
[email protected]a0b78dc2011-11-11 10:43:106815 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
6816 return;
6817 }
6818
[email protected]de26b3c2011-08-03 21:54:276819 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:036820 gfx::Size size = GetBoundReadFrameBufferSize();
6821 GLint copyX = 0;
6822 GLint copyY = 0;
6823 GLint copyWidth = 0;
6824 GLint copyHeight = 0;
6825 Clip(x, width, size.width(), &copyX, &copyWidth);
6826 Clip(y, height, size.height(), &copyY, &copyHeight);
[email protected]0d6bfdc2011-11-02 01:32:206827
6828 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
6829 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D: dimensions too big");
6830 return;
6831 }
6832
[email protected]6e288612010-12-21 20:45:036833 if (copyX != x ||
6834 copyY != y ||
6835 copyWidth != width ||
6836 copyHeight != height) {
[email protected]0d6bfdc2011-11-02 01:32:206837 // some part was clipped so clear the sub rect.
[email protected]6e288612010-12-21 20:45:036838 uint32 pixels_size = 0;
6839 if (!GLES2Util::ComputeImageDataSize(
6840 width, height, format, type, unpack_alignment_, &pixels_size)) {
6841 SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large");
6842 return;
6843 }
6844 scoped_array<char> zero(new char[pixels_size]);
6845 memset(zero.get(), 0, pixels_size);
6846 glTexSubImage2D(
6847 target, level, xoffset, yoffset, width, height,
6848 format, type, zero.get());
6849 }
[email protected]0d6bfdc2011-11-02 01:32:206850
[email protected]6e288612010-12-21 20:45:036851 if (copyHeight > 0 && copyWidth > 0) {
6852 GLint dx = copyX - x;
6853 GLint dy = copyY - y;
6854 GLint destX = xoffset + dx;
6855 GLint destY = yoffset + dy;
6856 glCopyTexSubImage2D(target, level,
6857 destX, destY, copyX, copyY,
6858 copyWidth, copyHeight);
6859 }
[email protected]cadde4a2010-07-31 17:10:436860}
6861
6862void GLES2DecoderImpl::DoTexSubImage2D(
6863 GLenum target,
6864 GLint level,
6865 GLint xoffset,
6866 GLint yoffset,
6867 GLsizei width,
6868 GLsizei height,
6869 GLenum format,
6870 GLenum type,
6871 const void * data) {
6872 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6873 if (!info) {
6874 SetGLError(GL_INVALID_OPERATION,
6875 "glTexSubImage2D: unknown texture for target");
6876 return;
6877 }
[email protected]df6cf1ad2011-01-29 01:20:526878 GLenum current_type = 0;
6879 GLenum internal_format = 0;
6880 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
6881 SetGLError(
6882 GL_INVALID_OPERATION,
6883 "glTexSubImage2D: level does not exist.");
6884 return;
6885 }
6886 if (format != internal_format) {
6887 SetGLError(GL_INVALID_OPERATION,
6888 "glTexSubImage2D: format does not match internal format.");
6889 return;
6890 }
6891 if (type != current_type) {
6892 SetGLError(GL_INVALID_OPERATION,
6893 "glTexSubImage2D: type does not match type of texture.");
6894 return;
6895 }
6896
[email protected]cadde4a2010-07-31 17:10:436897 if (!info->ValidForTexture(
6898 target, level, xoffset, yoffset, width, height, format, type)) {
6899 SetGLError(GL_INVALID_VALUE,
6900 "glTexSubImage2D: bad dimensions.");
6901 return;
6902 }
[email protected]473c01ccb2011-06-07 01:33:306903
[email protected]4502e6492011-12-14 19:39:156904 GLsizei tex_width = 0;
6905 GLsizei tex_height = 0;
6906 bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height);
6907 DCHECK(ok);
6908 if (xoffset != 0 || yoffset != 0 ||
6909 width != tex_width || height != tex_height) {
6910 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
6911 SetGLError(GL_OUT_OF_MEMORY, "glTexSubImage2D: dimensions too big");
[email protected]473c01ccb2011-06-07 01:33:306912 return;
6913 }
[email protected]4502e6492011-12-14 19:39:156914 glTexSubImage2D(
6915 target, level, xoffset, yoffset, width, height, format, type, data);
[email protected]0d6bfdc2011-11-02 01:32:206916 return;
6917 }
[email protected]4502e6492011-12-14 19:39:156918
6919 if (teximage2d_faster_than_texsubimage2d_ && !info->IsImmutable()) {
6920 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
6921 // same as internal_foramt. If that changes we'll need to look them up.
6922 WrappedTexImage2D(
6923 target, level, format, width, height, 0, format, type, data);
6924 } else {
6925 glTexSubImage2D(
6926 target, level, xoffset, yoffset, width, height, format, type, data);
6927 }
6928 texture_manager()->SetLevelCleared(info, target, level);
[email protected]cadde4a2010-07-31 17:10:436929}
6930
[email protected]b493ee622011-04-13 23:52:006931error::Error GLES2DecoderImpl::HandleTexSubImage2D(
6932 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]366ae242011-05-10 02:23:586933 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:006934 GLboolean internal = static_cast<GLboolean>(c.internal);
6935 if (internal == GL_TRUE && tex_image_2d_failed_)
6936 return error::kNoError;
6937
6938 GLenum target = static_cast<GLenum>(c.target);
6939 GLint level = static_cast<GLint>(c.level);
6940 GLint xoffset = static_cast<GLint>(c.xoffset);
6941 GLint yoffset = static_cast<GLint>(c.yoffset);
6942 GLsizei width = static_cast<GLsizei>(c.width);
6943 GLsizei height = static_cast<GLsizei>(c.height);
6944 GLenum format = static_cast<GLenum>(c.format);
6945 GLenum type = static_cast<GLenum>(c.type);
6946 uint32 data_size;
6947 if (!GLES2Util::ComputeImageDataSize(
6948 width, height, format, type, unpack_alignment_, &data_size)) {
6949 return error::kOutOfBounds;
6950 }
6951 const void* pixels = GetSharedMemoryAs<const void*>(
6952 c.pixels_shm_id, c.pixels_shm_offset, data_size);
6953 if (!validators_->texture_target.IsValid(target)) {
6954 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
6955 return error::kNoError;
6956 }
6957 if (width < 0) {
6958 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
6959 return error::kNoError;
6960 }
6961 if (height < 0) {
6962 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
6963 return error::kNoError;
6964 }
6965 if (!validators_->texture_format.IsValid(format)) {
6966 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
6967 return error::kNoError;
6968 }
6969 if (!validators_->pixel_type.IsValid(type)) {
6970 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
6971 return error::kNoError;
6972 }
6973 if (pixels == NULL) {
6974 return error::kOutOfBounds;
6975 }
6976 DoTexSubImage2D(
6977 target, level, xoffset, yoffset, width, height, format, type, pixels);
6978 return error::kNoError;
6979}
6980
6981error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
6982 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
6983 GLboolean internal = static_cast<GLboolean>(c.internal);
6984 if (internal == GL_TRUE && tex_image_2d_failed_)
6985 return error::kNoError;
6986
6987 GLenum target = static_cast<GLenum>(c.target);
6988 GLint level = static_cast<GLint>(c.level);
6989 GLint xoffset = static_cast<GLint>(c.xoffset);
6990 GLint yoffset = static_cast<GLint>(c.yoffset);
6991 GLsizei width = static_cast<GLsizei>(c.width);
6992 GLsizei height = static_cast<GLsizei>(c.height);
6993 GLenum format = static_cast<GLenum>(c.format);
6994 GLenum type = static_cast<GLenum>(c.type);
6995 uint32 data_size;
6996 if (!GLES2Util::ComputeImageDataSize(
6997 width, height, format, type, unpack_alignment_, &data_size)) {
6998 return error::kOutOfBounds;
6999 }
7000 const void* pixels = GetImmediateDataAs<const void*>(
7001 c, data_size, immediate_data_size);
7002 if (!validators_->texture_target.IsValid(target)) {
7003 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
7004 return error::kNoError;
7005 }
7006 if (width < 0) {
7007 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
7008 return error::kNoError;
7009 }
7010 if (height < 0) {
7011 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
7012 return error::kNoError;
7013 }
7014 if (!validators_->texture_format.IsValid(format)) {
7015 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
7016 return error::kNoError;
7017 }
7018 if (!validators_->pixel_type.IsValid(type)) {
7019 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
7020 return error::kNoError;
7021 }
7022 if (pixels == NULL) {
7023 return error::kOutOfBounds;
7024 }
7025 DoTexSubImage2D(
7026 target, level, xoffset, yoffset, width, height, format, type, pixels);
7027 return error::kNoError;
7028}
7029
[email protected]f7a64ee2010-02-01 22:24:147030error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:197031 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:367032 GLuint index = static_cast<GLuint>(c.index);
7033 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:257034 typedef gles2::GetVertexAttribPointerv::Result Result;
7035 Result* result = GetSharedMemoryAs<Result*>(
7036 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:367037 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:147038 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:367039 }
[email protected]07d0cc82010-02-17 04:51:407040 // Check that the client initialized the result.
7041 if (result->size != 0) {
7042 return error::kInvalidArguments;
7043 }
[email protected]9438b012010-06-15 22:55:057044 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:297045 SetGLError(GL_INVALID_ENUM,
7046 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:147047 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367048 }
[email protected]3916c97e2010-02-25 03:20:507049 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:297050 SetGLError(GL_INVALID_VALUE,
7051 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:147052 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367053 }
[email protected]0bfd9882010-02-05 23:02:257054 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:087055 *result->GetData() =
[email protected]3757a372012-01-19 05:20:447056 vertex_attrib_manager_->GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:147057 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327058}
7059
[email protected]f7b85372010-02-03 01:11:377060bool GLES2DecoderImpl::GetUniformSetup(
7061 GLuint program, GLint location,
7062 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:107063 error::Error* error, GLuint* service_id, void** result_pointer,
7064 GLenum* result_type) {
7065 DCHECK(error);
7066 DCHECK(service_id);
7067 DCHECK(result_pointer);
7068 DCHECK(result_type);
[email protected]f7b85372010-02-03 01:11:377069 *error = error::kNoError;
7070 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:257071 SizedResult<GLint>* result;
7072 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7073 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
7074 if (!result) {
[email protected]f7b85372010-02-03 01:11:377075 *error = error::kOutOfBounds;
7076 return false;
7077 }
[email protected]0bfd9882010-02-05 23:02:257078 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:377079 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:257080 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:587081 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7082 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:377083 if (!info) {
[email protected]ae51d192010-04-27 00:48:037084 return false;
7085 }
7086 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:377087 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:297088 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:377089 return false;
7090 }
[email protected]ae51d192010-04-27 00:48:037091 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:367092 GLint array_index = -1;
7093 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
7094 info->GetUniformInfoByLocation(location, &array_index);
7095 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:377096 // No such location.
[email protected]8eee29c2010-04-29 03:38:297097 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:377098 return false;
7099 }
[email protected]43c2f1f2011-03-25 18:35:367100 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:507101 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:377102 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:297103 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:377104 return false;
7105 }
[email protected]0bfd9882010-02-05 23:02:257106 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7107 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
7108 if (!result) {
[email protected]f7b85372010-02-03 01:11:377109 *error = error::kOutOfBounds;
7110 return false;
7111 }
[email protected]0bfd9882010-02-05 23:02:257112 result->size = size;
[email protected]939e7362010-05-13 20:49:107113 *result_type = type;
[email protected]f7b85372010-02-03 01:11:377114 return true;
7115}
7116
[email protected]f7a64ee2010-02-01 22:24:147117error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:197118 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:377119 GLuint program = c.program;
7120 GLint location = c.location;
7121 GLuint service_id;
[email protected]939e7362010-05-13 20:49:107122 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:377123 Error error;
[email protected]0bfd9882010-02-05 23:02:257124 void* result;
[email protected]f7b85372010-02-03 01:11:377125 if (GetUniformSetup(
7126 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:107127 &error, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:257128 glGetUniformiv(
7129 service_id, location,
7130 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:377131 }
7132 return error;
[email protected]96449d2c2009-11-25 00:01:327133}
7134
[email protected]f7a64ee2010-02-01 22:24:147135error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:197136 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:377137 GLuint program = c.program;
7138 GLint location = c.location;
7139 GLuint service_id;
7140 Error error;
[email protected]0bfd9882010-02-05 23:02:257141 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:107142 Result* result;
7143 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:377144 if (GetUniformSetup(
7145 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:107146 &error, &service_id, reinterpret_cast<void**>(&result), &result_type)) {
7147 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
7148 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
7149 GLsizei num_values = result->GetNumResults();
7150 scoped_array<GLint> temp(new GLint[num_values]);
7151 glGetUniformiv(service_id, location, temp.get());
7152 GLfloat* dst = result->GetData();
7153 for (GLsizei ii = 0; ii < num_values; ++ii) {
7154 dst[ii] = (temp[ii] != 0);
7155 }
7156 } else {
7157 glGetUniformfv(service_id, location, result->GetData());
7158 }
[email protected]f7b85372010-02-03 01:11:377159 }
7160 return error;
[email protected]96449d2c2009-11-25 00:01:327161}
7162
[email protected]f7a64ee2010-02-01 22:24:147163error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:197164 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:257165 GLenum shader_type = static_cast<GLenum>(c.shadertype);
7166 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
7167 typedef gles2::GetShaderPrecisionFormat::Result Result;
7168 Result* result = GetSharedMemoryAs<Result*>(
7169 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7170 if (!result) {
7171 return error::kOutOfBounds;
7172 }
[email protected]07d0cc82010-02-17 04:51:407173 // Check that the client initialized the result.
7174 if (result->success != 0) {
7175 return error::kInvalidArguments;
7176 }
[email protected]9438b012010-06-15 22:55:057177 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:297178 SetGLError(GL_INVALID_ENUM,
7179 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
7180 return error::kNoError;
7181 }
[email protected]9438b012010-06-15 22:55:057182 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:297183 SetGLError(GL_INVALID_ENUM,
7184 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
7185 return error::kNoError;
7186 }
7187
7188 result->success = 1; // true
7189 switch (precision_type) {
7190 case GL_LOW_INT:
7191 case GL_MEDIUM_INT:
7192 case GL_HIGH_INT:
7193 result->min_range = -31;
7194 result->max_range = 31;
7195 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:107196 break;
[email protected]8eee29c2010-04-29 03:38:297197 case GL_LOW_FLOAT:
7198 case GL_MEDIUM_FLOAT:
7199 case GL_HIGH_FLOAT:
7200 result->min_range = -62;
7201 result->max_range = 62;
7202 result->precision = -16;
7203 break;
7204 default:
7205 NOTREACHED();
7206 break;
[email protected]0bfd9882010-02-05 23:02:257207 }
[email protected]f7a64ee2010-02-01 22:24:147208 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327209}
7210
[email protected]f7a64ee2010-02-01 22:24:147211error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:197212 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:257213 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:587214 GLuint program = static_cast<GLuint>(c.program);
7215 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7216 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:037217 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257218 return error::kNoError;
7219 }
7220 typedef gles2::GetAttachedShaders::Result Result;
7221 uint32 max_count = Result::ComputeMaxResults(result_size);
7222 Result* result = GetSharedMemoryAs<Result*>(
7223 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
7224 if (!result) {
7225 return error::kOutOfBounds;
7226 }
[email protected]07d0cc82010-02-17 04:51:407227 // Check that the client initialized the result.
7228 if (result->size != 0) {
7229 return error::kInvalidArguments;
7230 }
[email protected]0bfd9882010-02-05 23:02:257231 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:037232 glGetAttachedShaders(
7233 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:257234 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:037235 if (!shader_manager()->GetClientId(result->GetData()[ii],
7236 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:257237 NOTREACHED();
7238 return error::kGenericError;
7239 }
7240 }
7241 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:147242 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327243}
7244
[email protected]f7a64ee2010-02-01 22:24:147245error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:197246 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:257247 GLuint program = c.program;
7248 GLuint index = c.index;
7249 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:257250 typedef gles2::GetActiveUniform::Result Result;
7251 Result* result = GetSharedMemoryAs<Result*>(
7252 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7253 if (!result) {
7254 return error::kOutOfBounds;
7255 }
[email protected]07d0cc82010-02-17 04:51:407256 // Check that the client initialized the result.
7257 if (result->success != 0) {
7258 return error::kInvalidArguments;
7259 }
[email protected]6b8cf1a2010-05-06 16:13:587260 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7261 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:037262 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257263 return error::kNoError;
7264 }
7265 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
7266 info->GetUniformInfo(index);
7267 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:297268 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:257269 return error::kNoError;
7270 }
7271 result->success = 1; // true.
7272 result->size = uniform_info->size;
7273 result->type = uniform_info->type;
7274 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297275 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:147276 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327277}
7278
[email protected]f7a64ee2010-02-01 22:24:147279error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:197280 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:257281 GLuint program = c.program;
7282 GLuint index = c.index;
7283 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:257284 typedef gles2::GetActiveAttrib::Result Result;
7285 Result* result = GetSharedMemoryAs<Result*>(
7286 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7287 if (!result) {
7288 return error::kOutOfBounds;
7289 }
[email protected]07d0cc82010-02-17 04:51:407290 // Check that the client initialized the result.
7291 if (result->success != 0) {
7292 return error::kInvalidArguments;
7293 }
[email protected]6b8cf1a2010-05-06 16:13:587294 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7295 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:037296 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257297 return error::kNoError;
7298 }
7299 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
7300 info->GetAttribInfo(index);
7301 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:297302 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:257303 return error::kNoError;
7304 }
7305 result->success = 1; // true.
7306 result->size = attrib_info->size;
7307 result->type = attrib_info->type;
7308 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297309 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:147310 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327311}
7312
[email protected]b273e432010-04-12 17:23:587313error::Error GLES2DecoderImpl::HandleShaderBinary(
7314 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
7315#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:297316 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:587317 return error::kNoError;
7318#else
7319 GLsizei n = static_cast<GLsizei>(c.n);
7320 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:297321 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:587322 return error::kNoError;
7323 }
7324 GLsizei length = static_cast<GLsizei>(c.length);
7325 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:297326 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:587327 return error::kNoError;
7328 }
7329 uint32 data_size;
7330 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
7331 return error::kOutOfBounds;
7332 }
7333 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
7334 c.shaders_shm_id, c.shaders_shm_offset, data_size);
7335 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
7336 const void* binary = GetSharedMemoryAs<const void*>(
7337 c.binary_shm_id, c.binary_shm_offset, length);
7338 if (shaders == NULL || binary == NULL) {
7339 return error::kOutOfBounds;
7340 }
7341 scoped_array<GLuint> service_ids(new GLuint[n]);
7342 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:037343 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
7344 if (!info) {
[email protected]8eee29c2010-04-29 03:38:297345 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:587346 return error::kNoError;
7347 }
[email protected]ae51d192010-04-27 00:48:037348 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:587349 }
7350 // TODO(gman): call glShaderBinary
7351 return error::kNoError;
7352#endif
7353}
7354
[email protected]6217d392010-03-25 22:08:357355error::Error GLES2DecoderImpl::HandleSwapBuffers(
7356 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:497357 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7358 int this_frame_number = frame_number_++;
[email protected]da151512011-11-11 23:27:387359 // TRACE_EVENT for gpu tests:
[email protected]529c6672012-01-04 02:18:267360 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers",
7361 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
7362 "width", (is_offscreen ? offscreen_size_.width() :
7363 surface_->GetSize().width()));
[email protected]64ace852011-05-19 21:49:497364 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
7365 "offscreen", is_offscreen,
7366 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:357367 // If offscreen then don't actually SwapBuffers to the display. Just copy
7368 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:497369 if (is_offscreen) {
[email protected]1fb8c482011-08-31 01:01:537370 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
7371 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
7372 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
7373 // fix this.
7374 if (needs_mac_nvidia_driver_workaround_) {
7375 offscreen_saved_frame_buffer_->Create();
7376 glFinish();
7377 }
7378
7379 // Allocate the offscreen saved color texture.
7380 DCHECK(offscreen_saved_color_format_);
7381 offscreen_saved_color_texture_->AllocateStorage(
7382 offscreen_size_, offscreen_saved_color_format_);
[email protected]1078f912011-12-23 13:12:147383 UpdateBackbufferMemoryAccounting();
[email protected]1fb8c482011-08-31 01:01:537384
7385 offscreen_saved_frame_buffer_->AttachRenderTexture(
7386 offscreen_saved_color_texture_.get());
7387 if (offscreen_saved_frame_buffer_->CheckStatus() !=
7388 GL_FRAMEBUFFER_COMPLETE) {
7389 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
7390 << "because offscreen saved FBO was incomplete.";
7391 return error::kLostContext;
7392 }
7393
[email protected]1fb8c482011-08-31 01:01:537394 // Clear the offscreen color texture.
7395 // TODO(piman): Is this still necessary?
7396 {
7397 ScopedFrameBufferBinder binder(this,
7398 offscreen_saved_frame_buffer_->id());
7399 glClearColor(0, 0, 0, 0);
7400 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
7401 glDisable(GL_SCISSOR_TEST);
7402 glClear(GL_COLOR_BUFFER_BIT);
7403 RestoreClearState();
7404 }
7405
7406 UpdateParentTextureInfo();
7407 }
7408
[email protected]6217d392010-03-25 22:08:357409 ScopedGLErrorSuppressor suppressor(this);
7410
[email protected]34ff8b0c2010-10-01 20:06:027411 if (IsOffscreenBufferMultisampled()) {
[email protected]51411e32012-01-19 20:21:137412 // For multisampled buffers, resolve the frame buffer.
[email protected]de26b3c2011-08-03 21:54:277413 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]89d6ed02011-04-20 00:23:237414 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:487415 } else {
[email protected]9a5afa432011-07-22 18:16:397416 if (surface_->IsOffscreen()) {
[email protected]51411e32012-01-19 20:21:137417 ScopedFrameBufferBinder binder(this,
7418 offscreen_target_frame_buffer_->id());
7419
[email protected]b86b14982010-10-11 18:45:487420 // Copy the target frame buffer to the saved offscreen texture.
7421 offscreen_saved_color_texture_->Copy(
[email protected]3a4d0c52011-06-29 23:11:587422 offscreen_saved_color_texture_->size(),
7423 offscreen_saved_color_format_);
[email protected]b86b14982010-10-11 18:45:487424
[email protected]a3ded6d2010-10-19 06:44:397425 // Ensure the side effects of the copy are visible to the parent
7426 // context. There is no need to do this for ANGLE because it uses a
7427 // single D3D device for all contexts.
[email protected]b86b14982010-10-11 18:45:487428 if (!IsAngle())
7429 glFlush();
7430 }
[email protected]89d6ed02011-04-20 00:23:237431 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:397432 }
[email protected]6217d392010-03-25 22:08:357433 } else {
[email protected]64ace852011-05-19 21:49:497434 TRACE_EVENT1("gpu", "GLContext::SwapBuffers", "frame", this_frame_number);
[email protected]f62a5ab2011-05-23 20:34:157435 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:017436 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:027437 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:017438 }
[email protected]6217d392010-03-25 22:08:357439 }
7440
[email protected]89d6ed02011-04-20 00:23:237441 return error::kNoError;
[email protected]6217d392010-03-25 22:08:357442}
7443
[email protected]d4239852011-08-12 04:51:227444error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
7445 uint32 immediate_data_size, const gles2::EnableFeatureCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:187446 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287447 if (!bucket || bucket->size() == 0) {
7448 return error::kInvalidArguments;
7449 }
[email protected]d4239852011-08-12 04:51:227450 typedef gles2::EnableFeatureCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:187451 Result* result = GetSharedMemoryAs<Result*>(
7452 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7453 if (!result) {
7454 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:107455 }
[email protected]b1d2dcb2010-05-17 19:24:187456 // Check that the client initialized the result.
7457 if (*result != 0) {
7458 return error::kInvalidArguments;
7459 }
7460 std::string feature_str;
7461 if (!bucket->GetAsString(&feature_str)) {
7462 return error::kInvalidArguments;
7463 }
7464
7465 // TODO(gman): make this some kind of table to function pointer thingy.
[email protected]d4239852011-08-12 04:51:227466 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
[email protected]b1d2dcb2010-05-17 19:24:187467 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]d4239852011-08-12 04:51:227468 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
[email protected]8fbedc02010-11-18 18:43:407469 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
7470 // TODO(gman): decide how to remove the need for this const_cast.
7471 // I could make validators_ non const but that seems bad as this is the only
7472 // place it is needed. I could make some special friend class of validators
7473 // just to allow this to set them. That seems silly. I could refactor this
7474 // code to use the extension mechanism or the initialization attributes to
7475 // turn this feature on. Given that the only real point of this is to make
7476 // the conformance tests pass and given that there is lots of real work that
7477 // needs to be done it seems like refactoring for one to one of those
7478 // methods is a very low priority.
7479 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]f0d74742011-10-03 16:31:047480 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
7481 force_webgl_glsl_validation_ = true;
7482 InitializeShaderTranslator();
[email protected]b1d2dcb2010-05-17 19:24:187483 } else {
7484 return error::kNoError;
7485 }
7486
7487 *result = 1; // true.
7488 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:107489}
7490
[email protected]c2f8c8402010-12-06 18:07:247491error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
7492 uint32 immediate_data_size,
7493 const gles2::GetRequestableExtensionsCHROMIUM& c) {
7494 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]80eb6b52012-01-19 00:14:417495 FeatureInfo::Ref info(new FeatureInfo());
[email protected]e82fb792011-09-22 00:33:297496 info->Initialize(disallowed_features_, NULL);
[email protected]c2f8c8402010-12-06 18:07:247497 bucket->SetFromString(info->extensions().c_str());
7498 return error::kNoError;
7499}
7500
7501error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
7502 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
7503 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287504 if (!bucket || bucket->size() == 0) {
7505 return error::kInvalidArguments;
7506 }
[email protected]c2f8c8402010-12-06 18:07:247507 std::string feature_str;
7508 if (!bucket->GetAsString(&feature_str)) {
7509 return error::kInvalidArguments;
7510 }
7511
7512 bool std_derivatives_enabled =
7513 feature_info_->feature_flags().oes_standard_derivatives;
7514 bool webglsl_enabled =
7515 feature_info_->feature_flags().chromium_webglsl;
7516
7517 feature_info_->AddFeatures(feature_str.c_str());
7518
[email protected]f0d74742011-10-03 16:31:047519 bool initialization_required = false;
7520 if (force_webgl_glsl_validation_ && !derivatives_explicitly_enabled_) {
7521 size_t derivatives_offset = feature_str.find(kOESDerivativeExtension);
7522 if (std::string::npos != derivatives_offset) {
7523 derivatives_explicitly_enabled_ = true;
7524 initialization_required = true;
7525 }
7526 }
7527
[email protected]c2f8c8402010-12-06 18:07:247528 // If we just enabled a feature which affects the shader translator,
7529 // we may need to re-initialize it.
7530 if (std_derivatives_enabled !=
7531 feature_info_->feature_flags().oes_standard_derivatives ||
7532 webglsl_enabled !=
[email protected]f0d74742011-10-03 16:31:047533 feature_info_->feature_flags().chromium_webglsl ||
7534 initialization_required) {
[email protected]c2f8c8402010-12-06 18:07:247535 InitializeShaderTranslator();
7536 }
7537
[email protected]302ce6d2011-07-07 23:28:117538 UpdateCapabilities();
7539
[email protected]c2f8c8402010-12-06 18:07:247540 return error::kNoError;
7541}
7542
[email protected]372e0412011-06-28 16:08:567543error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
7544 uint32 immediate_data_size, const gles2::GetMultipleIntegervCHROMIUM& c) {
7545 GLuint count = c.count;
7546 uint32 pnames_size;
7547 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
7548 return error::kOutOfBounds;
7549 }
7550 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
7551 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
7552 if (pnames == NULL) {
7553 return error::kOutOfBounds;
7554 }
7555
7556 // We have to copy them since we use them twice so the client
7557 // can't change them between the time we validate them and the time we use
7558 // them.
7559 scoped_array<GLenum> enums(new GLenum[count]);
7560 memcpy(enums.get(), pnames, pnames_size);
7561
7562 // Count up the space needed for the result.
7563 uint32 num_results = 0;
7564 for (GLuint ii = 0; ii < count; ++ii) {
7565 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
7566 if (num == 0) {
7567 SetGLError(GL_INVALID_ENUM,
7568 "glGetMulitpleCHROMIUM: pname GL_INVALID_ENUM");
7569 return error::kNoError;
7570 }
7571 // Num will never be more than 4.
7572 DCHECK_LE(num, 4u);
7573 if (!SafeAdd(num_results, num, &num_results)) {
7574 return error::kOutOfBounds;
7575 }
7576 }
7577
7578 uint32 result_size = 0;
7579 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
7580 return error::kOutOfBounds;
7581 }
7582
7583 if (result_size != static_cast<uint32>(c.size)) {
7584 SetGLError(GL_INVALID_VALUE,
7585 "glGetMulitpleCHROMIUM: bad size GL_INVALID_VALUE");
7586 return error::kNoError;
7587 }
7588
7589 GLint* results = GetSharedMemoryAs<GLint*>(
7590 c.results_shm_id, c.results_shm_offset, result_size);
7591 if (results == NULL) {
7592 return error::kOutOfBounds;
7593 }
7594
7595 // Check the results have been cleared in case the context was lost.
7596 for (uint32 ii = 0; ii < num_results; ++ii) {
7597 if (results[ii]) {
7598 return error::kInvalidArguments;
7599 }
7600 }
7601
7602 // Get each result.
7603 GLint* start = results;
7604 for (GLuint ii = 0; ii < count; ++ii) {
7605 GLsizei num_written = 0;
7606 if (!GetHelper(enums[ii], results, &num_written)) {
7607 glGetIntegerv(enums[ii], results);
7608 }
7609 results += num_written;
7610 }
7611
7612 // Just to verify. Should this be a DCHECK?
7613 if (static_cast<uint32>(results - start) != num_results) {
7614 return error::kOutOfBounds;
7615 }
7616
7617 return error::kNoError;
7618}
7619
[email protected]2318d342011-07-11 22:27:427620error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
7621 uint32 immediate_data_size, const gles2::GetProgramInfoCHROMIUM& c) {
7622 GLuint program = static_cast<GLuint>(c.program);
7623 uint32 bucket_id = c.bucket_id;
7624 Bucket* bucket = CreateBucket(bucket_id);
7625 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
7626 ProgramManager::ProgramInfo* info = NULL;
[email protected]9a14ae612011-08-08 17:51:467627 info = GetProgramInfo(program);
7628 if (!info || !info->IsValid()) {
7629 return error::kNoError;
[email protected]2318d342011-07-11 22:27:427630 }
7631 info->GetProgramInfo(bucket);
7632 return error::kNoError;
7633}
7634
[email protected]38d139d2011-07-14 00:38:437635error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
7636 switch (reset_status_) {
7637 case GL_NO_ERROR:
7638 // TODO(kbr): improve the precision of the error code in this case.
7639 // Consider delegating to context for error code if MakeCurrent fails.
7640 return error::kUnknown;
7641 case GL_GUILTY_CONTEXT_RESET_ARB:
7642 return error::kGuilty;
7643 case GL_INNOCENT_CONTEXT_RESET_ARB:
7644 return error::kInnocent;
7645 case GL_UNKNOWN_CONTEXT_RESET_ARB:
7646 return error::kUnknown;
7647 }
7648
7649 NOTREACHED();
7650 return error::kUnknown;
7651}
7652
7653bool GLES2DecoderImpl::WasContextLost() {
7654 if (context_->WasAllocatedUsingARBRobustness() && has_arb_robustness_) {
7655 GLenum status = glGetGraphicsResetStatusARB();
7656 if (status != GL_NO_ERROR) {
7657 // The graphics card was reset. Signal a lost context to the application.
7658 reset_status_ = status;
7659 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
7660 << " context lost via ARB_robustness. Reset status = 0x"
7661 << std::hex << status << std::dec;
7662 return true;
7663 }
7664 }
7665 return false;
7666}
7667
[email protected]b0af4f52011-09-28 22:04:427668error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
7669 uint32 immediate_data_size,
7670 const gles2::CreateStreamTextureCHROMIUM& c) {
7671 if (!feature_info_->feature_flags().chromium_stream_texture) {
7672 SetGLError(GL_INVALID_OPERATION,
7673 "glOpenStreamTextureCHROMIUM: "
7674 "not supported.");
7675 return error::kNoError;
7676 }
7677
7678 uint32 client_id = c.client_id;
7679 typedef gles2::CreateStreamTextureCHROMIUM::Result Result;
7680 Result* result = GetSharedMemoryAs<Result*>(
7681 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7682
[email protected]e5081262012-01-05 23:09:037683 if (!result)
7684 return error::kOutOfBounds;
[email protected]b0af4f52011-09-28 22:04:427685 *result = GL_ZERO;
7686 TextureManager::TextureInfo* info =
7687 texture_manager()->GetTextureInfo(client_id);
7688 if (!info) {
7689 SetGLError(GL_INVALID_VALUE,
7690 "glCreateStreamTextureCHROMIUM: "
7691 "bad texture id.");
7692 return error::kNoError;
7693 }
7694
7695 if (info->IsStreamTexture()) {
7696 SetGLError(GL_INVALID_OPERATION,
7697 "glCreateStreamTextureCHROMIUM: "
7698 "is already a stream texture.");
7699 return error::kNoError;
7700 }
7701
7702 if (info->target() && info->target() != GL_TEXTURE_EXTERNAL_OES) {
7703 SetGLError(GL_INVALID_OPERATION,
7704 "glCreateStreamTextureCHROMIUM: "
7705 "is already bound to incompatible target.");
7706 return error::kNoError;
7707 }
7708
7709 if (!stream_texture_manager_)
7710 return error::kInvalidArguments;
7711
7712 GLuint object_id = stream_texture_manager_->CreateStreamTexture(
7713 info->service_id(), client_id);
7714
7715 if (object_id) {
7716 info->SetStreamTexture(true);
7717 } else {
7718 SetGLError(GL_OUT_OF_MEMORY,
7719 "glCreateStreamTextureCHROMIUM: "
7720 "failed to create platform texture.");
7721 }
7722
7723 *result = object_id;
7724 return error::kNoError;
7725}
7726
7727error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
7728 uint32 immediate_data_size,
7729 const gles2::DestroyStreamTextureCHROMIUM& c) {
7730 GLuint client_id = c.texture;
7731 TextureManager::TextureInfo* info =
7732 texture_manager()->GetTextureInfo(client_id);
7733 if (info && info->IsStreamTexture()) {
7734 if (!stream_texture_manager_)
7735 return error::kInvalidArguments;
7736
7737 stream_texture_manager_->DestroyStreamTexture(info->service_id());
7738 info->SetStreamTexture(false);
[email protected]80eb6b52012-01-19 00:14:417739 texture_manager()->SetInfoTarget(info, 0);
[email protected]b0af4f52011-09-28 22:04:427740 } else {
7741 SetGLError(GL_INVALID_VALUE,
7742 "glDestroyStreamTextureCHROMIUM: bad texture id.");
7743 }
7744
7745 return error::kNoError;
7746}
7747
[email protected]e51bdf32011-11-23 22:21:467748#if defined(OS_MACOSX)
7749void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
7750 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
7751 texture_id);
7752 if (it != texture_to_io_surface_map_.end()) {
7753 // Found a previous IOSurface bound to this texture; release it.
7754 CFTypeRef surface = it->second;
7755 CFRelease(surface);
7756 texture_to_io_surface_map_.erase(it);
7757 }
7758}
7759#endif
7760
7761void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
7762 GLenum target, GLsizei width, GLsizei height,
7763 GLuint io_surface_id, GLuint plane) {
7764#if defined(OS_MACOSX)
7765 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
7766 SetGLError(GL_INVALID_OPERATION,
7767 "glTexImageIOSurface2DCHROMIUM: only supported on desktop GL.");
7768 return;
7769 }
7770
7771 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
7772 if (!surface_support) {
7773 SetGLError(GL_INVALID_OPERATION,
7774 "glTexImageIOSurface2DCHROMIUM: only supported on 10.6.");
7775 return;
7776 }
7777
7778 if (target != GL_TEXTURE_RECTANGLE_ARB) {
7779 // This might be supported in the future, and if we could require
7780 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
7781 // could delete a lot of code. For now, perform strict validation so we
7782 // know what's going on.
7783 SetGLError(
7784 GL_INVALID_OPERATION,
7785 "glTexImageIOSurface2DCHROMIUM: requires TEXTURE_RECTANGLE_ARB target");
7786 return;
7787 }
7788
7789 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7790 if (!info) {
7791 SetGLError(GL_INVALID_OPERATION,
7792 "glTexImageIOSurface2DCHROMIUM: no rectangle texture bound");
7793 return;
7794 }
7795 if (info == texture_manager()->GetDefaultTextureInfo(target)) {
7796 // Maybe this is conceptually valid, but disallow it to avoid accidents.
7797 SetGLError(GL_INVALID_OPERATION,
7798 "glTexImageIOSurface2DCHROMIUM: can't bind default texture");
7799 return;
7800 }
7801
7802 // Look up the new IOSurface. Note that because of asynchrony
7803 // between processes this might fail; during live resizing the
7804 // plugin process might allocate and release an IOSurface before
7805 // this process gets a chance to look it up. Hold on to any old
7806 // IOSurface in this case.
7807 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
7808 if (!surface) {
7809 SetGLError(GL_INVALID_OPERATION,
7810 "glTexImageIOSurface2DCHROMIUM: no IOSurface with the given ID");
7811 return;
7812 }
7813
7814 // Release any IOSurface previously bound to this texture.
7815 ReleaseIOSurfaceForTexture(info->service_id());
7816
7817 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
7818 texture_to_io_surface_map_.insert(
7819 std::make_pair(info->service_id(), surface));
7820
7821 CGLContextObj context =
7822 static_cast<CGLContextObj>(context_->GetHandle());
7823
7824 CGLError err = surface_support->CGLTexImageIOSurface2D(
7825 context,
7826 target,
7827 GL_RGBA,
7828 width,
7829 height,
7830 GL_BGRA,
7831 GL_UNSIGNED_INT_8_8_8_8_REV,
7832 surface,
7833 plane);
7834
7835 if (err != kCGLNoError) {
7836 SetGLError(
7837 GL_INVALID_OPERATION,
7838 "glTexImageIOSurface2DCHROMIUM: error in CGLTexImageIOSurface2D");
7839 return;
7840 }
7841
7842 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:417843 info, target, 0, GL_RGBA, width, height, 1, 0,
[email protected]e51bdf32011-11-23 22:21:467844 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
7845
7846#else
7847 SetGLError(GL_INVALID_OPERATION,
7848 "glTexImageIOSurface2DCHROMIUM: not supported.");
7849#endif
7850}
7851
[email protected]97dc7cbe2011-12-06 17:26:177852static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
7853 switch (internalformat) {
7854 case GL_RGB565:
7855 return GL_RGB;
7856 case GL_RGBA4:
7857 return GL_RGBA;
7858 case GL_RGB5_A1:
7859 return GL_RGBA;
7860 case GL_RGB8_OES:
7861 return GL_RGB;
7862 case GL_RGBA8_OES:
7863 return GL_RGBA;
7864 case GL_LUMINANCE8_ALPHA8_EXT:
7865 return GL_LUMINANCE_ALPHA;
7866 case GL_LUMINANCE8_EXT:
7867 return GL_LUMINANCE;
7868 case GL_ALPHA8_EXT:
7869 return GL_ALPHA;
7870 case GL_RGBA32F_EXT:
7871 return GL_RGBA;
7872 case GL_RGB32F_EXT:
7873 return GL_RGB;
7874 case GL_ALPHA32F_EXT:
7875 return GL_ALPHA;
7876 case GL_LUMINANCE32F_EXT:
7877 return GL_LUMINANCE;
7878 case GL_LUMINANCE_ALPHA32F_EXT:
7879 return GL_LUMINANCE_ALPHA;
7880 case GL_RGBA16F_EXT:
7881 return GL_RGBA;
7882 case GL_RGB16F_EXT:
7883 return GL_RGB;
7884 case GL_ALPHA16F_EXT:
7885 return GL_ALPHA;
7886 case GL_LUMINANCE16F_EXT:
7887 return GL_LUMINANCE;
7888 case GL_LUMINANCE_ALPHA16F_EXT:
7889 return GL_LUMINANCE_ALPHA;
7890 case GL_BGRA8_EXT:
7891 return GL_BGRA_EXT;
7892 default:
7893 return GL_NONE;
7894 }
7895}
7896
7897static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
7898 switch (internalformat) {
7899 case GL_RGB565:
7900 return GL_UNSIGNED_SHORT_5_6_5;
7901 case GL_RGBA4:
7902 return GL_UNSIGNED_SHORT_4_4_4_4;
7903 case GL_RGB5_A1:
7904 return GL_UNSIGNED_SHORT_5_5_5_1;
7905 case GL_RGB8_OES:
7906 return GL_UNSIGNED_BYTE;
7907 case GL_RGBA8_OES:
7908 return GL_UNSIGNED_BYTE;
7909 case GL_LUMINANCE8_ALPHA8_EXT:
7910 return GL_UNSIGNED_BYTE;
7911 case GL_LUMINANCE8_EXT:
7912 return GL_UNSIGNED_BYTE;
7913 case GL_ALPHA8_EXT:
7914 return GL_UNSIGNED_BYTE;
7915 case GL_RGBA32F_EXT:
7916 return GL_FLOAT;
7917 case GL_RGB32F_EXT:
7918 return GL_FLOAT;
7919 case GL_ALPHA32F_EXT:
7920 return GL_FLOAT;
7921 case GL_LUMINANCE32F_EXT:
7922 return GL_FLOAT;
7923 case GL_LUMINANCE_ALPHA32F_EXT:
7924 return GL_FLOAT;
7925 case GL_RGBA16F_EXT:
7926 return GL_HALF_FLOAT_OES;
7927 case GL_RGB16F_EXT:
7928 return GL_HALF_FLOAT_OES;
7929 case GL_ALPHA16F_EXT:
7930 return GL_HALF_FLOAT_OES;
7931 case GL_LUMINANCE16F_EXT:
7932 return GL_HALF_FLOAT_OES;
7933 case GL_LUMINANCE_ALPHA16F_EXT:
7934 return GL_HALF_FLOAT_OES;
7935 case GL_BGRA8_EXT:
7936 return GL_UNSIGNED_BYTE;
7937 default:
7938 return GL_NONE;
7939 }
7940}
7941
7942void GLES2DecoderImpl::DoTexStorage2DEXT(
7943 GLenum target,
7944 GLint levels,
7945 GLenum internal_format,
7946 GLsizei width,
7947 GLsizei height) {
[email protected]80eb6b52012-01-19 00:14:417948 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
[email protected]97dc7cbe2011-12-06 17:26:177949 TextureManager::ComputeMipMapCount(width, height, 1) < levels) {
7950 SetGLError(GL_INVALID_VALUE, "glTexStorage2DEXT: dimensions out of range");
7951 return;
7952 }
7953 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7954 if (!info) {
7955 SetGLError(GL_INVALID_OPERATION,
7956 "glTexStorage2DEXT: unknown texture for target");
7957 return;
7958 }
7959 if (info->IsAttachedToFramebuffer()) {
7960 state_dirty_ = true;
7961 }
7962 if (info->IsImmutable()) {
7963 SetGLError(GL_INVALID_OPERATION,
7964 "glTexStorage2DEXT: texture is immutable");
7965 return;
7966 }
7967 CopyRealGLErrorsToWrapper();
[email protected]f0e6a34f2012-01-04 20:53:407968 glTexStorage2DEXT(target, levels, GetTexInternalFormat(internal_format),
7969 width, height);
[email protected]97dc7cbe2011-12-06 17:26:177970 GLenum error = PeekGLError();
7971 if (error == GL_NO_ERROR) {
7972 GLenum format = ExtractFormatFromStorageFormat(internal_format);
7973 GLenum type = ExtractTypeFromStorageFormat(internal_format);
[email protected]4502e6492011-12-14 19:39:157974 GLsizei level_width = width;
7975 GLsizei level_height = height;
7976 for (int ii = 0; ii < levels; ++ii) {
7977 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:417978 info, target, 0, format, level_width, level_height, 1, 0, format,
7979 type, false);
[email protected]4502e6492011-12-14 19:39:157980 level_width = std::max(1, level_width >> 1);
7981 level_height = std::max(1, level_height >> 1);
7982 }
[email protected]97dc7cbe2011-12-06 17:26:177983 info->SetImmutable(true);
7984 }
[email protected]97dc7cbe2011-12-06 17:26:177985}
[email protected]e51bdf32011-11-23 22:21:467986
[email protected]96449d2c2009-11-25 00:01:327987// Include the auto-generated part of this file. We split this because it means
7988// we can easily edit the non-auto generated parts right here in this file
7989// instead of having to edit some template or the code generator.
7990#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
7991
7992} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:257993} // namespace gpu