blob: a92cb6ebf5c12ff4051faba67effbba2a8c46098 [file] [log] [blame]
[email protected]4874aae2011-03-18 01:19:561// Copyright (c) 2011 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]2041cf342010-02-19 03:15:5917#include "base/callback.h"
[email protected]3b63f8f42011-03-28 01:54:1518#include "base/memory/scoped_ptr.h"
19#include "base/memory/weak_ptr.h"
[email protected]d37231fa2010-04-09 21:16:0220#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3221#define GLES2_GPU_SERVICE 1
22#include "gpu/command_buffer/common/gles2_cmd_format.h"
23#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1024#include "gpu/command_buffer/common/id_allocator.h"
[email protected]366ae242011-05-10 02:23:5825#include "gpu/command_buffer/common/trace_event.h"
[email protected]3916c97e2010-02-25 03:20:5026#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3227#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5028#include "gpu/command_buffer/service/context_group.h"
[email protected]915a59a12010-09-30 21:29:1129#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5830#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3231#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4632#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]a93bb842010-02-16 23:03:4733#include "gpu/command_buffer/service/program_manager.h"
[email protected]a25fa872010-03-25 02:57:5834#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4735#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4536#include "gpu/command_buffer/service/shader_translator.h"
[email protected]a93bb842010-02-16 23:03:4737#include "gpu/command_buffer/service/texture_manager.h"
[email protected]d8ea9772011-07-11 18:11:4338#include "gpu/command_buffer/service/vertex_attrib_manager.h"
[email protected]5ae0b282011-03-28 19:24:4939#include "ui/gfx/gl/gl_context.h"
40#include "ui/gfx/gl/gl_implementation.h"
[email protected]f62a5ab2011-05-23 20:34:1541#include "ui/gfx/gl/gl_surface.h"
[email protected]de17df392010-04-23 21:09:4142
[email protected]6217d392010-03-25 22:08:3543#if !defined(GL_DEPTH24_STENCIL8)
44#define GL_DEPTH24_STENCIL8 0x88F0
45#endif
46
[email protected]a7a27ace2009-12-12 00:11:2547namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3248namespace gles2 {
49
[email protected]6217d392010-03-25 22:08:3550class GLES2DecoderImpl;
51
[email protected]07f54fcc2009-12-22 02:46:3052// Check that certain assumptions the code makes are true. There are places in
53// the code where shared memory is passed direclty to GL. Example, glUniformiv,
54// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
55// a few others) are 32bits. If they are not 32bits the code will have to change
56// to call those GL functions with service side memory and then copy the results
57// to shared memory, converting the sizes.
58COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
59 GLint_not_same_size_as_uint32);
60COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
61 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3762COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
63 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3064
[email protected]43f28f832010-02-03 02:28:4865// TODO(kbr): the use of this anonymous namespace core dumps the
66// linker on Mac OS X 10.6 when the symbol ordering file is used
67// namespace {
[email protected]96449d2c2009-11-25 00:01:3268
69// Returns the address of the first byte after a struct.
70template <typename T>
71const void* AddressAfterStruct(const T& pod) {
72 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
73}
74
[email protected]07f54fcc2009-12-22 02:46:3075// Returns the address of the frst byte after the struct or NULL if size >
76// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3277template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3078RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
79 uint32 size,
80 uint32 immediate_data_size) {
81 return (size <= immediate_data_size) ?
82 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
83 NULL;
[email protected]96449d2c2009-11-25 00:01:3284}
85
[email protected]07f54fcc2009-12-22 02:46:3086// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1887bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3288 GLuint count,
89 size_t size,
[email protected]a76b0052010-03-05 00:33:1890 unsigned int elements_per_unit,
91 uint32* dst) {
92 uint32 value;
93 if (!SafeMultiplyUint32(count, size, &value)) {
94 return false;
95 }
96 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
97 return false;
98 }
99 *dst = value;
100 return true;
[email protected]96449d2c2009-11-25 00:01:32101}
102
103// A struct to hold info about each command.
104struct CommandInfo {
105 int arg_flags; // How to handle the arguments for this command
106 int arg_count; // How many arguments are expected for this command.
107};
108
109// A table of CommandInfo for all the commands.
110const CommandInfo g_command_info[] = {
111 #define GLES2_CMD_OP(name) { \
112 name::kArgFlags, \
113 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
114
115 GLES2_COMMAND_LIST(GLES2_CMD_OP)
116
117 #undef GLES2_CMD_OP
118};
119
[email protected]34ff8b0c2010-10-01 20:06:02120static bool IsAngle() {
121#if defined(OS_WIN)
122 return gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
123#else
124 return false;
125#endif
126}
127
[email protected]297ca1c2011-06-20 23:08:46128static void WrappedTexImage2D(
[email protected]473c01ccb2011-06-07 01:33:30129 GLenum target,
130 GLint level,
131 GLenum internal_format,
132 GLsizei width,
133 GLsizei height,
134 GLint border,
135 GLenum format,
136 GLenum type,
137 const void* pixels) {
138 GLenum gl_internal_format = internal_format;
139 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
140 if (format == GL_BGRA_EXT && internal_format == GL_BGRA_EXT) {
141 gl_internal_format = GL_RGBA;
142 } else if (type == GL_FLOAT) {
143 if (format == GL_RGBA) {
144 gl_internal_format = GL_RGBA32F_ARB;
145 } else if (format == GL_RGB) {
146 gl_internal_format = GL_RGB32F_ARB;
147 }
148 } else if (type == GL_HALF_FLOAT_OES) {
149 if (format == GL_RGBA) {
150 gl_internal_format = GL_RGBA16F_ARB;
151 } else if (format == GL_RGB) {
152 gl_internal_format = GL_RGB16F_ARB;
153 }
154 }
155 }
156 glTexImage2D(
157 target, level, gl_internal_format, width, height, border, format, type,
158 pixels);
159}
160
[email protected]297ca1c2011-06-20 23:08:46161// Wrapper for glEnable/glDisable that doesn't suck.
162static void EnableDisable(GLenum pname, bool enable) {
163 if (enable) {
164 glEnable(pname);
165 } else {
166 glDisable(pname);
167 }
168}
169
[email protected]6217d392010-03-25 22:08:35170// This class prevents any GL errors that occur when it is in scope from
171// being reported to the client.
172class ScopedGLErrorSuppressor {
173 public:
174 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
175 ~ScopedGLErrorSuppressor();
176 private:
177 GLES2DecoderImpl* decoder_;
178 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
179};
180
181// Temporarily changes a decoder's bound 2D texture and restore it when this
182// object goes out of scope. Also temporarily switches to using active texture
183// unit zero in case the client has changed that to something invalid.
184class ScopedTexture2DBinder {
185 public:
186 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
187 ~ScopedTexture2DBinder();
188
189 private:
190 GLES2DecoderImpl* decoder_;
191 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
192};
193
194// Temporarily changes a decoder's bound render buffer and restore it when this
195// object goes out of scope.
196class ScopedRenderBufferBinder {
197 public:
198 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
199 ~ScopedRenderBufferBinder();
200
201 private:
202 GLES2DecoderImpl* decoder_;
203 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
204};
205
206// Temporarily changes a decoder's bound frame buffer and restore it when this
207// object goes out of scope.
208class ScopedFrameBufferBinder {
209 public:
210 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
211 ~ScopedFrameBufferBinder();
212
213 private:
214 GLES2DecoderImpl* decoder_;
215 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
216};
217
[email protected]34ff8b0c2010-10-01 20:06:02218// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52219// the multisampled offscreen render buffer if that buffer is multisampled, and,
[email protected]de26b3c2011-08-03 21:54:27220// if it is bound or enforce_internal_framebuffer is true. If internal is
221// true, the resolved framebuffer is not visible to the parent.
[email protected]34ff8b0c2010-10-01 20:06:02222class ScopedResolvedFrameBufferBinder {
223 public:
[email protected]e7e38032011-07-26 17:25:25224 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
[email protected]de26b3c2011-08-03 21:54:27225 bool enforce_internal_framebuffer,
226 bool internal);
[email protected]34ff8b0c2010-10-01 20:06:02227 ~ScopedResolvedFrameBufferBinder();
228
229 private:
230 GLES2DecoderImpl* decoder_;
231 bool resolve_and_bind_;
232 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
233};
234
[email protected]6217d392010-03-25 22:08:35235// Encapsulates an OpenGL texture.
236class Texture {
237 public:
238 explicit Texture(GLES2DecoderImpl* decoder);
239 ~Texture();
240
241 // Create a new render texture.
242 void Create();
243
244 // Set the initial size and format of a render texture or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02245 bool AllocateStorage(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35246
247 // Copy the contents of the currently bound frame buffer.
[email protected]3a4d0c52011-06-29 23:11:58248 void Copy(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35249
250 // Destroy the render texture. This must be explicitly called before
251 // destroying this object.
252 void Destroy();
253
[email protected]97872062010-11-03 19:07:05254 // Invalidate the texture. This can be used when a context is lost and it is
255 // not possible to make it current in order to free the resource.
256 void Invalidate();
257
[email protected]6217d392010-03-25 22:08:35258 GLuint id() const {
259 return id_;
260 }
261
[email protected]d37231fa2010-04-09 21:16:02262 gfx::Size size() const {
263 return size_;
264 }
265
[email protected]6217d392010-03-25 22:08:35266 private:
267 GLES2DecoderImpl* decoder_;
268 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02269 gfx::Size size_;
[email protected]6217d392010-03-25 22:08:35270 DISALLOW_COPY_AND_ASSIGN(Texture);
271};
272
273// Encapsulates an OpenGL render buffer of any format.
274class RenderBuffer {
275 public:
276 explicit RenderBuffer(GLES2DecoderImpl* decoder);
277 ~RenderBuffer();
278
279 // Create a new render buffer.
280 void Create();
281
282 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02283 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35284
285 // Destroy the render buffer. This must be explicitly called before destroying
286 // this object.
287 void Destroy();
288
[email protected]97872062010-11-03 19:07:05289 // Invalidate the render buffer. This can be used when a context is lost and
290 // it is not possible to make it current in order to free the resource.
291 void Invalidate();
292
[email protected]6217d392010-03-25 22:08:35293 GLuint id() const {
294 return id_;
295 }
296
297 private:
298 GLES2DecoderImpl* decoder_;
299 GLuint id_;
300 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
301};
302
303// Encapsulates an OpenGL frame buffer.
304class FrameBuffer {
305 public:
306 explicit FrameBuffer(GLES2DecoderImpl* decoder);
307 ~FrameBuffer();
308
309 // Create a new frame buffer.
310 void Create();
311
312 // Attach a color render buffer to a frame buffer.
313 void AttachRenderTexture(Texture* texture);
314
[email protected]b9363b22010-06-09 22:06:15315 // Attach a render buffer to a frame buffer. Note that this unbinds any
316 // currently bound frame buffer.
317 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35318
319 // Clear the given attached buffers.
320 void Clear(GLbitfield buffers);
321
322 // Destroy the frame buffer. This must be explicitly called before destroying
323 // this object.
324 void Destroy();
325
[email protected]97872062010-11-03 19:07:05326 // Invalidate the frame buffer. This can be used when a context is lost and it
327 // is not possible to make it current in order to free the resource.
328 void Invalidate();
329
[email protected]6217d392010-03-25 22:08:35330 // See glCheckFramebufferStatusEXT.
331 GLenum CheckStatus();
332
333 GLuint id() const {
334 return id_;
335 }
336
337 private:
338 GLES2DecoderImpl* decoder_;
339 GLuint id_;
340 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
341};
[email protected]34ff8b0c2010-10-01 20:06:02342
343class ContextCreationAttribParser {
344 public:
345 ContextCreationAttribParser();
346 bool Parse(const std::vector<int32>& attribs);
347
348 // -1 if invalid or unspecified.
349 int32 alpha_size_;
350 int32 blue_size_;
351 int32 green_size_;
352 int32 red_size_;
353 int32 depth_size_;
354 int32 stencil_size_;
355 int32 samples_;
356 int32 sample_buffers_;
357};
358
359ContextCreationAttribParser::ContextCreationAttribParser()
360 : alpha_size_(-1),
361 blue_size_(-1),
362 green_size_(-1),
363 red_size_(-1),
364 depth_size_(-1),
365 stencil_size_(-1),
366 samples_(-1),
367 sample_buffers_(-1) {
368}
369
370bool ContextCreationAttribParser::Parse(const std::vector<int32>& attribs) {
371 // From <EGL/egl.h>.
372 const int32 EGL_ALPHA_SIZE = 0x3021;
373 const int32 EGL_BLUE_SIZE = 0x3022;
374 const int32 EGL_GREEN_SIZE = 0x3023;
375 const int32 EGL_RED_SIZE = 0x3024;
376 const int32 EGL_DEPTH_SIZE = 0x3025;
377 const int32 EGL_STENCIL_SIZE = 0x3026;
378 const int32 EGL_SAMPLES = 0x3031;
379 const int32 EGL_SAMPLE_BUFFERS = 0x3032;
380 const int32 EGL_NONE = 0x3038;
381
382 for (size_t i = 0; i < attribs.size(); i += 2) {
383 const int32 attrib = attribs[i];
384 if (i + 1 >= attribs.size()) {
385 if (attrib == EGL_NONE)
386 return true;
387
388 DLOG(ERROR) << "Missing value after context creation attribute: "
389 << attrib;
390 return false;
391 }
392
393 const int32 value = attribs[i+1];
394 switch (attrib) {
395 case EGL_ALPHA_SIZE:
396 alpha_size_ = value;
397 break;
398 case EGL_BLUE_SIZE:
399 blue_size_ = value;
400 break;
401 case EGL_GREEN_SIZE:
402 green_size_ = value;
403 break;
404 case EGL_RED_SIZE:
405 red_size_ = value;
406 break;
407 case EGL_DEPTH_SIZE:
408 depth_size_ = value;
409 break;
410 case EGL_STENCIL_SIZE:
411 stencil_size_ = value;
412 break;
413 case EGL_SAMPLES:
414 samples_ = value;
415 break;
416 case EGL_SAMPLE_BUFFERS:
417 sample_buffers_ = value;
418 break;
419 case EGL_NONE:
420 // Terminate list, even if more attributes.
421 return true;
422 default:
423 DLOG(ERROR) << "Invalid context creation attribute: " << attrib;
424 return false;
425 }
426 }
427
428 return true;
429}
430
[email protected]43f28f832010-02-03 02:28:48431// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32432
[email protected]ddb1e5a2010-12-13 20:10:45433bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
434 uint32* service_texture_id) {
435 return false;
436}
437
[email protected]a3ded6d2010-10-19 06:44:39438GLES2Decoder::GLES2Decoder()
439 : debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32440}
441
[email protected]3916c97e2010-02-25 03:20:50442GLES2Decoder::~GLES2Decoder() {
443}
444
[email protected]f39f4b3f2010-05-12 17:04:08445// This class implements GLES2Decoder so we don't have to expose all the GLES2
446// cmd stuff to outside this class.
447class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
448 public GLES2Decoder {
449 public:
[email protected]aa7666122011-09-02 19:45:52450 explicit GLES2DecoderImpl(ContextGroup* group);
[email protected]f39f4b3f2010-05-12 17:04:08451
[email protected]96449d2c2009-11-25 00:01:32452 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14453 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50454 unsigned int arg_count,
455 const void* args);
[email protected]96449d2c2009-11-25 00:01:32456
457 // Overridden from AsyncAPIInterface.
458 virtual const char* GetCommandName(unsigned int command_id) const;
459
460 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38461 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
462 const scoped_refptr<gfx::GLContext>& context,
[email protected]6217d392010-03-25 22:08:35463 const gfx::Size& size,
[email protected]c410da802011-03-14 19:17:41464 const DisallowedExtensions& disallowed_extensions,
[email protected]a3ded6d2010-10-19 06:44:39465 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:24466 const std::vector<int32>& attribs);
[email protected]96449d2c2009-11-25 00:01:32467 virtual void Destroy();
[email protected]3c644d82011-06-20 19:58:24468 virtual bool SetParent(GLES2Decoder* parent_decoder,
469 uint32 parent_texture_id);
[email protected]799b4b22011-08-22 17:09:59470 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]9a5afa432011-07-22 18:16:39471 void UpdateParentTextureInfo();
[email protected]eb54a562010-01-20 21:55:18472 virtual bool MakeCurrent();
[email protected]56ac89b2010-03-17 21:16:55473 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30474 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]f62a5ab2011-05-23 20:34:15475 virtual gfx::GLSurface* GetGLSurface() { return surface_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39476 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]43f28f832010-02-03 02:28:48477
[email protected]7ff86b92010-11-25 17:50:00478 virtual void SetResizeCallback(Callback1<gfx::Size>::Type* callback);
[email protected]22f320a2011-08-30 01:17:00479
480#if defined(OS_MACOSX)
[email protected]43f28f832010-02-03 02:28:48481 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
[email protected]22f320a2011-08-30 01:17:00482#endif
483
[email protected]1318e922010-09-17 22:03:16484 virtual bool GetServiceTextureId(uint32 client_texture_id,
485 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48486
[email protected]8e3e0662010-08-23 18:46:30487 // Restores the current state to the user's settings.
488 void RestoreCurrentFramebufferBindings();
489 void RestoreCurrentRenderbufferBindings();
490 void RestoreCurrentTexture2DBindings();
491
[email protected]297ca1c2011-06-20 23:08:46492 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
493 void ApplyDirtyState();
494
495 // These check the state of the currently bound framebuffer or the
496 // backbuffer if no framebuffer is bound.
497 bool BoundFramebufferHasColorAttachmentWithAlpha();
498 bool BoundFramebufferHasDepthAttachment();
499 bool BoundFramebufferHasStencilAttachment();
500
[email protected]38d139d2011-07-14 00:38:43501 virtual error::ContextLostReason GetContextLostReason();
502
[email protected]96449d2c2009-11-25 00:01:32503 private:
[email protected]6217d392010-03-25 22:08:35504 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02505 friend class ScopedResolvedFrameBufferBinder;
[email protected]6217d392010-03-25 22:08:35506 friend class RenderBuffer;
507 friend class FrameBuffer;
508
[email protected]3916c97e2010-02-25 03:20:50509 // State associated with each texture unit.
510 struct TextureUnit {
511 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
512
513 // The last target that was bound to this texture unit.
514 GLenum bind_target;
515
516 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
517 TextureManager::TextureInfo::Ref bound_texture_2d;
518
519 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
520 // glBindTexture
521 TextureManager::TextureInfo::Ref bound_texture_cube_map;
[email protected]61eeb33f2011-07-26 15:30:31522
523 // texture currently bound to this unit's GL_TEXTURE_EXTERNAL_OES with
524 // glBindTexture
525 TextureManager::TextureInfo::Ref bound_texture_external_oes;
526
527 TextureManager::TextureInfo::Ref GetInfoForSamplerType(GLenum type) {
528 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
529 type == GL_SAMPLER_EXTERNAL_OES);
530 return type == GL_SAMPLER_2D ? bound_texture_2d :
531 (type == GL_SAMPLER_EXTERNAL_OES ? bound_texture_external_oes :
532 bound_texture_cube_map);
533 }
[email protected]3916c97e2010-02-25 03:20:50534 };
535
[email protected]c2f8c8402010-12-06 18:07:24536 // Initialize or re-initialize the shader translator.
537 bool InitializeShaderTranslator();
538
[email protected]302ce6d2011-07-07 23:28:11539 void UpdateCapabilities();
540
[email protected]ae51d192010-04-27 00:48:03541 // Helpers for the glGen and glDelete functions.
542 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
543 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
544 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
545 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
546 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
547 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
548 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
549 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47550
[email protected]3916c97e2010-02-25 03:20:50551 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50552 BufferManager* buffer_manager() {
553 return group_->buffer_manager();
554 }
555
[email protected]a25fa872010-03-25 02:57:58556 RenderbufferManager* renderbuffer_manager() {
557 return group_->renderbuffer_manager();
558 }
559
560 FramebufferManager* framebuffer_manager() {
561 return group_->framebuffer_manager();
562 }
563
[email protected]3916c97e2010-02-25 03:20:50564 ProgramManager* program_manager() {
565 return group_->program_manager();
566 }
567
568 ShaderManager* shader_manager() {
569 return group_->shader_manager();
570 }
571
572 TextureManager* texture_manager() {
573 return group_->texture_manager();
574 }
575
[email protected]34ff8b0c2010-10-01 20:06:02576 bool IsOffscreenBufferMultisampled() const {
577 return offscreen_target_samples_ > 1;
578 }
579
[email protected]a93bb842010-02-16 23:03:47580 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03581 TextureManager::TextureInfo* CreateTextureInfo(
582 GLuint client_id, GLuint service_id) {
[email protected]915a59a12010-09-30 21:29:11583 return texture_manager()->CreateTextureInfo(
584 feature_info_, client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47585 }
586
587 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03588 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50589 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03590 texture_manager()->GetTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50591 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47592 }
593
594 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03595 void RemoveTextureInfo(GLuint client_id) {
[email protected]915a59a12010-09-30 21:29:11596 texture_manager()->RemoveTextureInfo(feature_info_, client_id);
[email protected]3916c97e2010-02-25 03:20:50597 }
[email protected]a93bb842010-02-16 23:03:47598
[email protected]d37231fa2010-04-09 21:16:02599 // Get the size (in pixels) of the currently bound frame buffer (either FBO
600 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30601 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02602
[email protected]9edc6b22010-12-23 02:00:26603 // Get the format of the currently bound frame buffer (either FBO or regular
604 // back buffer)
605 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46606 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26607
[email protected]a93bb842010-02-16 23:03:47608 // Wrapper for CompressedTexImage2D commands.
609 error::Error DoCompressedTexImage2D(
610 GLenum target,
611 GLint level,
612 GLenum internal_format,
613 GLsizei width,
614 GLsizei height,
615 GLint border,
616 GLsizei image_size,
617 const void* data);
618
[email protected]cadde4a2010-07-31 17:10:43619 // Wrapper for CompressedTexSubImage2D.
620 void DoCompressedTexSubImage2D(
621 GLenum target,
622 GLint level,
623 GLint xoffset,
624 GLint yoffset,
625 GLsizei width,
626 GLsizei height,
627 GLenum format,
628 GLsizei imageSize,
629 const void * data);
630
631 // Wrapper for CopyTexImage2D.
632 void DoCopyTexImage2D(
633 GLenum target,
634 GLint level,
635 GLenum internal_format,
636 GLint x,
637 GLint y,
638 GLsizei width,
639 GLsizei height,
640 GLint border);
641
642 // Wrapper for CopyTexSubImage2D.
643 void DoCopyTexSubImage2D(
644 GLenum target,
645 GLint level,
646 GLint xoffset,
647 GLint yoffset,
648 GLint x,
649 GLint y,
650 GLsizei width,
651 GLsizei height);
652
[email protected]a93bb842010-02-16 23:03:47653 // Wrapper for TexImage2D commands.
654 error::Error DoTexImage2D(
655 GLenum target,
656 GLint level,
657 GLenum internal_format,
658 GLsizei width,
659 GLsizei height,
660 GLint border,
661 GLenum format,
662 GLenum type,
663 const void* pixels,
664 uint32 pixels_size);
665
[email protected]cadde4a2010-07-31 17:10:43666 // Wrapper for TexSubImage2D.
667 void DoTexSubImage2D(
668 GLenum target,
669 GLint level,
670 GLint xoffset,
671 GLint yoffset,
672 GLsizei width,
673 GLsizei height,
674 GLenum format,
675 GLenum type,
676 const void * data);
677
[email protected]a93bb842010-02-16 23:03:47678 // Creates a ProgramInfo for the given program.
[email protected]d685a682011-04-29 16:19:57679 ProgramManager::ProgramInfo* CreateProgramInfo(
680 GLuint client_id, GLuint service_id) {
681 return program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47682 }
683
[email protected]07f54fcc2009-12-22 02:46:30684 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03685 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14686 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46687 }
[email protected]07f54fcc2009-12-22 02:46:30688
[email protected]6b8cf1a2010-05-06 16:13:58689 // Gets the program info for the given program. If it's not a program
690 // generates a GL error. Returns NULL if not program.
691 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
692 GLuint client_id, const char* function_name) {
693 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
694 if (!info) {
695 if (GetShaderInfo(client_id)) {
696 SetGLError(GL_INVALID_OPERATION,
697 (std::string(function_name) +
698 ": shader passed for program").c_str());
699 } else {
700 SetGLError(GL_INVALID_VALUE,
701 (std::string(function_name) + ": unknown program").c_str());
702 }
703 }
704 return info;
705 }
706
707
[email protected]45bf5152010-02-12 00:11:31708 // Creates a ShaderInfo for the given shader.
[email protected]d685a682011-04-29 16:19:57709 ShaderManager::ShaderInfo* CreateShaderInfo(
710 GLuint client_id,
711 GLuint service_id,
712 GLenum shader_type) {
713 return shader_manager()->CreateShaderInfo(
714 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31715 }
716
717 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03718 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14719 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31720 }
721
[email protected]6b8cf1a2010-05-06 16:13:58722 // Gets the shader info for the given shader. If it's not a shader generates a
723 // GL error. Returns NULL if not shader.
724 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
725 GLuint client_id, const char* function_name) {
726 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
727 if (!info) {
728 if (GetProgramInfo(client_id)) {
729 SetGLError(
730 GL_INVALID_OPERATION,
731 (std::string(function_name) +
732 ": program passed for shader").c_str());
733 } else {
734 SetGLError(GL_INVALID_VALUE,
735 (std::string(function_name) + ": unknown shader").c_str());
736 }
737 }
738 return info;
739 }
740
[email protected]a93bb842010-02-16 23:03:47741 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03742 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
743 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47744 }
745
[email protected]07f54fcc2009-12-22 02:46:30746 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03747 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
748 BufferManager::BufferInfo* info =
749 buffer_manager()->GetBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50750 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46751 }
[email protected]07f54fcc2009-12-22 02:46:30752
[email protected]a93bb842010-02-16 23:03:47753 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
754 // on glDeleteBuffers so we can make sure the user does not try to render
755 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03756 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47757
[email protected]a25fa872010-03-25 02:57:58758 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03759 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
760 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58761 }
762
763 // Gets the framebuffer info for the given framebuffer.
764 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03765 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58766 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03767 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58768 return (info && !info->IsDeleted()) ? info : NULL;
769 }
770
771 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03772 void RemoveFramebufferInfo(GLuint client_id) {
773 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58774 }
775
776 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03777 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
778 return renderbuffer_manager()->CreateRenderbufferInfo(
779 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58780 }
781
782 // Gets the renderbuffer info for the given renderbuffer.
783 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03784 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58785 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03786 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58787 return (info && !info->IsDeleted()) ? info : NULL;
788 }
789
790 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03791 void RemoveRenderbufferInfo(GLuint client_id) {
792 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58793 }
794
[email protected]558847a2010-03-24 07:02:54795 error::Error GetAttribLocationHelper(
796 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
797 const std::string& name_str);
798
799 error::Error GetUniformLocationHelper(
800 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
801 const std::string& name_str);
802
[email protected]3916c97e2010-02-25 03:20:50803 // Helper for glShaderSource.
804 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03805 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30806
[email protected]3a2e7c7b2010-08-06 01:12:28807 // Clears any uncleared render buffers attached to the given frame buffer.
[email protected]8e3e0662010-08-23 18:46:30808 void ClearUnclearedRenderbuffers(
809 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28810
[email protected]c007aa02010-09-02 22:22:40811 // Restore all GL state that affects clearing.
812 void RestoreClearState();
813
[email protected]3a2e7c7b2010-08-06 01:12:28814 // Remembers the state of some capabilities.
[email protected]297ca1c2011-06-20 23:08:46815 // Returns: true if glEnable/glDisable should actually be called.
816 bool SetCapabilityState(GLenum cap, bool enabled);
[email protected]3a2e7c7b2010-08-06 01:12:28817
[email protected]3a03a8f2011-03-19 00:51:27818 // Check that the current frame buffer is complete. Generates error if not.
819 bool CheckFramebufferComplete(const char* func_name);
820
[email protected]939e7362010-05-13 20:49:10821 // Checks if the current program exists and is valid. If not generates the
822 // appropriate GL error. Returns true if the current program is in a usable
823 // state.
824 bool CheckCurrentProgram(const char* function_name);
825
826 // Checks if the current program exists and is valid and that location is not
827 // -1. If the current program is not valid generates the appropriate GL
828 // error. Returns true if the current program is in a usable state and
829 // location is not -1.
830 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
831
832 // Gets the type of a uniform for a location in the current program. Sets GL
833 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:36834 // program is valid and the location exists. Adjusts count so it
835 // does not overflow the uniform.
836 bool PrepForSetUniformByLocation(
837 GLint location, const char* function_name, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:10838
[email protected]b273e432010-04-12 17:23:58839 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
840 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
841
[email protected]96449d2c2009-11-25 00:01:32842 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03843 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32844
845 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03846 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32847
[email protected]3916c97e2010-02-25 03:20:50848 // Wrapper for glActiveTexture
849 void DoActiveTexture(GLenum texture_unit);
850
[email protected]ae51d192010-04-27 00:48:03851 // Wrapper for glAttachShader
852 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
853
[email protected]96449d2c2009-11-25 00:01:32854 // Wrapper for glBindBuffer since we need to track the current targets.
855 void DoBindBuffer(GLenum target, GLuint buffer);
856
[email protected]86093972010-03-11 00:13:56857 // Wrapper for glBindFramebuffer since we need to track the current targets.
858 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
859
860 // Wrapper for glBindRenderbuffer since we need to track the current targets.
861 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
862
[email protected]a93bb842010-02-16 23:03:47863 // Wrapper for glBindTexture since we need to track the current targets.
864 void DoBindTexture(GLenum target, GLuint texture);
865
[email protected]8e3e0662010-08-23 18:46:30866 // Wrapper for glBlitFramebufferEXT.
867 void DoBlitFramebufferEXT(
868 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
869 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
870 GLbitfield mask, GLenum filter);
871
[email protected]36cef8ce2010-03-16 07:34:45872 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:11873 void DoBufferData(
874 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
875
[email protected]36cef8ce2010-03-16 07:34:45876 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:11877 void DoBufferSubData(
878 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
879
[email protected]36cef8ce2010-03-16 07:34:45880 // Wrapper for glCheckFramebufferStatus
881 GLenum DoCheckFramebufferStatus(GLenum target);
882
[email protected]3a03a8f2011-03-19 00:51:27883 // Wrapper for glClear
884 void DoClear(GLbitfield mask);
885
[email protected]3a2e7c7b2010-08-06 01:12:28886 // Wrappers for clear and mask settings functions.
887 void DoClearColor(
888 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
889 void DoClearDepthf(GLclampf depth);
890 void DoClearStencil(GLint s);
891 void DoColorMask(
892 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
893 void DoDepthMask(GLboolean depth);
894 void DoStencilMask(GLuint mask);
895 void DoStencilMaskSeparate(GLenum face, GLuint mask);
896
[email protected]45bf5152010-02-12 00:11:31897 // Wrapper for glCompileShader.
898 void DoCompileShader(GLuint shader);
899
[email protected]269200b12010-11-18 22:53:06900 // Helper for DeleteSharedIdsCHROMIUM commands.
901 void DoDeleteSharedIdsCHROMIUM(
902 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:10903
[email protected]ae51d192010-04-27 00:48:03904 // Wrapper for glDetachShader
905 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
906
[email protected]3a2e7c7b2010-08-06 01:12:28907 // Wrapper for glDisable
908 void DoDisable(GLenum cap);
909
[email protected]07f54fcc2009-12-22 02:46:30910 // Wrapper for glDisableVertexAttribArray.
911 void DoDisableVertexAttribArray(GLuint index);
912
[email protected]3a2e7c7b2010-08-06 01:12:28913 // Wrapper for glEnable
914 void DoEnable(GLenum cap);
915
[email protected]07f54fcc2009-12-22 02:46:30916 // Wrapper for glEnableVertexAttribArray.
917 void DoEnableVertexAttribArray(GLuint index);
918
[email protected]36cef8ce2010-03-16 07:34:45919 // Wrapper for glFramebufferRenderbufffer.
920 void DoFramebufferRenderbuffer(
921 GLenum target, GLenum attachment, GLenum renderbuffertarget,
922 GLuint renderbuffer);
923
924 // Wrapper for glFramebufferTexture2D.
925 void DoFramebufferTexture2D(
926 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
927 GLint level);
928
[email protected]a93bb842010-02-16 23:03:47929 // Wrapper for glGenerateMipmap
930 void DoGenerateMipmap(GLenum target);
931
[email protected]269200b12010-11-18 22:53:06932 // Helper for GenSharedIdsCHROMIUM commands.
933 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:10934 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
935
[email protected]b273e432010-04-12 17:23:58936 // Wrapper for DoGetBooleanv.
937 void DoGetBooleanv(GLenum pname, GLboolean* params);
938
939 // Wrapper for DoGetFloatv.
940 void DoGetFloatv(GLenum pname, GLfloat* params);
941
[email protected]36cef8ce2010-03-16 07:34:45942 // Wrapper for glGetFramebufferAttachmentParameteriv.
943 void DoGetFramebufferAttachmentParameteriv(
944 GLenum target, GLenum attachment, GLenum pname, GLint* params);
945
[email protected]a0c3e972010-04-21 00:49:13946 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:58947 void DoGetIntegerv(GLenum pname, GLint* params);
948
[email protected]29a9eb52010-04-13 09:04:23949 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:06950 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:23951 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
952
[email protected]a0c3e972010-04-21 00:49:13953 // Wrapper for glGetProgramiv.
954 void DoGetProgramiv(
955 GLuint program_id, GLenum pname, GLint* params);
956
[email protected]36cef8ce2010-03-16 07:34:45957 // Wrapper for glRenderbufferParameteriv.
958 void DoGetRenderbufferParameteriv(
959 GLenum target, GLenum pname, GLint* params);
960
[email protected]ddd968b82010-03-02 00:44:29961 // Wrapper for glGetShaderiv
962 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
963
[email protected]b1122982010-05-17 23:04:24964 // Wrappers for glGetVertexAttrib.
965 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
966 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
967
[email protected]1958e0e2010-04-22 05:17:15968 // Wrappers for glIsXXX functions.
969 bool DoIsBuffer(GLuint client_id);
970 bool DoIsFramebuffer(GLuint client_id);
971 bool DoIsProgram(GLuint client_id);
972 bool DoIsRenderbuffer(GLuint client_id);
973 bool DoIsShader(GLuint client_id);
974 bool DoIsTexture(GLuint client_id);
975
[email protected]07f54fcc2009-12-22 02:46:30976 // Wrapper for glLinkProgram
977 void DoLinkProgram(GLuint program);
978
[email protected]269200b12010-11-18 22:53:06979 // Helper for RegisterSharedIdsCHROMIUM.
980 void DoRegisterSharedIdsCHROMIUM(
981 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:10982
[email protected]36cef8ce2010-03-16 07:34:45983 // Wrapper for glRenderbufferStorage.
984 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:03985 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:45986
[email protected]8e3e0662010-08-23 18:46:30987 // Wrapper for glRenderbufferStorageMultisampleEXT.
988 void DoRenderbufferStorageMultisample(
989 GLenum target, GLsizei samples, GLenum internalformat,
990 GLsizei width, GLsizei height);
991
[email protected]b273e432010-04-12 17:23:58992 // Wrapper for glReleaseShaderCompiler.
993 void DoReleaseShaderCompiler() { }
994
[email protected]3916c97e2010-02-25 03:20:50995 // Wrappers for glTexParameter functions.
996 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
997 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
998 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
999 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1000
1001 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1002 // spec only these 2 functions can be used to set sampler uniforms.
1003 void DoUniform1i(GLint location, GLint v0);
[email protected]939e7362010-05-13 20:49:101004 void DoUniform1iv(GLint location, GLsizei count, const GLint* value);
[email protected]43c2f1f2011-03-25 18:35:361005 void DoUniform2iv(GLint location, GLsizei count, const GLint* value);
1006 void DoUniform3iv(GLint location, GLsizei count, const GLint* value);
1007 void DoUniform4iv(GLint location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101008
1009 // Wrappers for glUniformfv because some drivers don't correctly accept
1010 // bool uniforms.
1011 void DoUniform1fv(GLint location, GLsizei count, const GLfloat* value);
1012 void DoUniform2fv(GLint location, GLsizei count, const GLfloat* value);
1013 void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value);
1014 void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501015
[email protected]43c2f1f2011-03-25 18:35:361016 void DoUniformMatrix2fv(
1017 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1018 void DoUniformMatrix3fv(
1019 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1020 void DoUniformMatrix4fv(
1021 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1022
[email protected]b1122982010-05-17 23:04:241023 // Wrappers for glVertexAttrib??
1024 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1025 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1026 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1027 void DoVertexAttrib4f(
1028 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1029 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1030 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1031 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1032 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1033
[email protected]07f54fcc2009-12-22 02:46:301034 // Wrapper for glUseProgram
1035 void DoUseProgram(GLuint program);
1036
[email protected]ae51d192010-04-27 00:48:031037 // Wrapper for glValidateProgram.
1038 void DoValidateProgram(GLuint program_client_id);
1039
[email protected]4e8a5b122010-05-08 22:00:101040 // Gets the number of values that will be returned by glGetXXX. Returns
1041 // false if pname is unknown.
1042 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1043
[email protected]96449d2c2009-11-25 00:01:321044 // Gets the GLError through our wrapper.
1045 GLenum GetGLError();
1046
[email protected]1002c2d2011-06-28 22:39:041047 // Gets the GLError and stores it in our wrapper. Effectively
1048 // this lets us peek at the error without losing it.
1049 GLenum PeekGLError();
1050
[email protected]96449d2c2009-11-25 00:01:321051 // Sets our wrapper for the GLError.
[email protected]8eee29c2010-04-29 03:38:291052 void SetGLError(GLenum error, const char* msg);
[email protected]96449d2c2009-11-25 00:01:321053
[email protected]07f54fcc2009-12-22 02:46:301054 // Copies the real GL errors to the wrapper. This is so we can
1055 // make sure there are no native GL errors before calling some GL function
1056 // so that on return we know any error generated was for that specific
1057 // command.
1058 void CopyRealGLErrorsToWrapper();
1059
[email protected]6217d392010-03-25 22:08:351060 // Clear all real GL errors. This is to prevent the client from seeing any
1061 // errors caused by GL calls that it was not responsible for issuing.
1062 void ClearRealGLErrors();
1063
[email protected]07f54fcc2009-12-22 02:46:301064 // Checks if the current program and vertex attributes are valid for drawing.
1065 bool IsDrawValid(GLuint max_vertex_accessed);
1066
[email protected]b1122982010-05-17 23:04:241067 // Returns true if attrib0 was simulated.
1068 bool SimulateAttrib0(GLuint max_vertex_accessed);
1069 void RestoreStateForSimulatedAttrib0();
1070
[email protected]ef526492010-06-02 23:12:251071 // Returns true if textures were set.
1072 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501073 void RestoreStateForNonRenderableTextures();
1074
[email protected]8fbedc02010-11-18 18:43:401075 // Returns true if GL_FIXED attribs were simulated.
1076 bool SimulateFixedAttribs(GLuint max_vertex_accessed, bool* simulated);
1077 void RestoreStateForSimulatedFixedAttribs();
1078
[email protected]07f54fcc2009-12-22 02:46:301079 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501080 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301081 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501082 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1083 bound_array_buffer_ : bound_element_array_buffer_;
1084 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:301085 }
1086
[email protected]a93bb842010-02-16 23:03:471087 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501088 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1089 TextureUnit& unit = texture_units_[active_texture_unit_];
1090 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471091 switch (target) {
1092 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501093 info = unit.bound_texture_2d;
1094 break;
[email protected]a93bb842010-02-16 23:03:471095 case GL_TEXTURE_CUBE_MAP:
1096 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1097 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1098 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1099 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1100 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1101 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501102 info = unit.bound_texture_cube_map;
1103 break;
[email protected]61eeb33f2011-07-26 15:30:311104 case GL_TEXTURE_EXTERNAL_OES:
1105 info = unit.bound_texture_external_oes;
1106 break;
[email protected]1aef98132010-02-23 18:00:071107 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
1108 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
1109 // because |texture_| is used by the FBO rendering mechanism for readback
1110 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:471111 default:
1112 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501113 return NULL;
[email protected]a93bb842010-02-16 23:03:471114 }
[email protected]3916c97e2010-02-25 03:20:501115 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:471116 }
1117
[email protected]61eeb33f2011-07-26 15:30:311118 GLenum GetBindTargetForSamplerType(GLenum type) {
1119 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1120 type == GL_SAMPLER_EXTERNAL_OES);
1121 return type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
1122 (type == GL_SAMPLER_EXTERNAL_OES ? GL_TEXTURE_EXTERNAL_OES :
1123 GL_TEXTURE_CUBE_MAP);
1124 }
1125
[email protected]8e3e0662010-08-23 18:46:301126 // Gets the framebuffer info for a particular target.
1127 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1128 GLenum target) {
1129 FramebufferManager::FramebufferInfo* info = NULL;
1130 switch (target) {
1131 case GL_FRAMEBUFFER:
1132 case GL_DRAW_FRAMEBUFFER:
1133 info = bound_draw_framebuffer_;
1134 break;
1135 case GL_READ_FRAMEBUFFER:
1136 info = bound_read_framebuffer_;
1137 break;
1138 default:
1139 NOTREACHED();
1140 break;
1141 }
1142 return (info && !info->IsDeleted()) ? info : NULL;
1143 }
1144
[email protected]f7b85372010-02-03 01:11:371145 // Validates the program and location for a glGetUniform call and returns
1146 // a SizeResult setup to receive the result. Returns true if glGetUniform
1147 // should be called.
1148 bool GetUniformSetup(
1149 GLuint program, GLint location,
1150 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:101151 error::Error* error, GLuint* service_id, void** result,
1152 GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371153
[email protected]38d139d2011-07-14 00:38:431154 // Returns true if the context was just lost due to e.g. GL_ARB_robustness.
1155 bool WasContextLost();
1156
[email protected]96449d2c2009-11-25 00:01:321157 // Generate a member function prototype for each command in an automated and
1158 // typesafe way.
1159 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141160 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191161 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321162 const gles2::name& args); \
1163
1164 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1165
1166 #undef GLES2_CMD_OP
1167
[email protected]2f2d7042010-04-14 21:45:581168 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381169 scoped_refptr<gfx::GLSurface> surface_;
1170 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021171
[email protected]a3ded6d2010-10-19 06:44:391172 // The ContextGroup for this decoder uses to track resources.
1173 ContextGroup::Ref group_;
1174
[email protected]6217d392010-03-25 22:08:351175 // A parent decoder can access this decoders saved offscreen frame buffer.
1176 // The parent pointer is reset if the parent is destroyed.
1177 base::WeakPtr<GLES2DecoderImpl> parent_;
1178
[email protected]34ff8b0c2010-10-01 20:06:021179 // Current width and height of the offscreen frame buffer.
1180 gfx::Size offscreen_size_;
1181
[email protected]96449d2c2009-11-25 00:01:321182 // Current GL error bits.
1183 uint32 error_bits_;
1184
[email protected]96449d2c2009-11-25 00:01:321185 // Util to help with GL.
1186 GLES2Util util_;
1187
1188 // pack alignment as last set by glPixelStorei
1189 GLint pack_alignment_;
1190
1191 // unpack alignment as last set by glPixelStorei
1192 GLint unpack_alignment_;
1193
1194 // The currently bound array buffer. If this is 0 it is illegal to call
1195 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501196 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321197
1198 // The currently bound element array buffer. If this is 0 it is illegal
1199 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501200 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301201
[email protected]f39f4b3f2010-05-12 17:04:081202 // Class that manages vertex attribs.
1203 VertexAttribManager vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301204
[email protected]b1122982010-05-17 23:04:241205 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1206 GLuint attrib_0_buffer_id_;
1207
1208 // The value currently in attrib_0.
1209 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1210
[email protected]fc753442011-02-04 19:49:491211 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1212 bool attrib_0_buffer_matches_value_;
1213
[email protected]b1122982010-05-17 23:04:241214 // The size of attrib 0.
1215 GLsizei attrib_0_size_;
1216
[email protected]8fbedc02010-11-18 18:43:401217 // The buffer used to simulate GL_FIXED attribs.
1218 GLuint fixed_attrib_buffer_id_;
1219
1220 // The size of fiixed attrib buffer.
1221 GLsizei fixed_attrib_buffer_size_;
1222
[email protected]3916c97e2010-02-25 03:20:501223 // Current active texture by 0 - n index.
1224 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1225 // be 2.
1226 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301227
[email protected]3916c97e2010-02-25 03:20:501228 // Which textures are bound to texture units through glActiveTexture.
1229 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471230
[email protected]3a2e7c7b2010-08-06 01:12:281231 // state saved for clearing so we can clear render buffers and then
1232 // restore to these values.
1233 GLclampf clear_red_;
1234 GLclampf clear_green_;
1235 GLclampf clear_blue_;
1236 GLclampf clear_alpha_;
1237 GLboolean mask_red_;
1238 GLboolean mask_green_;
1239 GLboolean mask_blue_;
1240 GLboolean mask_alpha_;
1241 GLint clear_stencil_;
1242 GLuint mask_stencil_front_;
1243 GLuint mask_stencil_back_;
1244 GLclampf clear_depth_;
1245 GLboolean mask_depth_;
1246 bool enable_scissor_test_;
[email protected]297ca1c2011-06-20 23:08:461247 bool enable_depth_test_;
1248 bool enable_stencil_test_;
1249 bool state_dirty_;
[email protected]3a2e7c7b2010-08-06 01:12:281250
[email protected]1d32bc82010-01-13 22:06:461251 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501252 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301253
[email protected]8e3e0662010-08-23 18:46:301254 // The currently bound framebuffers
1255 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1256 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561257
1258 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081259 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561260
[email protected]b9363b22010-06-09 22:06:151261 // The offscreen frame buffer that the client renders to. With EGL, the
1262 // depth and stencil buffers are separate. With regular GL there is a single
1263 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1264 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351265 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1266 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021267 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151268 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1269 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021270 GLenum offscreen_target_color_format_;
1271 GLenum offscreen_target_depth_format_;
1272 GLenum offscreen_target_stencil_format_;
1273 GLsizei offscreen_target_samples_;
[email protected]6217d392010-03-25 22:08:351274
[email protected]de26b3c2011-08-03 21:54:271275 // The copy that is saved when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021276 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351277 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]de26b3c2011-08-03 21:54:271278
1279 // The copy that is used as the destination for multi-sample resolves.
1280 scoped_ptr<FrameBuffer> offscreen_resolved_frame_buffer_;
1281 scoped_ptr<Texture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051282 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351283
[email protected]7ff86b92010-11-25 17:50:001284 scoped_ptr<Callback1<gfx::Size>::Type> resize_callback_;
[email protected]22f320a2011-08-30 01:17:001285
1286#if defined(OS_MACOSX)
[email protected]43f28f832010-02-03 02:28:481287 scoped_ptr<Callback0::Type> swap_buffers_callback_;
[email protected]22f320a2011-08-30 01:17:001288#endif
[email protected]43f28f832010-02-03 02:28:481289
[email protected]32fe9aa2011-01-21 23:47:131290 // The format of the back buffer_
1291 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461292 bool back_buffer_has_depth_;
1293 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131294
[email protected]473c01ccb2011-06-07 01:33:301295 bool teximage2d_faster_than_texsubimage2d_;
1296 bool bufferdata_faster_than_buffersubdata_;
1297
[email protected]8eee29c2010-04-29 03:38:291298 // The last error message set.
1299 std::string last_error_;
1300
[email protected]a3a93e7b2010-08-28 00:48:561301 // The current decoder error.
1302 error::Error current_decoder_error_;
1303
[email protected]b1d2dcb2010-05-17 19:24:181304 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451305 scoped_ptr<ShaderTranslator> vertex_translator_;
1306 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181307
[email protected]c410da802011-03-14 19:17:411308 DisallowedExtensions disallowed_extensions_;
1309
[email protected]915a59a12010-09-30 21:29:111310 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051311 const Validators* validators_;
[email protected]915a59a12010-09-30 21:29:111312 FeatureInfo* feature_info_;
[email protected]9438b012010-06-15 22:55:051313
[email protected]b493ee622011-04-13 23:52:001314 // This indicates all the following texSubImage2D calls that are part of the
1315 // failed texImage2D call should be ignored.
1316 bool tex_image_2d_failed_;
1317
[email protected]65225772011-05-12 21:10:241318 int frame_number_;
1319
[email protected]38d139d2011-07-14 00:38:431320 bool has_arb_robustness_;
1321 GLenum reset_status_;
1322
[email protected]75c023c2011-08-22 23:54:511323 bool needs_mac_nvidia_driver_workaround_;
1324
[email protected]96449d2c2009-11-25 00:01:321325 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1326};
1327
[email protected]6217d392010-03-25 22:08:351328ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1329 : decoder_(decoder) {
1330 decoder_->CopyRealGLErrorsToWrapper();
1331}
1332
1333ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1334 decoder_->ClearRealGLErrors();
1335}
1336
1337ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1338 GLuint id)
1339 : decoder_(decoder) {
1340 ScopedGLErrorSuppressor suppressor(decoder_);
1341
1342 // TODO(apatrick): Check if there are any other states that need to be reset
1343 // before binding a new texture.
1344 glActiveTexture(GL_TEXTURE0);
1345 glBindTexture(GL_TEXTURE_2D, id);
1346}
1347
1348ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1349 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301350 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351351}
1352
1353ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1354 GLuint id)
1355 : decoder_(decoder) {
1356 ScopedGLErrorSuppressor suppressor(decoder_);
1357 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1358}
1359
1360ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1361 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301362 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351363}
1364
1365ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1366 GLuint id)
1367 : decoder_(decoder) {
1368 ScopedGLErrorSuppressor suppressor(decoder_);
1369 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1370}
1371
1372ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1373 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301374 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351375}
1376
[email protected]34ff8b0c2010-10-01 20:06:021377ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271378 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521379 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021380 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1381 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]c0701082011-04-20 00:34:521382 (!decoder_->bound_read_framebuffer_.get() ||
1383 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021384 if (!resolve_and_bind_)
1385 return;
1386
1387 ScopedGLErrorSuppressor suppressor(decoder_);
1388 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1389 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271390 GLuint targetid;
1391 if (internal) {
1392 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1393 decoder_->offscreen_resolved_frame_buffer_.reset(
1394 new FrameBuffer(decoder_));
1395 decoder_->offscreen_resolved_frame_buffer_->Create();
1396 decoder_->offscreen_resolved_color_texture_.reset(new Texture(decoder_));
1397 decoder_->offscreen_resolved_color_texture_->Create();
1398
1399 DCHECK(decoder_->offscreen_saved_color_format_);
1400 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1401 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_);
1402
1403 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1404 decoder_->offscreen_resolved_color_texture_.get());
1405 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1406 GL_FRAMEBUFFER_COMPLETE) {
1407 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1408 << "because offscreen resolved FBO was incomplete.";
1409 return;
1410 }
1411 }
1412 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1413 } else {
1414 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1415 }
1416 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021417 const int width = decoder_->offscreen_size_.width();
1418 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181419 glDisable(GL_SCISSOR_TEST);
[email protected]34ff8b0c2010-10-01 20:06:021420 if (IsAngle()) {
1421 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1422 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1423 } else {
1424 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1425 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1426 }
[email protected]de26b3c2011-08-03 21:54:271427 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021428}
1429
1430ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1431 if (!resolve_and_bind_)
1432 return;
1433
1434 ScopedGLErrorSuppressor suppressor(decoder_);
1435 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181436 if (decoder_->enable_scissor_test_) {
1437 glEnable(GL_SCISSOR_TEST);
1438 }
[email protected]34ff8b0c2010-10-01 20:06:021439}
1440
[email protected]6217d392010-03-25 22:08:351441Texture::Texture(GLES2DecoderImpl* decoder)
1442 : decoder_(decoder),
[email protected]3a4d0c52011-06-29 23:11:581443 id_(0) {
[email protected]6217d392010-03-25 22:08:351444}
1445
1446Texture::~Texture() {
1447 // This does not destroy the render texture because that would require that
1448 // the associated GL context was current. Just check that it was explicitly
1449 // destroyed.
1450 DCHECK_EQ(id_, 0u);
1451}
1452
1453void Texture::Create() {
1454 ScopedGLErrorSuppressor suppressor(decoder_);
1455 Destroy();
1456 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581457 ScopedTexture2DBinder binder(decoder_, id_);
1458 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1459 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1460 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1461 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]6217d392010-03-25 22:08:351462}
1463
[email protected]34ff8b0c2010-10-01 20:06:021464bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351465 DCHECK_NE(id_, 0u);
1466 ScopedGLErrorSuppressor suppressor(decoder_);
1467 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]6217d392010-03-25 22:08:351468
1469 glTexImage2D(GL_TEXTURE_2D,
1470 0, // mip level
[email protected]34ff8b0c2010-10-01 20:06:021471 format,
[email protected]6217d392010-03-25 22:08:351472 size.width(),
1473 size.height(),
1474 0, // border
[email protected]34ff8b0c2010-10-01 20:06:021475 format,
[email protected]6217d392010-03-25 22:08:351476 GL_UNSIGNED_BYTE,
1477 NULL);
1478
[email protected]d37231fa2010-04-09 21:16:021479 size_ = size;
1480
[email protected]6217d392010-03-25 22:08:351481 return glGetError() == GL_NO_ERROR;
1482}
1483
[email protected]3a4d0c52011-06-29 23:11:581484void Texture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351485 DCHECK_NE(id_, 0u);
1486 ScopedGLErrorSuppressor suppressor(decoder_);
1487 ScopedTexture2DBinder binder(decoder_, id_);
1488 glCopyTexImage2D(GL_TEXTURE_2D,
1489 0, // level
[email protected]3a4d0c52011-06-29 23:11:581490 format,
[email protected]6217d392010-03-25 22:08:351491 0, 0,
1492 size.width(),
1493 size.height(),
1494 0); // border
1495}
1496
1497void Texture::Destroy() {
1498 if (id_ != 0) {
1499 ScopedGLErrorSuppressor suppressor(decoder_);
1500 glDeleteTextures(1, &id_);
1501 id_ = 0;
1502 }
1503}
1504
[email protected]97872062010-11-03 19:07:051505void Texture::Invalidate() {
1506 id_ = 0;
1507}
1508
[email protected]6217d392010-03-25 22:08:351509RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1510 : decoder_(decoder),
1511 id_(0) {
1512}
1513
1514RenderBuffer::~RenderBuffer() {
1515 // This does not destroy the render buffer because that would require that
1516 // the associated GL context was current. Just check that it was explicitly
1517 // destroyed.
1518 DCHECK_EQ(id_, 0u);
1519}
1520
1521void RenderBuffer::Create() {
1522 ScopedGLErrorSuppressor suppressor(decoder_);
1523 Destroy();
1524 glGenRenderbuffersEXT(1, &id_);
1525}
1526
[email protected]34ff8b0c2010-10-01 20:06:021527bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1528 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351529 ScopedGLErrorSuppressor suppressor(decoder_);
1530 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021531 if (samples <= 1) {
1532 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1533 format,
1534 size.width(),
1535 size.height());
1536 } else {
1537 if (IsAngle()) {
1538 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1539 samples,
1540 format,
1541 size.width(),
1542 size.height());
1543 } else {
1544 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1545 samples,
1546 format,
1547 size.width(),
1548 size.height());
1549 }
1550 }
[email protected]6217d392010-03-25 22:08:351551 return glGetError() == GL_NO_ERROR;
1552}
1553
1554void RenderBuffer::Destroy() {
1555 if (id_ != 0) {
1556 ScopedGLErrorSuppressor suppressor(decoder_);
1557 glDeleteRenderbuffersEXT(1, &id_);
1558 id_ = 0;
1559 }
1560}
1561
[email protected]97872062010-11-03 19:07:051562void RenderBuffer::Invalidate() {
1563 id_ = 0;
1564}
1565
[email protected]6217d392010-03-25 22:08:351566FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1567 : decoder_(decoder),
1568 id_(0) {
1569}
1570
1571FrameBuffer::~FrameBuffer() {
1572 // This does not destroy the frame buffer because that would require that
1573 // the associated GL context was current. Just check that it was explicitly
1574 // destroyed.
1575 DCHECK_EQ(id_, 0u);
1576}
1577
1578void FrameBuffer::Create() {
1579 ScopedGLErrorSuppressor suppressor(decoder_);
1580 Destroy();
1581 glGenFramebuffersEXT(1, &id_);
1582}
1583
1584void FrameBuffer::AttachRenderTexture(Texture* texture) {
1585 DCHECK_NE(id_, 0u);
1586 ScopedGLErrorSuppressor suppressor(decoder_);
1587 ScopedFrameBufferBinder binder(decoder_, id_);
1588 GLuint attach_id = texture ? texture->id() : 0;
1589 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1590 GL_COLOR_ATTACHMENT0,
1591 GL_TEXTURE_2D,
1592 attach_id,
1593 0);
1594}
1595
[email protected]b9363b22010-06-09 22:06:151596void FrameBuffer::AttachRenderBuffer(GLenum target,
1597 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351598 DCHECK_NE(id_, 0u);
1599 ScopedGLErrorSuppressor suppressor(decoder_);
1600 ScopedFrameBufferBinder binder(decoder_, id_);
1601 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1602 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151603 target,
[email protected]6217d392010-03-25 22:08:351604 GL_RENDERBUFFER,
1605 attach_id);
1606}
1607
1608void FrameBuffer::Clear(GLbitfield buffers) {
1609 ScopedGLErrorSuppressor suppressor(decoder_);
1610 ScopedFrameBufferBinder binder(decoder_, id_);
1611 glClear(buffers);
1612}
1613
1614void FrameBuffer::Destroy() {
1615 if (id_ != 0) {
1616 ScopedGLErrorSuppressor suppressor(decoder_);
1617 glDeleteFramebuffersEXT(1, &id_);
1618 id_ = 0;
1619 }
1620}
1621
[email protected]97872062010-11-03 19:07:051622void FrameBuffer::Invalidate() {
1623 id_ = 0;
1624}
1625
[email protected]6217d392010-03-25 22:08:351626GLenum FrameBuffer::CheckStatus() {
1627 DCHECK_NE(id_, 0u);
1628 ScopedGLErrorSuppressor suppressor(decoder_);
1629 ScopedFrameBufferBinder binder(decoder_, id_);
1630 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1631}
1632
[email protected]aa7666122011-09-02 19:45:521633GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1634 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321635}
1636
[email protected]aa7666122011-09-02 19:45:521637GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391638 : GLES2Decoder(),
[email protected]3b1ecc262011-08-03 22:49:571639 group_(group),
[email protected]96449d2c2009-11-25 00:01:321640 error_bits_(0),
[email protected]96449d2c2009-11-25 00:01:321641 pack_alignment_(4),
1642 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241643 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491644 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241645 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401646 fixed_attrib_buffer_id_(0),
1647 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501648 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281649 clear_red_(0),
1650 clear_green_(0),
1651 clear_blue_(0),
1652 clear_alpha_(0),
1653 mask_red_(true),
1654 mask_green_(true),
1655 mask_blue_(true),
1656 mask_alpha_(true),
1657 clear_stencil_(0),
1658 mask_stencil_front_(-1),
1659 mask_stencil_back_(-1),
1660 clear_depth_(1.0f),
1661 mask_depth_(true),
1662 enable_scissor_test_(false),
[email protected]297ca1c2011-06-20 23:08:461663 enable_depth_test_(false),
1664 enable_stencil_test_(false),
1665 state_dirty_(true),
[email protected]34ff8b0c2010-10-01 20:06:021666 offscreen_target_color_format_(0),
1667 offscreen_target_depth_format_(0),
1668 offscreen_target_stencil_format_(0),
1669 offscreen_target_samples_(0),
[email protected]97872062010-11-03 19:07:051670 offscreen_saved_color_format_(0),
[email protected]32fe9aa2011-01-21 23:47:131671 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:461672 back_buffer_has_depth_(false),
1673 back_buffer_has_stencil_(false),
[email protected]473c01ccb2011-06-07 01:33:301674 teximage2d_faster_than_texsubimage2d_(true),
1675 bufferdata_faster_than_buffersubdata_(true),
[email protected]a3a93e7b2010-08-28 00:48:561676 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051677 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111678 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001679 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241680 tex_image_2d_failed_(false),
[email protected]38d139d2011-07-14 00:38:431681 frame_number_(0),
1682 has_arb_robustness_(false),
[email protected]75c023c2011-08-22 23:54:511683 reset_status_(GL_NO_ERROR),
1684 needs_mac_nvidia_driver_workaround_(false) {
[email protected]3b1ecc262011-08-03 22:49:571685 DCHECK(group);
1686
[email protected]b1122982010-05-17 23:04:241687 attrib_0_value_.v[0] = 0.0f;
1688 attrib_0_value_.v[1] = 0.0f;
1689 attrib_0_value_.v[2] = 0.0f;
1690 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151691
[email protected]c2f8c8402010-12-06 18:07:241692 // The shader translator is used for WebGL even when running on EGL
1693 // because additional restrictions are needed (like only enabling
1694 // GL_OES_standard_derivatives on demand). It is used for the unit
1695 // tests because
1696 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1697 // empty string to CompileShader and this is not a valid shader.
1698 // TODO(apatrick): fix this test.
1699 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
1700 !feature_info_->feature_flags().chromium_webglsl) ||
[email protected]b9363b22010-06-09 22:06:151701 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) {
1702 use_shader_translator_ = false;
1703 }
[email protected]473c01ccb2011-06-07 01:33:301704
1705 // TODO(gman): Consider setting these based on GPU and/or driver.
1706 if (IsAngle()) {
1707 teximage2d_faster_than_texsubimage2d_ = false;
1708 bufferdata_faster_than_buffersubdata_ = false;
1709 }
[email protected]96449d2c2009-11-25 00:01:321710}
1711
[email protected]c410da802011-03-14 19:17:411712bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:381713 const scoped_refptr<gfx::GLSurface>& surface,
1714 const scoped_refptr<gfx::GLContext>& context,
[email protected]c410da802011-03-14 19:17:411715 const gfx::Size& size,
1716 const DisallowedExtensions& disallowed_extensions,
1717 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:241718 const std::vector<int32>& attribs) {
[email protected]4bedba72010-04-20 22:08:541719 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301720 DCHECK(!context_.get());
1721
[email protected]fbe20372011-06-01 01:46:381722 // Take ownership of the GLSurface. TODO(apatrick): once the parent / child
1723 // context is retired, the decoder should not take an initial surface as
1724 // an argument to this function.
1725 // Maybe create a short lived offscreen GLSurface for the purpose of
1726 // initializing the decoder's GLContext.
1727 surface_ = surface;
[email protected]f62a5ab2011-05-23 20:34:151728
[email protected]66791e382010-07-14 20:48:301729 // Take ownership of the GLContext.
[email protected]fbe20372011-06-01 01:46:381730 context_ = context;
[email protected]d37231fa2010-04-09 21:16:021731
[email protected]246a70452010-03-05 21:53:501732 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:011733 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
1734 << "MakeCurrent failed.";
[email protected]246a70452010-03-05 21:53:501735 Destroy();
1736 return false;
[email protected]eb54a562010-01-20 21:55:181737 }
1738
[email protected]c410da802011-03-14 19:17:411739 if (!group_->Initialize(disallowed_extensions, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:221740 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:391741 << "failed to initialize.";
1742 Destroy();
[email protected]ae1741092010-11-17 19:16:031743 return false;
[email protected]a3ded6d2010-10-19 06:44:391744 }
1745
[email protected]246a70452010-03-05 21:53:501746 CHECK_GL_ERROR();
[email protected]c410da802011-03-14 19:17:411747 disallowed_extensions_ = disallowed_extensions;
[email protected]246a70452010-03-05 21:53:501748
[email protected]f39f4b3f2010-05-12 17:04:081749 vertex_attrib_manager_.Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:321750
[email protected]302ce6d2011-07-07 23:28:111751 util_.set_num_compressed_texture_formats(
1752 validators_->compressed_texture_format.GetValues().size());
1753
[email protected]1071e572011-02-09 20:00:121754 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1755 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
1756 // OpenGL ES 2.0 does not have this issue.
1757 glEnableVertexAttribArray(0);
1758 }
[email protected]b1122982010-05-17 23:04:241759 glGenBuffersARB(1, &attrib_0_buffer_id_);
1760 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
1761 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
1762 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:401763 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:081764
[email protected]246a70452010-03-05 21:53:501765 texture_units_.reset(
1766 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:151767 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:491768 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:311769 // We want the last bind to be 2D.
1770 TextureManager::TextureInfo* info;
1771 if (feature_info_->feature_flags().oes_egl_image_external) {
1772 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_EXTERNAL_OES);
1773 texture_units_[tt].bound_texture_external_oes = info;
1774 glBindTexture(GL_TEXTURE_EXTERNAL_OES, info->service_id());
1775 }
1776 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:491777 texture_units_[tt].bound_texture_cube_map = info;
1778 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
1779 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
1780 texture_units_[tt].bound_texture_2d = info;
1781 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:151782 }
[email protected]00f893d2010-08-24 18:55:491783 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:501784 CHECK_GL_ERROR();
1785
[email protected]297ca1c2011-06-20 23:08:461786 ContextCreationAttribParser attrib_parser;
1787 if (!attrib_parser.Parse(attribs))
1788 return false;
[email protected]41c56362011-06-14 16:47:431789
[email protected]297ca1c2011-06-20 23:08:461790 // These are NOT if the back buffer has these proprorties. They are
1791 // if we want the command buffer to enforce them regardless of what
1792 // the real backbuffer is assuming the real back buffer gives us more than
1793 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
1794 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
1795 // can't do anything about that.
1796
1797 GLint v = 0;
1798 glGetIntegerv(GL_ALPHA_BITS, &v);
1799 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
1800 // user requested RGB then RGB. If the user did not specify a preference than
1801 // use whatever we were given. Same for DEPTH and STENCIL.
1802 back_buffer_color_format_ =
1803 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
1804 glGetIntegerv(GL_DEPTH_BITS, &v);
1805 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
1806 glGetIntegerv(GL_STENCIL_BITS, &v);
1807 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
1808
1809 if (surface_->IsOffscreen()) {
[email protected]34ff8b0c2010-10-01 20:06:021810 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:541811 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:021812 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
1813 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:431814 // max_sample_count must be initialized to a sane value. If
1815 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
1816 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:021817 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
1818 offscreen_target_samples_ = std::min(attrib_parser.samples_,
1819 max_sample_count);
1820 } else {
1821 offscreen_target_samples_ = 1;
1822 }
1823
1824 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
1825 const bool rgb8_supported =
1826 context_->HasExtension("GL_OES_rgb8_rgba8");
1827 // The only available default render buffer formats in GLES2 have very
1828 // little precision. Don't enable multisampling unless 8-bit render
1829 // buffer formats are available--instead fall back to 8-bit textures.
1830 if (rgb8_supported && offscreen_target_samples_ > 1) {
1831 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1832 GL_RGBA8 : GL_RGB8;
1833 } else {
1834 offscreen_target_samples_ = 1;
1835 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1836 GL_RGBA : GL_RGB;
1837 }
1838
1839 // ANGLE only supports packed depth/stencil formats, so use it if it is
1840 // available.
1841 const bool depth24_stencil8_supported =
1842 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271843 VLOG(1) << "GL_OES_packed_depth_stencil "
1844 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:001845 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1846 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021847 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1848 offscreen_target_stencil_format_ = 0;
1849 } else {
1850 // It may be the case that this depth/stencil combination is not
1851 // supported, but this will be checked later by CheckFramebufferStatus.
1852 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1853 GL_DEPTH_COMPONENT16 : 0;
1854 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1855 GL_STENCIL_INDEX8 : 0;
1856 }
1857 } else {
1858 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1859 GL_RGBA : GL_RGB;
1860
1861 // If depth is requested at all, use the packed depth stencil format if
1862 // it's available, as some desktop GL drivers don't support any non-packed
1863 // formats for depth attachments.
1864 const bool depth24_stencil8_supported =
1865 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271866 VLOG(1) << "GL_EXT_packed_depth_stencil "
1867 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:021868
[email protected]71ee3642010-10-14 18:08:001869 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1870 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021871 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1872 offscreen_target_stencil_format_ = 0;
1873 } else {
1874 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1875 GL_DEPTH_COMPONENT : 0;
1876 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1877 GL_STENCIL_INDEX : 0;
1878 }
1879 }
1880
[email protected]97872062010-11-03 19:07:051881 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
1882 GL_RGBA : GL_RGB;
1883
[email protected]6217d392010-03-25 22:08:351884 // Create the target frame buffer. This is the one that the client renders
1885 // directly to.
1886 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
1887 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021888 // Due to GLES2 format limitations, either the color texture (for
1889 // non-multisampling) or the color render buffer (for multisampling) will be
1890 // attached to the offscreen frame buffer. The render buffer has more
1891 // limited formats available to it, but the texture can't do multisampling.
1892 if (IsOffscreenBufferMultisampled()) {
1893 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
1894 offscreen_target_color_render_buffer_->Create();
1895 } else {
1896 offscreen_target_color_texture_.reset(new Texture(this));
1897 offscreen_target_color_texture_->Create();
1898 }
1899 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151900 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021901 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151902 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:351903
1904 // Create the saved offscreen texture. The target frame buffer is copied
1905 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021906 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
1907 offscreen_saved_frame_buffer_->Create();
1908 //
[email protected]6217d392010-03-25 22:08:351909 offscreen_saved_color_texture_.reset(new Texture(this));
1910 offscreen_saved_color_texture_->Create();
1911
[email protected]6217d392010-03-25 22:08:351912 // Allocate the render buffers at their initial size and check the status
1913 // of the frame buffers is okay.
[email protected]799b4b22011-08-22 17:09:591914 if (!ResizeOffscreenFrameBuffer(size)) {
[email protected]d0498742010-09-20 20:27:011915 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:351916 Destroy();
1917 return false;
1918 }
1919
1920 // Bind to the new default frame buffer (the offscreen target frame buffer).
1921 // This should now be associated with ID zero.
1922 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
1923 }
1924
[email protected]76a0ee102010-04-07 21:03:041925 // OpenGL ES 2.0 implicitly enables the desktop GL capability
1926 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
1927 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:371928 // mailing list archives. It also implicitly enables the desktop GL
1929 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
1930 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:151931 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1932 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:371933 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:151934 }
[email protected]de17df392010-04-23 21:09:411935
[email protected]38d139d2011-07-14 00:38:431936 has_arb_robustness_ = context->HasExtension("GL_ARB_robustness");
1937
[email protected]75c023c2011-08-22 23:54:511938#if defined(OS_MACOSX)
1939 const char* vendor_str = reinterpret_cast<const char*>(
1940 glGetString(GL_VENDOR));
1941 needs_mac_nvidia_driver_workaround_ =
[email protected]e6ad33a2011-08-24 23:44:031942 vendor_str && strstr(vendor_str, "NVIDIA");
[email protected]75c023c2011-08-22 23:54:511943#endif
1944
[email protected]c2f8c8402010-12-06 18:07:241945 if (!InitializeShaderTranslator()) {
1946 return false;
[email protected]de17df392010-04-23 21:09:411947 }
[email protected]76a0ee102010-04-07 21:03:041948
[email protected]246a70452010-03-05 21:53:501949 return true;
[email protected]96449d2c2009-11-25 00:01:321950}
1951
[email protected]302ce6d2011-07-07 23:28:111952void GLES2DecoderImpl::UpdateCapabilities() {
1953 util_.set_num_compressed_texture_formats(
1954 validators_->compressed_texture_format.GetValues().size());
1955 util_.set_num_shader_binary_formats(
1956 validators_->shader_binary_format.GetValues().size());
1957}
1958
[email protected]c2f8c8402010-12-06 18:07:241959bool GLES2DecoderImpl::InitializeShaderTranslator() {
1960 // Re-check the state of use_shader_translator_ each time this is called.
1961 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
1962 feature_info_->feature_flags().chromium_webglsl &&
1963 !use_shader_translator_) {
1964 use_shader_translator_ = true;
1965 }
1966 if (!use_shader_translator_) {
1967 return true;
1968 }
1969 ShBuiltInResources resources;
1970 ShInitBuiltInResources(&resources);
1971 resources.MaxVertexAttribs = group_->max_vertex_attribs();
1972 resources.MaxVertexUniformVectors =
1973 group_->max_vertex_uniform_vectors();
1974 resources.MaxVaryingVectors = group_->max_varying_vectors();
1975 resources.MaxVertexTextureImageUnits =
1976 group_->max_vertex_texture_image_units();
1977 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
1978 resources.MaxTextureImageUnits = group_->max_texture_image_units();
1979 resources.MaxFragmentUniformVectors =
1980 group_->max_fragment_uniform_vectors();
1981 resources.MaxDrawBuffers = 1;
1982 resources.OES_standard_derivatives =
1983 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
1984 vertex_translator_.reset(new ShaderTranslator);
1985 ShShaderSpec shader_spec = feature_info_->feature_flags().chromium_webglsl ?
1986 SH_WEBGL_SPEC : SH_GLES2_SPEC;
1987 bool is_glsl_es =
1988 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
1989 if (!vertex_translator_->Init(
1990 SH_VERTEX_SHADER, shader_spec, &resources, is_glsl_es)) {
1991 LOG(ERROR) << "Could not initialize vertex shader translator.";
1992 Destroy();
1993 return false;
1994 }
1995 fragment_translator_.reset(new ShaderTranslator);
1996 if (!fragment_translator_->Init(
1997 SH_FRAGMENT_SHADER, shader_spec, &resources, is_glsl_es)) {
1998 LOG(ERROR) << "Could not initialize fragment shader translator.";
1999 Destroy();
2000 return false;
2001 }
2002 return true;
2003}
2004
[email protected]ae51d192010-04-27 00:48:032005bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472006 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032007 if (GetBufferInfo(client_ids[ii])) {
2008 return false;
2009 }
2010 }
2011 scoped_array<GLuint> service_ids(new GLuint[n]);
2012 glGenBuffersARB(n, service_ids.get());
2013 for (GLsizei ii = 0; ii < n; ++ii) {
2014 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2015 }
2016 return true;
2017}
2018
2019bool GLES2DecoderImpl::GenFramebuffersHelper(
2020 GLsizei n, const GLuint* client_ids) {
2021 for (GLsizei ii = 0; ii < n; ++ii) {
2022 if (GetFramebufferInfo(client_ids[ii])) {
2023 return false;
2024 }
2025 }
2026 scoped_array<GLuint> service_ids(new GLuint[n]);
2027 glGenFramebuffersEXT(n, service_ids.get());
2028 for (GLsizei ii = 0; ii < n; ++ii) {
2029 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2030 }
2031 return true;
2032}
2033
2034bool GLES2DecoderImpl::GenRenderbuffersHelper(
2035 GLsizei n, const GLuint* client_ids) {
2036 for (GLsizei ii = 0; ii < n; ++ii) {
2037 if (GetRenderbufferInfo(client_ids[ii])) {
2038 return false;
2039 }
2040 }
2041 scoped_array<GLuint> service_ids(new GLuint[n]);
2042 glGenRenderbuffersEXT(n, service_ids.get());
2043 for (GLsizei ii = 0; ii < n; ++ii) {
2044 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2045 }
2046 return true;
2047}
2048
2049bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2050 for (GLsizei ii = 0; ii < n; ++ii) {
2051 if (GetTextureInfo(client_ids[ii])) {
2052 return false;
2053 }
2054 }
2055 scoped_array<GLuint> service_ids(new GLuint[n]);
2056 glGenTextures(n, service_ids.get());
2057 for (GLsizei ii = 0; ii < n; ++ii) {
2058 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2059 }
2060 return true;
2061}
2062
2063void GLES2DecoderImpl::DeleteBuffersHelper(
2064 GLsizei n, const GLuint* client_ids) {
2065 for (GLsizei ii = 0; ii < n; ++ii) {
2066 BufferManager::BufferInfo* info = GetBufferInfo(client_ids[ii]);
2067 if (info) {
2068 GLuint service_id = info->service_id();
2069 glDeleteBuffersARB(1, &service_id);
2070 RemoveBufferInfo(client_ids[ii]);
2071 }
[email protected]a93bb842010-02-16 23:03:472072 }
[email protected]07f54fcc2009-12-22 02:46:302073}
2074
[email protected]ae51d192010-04-27 00:48:032075void GLES2DecoderImpl::DeleteFramebuffersHelper(
2076 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582077 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032078 FramebufferManager::FramebufferInfo* info =
2079 GetFramebufferInfo(client_ids[ii]);
2080 if (info) {
[email protected]297ca1c2011-06-20 23:08:462081 if (info == bound_draw_framebuffer_) {
2082 bound_draw_framebuffer_ = NULL;
2083 state_dirty_ = true;
2084 }
[email protected]ae51d192010-04-27 00:48:032085 GLuint service_id = info->service_id();
2086 glDeleteFramebuffersEXT(1, &service_id);
2087 RemoveFramebufferInfo(client_ids[ii]);
2088 }
[email protected]a25fa872010-03-25 02:57:582089 }
[email protected]07f54fcc2009-12-22 02:46:302090}
2091
[email protected]ae51d192010-04-27 00:48:032092void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2093 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582094 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032095 RenderbufferManager::RenderbufferInfo* info =
2096 GetRenderbufferInfo(client_ids[ii]);
2097 if (info) {
[email protected]297ca1c2011-06-20 23:08:462098 state_dirty_ = true;
[email protected]ae51d192010-04-27 00:48:032099 GLuint service_id = info->service_id();
2100 glDeleteRenderbuffersEXT(1, &service_id);
2101 RemoveRenderbufferInfo(client_ids[ii]);
2102 }
[email protected]a25fa872010-03-25 02:57:582103 }
[email protected]07f54fcc2009-12-22 02:46:302104}
2105
[email protected]ae51d192010-04-27 00:48:032106void GLES2DecoderImpl::DeleteTexturesHelper(
2107 GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472108 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032109 TextureManager::TextureInfo* info = GetTextureInfo(client_ids[ii]);
2110 if (info) {
[email protected]297ca1c2011-06-20 23:08:462111 if (info->IsAttachedToFramebuffer()) {
2112 state_dirty_ = true;
2113 }
[email protected]5f4f2a732011-07-30 00:47:552114 GLuint service_id = info->service_id();
2115 glDeleteTextures(1, &service_id);
[email protected]ae51d192010-04-27 00:48:032116 RemoveTextureInfo(client_ids[ii]);
2117 }
[email protected]a93bb842010-02-16 23:03:472118 }
[email protected]07f54fcc2009-12-22 02:46:302119}
2120
[email protected]43f28f832010-02-03 02:28:482121// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322122
[email protected]eb54a562010-01-20 21:55:182123bool GLES2DecoderImpl::MakeCurrent() {
[email protected]38d139d2011-07-14 00:38:432124 bool result = context_.get() ? context_->MakeCurrent(surface_.get()) : false;
2125 if (result && WasContextLost()) {
2126 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2127 result = false;
2128 }
2129
2130 return result;
[email protected]eb54a562010-01-20 21:55:182131}
2132
[email protected]8e3e0662010-08-23 18:46:302133void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
2134 glBindRenderbufferEXT(
2135 GL_RENDERBUFFER,
2136 bound_renderbuffer_ ? bound_renderbuffer_->service_id() : 0);
2137}
2138
2139static void RebindCurrentFramebuffer(
2140 GLenum target,
2141 FramebufferManager::FramebufferInfo* info,
2142 FrameBuffer* offscreen_frame_buffer) {
2143 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462144
[email protected]8e3e0662010-08-23 18:46:302145 if (framebuffer_id == 0 && offscreen_frame_buffer) {
2146 framebuffer_id = offscreen_frame_buffer->id();
2147 }
[email protected]297ca1c2011-06-20 23:08:462148
[email protected]8e3e0662010-08-23 18:46:302149 glBindFramebufferEXT(target, framebuffer_id);
2150}
2151
2152void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]297ca1c2011-06-20 23:08:462153 state_dirty_ = true;
2154
[email protected]a3ded6d2010-10-19 06:44:392155 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302156 RebindCurrentFramebuffer(
2157 GL_FRAMEBUFFER,
2158 bound_draw_framebuffer_.get(),
2159 offscreen_target_frame_buffer_.get());
2160 } else {
2161 RebindCurrentFramebuffer(
2162 GL_READ_FRAMEBUFFER_EXT,
2163 bound_read_framebuffer_.get(),
2164 offscreen_target_frame_buffer_.get());
2165 RebindCurrentFramebuffer(
2166 GL_DRAW_FRAMEBUFFER_EXT,
2167 bound_draw_framebuffer_.get(),
2168 offscreen_target_frame_buffer_.get());
2169 }
2170}
2171
2172void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2173 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2174 GLuint last_id;
2175 if (info.bound_texture_2d) {
2176 last_id = info.bound_texture_2d->service_id();
2177 } else {
2178 last_id = 0;
2179 }
2180
2181 glBindTexture(GL_TEXTURE_2D, last_id);
2182 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2183}
2184
[email protected]3a03a8f2011-03-19 00:51:272185bool GLES2DecoderImpl::CheckFramebufferComplete(const char* func_name) {
2186 if (bound_draw_framebuffer_ && bound_draw_framebuffer_->IsNotComplete()) {
[email protected]be45d7c2011-04-15 18:03:352187 SetGLError(GL_INVALID_FRAMEBUFFER_OPERATION,
[email protected]3a03a8f2011-03-19 00:51:272188 (std::string(func_name) + " framebuffer incomplete").c_str());
2189 return false;
2190 }
2191 return true;
2192}
2193
[email protected]8e3e0662010-08-23 18:46:302194gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
2195 if (bound_read_framebuffer_ != 0) {
[email protected]9edc6b22010-12-23 02:00:262196 const FramebufferManager::FramebufferInfo::Attachment* attachment =
2197 bound_read_framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
2198 if (attachment) {
2199 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502200 }
[email protected]9edc6b22010-12-23 02:00:262201 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022202 } else if (offscreen_target_frame_buffer_.get()) {
2203 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352204 } else {
[email protected]f62a5ab2011-05-23 20:34:152205 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022206 }
[email protected]246a70452010-03-05 21:53:502207}
2208
[email protected]9edc6b22010-12-23 02:00:262209GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
2210 if (bound_read_framebuffer_ != 0) {
[email protected]297ca1c2011-06-20 23:08:462211 return bound_read_framebuffer_->GetColorAttachmentFormat();
2212 } else if (offscreen_target_frame_buffer_.get()) {
2213 return offscreen_target_color_format_;
2214 } else {
2215 return back_buffer_color_format_;
2216 }
2217}
2218
2219GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
2220 if (bound_draw_framebuffer_ != 0) {
2221 return bound_draw_framebuffer_->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262222 } else if (offscreen_target_frame_buffer_.get()) {
2223 return offscreen_target_color_format_;
2224 } else {
[email protected]32fe9aa2011-01-21 23:47:132225 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262226 }
2227}
2228
[email protected]9a5afa432011-07-22 18:16:392229void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]34ff8b0c2010-10-01 20:06:022230 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582231 // Update the info about the offscreen saved color texture in the parent.
2232 // The reference to the parent is a weak pointer and will become null if the
2233 // parent is later destroyed.
[email protected]6217d392010-03-25 22:08:352234 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]8d25d042010-06-16 19:48:142235 GLuint client_id;
[email protected]262d7aa2010-12-03 22:07:292236 TextureManager* parent_texture_manager = parent_->texture_manager();
2237 CHECK(parent_texture_manager->GetClientId(service_id, &client_id));
[email protected]8d25d042010-06-16 19:48:142238 TextureManager::TextureInfo* info = parent_->GetTextureInfo(client_id);
[email protected]6217d392010-03-25 22:08:352239 DCHECK(info);
2240
[email protected]262d7aa2010-12-03 22:07:292241 parent_texture_manager->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:112242 feature_info_,
[email protected]ef526492010-06-02 23:12:252243 info,
2244 GL_TEXTURE_2D,
2245 0, // level
2246 GL_RGBA,
[email protected]799b4b22011-08-22 17:09:592247 offscreen_size_.width(),
2248 offscreen_size_.height(),
[email protected]ef526492010-06-02 23:12:252249 1, // depth
2250 0, // border
2251 GL_RGBA,
2252 GL_UNSIGNED_BYTE);
[email protected]262d7aa2010-12-03 22:07:292253 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042254 feature_info_,
2255 info,
2256 GL_TEXTURE_MAG_FILTER,
2257 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292258 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042259 feature_info_,
2260 info,
2261 GL_TEXTURE_MIN_FILTER,
2262 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292263 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042264 feature_info_,
2265 info,
2266 GL_TEXTURE_WRAP_S,
2267 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292268 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042269 feature_info_,
2270 info,
2271 GL_TEXTURE_WRAP_T,
2272 GL_CLAMP_TO_EDGE);
[email protected]0c8c9d22010-06-25 17:36:392273 }
[email protected]6217d392010-03-25 22:08:352274}
2275
[email protected]799b4b22011-08-22 17:09:592276void GLES2DecoderImpl::SetResizeCallback(
2277 Callback1<gfx::Size>::Type* callback) {
[email protected]7ff86b92010-11-25 17:50:002278 resize_callback_.reset(callback);
2279}
2280
[email protected]22f320a2011-08-30 01:17:002281#if defined(OS_MACOSX)
[email protected]43f28f832010-02-03 02:28:482282void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
2283 swap_buffers_callback_.reset(callback);
2284}
[email protected]22f320a2011-08-30 01:17:002285#endif
[email protected]43f28f832010-02-03 02:28:482286
[email protected]1318e922010-09-17 22:03:162287bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2288 uint32* service_texture_id) {
2289 TextureManager::TextureInfo* texture =
2290 texture_manager()->GetTextureInfo(client_texture_id);
2291 if (texture) {
2292 *service_texture_id = texture->service_id();
2293 return true;
2294 }
2295 return false;
2296}
2297
[email protected]96449d2c2009-11-25 00:01:322298void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392299 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052300
2301 if (group_.get())
2302 group_->set_have_context(have_context);
2303
[email protected]3c644d82011-06-20 19:58:242304 SetParent(NULL, 0);
2305
[email protected]eadc96792010-10-27 19:39:392306 if (have_context) {
[email protected]ca488e12010-12-13 20:06:142307 if (current_program_) {
2308 program_manager()->UnuseProgram(shader_manager(), current_program_);
2309 current_program_ = NULL;
2310 }
2311
[email protected]b1122982010-05-17 23:04:242312 if (attrib_0_buffer_id_) {
2313 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2314 }
[email protected]8fbedc02010-11-18 18:43:402315 if (fixed_attrib_buffer_id_) {
2316 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2317 }
[email protected]b1122982010-05-17 23:04:242318
[email protected]97872062010-11-03 19:07:052319 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542320 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052321 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542322 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052323 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022324 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052325 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152326 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052327 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152328 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052329 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022330 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052331 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542332 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:272333 if (offscreen_resolved_frame_buffer_.get())
2334 offscreen_resolved_frame_buffer_->Destroy();
2335 if (offscreen_resolved_color_texture_.get())
2336 offscreen_resolved_color_texture_->Destroy();
[email protected]66791e382010-07-14 20:48:302337
[email protected]eadc96792010-10-27 19:39:392338 // must release the ContextGroup before destroying the context as its
2339 // destructor uses GL.
2340 group_ = NULL;
[email protected]97872062010-11-03 19:07:052341 } else {
2342 if (offscreen_target_frame_buffer_.get())
2343 offscreen_target_frame_buffer_->Invalidate();
2344 if (offscreen_target_color_texture_.get())
2345 offscreen_target_color_texture_->Invalidate();
2346 if (offscreen_target_color_render_buffer_.get())
2347 offscreen_target_color_render_buffer_->Invalidate();
2348 if (offscreen_target_depth_render_buffer_.get())
2349 offscreen_target_depth_render_buffer_->Invalidate();
2350 if (offscreen_target_stencil_render_buffer_.get())
2351 offscreen_target_stencil_render_buffer_->Invalidate();
2352 if (offscreen_saved_frame_buffer_.get())
2353 offscreen_saved_frame_buffer_->Invalidate();
2354 if (offscreen_saved_color_texture_.get())
2355 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:272356 if (offscreen_resolved_frame_buffer_.get())
2357 offscreen_resolved_frame_buffer_->Invalidate();
2358 if (offscreen_resolved_color_texture_.get())
2359 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022360 }
[email protected]97872062010-11-03 19:07:052361
[email protected]fe871662011-06-16 20:43:052362 if (context_.get()) {
2363 context_->ReleaseCurrent(NULL);
[email protected]0fc35742011-04-13 17:57:542364 context_->Destroy();
[email protected]fe871662011-06-16 20:43:052365 }
[email protected]fbe20372011-06-01 01:46:382366 context_ = NULL;
[email protected]0fc35742011-04-13 17:57:542367
[email protected]97872062010-11-03 19:07:052368 offscreen_target_frame_buffer_.reset();
2369 offscreen_target_color_texture_.reset();
2370 offscreen_target_color_render_buffer_.reset();
2371 offscreen_target_depth_render_buffer_.reset();
2372 offscreen_target_stencil_render_buffer_.reset();
2373 offscreen_saved_frame_buffer_.reset();
2374 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:272375 offscreen_resolved_frame_buffer_.reset();
2376 offscreen_resolved_color_texture_.reset();
[email protected]96449d2c2009-11-25 00:01:322377}
2378
[email protected]3c644d82011-06-20 19:58:242379bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
2380 uint32 new_parent_texture_id) {
[email protected]9a5afa432011-07-22 18:16:392381 if (!offscreen_saved_color_texture_.get())
2382 return false;
2383
[email protected]3c644d82011-06-20 19:58:242384 // Remove the saved frame buffer mapping from the parent decoder. The
2385 // parent pointer is a weak pointer so it will be null if the parent has
2386 // already been destroyed.
2387 if (parent_) {
2388 // First check the texture has been mapped into the parent. This might not
2389 // be the case if initialization failed midway through.
2390 GLuint service_id = offscreen_saved_color_texture_->id();
2391 GLuint client_id = 0;
2392 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
2393 parent_->texture_manager()->RemoveTextureInfo(feature_info_, client_id);
2394 }
2395 }
2396
2397 GLES2DecoderImpl* new_parent_impl = static_cast<GLES2DecoderImpl*>(
2398 new_parent);
2399 if (new_parent_impl) {
2400 // Map the ID of the saved offscreen texture into the parent so that
2401 // it can reference it.
2402 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]98687862011-07-11 23:31:302403
2404 // Replace texture info when ID is already in use by parent.
2405 if (new_parent_impl->texture_manager()->GetTextureInfo(
2406 new_parent_texture_id))
2407 new_parent_impl->texture_manager()->RemoveTextureInfo(
2408 feature_info_, new_parent_texture_id);
2409
[email protected]3c644d82011-06-20 19:58:242410 TextureManager::TextureInfo* info =
[email protected]5f4f2a732011-07-30 00:47:552411 new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id);
2412 info->SetNotOwned();
[email protected]3c644d82011-06-20 19:58:242413 new_parent_impl->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
2414
2415 parent_ = new_parent_impl->AsWeakPtr();
[email protected]9a5afa432011-07-22 18:16:392416
2417 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:242418 } else {
2419 parent_.reset();
2420 }
2421
2422 return true;
2423}
2424
[email protected]799b4b22011-08-22 17:09:592425bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2426 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
2427 if (!is_offscreen) {
2428 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
2429 << " with an onscreen framebuffer.";
2430 return false;
2431 }
2432
2433 if (offscreen_size_ == size)
2434 return true;
2435
2436 offscreen_size_ = size;
2437 int w = offscreen_size_.width();
2438 int h = offscreen_size_.height();
2439 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
2440 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2441 << "to allocate storage due to excessive dimensions.";
2442 return false;
2443 }
2444
2445 // Reallocate the offscreen target buffers.
2446 DCHECK(offscreen_target_color_format_);
2447 if (IsOffscreenBufferMultisampled()) {
2448 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2449 offscreen_size_, offscreen_target_color_format_,
2450 offscreen_target_samples_)) {
2451 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2452 << "to allocate storage for offscreen target color buffer.";
2453 return false;
2454 }
2455 } else {
2456 if (!offscreen_target_color_texture_->AllocateStorage(
2457 offscreen_size_, offscreen_target_color_format_)) {
2458 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2459 << "to allocate storage for offscreen target color texture.";
2460 return false;
2461 }
2462 }
2463 if (offscreen_target_depth_format_ &&
2464 !offscreen_target_depth_render_buffer_->AllocateStorage(
2465 offscreen_size_, offscreen_target_depth_format_,
2466 offscreen_target_samples_)) {
2467 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2468 << "to allocate storage for offscreen target depth buffer.";
2469 return false;
2470 }
2471 if (offscreen_target_stencil_format_ &&
2472 !offscreen_target_stencil_render_buffer_->AllocateStorage(
2473 offscreen_size_, offscreen_target_stencil_format_,
2474 offscreen_target_samples_)) {
2475 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2476 << "to allocate storage for offscreen target stencil buffer.";
2477 return false;
2478 }
2479
2480 // Attach the offscreen target buffers to the target frame buffer.
2481 if (IsOffscreenBufferMultisampled()) {
2482 offscreen_target_frame_buffer_->AttachRenderBuffer(
2483 GL_COLOR_ATTACHMENT0,
2484 offscreen_target_color_render_buffer_.get());
2485 } else {
2486 offscreen_target_frame_buffer_->AttachRenderTexture(
2487 offscreen_target_color_texture_.get());
2488 }
2489 if (offscreen_target_depth_format_) {
2490 offscreen_target_frame_buffer_->AttachRenderBuffer(
2491 GL_DEPTH_ATTACHMENT,
2492 offscreen_target_depth_render_buffer_.get());
2493 }
2494 const bool packed_depth_stencil =
2495 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2496 if (packed_depth_stencil) {
2497 offscreen_target_frame_buffer_->AttachRenderBuffer(
2498 GL_STENCIL_ATTACHMENT,
2499 offscreen_target_depth_render_buffer_.get());
2500 } else if (offscreen_target_stencil_format_) {
2501 offscreen_target_frame_buffer_->AttachRenderBuffer(
2502 GL_STENCIL_ATTACHMENT,
2503 offscreen_target_stencil_render_buffer_.get());
2504 }
2505
2506 if (offscreen_target_frame_buffer_->CheckStatus() !=
2507 GL_FRAMEBUFFER_COMPLETE) {
2508 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2509 << "because offscreen FBO was incomplete.";
2510 return false;
2511 }
2512
2513 // Clear the target frame buffer.
2514 {
2515 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
2516 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2517 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
2518 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2519 glClearStencil(0);
2520 glStencilMaskSeparate(GL_FRONT, -1);
2521 glStencilMaskSeparate(GL_BACK, -1);
2522 glClearDepth(0);
2523 glDepthMask(GL_TRUE);
2524 glDisable(GL_SCISSOR_TEST);
2525 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2526 RestoreClearState();
2527 }
[email protected]d85ef76d2011-09-08 22:21:432528
2529 // Destroy the offscreen resolved framebuffers.
2530 if (offscreen_resolved_frame_buffer_.get())
2531 offscreen_resolved_frame_buffer_->Destroy();
2532 if (offscreen_resolved_color_texture_.get())
2533 offscreen_resolved_color_texture_->Destroy();
2534 offscreen_resolved_color_texture_.reset();
2535 offscreen_resolved_frame_buffer_.reset();
2536
[email protected]799b4b22011-08-22 17:09:592537 return true;
[email protected]6217d392010-03-25 22:08:352538}
2539
[email protected]799b4b22011-08-22 17:09:592540error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
2541 uint32 immediate_data_size, const gles2::ResizeCHROMIUM& c) {
2542 GLuint width = static_cast<GLuint>(c.width);
2543 GLuint height = static_cast<GLuint>(c.height);
2544 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
[email protected]2e7bbf22011-07-22 18:41:292545#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(TOUCH_UI)
[email protected]7ff86b92010-11-25 17:50:002546 // Make sure that we are done drawing to the back buffer before resizing.
2547 glFinish();
2548#endif
[email protected]799b4b22011-08-22 17:09:592549 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
2550 if (is_offscreen) {
2551 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height)))
2552 return error::kLostContext;
[email protected]7ff86b92010-11-25 17:50:002553 }
[email protected]799b4b22011-08-22 17:09:592554
2555 if (resize_callback_.get())
2556 resize_callback_->Run(gfx::Size(width, height));
2557
2558 return error::kNoError;
[email protected]43ecf372010-11-16 19:19:392559}
2560
[email protected]96449d2c2009-11-25 00:01:322561const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
2562 if (command_id > kStartPoint && command_id < kNumCommands) {
2563 return gles2::GetCommandName(static_cast<CommandId>(command_id));
2564 }
2565 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
2566}
2567
2568// Decode command with its arguments, and call the corresponding GL function.
2569// Note: args is a pointer to the command buffer. As such, it could be changed
2570// by a (malicious) client at any time, so if validation has to happen, it
2571// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:142572error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:322573 unsigned int command,
2574 unsigned int arg_count,
2575 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:142576 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192577 if (debug()) {
2578 // TODO(gman): Change output to something useful for NaCl.
[email protected]8e1b98a2011-06-14 23:39:532579 DLOG(INFO) << "[" << this << "]" << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192580 }
[email protected]96449d2c2009-11-25 00:01:322581 unsigned int command_index = command - kStartPoint - 1;
2582 if (command_index < arraysize(g_command_info)) {
2583 const CommandInfo& info = g_command_info[command_index];
2584 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
2585 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
2586 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:192587 uint32 immediate_data_size =
2588 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:322589 switch (command) {
2590 #define GLES2_CMD_OP(name) \
2591 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:192592 result = Handle ## name( \
2593 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:322594 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:192595 break; \
[email protected]96449d2c2009-11-25 00:01:322596
2597 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:322598 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:382599 }
2600 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:302601 GLenum error;
2602 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:382603 // TODO(gman): Change output to something useful for NaCl.
[email protected]8eee29c2010-04-29 03:38:292604 SetGLError(error, NULL);
[email protected]8e1b98a2011-06-14 23:39:532605 DLOG(INFO) << "[" << this << "]"
2606 << "GL ERROR: " << error << " : " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192607 }
[email protected]96449d2c2009-11-25 00:01:322608 }
2609 } else {
[email protected]f7a64ee2010-02-01 22:24:142610 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:322611 }
[email protected]b9849abf2009-11-25 19:13:192612 } else {
2613 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:322614 }
[email protected]a3a93e7b2010-08-28 00:48:562615 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
2616 result = current_decoder_error_;
2617 current_decoder_error_ = error::kNoError;
2618 }
[email protected]b9849abf2009-11-25 19:13:192619 return result;
[email protected]96449d2c2009-11-25 00:01:322620}
2621
[email protected]ae51d192010-04-27 00:48:032622void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
2623 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:502624}
2625
[email protected]ae51d192010-04-27 00:48:032626bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
2627 if (GetProgramInfo(client_id)) {
2628 return false;
2629 }
[email protected]96449d2c2009-11-25 00:01:322630 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:032631 if (service_id != 0) {
2632 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:322633 }
[email protected]ae51d192010-04-27 00:48:032634 return true;
[email protected]96449d2c2009-11-25 00:01:322635}
2636
[email protected]ae51d192010-04-27 00:48:032637bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
2638 if (GetShaderInfo(client_id)) {
2639 return false;
[email protected]96449d2c2009-11-25 00:01:322640 }
[email protected]ae51d192010-04-27 00:48:032641 GLuint service_id = glCreateShader(type);
2642 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:382643 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:032644 }
2645 return true;
[email protected]96449d2c2009-11-25 00:01:322646}
2647
[email protected]3916c97e2010-02-25 03:20:502648void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:452649 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]660858b2011-07-13 23:16:142650 if (texture_index >= group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:292651 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:502652 return;
2653 }
[email protected]36cef8ce2010-03-16 07:34:452654 active_texture_unit_ = texture_index;
2655 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:502656}
2657
[email protected]051b1372010-04-12 02:42:082658void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:502659 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082660 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032661 if (client_id != 0) {
2662 info = GetBufferInfo(client_id);
2663 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:352664 if (!group_->bind_generates_resource()) {
2665 SetGLError(GL_INVALID_VALUE,
2666 "glBindBuffer: id not generated by glGenBuffers");
2667 return;
2668 }
2669
[email protected]ae51d192010-04-27 00:48:032670 // It's a new id so make a buffer info for it.
2671 glGenBuffersARB(1, &service_id);
2672 CreateBufferInfo(client_id, service_id);
2673 info = GetBufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:572674 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:102675 group_->GetIdAllocator(id_namespaces::kBuffers);
2676 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032677 }
[email protected]051b1372010-04-12 02:42:082678 }
[email protected]ae51d192010-04-27 00:48:032679 if (info) {
[email protected]4e8a5b122010-05-08 22:00:102680 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:292681 SetGLError(GL_INVALID_OPERATION,
2682 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:472683 return;
2684 }
[email protected]ae51d192010-04-27 00:48:032685 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:472686 }
[email protected]96449d2c2009-11-25 00:01:322687 switch (target) {
2688 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502689 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322690 break;
2691 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502692 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322693 break;
2694 default:
[email protected]a93bb842010-02-16 23:03:472695 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:322696 break;
2697 }
[email protected]051b1372010-04-12 02:42:082698 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:322699}
2700
[email protected]297ca1c2011-06-20 23:08:462701bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
2702 return (GLES2Util::GetChannelsForFormat(
2703 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
2704}
2705
2706bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
2707 if (bound_draw_framebuffer_) {
2708 return bound_draw_framebuffer_->HasDepthAttachment();
2709 }
2710 if (offscreen_target_frame_buffer_.get()) {
2711 return offscreen_target_depth_format_ != 0;
2712 }
2713 return back_buffer_has_depth_;
2714}
2715
2716bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
2717 if (bound_draw_framebuffer_) {
2718 return bound_draw_framebuffer_->HasStencilAttachment();
2719 }
2720 if (offscreen_target_frame_buffer_.get()) {
2721 return offscreen_target_stencil_format_ != 0 ||
2722 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2723 }
2724 return back_buffer_has_stencil_;
2725}
2726
2727void GLES2DecoderImpl::ApplyDirtyState() {
2728 if (state_dirty_) {
2729 glColorMask(
2730 mask_red_, mask_green_, mask_blue_,
2731 mask_alpha_ && BoundFramebufferHasColorAttachmentWithAlpha());
2732 bool have_depth = BoundFramebufferHasDepthAttachment();
2733 glDepthMask(mask_depth_ && have_depth);
2734 EnableDisable(GL_DEPTH_TEST, enable_depth_test_ && have_depth);
2735 bool have_stencil = BoundFramebufferHasStencilAttachment();
2736 glStencilMaskSeparate(GL_FRONT, have_stencil ? mask_stencil_front_ : 0);
2737 glStencilMaskSeparate(GL_BACK, have_stencil ? mask_stencil_back_ : 0);
2738 EnableDisable(GL_STENCIL_TEST, enable_stencil_test_ && have_stencil);
2739 state_dirty_ = false;
2740 }
2741}
2742
[email protected]051b1372010-04-12 02:42:082743void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
2744 FramebufferManager::FramebufferInfo* info = NULL;
2745 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032746 if (client_id != 0) {
2747 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082748 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:352749 if (!group_->bind_generates_resource()) {
2750 SetGLError(GL_INVALID_VALUE,
2751 "glBindFramebuffer: id not generated by glGenFramebuffers");
2752 return;
2753 }
2754
[email protected]ae51d192010-04-27 00:48:032755 // It's a new id so make a framebuffer info for it.
2756 glGenFramebuffersEXT(1, &service_id);
2757 CreateFramebufferInfo(client_id, service_id);
2758 info = GetFramebufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:572759 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:102760 group_->GetIdAllocator(id_namespaces::kFramebuffers);
2761 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032762 } else {
2763 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082764 }
[email protected]06c8b082011-01-05 18:00:362765 info->MarkAsValid();
[email protected]eff9a222010-12-21 21:48:562766 } else {
[email protected]2e7bbf22011-07-22 18:41:292767 service_id = surface_->GetBackingFrameBufferObject();
[email protected]051b1372010-04-12 02:42:082768 }
[email protected]8e3e0662010-08-23 18:46:302769
2770 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
2771 bound_draw_framebuffer_ = info;
2772 }
2773 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
2774 bound_read_framebuffer_ = info;
2775 }
[email protected]6217d392010-03-25 22:08:352776
[email protected]297ca1c2011-06-20 23:08:462777 state_dirty_ = true;
2778
[email protected]6217d392010-03-25 22:08:352779 // When rendering to an offscreen frame buffer, instead of unbinding from
2780 // the current frame buffer, bind to the offscreen target frame buffer.
[email protected]297ca1c2011-06-20 23:08:462781 if (info == NULL && offscreen_target_frame_buffer_.get()) {
[email protected]051b1372010-04-12 02:42:082782 service_id = offscreen_target_frame_buffer_->id();
[email protected]297ca1c2011-06-20 23:08:462783 }
[email protected]6217d392010-03-25 22:08:352784
[email protected]051b1372010-04-12 02:42:082785 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562786}
2787
[email protected]051b1372010-04-12 02:42:082788void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
2789 RenderbufferManager::RenderbufferInfo* info = NULL;
2790 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032791 if (client_id != 0) {
2792 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082793 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:352794 if (!group_->bind_generates_resource()) {
2795 SetGLError(
2796 GL_INVALID_VALUE,
2797 "glBindRenderbuffer: id not generated by glGenRenderbuffers");
2798 return;
2799 }
2800
[email protected]ae51d192010-04-27 00:48:032801 // It's a new id so make a renderbuffer info for it.
2802 glGenRenderbuffersEXT(1, &service_id);
2803 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:102804 info = GetRenderbufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:572805 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:102806 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
2807 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032808 } else {
2809 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082810 }
[email protected]06c8b082011-01-05 18:00:362811 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:082812 }
2813 bound_renderbuffer_ = info;
2814 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562815}
2816
[email protected]051b1372010-04-12 02:42:082817void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032818 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082819 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032820 if (client_id != 0) {
2821 info = GetTextureInfo(client_id);
2822 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:352823 if (!group_->bind_generates_resource()) {
2824 SetGLError(GL_INVALID_VALUE,
2825 "glBindTexture: id not generated by glGenTextures");
2826 return;
2827 }
2828
[email protected]ae51d192010-04-27 00:48:032829 // It's a new id so make a texture info for it.
2830 glGenTextures(1, &service_id);
2831 CreateTextureInfo(client_id, service_id);
2832 info = GetTextureInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:572833 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:102834 group_->GetIdAllocator(id_namespaces::kTextures);
2835 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032836 }
2837 } else {
2838 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:082839 }
[email protected]ae51d192010-04-27 00:48:032840
[email protected]1958e0e2010-04-22 05:17:152841 // Check the texture exists
2842 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:032843 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:292844 SetGLError(GL_INVALID_OPERATION,
2845 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:152846 return;
2847 }
2848 if (info->target() == 0) {
2849 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:472850 }
[email protected]ae51d192010-04-27 00:48:032851 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:502852 TextureUnit& unit = texture_units_[active_texture_unit_];
2853 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:472854 switch (target) {
2855 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:502856 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:472857 break;
2858 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:502859 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:472860 break;
[email protected]61eeb33f2011-07-26 15:30:312861 case GL_TEXTURE_EXTERNAL_OES:
2862 unit.bound_texture_external_oes = info;
2863 break;
[email protected]a93bb842010-02-16 23:03:472864 default:
2865 NOTREACHED(); // Validation should prevent us getting here.
2866 break;
2867 }
2868}
2869
[email protected]07f54fcc2009-12-22 02:46:302870void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082871 if (vertex_attrib_manager_.Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:122872 if (index != 0 ||
2873 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:242874 glDisableVertexAttribArray(index);
2875 }
[email protected]07f54fcc2009-12-22 02:46:302876 } else {
[email protected]8eee29c2010-04-29 03:38:292877 SetGLError(GL_INVALID_VALUE,
2878 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302879 }
2880}
2881
2882void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082883 if (vertex_attrib_manager_.Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:302884 glEnableVertexAttribArray(index);
2885 } else {
[email protected]8eee29c2010-04-29 03:38:292886 SetGLError(GL_INVALID_VALUE,
2887 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302888 }
2889}
2890
[email protected]a93bb842010-02-16 23:03:472891void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:502892 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]915a59a12010-09-30 21:29:112893 if (!info || !texture_manager()->MarkMipmapsGenerated(feature_info_, info)) {
[email protected]8eee29c2010-04-29 03:38:292894 SetGLError(GL_INVALID_OPERATION,
2895 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:472896 return;
2897 }
[email protected]59f3ca02011-03-26 22:24:192898 // Workaround for Mac driver bug. In the large scheme of things setting
2899 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
2900 // hit so there's probably no need to make this conditional.
2901 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
[email protected]a93bb842010-02-16 23:03:472902 glGenerateMipmapEXT(target);
[email protected]59f3ca02011-03-26 22:24:192903 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
[email protected]a93bb842010-02-16 23:03:472904}
2905
[email protected]b273e432010-04-12 17:23:582906bool GLES2DecoderImpl::GetHelper(
2907 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:582908 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:152909 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2910 switch (pname) {
[email protected]b273e432010-04-12 17:23:582911 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2912 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102913 if (params) {
[email protected]5094b0f2010-11-09 19:45:242914 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:102915 }
[email protected]b273e432010-04-12 17:23:582916 return true;
2917 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2918 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102919 if (params) {
[email protected]5094b0f2010-11-09 19:45:242920 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:102921 }
[email protected]b273e432010-04-12 17:23:582922 return true;
2923 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
2924 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102925 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482926 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102927 }
[email protected]b273e432010-04-12 17:23:582928 return true;
2929 case GL_MAX_VARYING_VECTORS:
2930 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102931 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482932 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:102933 }
[email protected]b273e432010-04-12 17:23:582934 return true;
2935 case GL_MAX_VERTEX_UNIFORM_VECTORS:
2936 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102937 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482938 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102939 }
[email protected]b273e432010-04-12 17:23:582940 return true;
[email protected]5094b0f2010-11-09 19:45:242941 case GL_MAX_VIEWPORT_DIMS:
2942 if (offscreen_target_frame_buffer_.get()) {
2943 *num_written = 2;
2944 if (params) {
2945 params[0] = renderbuffer_manager()->max_renderbuffer_size();
2946 params[1] = renderbuffer_manager()->max_renderbuffer_size();
2947 }
2948 return true;
2949 }
[email protected]b9363b22010-06-09 22:06:152950 }
2951 }
2952 switch (pname) {
[email protected]297ca1c2011-06-20 23:08:462953 case GL_COLOR_WRITEMASK:
2954 *num_written = 4;
2955 if (params) {
2956 params[0] = mask_red_;
2957 params[1] = mask_green_;
2958 params[2] = mask_blue_;
2959 params[3] = mask_alpha_;
2960 }
2961 return true;
2962 case GL_DEPTH_WRITEMASK:
2963 *num_written = 1;
2964 if (params) {
2965 params[0] = mask_depth_;
2966 }
2967 return true;
2968 case GL_STENCIL_BACK_WRITEMASK:
2969 *num_written = 1;
2970 if (params) {
2971 params[0] = mask_stencil_back_;
2972 }
2973 return true;
2974 case GL_STENCIL_WRITEMASK:
2975 *num_written = 1;
2976 if (params) {
2977 params[0] = mask_stencil_front_;
2978 }
2979 return true;
2980 case GL_DEPTH_TEST:
2981 *num_written = 1;
2982 if (params) {
2983 params[0] = enable_depth_test_;
2984 }
2985 return true;
2986 case GL_STENCIL_TEST:
2987 *num_written = 1;
2988 if (params) {
2989 params[0] = enable_stencil_test_;
2990 }
2991 return true;
2992 case GL_ALPHA_BITS:
2993 *num_written = 1;
2994 if (params) {
2995 GLint v = 0;
2996 glGetIntegerv(GL_ALPHA_BITS, &v);
2997 params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0;
2998 }
2999 return true;
3000 case GL_DEPTH_BITS:
3001 *num_written = 1;
3002 if (params) {
3003 GLint v = 0;
3004 glGetIntegerv(GL_DEPTH_BITS, &v);
3005 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
3006 }
3007 return true;
3008 case GL_STENCIL_BITS:
3009 *num_written = 1;
3010 if (params) {
3011 GLint v = 0;
3012 glGetIntegerv(GL_STENCIL_BITS, &v);
3013 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
3014 }
3015 return true;
[email protected]656dcaad2010-05-07 17:18:373016 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113017 *num_written = validators_->compressed_texture_format.GetValues().size();
3018 if (params) {
3019 for (GLint ii = 0; ii < *num_written; ++ii) {
3020 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
3021 }
3022 }
[email protected]656dcaad2010-05-07 17:18:373023 return true;
[email protected]b273e432010-04-12 17:23:583024 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
3025 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103026 if (params) {
[email protected]302ce6d2011-07-07 23:28:113027 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103028 }
[email protected]b273e432010-04-12 17:23:583029 return true;
3030 case GL_NUM_SHADER_BINARY_FORMATS:
3031 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103032 if (params) {
[email protected]302ce6d2011-07-07 23:28:113033 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103034 }
[email protected]b273e432010-04-12 17:23:583035 return true;
3036 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113037 *num_written = validators_->shader_binary_format.GetValues().size();
3038 if (params) {
3039 for (GLint ii = 0; ii < *num_written; ++ii) {
3040 params[ii] = validators_->shader_binary_format.GetValues()[ii];
3041 }
3042 }
3043 return true;
[email protected]b273e432010-04-12 17:23:583044 case GL_SHADER_COMPILER:
3045 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103046 if (params) {
3047 *params = GL_TRUE;
3048 }
[email protected]b273e432010-04-12 17:23:583049 return true;
[email protected]6b8cf1a2010-05-06 16:13:583050 case GL_ARRAY_BUFFER_BINDING:
3051 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103052 if (params) {
3053 if (bound_array_buffer_) {
3054 GLuint client_id = 0;
3055 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
3056 &client_id);
3057 *params = client_id;
3058 } else {
3059 *params = 0;
3060 }
[email protected]6b8cf1a2010-05-06 16:13:583061 }
3062 return true;
3063 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3064 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103065 if (params) {
3066 if (bound_element_array_buffer_) {
3067 GLuint client_id = 0;
3068 buffer_manager()->GetClientId(
3069 bound_element_array_buffer_->service_id(),
3070 &client_id);
3071 *params = client_id;
3072 } else {
3073 *params = 0;
3074 }
[email protected]6b8cf1a2010-05-06 16:13:583075 }
3076 return true;
3077 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:303078 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:583079 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103080 if (params) {
[email protected]8e3e0662010-08-23 18:46:303081 if (bound_draw_framebuffer_) {
[email protected]4e8a5b122010-05-08 22:00:103082 GLuint client_id = 0;
3083 framebuffer_manager()->GetClientId(
[email protected]8e3e0662010-08-23 18:46:303084 bound_draw_framebuffer_->service_id(), &client_id);
3085 *params = client_id;
3086 } else {
3087 *params = 0;
3088 }
3089 }
3090 return true;
3091 case GL_READ_FRAMEBUFFER_BINDING:
3092 *num_written = 1;
3093 if (params) {
3094 if (bound_read_framebuffer_) {
3095 GLuint client_id = 0;
3096 framebuffer_manager()->GetClientId(
3097 bound_read_framebuffer_->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103098 *params = client_id;
3099 } else {
3100 *params = 0;
3101 }
[email protected]6b8cf1a2010-05-06 16:13:583102 }
3103 return true;
3104 case GL_RENDERBUFFER_BINDING:
3105 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103106 if (params) {
3107 if (bound_renderbuffer_) {
3108 GLuint client_id = 0;
3109 renderbuffer_manager()->GetClientId(
3110 bound_renderbuffer_->service_id(), &client_id);
3111 *params = client_id;
3112 } else {
3113 *params = 0;
3114 }
[email protected]6b8cf1a2010-05-06 16:13:583115 }
3116 return true;
3117 case GL_CURRENT_PROGRAM:
3118 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103119 if (params) {
3120 if (current_program_) {
3121 GLuint client_id = 0;
3122 program_manager()->GetClientId(
3123 current_program_->service_id(), &client_id);
3124 *params = client_id;
3125 } else {
3126 *params = 0;
3127 }
[email protected]6b8cf1a2010-05-06 16:13:583128 }
3129 return true;
[email protected]4e8a5b122010-05-08 22:00:103130 case GL_TEXTURE_BINDING_2D:
3131 *num_written = 1;
3132 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583133 TextureUnit& unit = texture_units_[active_texture_unit_];
3134 if (unit.bound_texture_2d) {
3135 GLuint client_id = 0;
3136 texture_manager()->GetClientId(
3137 unit.bound_texture_2d->service_id(), &client_id);
3138 *params = client_id;
3139 } else {
3140 *params = 0;
3141 }
[email protected]6b8cf1a2010-05-06 16:13:583142 }
[email protected]4e8a5b122010-05-08 22:00:103143 return true;
3144 case GL_TEXTURE_BINDING_CUBE_MAP:
3145 *num_written = 1;
3146 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583147 TextureUnit& unit = texture_units_[active_texture_unit_];
3148 if (unit.bound_texture_cube_map) {
3149 GLuint client_id = 0;
3150 texture_manager()->GetClientId(
3151 unit.bound_texture_cube_map->service_id(), &client_id);
3152 *params = client_id;
3153 } else {
3154 *params = 0;
3155 }
[email protected]6b8cf1a2010-05-06 16:13:583156 }
[email protected]4e8a5b122010-05-08 22:00:103157 return true;
[email protected]61eeb33f2011-07-26 15:30:313158 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3159 *num_written = 1;
3160 if (params) {
3161 TextureUnit& unit = texture_units_[active_texture_unit_];
3162 if (unit.bound_texture_external_oes) {
3163 GLuint client_id = 0;
3164 texture_manager()->GetClientId(
3165 unit.bound_texture_external_oes->service_id(), &client_id);
3166 *params = client_id;
3167 } else {
3168 *params = 0;
3169 }
3170 }
3171 return true;
[email protected]b273e432010-04-12 17:23:583172 default:
[email protected]4e8a5b122010-05-08 22:00:103173 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533174 return false;
[email protected]b273e432010-04-12 17:23:583175 }
3176}
3177
[email protected]4e8a5b122010-05-08 22:00:103178bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3179 GLenum pname, GLsizei* num_values) {
3180 return GetHelper(pname, NULL, num_values);
3181}
3182
[email protected]b273e432010-04-12 17:23:583183void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3184 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103185 GLsizei num_written = 0;
3186 if (GetHelper(pname, NULL, &num_written)) {
3187 scoped_array<GLint> values(new GLint[num_written]);
3188 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583189 for (GLsizei ii = 0; ii < num_written; ++ii) {
3190 params[ii] = static_cast<GLboolean>(values[ii]);
3191 }
3192 } else {
3193 glGetBooleanv(pname, params);
3194 }
3195}
3196
3197void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3198 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103199 GLsizei num_written = 0;
3200 if (GetHelper(pname, NULL, &num_written)) {
3201 scoped_array<GLint> values(new GLint[num_written]);
3202 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583203 for (GLsizei ii = 0; ii < num_written; ++ii) {
3204 params[ii] = static_cast<GLfloat>(values[ii]);
3205 }
3206 } else {
3207 glGetFloatv(pname, params);
3208 }
3209}
3210
3211void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3212 DCHECK(params);
3213 GLsizei num_written;
3214 if (!GetHelper(pname, params, &num_written)) {
3215 glGetIntegerv(pname, params);
3216 }
3217}
3218
[email protected]a0c3e972010-04-21 00:49:133219void GLES2DecoderImpl::DoGetProgramiv(
3220 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583221 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3222 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133223 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133224 return;
3225 }
3226 info->GetProgramiv(pname, params);
3227}
3228
[email protected]558847a2010-03-24 07:02:543229error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3230 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
[email protected]6b8cf1a2010-05-06 16:13:583231 GLuint program = static_cast<GLuint>(c.program);
3232 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3233 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033234 if (!info) {
[email protected]558847a2010-03-24 07:02:543235 return error::kNoError;
3236 }
3237 GLuint index = static_cast<GLuint>(c.index);
3238 uint32 name_size = c.data_size;
3239 const char* name = GetSharedMemoryAs<const char*>(
3240 c.name_shm_id, c.name_shm_offset, name_size);
3241 if (name == NULL) {
3242 return error::kOutOfBounds;
3243 }
3244 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033245 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543246 return error::kNoError;
3247}
3248
3249error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3250 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583251 GLuint program = static_cast<GLuint>(c.program);
3252 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3253 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033254 if (!info) {
[email protected]558847a2010-03-24 07:02:543255 return error::kNoError;
3256 }
3257 GLuint index = static_cast<GLuint>(c.index);
3258 uint32 name_size = c.data_size;
3259 const char* name = GetImmediateDataAs<const char*>(
3260 c, name_size, immediate_data_size);
3261 if (name == NULL) {
3262 return error::kOutOfBounds;
3263 }
3264 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033265 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543266 return error::kNoError;
3267}
3268
3269error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3270 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583271 GLuint program = static_cast<GLuint>(c.program);
3272 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3273 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033274 if (!info) {
[email protected]558847a2010-03-24 07:02:543275 return error::kNoError;
3276 }
3277 GLuint index = static_cast<GLuint>(c.index);
3278 Bucket* bucket = GetBucket(c.name_bucket_id);
3279 if (!bucket || bucket->size() == 0) {
3280 return error::kInvalidArguments;
3281 }
3282 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183283 if (!bucket->GetAsString(&name_str)) {
3284 return error::kInvalidArguments;
3285 }
[email protected]ae51d192010-04-27 00:48:033286 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543287 return error::kNoError;
3288}
3289
[email protected]f7a64ee2010-02-01 22:24:143290error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463291 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033292 GLuint client_id = c.shader;
3293 if (client_id) {
3294 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3295 if (info) {
[email protected]ca488e12010-12-13 20:06:143296 if (!info->IsDeleted()) {
3297 glDeleteShader(info->service_id());
3298 shader_manager()->MarkAsDeleted(info);
3299 }
[email protected]ae51d192010-04-27 00:48:033300 } else {
[email protected]8eee29c2010-04-29 03:38:293301 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033302 }
[email protected]96449d2c2009-11-25 00:01:323303 }
[email protected]f7a64ee2010-02-01 22:24:143304 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323305}
3306
[email protected]f7a64ee2010-02-01 22:24:143307error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463308 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033309 GLuint client_id = c.program;
3310 if (client_id) {
3311 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3312 if (info) {
[email protected]ca488e12010-12-13 20:06:143313 if (!info->IsDeleted()) {
3314 glDeleteProgram(info->service_id());
3315 program_manager()->MarkAsDeleted(shader_manager(), info);
3316 }
[email protected]ae51d192010-04-27 00:48:033317 } else {
[email protected]8eee29c2010-04-29 03:38:293318 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033319 }
[email protected]96449d2c2009-11-25 00:01:323320 }
[email protected]f7a64ee2010-02-01 22:24:143321 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323322}
3323
[email protected]269200b12010-11-18 22:53:063324void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103325 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573326 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103327 for (GLsizei ii = 0; ii < n; ++ii) {
3328 id_allocator->FreeID(ids[ii]);
3329 }
3330}
3331
[email protected]269200b12010-11-18 22:53:063332error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
3333 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103334 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3335 GLsizei n = static_cast<GLsizei>(c.n);
3336 uint32 data_size;
3337 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3338 return error::kOutOfBounds;
3339 }
3340 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3341 c.ids_shm_id, c.ids_shm_offset, data_size);
3342 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063343 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103344 return error::kNoError;
3345 }
3346 if (ids == NULL) {
3347 return error::kOutOfBounds;
3348 }
[email protected]269200b12010-11-18 22:53:063349 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103350 return error::kNoError;
3351}
3352
[email protected]269200b12010-11-18 22:53:063353void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103354 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573355 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103356 if (id_offset == 0) {
3357 for (GLsizei ii = 0; ii < n; ++ii) {
3358 ids[ii] = id_allocator->AllocateID();
3359 }
3360 } else {
3361 for (GLsizei ii = 0; ii < n; ++ii) {
3362 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
3363 id_offset = ids[ii] + 1;
3364 }
3365 }
3366}
3367
[email protected]269200b12010-11-18 22:53:063368error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
3369 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103370 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3371 GLuint id_offset = static_cast<GLuint>(c.id_offset);
3372 GLsizei n = static_cast<GLsizei>(c.n);
3373 uint32 data_size;
3374 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3375 return error::kOutOfBounds;
3376 }
3377 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3378 c.ids_shm_id, c.ids_shm_offset, data_size);
3379 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063380 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103381 return error::kNoError;
3382 }
3383 if (ids == NULL) {
3384 return error::kOutOfBounds;
3385 }
[email protected]269200b12010-11-18 22:53:063386 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:103387 return error::kNoError;
3388}
3389
[email protected]269200b12010-11-18 22:53:063390void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103391 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573392 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103393 for (GLsizei ii = 0; ii < n; ++ii) {
3394 if (!id_allocator->MarkAsUsed(ids[ii])) {
3395 for (GLsizei jj = 0; jj < ii; ++jj) {
3396 id_allocator->FreeID(ids[jj]);
3397 }
3398 SetGLError(
3399 GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:063400 "RegisterSharedIdsCHROMIUM: attempt to register "
3401 "id that already exists");
[email protected]066849e32010-05-03 19:14:103402 return;
3403 }
3404 }
3405}
3406
[email protected]269200b12010-11-18 22:53:063407error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
3408 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103409 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3410 GLsizei n = static_cast<GLsizei>(c.n);
3411 uint32 data_size;
3412 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3413 return error::kOutOfBounds;
3414 }
3415 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3416 c.ids_shm_id, c.ids_shm_offset, data_size);
3417 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063418 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103419 return error::kNoError;
3420 }
3421 if (ids == NULL) {
3422 return error::kOutOfBounds;
3423 }
[email protected]269200b12010-11-18 22:53:063424 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103425 return error::kNoError;
3426}
3427
[email protected]3a03a8f2011-03-19 00:51:273428void GLES2DecoderImpl::DoClear(GLbitfield mask) {
3429 if (CheckFramebufferComplete("glClear")) {
[email protected]297ca1c2011-06-20 23:08:463430 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:273431 glClear(mask);
3432 }
3433}
3434
[email protected]36cef8ce2010-03-16 07:34:453435void GLES2DecoderImpl::DoFramebufferRenderbuffer(
3436 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:033437 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:303438 FramebufferManager::FramebufferInfo* framebuffer_info =
3439 GetFramebufferInfoForTarget(target);
3440 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293441 SetGLError(GL_INVALID_OPERATION,
3442 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453443 return;
3444 }
[email protected]ae51d192010-04-27 00:48:033445 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283446 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033447 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283448 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:033449 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293450 SetGLError(GL_INVALID_OPERATION,
3451 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:033452 return;
3453 }
3454 service_id = info->service_id();
3455 }
[email protected]9edc6b22010-12-23 02:00:263456 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033457 glFramebufferRenderbufferEXT(
3458 target, attachment, renderbuffertarget, service_id);
[email protected]1002c2d2011-06-28 22:39:043459 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263460 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:303461 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]9edc6b22010-12-23 02:00:263462 if (service_id == 0 ||
3463 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
3464 if (info) {
3465 ClearUnclearedRenderbuffers(target, framebuffer_info);
3466 }
[email protected]3a2e7c7b2010-08-06 01:12:283467 }
3468 }
[email protected]297ca1c2011-06-20 23:08:463469 if (framebuffer_info == bound_draw_framebuffer_) {
3470 state_dirty_ = true;
3471 }
[email protected]3a2e7c7b2010-08-06 01:12:283472}
3473
[email protected]297ca1c2011-06-20 23:08:463474bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
[email protected]3a2e7c7b2010-08-06 01:12:283475 switch (cap) {
3476 case GL_SCISSOR_TEST:
3477 enable_scissor_test_ = enabled;
[email protected]297ca1c2011-06-20 23:08:463478 return true;
3479 case GL_DEPTH_TEST: {
3480 if (enable_depth_test_ != enabled) {
3481 enable_depth_test_ = enabled;
3482 state_dirty_ = true;
3483 }
3484 return false;
3485 }
3486 case GL_STENCIL_TEST:
3487 if (enable_stencil_test_ != enabled) {
3488 enable_stencil_test_ = enabled;
3489 state_dirty_ = true;
3490 }
3491 return false;
[email protected]3a2e7c7b2010-08-06 01:12:283492 default:
[email protected]297ca1c2011-06-20 23:08:463493 return true;
[email protected]3a2e7c7b2010-08-06 01:12:283494 }
3495}
3496
3497void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:463498 if (SetCapabilityState(cap, false)) {
3499 glDisable(cap);
3500 }
[email protected]3a2e7c7b2010-08-06 01:12:283501}
3502
3503void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:463504 if (SetCapabilityState(cap, true)) {
3505 glEnable(cap);
3506 }
[email protected]3a2e7c7b2010-08-06 01:12:283507}
3508
3509void GLES2DecoderImpl::DoClearColor(
3510 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
3511 clear_red_ = red;
3512 clear_green_ = green;
3513 clear_blue_ = blue;
3514 clear_alpha_ = alpha;
3515 glClearColor(red, green, blue, alpha);
3516}
3517
3518void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
3519 clear_depth_ = depth;
3520 glClearDepth(depth);
3521}
3522
3523void GLES2DecoderImpl::DoClearStencil(GLint s) {
3524 clear_stencil_ = s;
3525 glClearStencil(s);
3526}
3527
3528void GLES2DecoderImpl::DoColorMask(
3529 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
3530 mask_red_ = red;
3531 mask_green_ = green;
3532 mask_blue_ = blue;
3533 mask_alpha_ = alpha;
[email protected]297ca1c2011-06-20 23:08:463534 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283535}
3536
3537void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
3538 mask_depth_ = depth;
[email protected]297ca1c2011-06-20 23:08:463539 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283540}
3541
3542void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
3543 mask_stencil_front_ = mask;
3544 mask_stencil_back_ = mask;
[email protected]297ca1c2011-06-20 23:08:463545 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283546}
3547
3548void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
[email protected]297ca1c2011-06-20 23:08:463549 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:283550 mask_stencil_front_ = mask;
[email protected]297ca1c2011-06-20 23:08:463551 }
3552 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:283553 mask_stencil_back_ = mask;
3554 }
[email protected]297ca1c2011-06-20 23:08:463555 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283556}
3557
3558// NOTE: There's an assumption here that Texture attachments
3559// are cleared because they are textures so we only need to clear
3560// the renderbuffers.
3561void GLES2DecoderImpl::ClearUnclearedRenderbuffers(
[email protected]8e3e0662010-08-23 18:46:303562 GLenum target, FramebufferManager::FramebufferInfo* info) {
3563 if (target == GL_READ_FRAMEBUFFER_EXT) {
3564 // TODO(gman): bind this to the DRAW point, clear then bind back to READ
3565 }
[email protected]3a2e7c7b2010-08-06 01:12:283566 GLbitfield clear_bits = 0;
3567 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:463568 glClearColor(
3569 0, 0, 0,
3570 (GLES2Util::GetChannelsForFormat(
3571 info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0 : 1);
[email protected]3a2e7c7b2010-08-06 01:12:283572 glColorMask(true, true, true, true);
3573 clear_bits |= GL_COLOR_BUFFER_BIT;
3574 }
3575
3576 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
3577 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3578 glClearStencil(0);
3579 glStencilMask(-1);
3580 clear_bits |= GL_STENCIL_BUFFER_BIT;
3581 }
3582
3583 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
3584 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3585 glClearDepth(1.0f);
3586 glDepthMask(true);
3587 clear_bits |= GL_DEPTH_BUFFER_BIT;
3588 }
3589
3590 glDisable(GL_SCISSOR_TEST);
3591 glClear(clear_bits);
3592
3593 info->MarkAttachedRenderbuffersAsCleared();
3594
[email protected]c007aa02010-09-02 22:22:403595 RestoreClearState();
3596
3597 if (target == GL_READ_FRAMEBUFFER_EXT) {
3598 // TODO(gman): rebind draw.
3599 }
3600}
3601
3602void GLES2DecoderImpl::RestoreClearState() {
[email protected]297ca1c2011-06-20 23:08:463603 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283604 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
[email protected]3a2e7c7b2010-08-06 01:12:283605 glClearStencil(clear_stencil_);
[email protected]3a2e7c7b2010-08-06 01:12:283606 glClearDepth(clear_depth_);
[email protected]3a2e7c7b2010-08-06 01:12:283607 if (enable_scissor_test_) {
3608 glEnable(GL_SCISSOR_TEST);
3609 }
[email protected]36cef8ce2010-03-16 07:34:453610}
3611
3612GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]8e3e0662010-08-23 18:46:303613 FramebufferManager::FramebufferInfo* info =
3614 GetFramebufferInfoForTarget(target);
3615 if (!info) {
[email protected]36cef8ce2010-03-16 07:34:453616 return GL_FRAMEBUFFER_COMPLETE;
3617 }
3618 return glCheckFramebufferStatusEXT(target);
3619}
3620
3621void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:033622 GLenum target, GLenum attachment, GLenum textarget,
3623 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:303624 FramebufferManager::FramebufferInfo* framebuffer_info =
3625 GetFramebufferInfoForTarget(target);
3626 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293627 SetGLError(GL_INVALID_OPERATION,
3628 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:453629 return;
3630 }
[email protected]ae51d192010-04-27 00:48:033631 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283632 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033633 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283634 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:033635 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293636 SetGLError(GL_INVALID_OPERATION,
3637 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:033638 return;
3639 }
3640 service_id = info->service_id();
3641 }
[email protected]9edc6b22010-12-23 02:00:263642 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033643 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]1002c2d2011-06-28 22:39:043644 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263645 if (error == GL_NO_ERROR) {
3646 framebuffer_info->AttachTexture(attachment, info, textarget, level);
3647 if (service_id != 0 &&
3648 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
3649 ClearUnclearedRenderbuffers(target, framebuffer_info);
3650 }
[email protected]3a2e7c7b2010-08-06 01:12:283651 }
[email protected]297ca1c2011-06-20 23:08:463652 if (framebuffer_info == bound_draw_framebuffer_) {
3653 state_dirty_ = true;
3654 }
[email protected]36cef8ce2010-03-16 07:34:453655}
3656
3657void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
3658 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:303659 FramebufferManager::FramebufferInfo* framebuffer_info =
3660 GetFramebufferInfoForTarget(target);
3661 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293662 SetGLError(GL_INVALID_OPERATION,
3663 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453664 return;
3665 }
3666 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:573667 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
3668 GLint type = 0;
3669 GLuint client_id = 0;
3670 glGetFramebufferAttachmentParameterivEXT(
3671 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
3672 switch (type) {
3673 case GL_RENDERBUFFER: {
3674 renderbuffer_manager()->GetClientId(*params, &client_id);
3675 break;
3676 }
3677 case GL_TEXTURE: {
3678 texture_manager()->GetClientId(*params, &client_id);
3679 break;
3680 }
3681 default:
3682 break;
3683 }
3684 *params = client_id;
3685 }
[email protected]36cef8ce2010-03-16 07:34:453686}
3687
3688void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
3689 GLenum target, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:083690 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293691 SetGLError(GL_INVALID_OPERATION,
3692 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453693 return;
3694 }
[email protected]3a03a8f2011-03-19 00:51:273695 switch (pname) {
3696 case GL_RENDERBUFFER_INTERNAL_FORMAT:
[email protected]b71f52c2010-06-18 22:20:203697 *params = bound_renderbuffer_->internal_format();
[email protected]3a03a8f2011-03-19 00:51:273698 break;
3699 case GL_RENDERBUFFER_WIDTH:
3700 *params = bound_renderbuffer_->width();
3701 break;
3702 case GL_RENDERBUFFER_HEIGHT:
3703 *params = bound_renderbuffer_->height();
3704 break;
3705 default:
3706 glGetRenderbufferParameterivEXT(target, pname, params);
3707 break;
[email protected]b71f52c2010-06-18 22:20:203708 }
[email protected]36cef8ce2010-03-16 07:34:453709}
3710
[email protected]8e3e0662010-08-23 18:46:303711void GLES2DecoderImpl::DoBlitFramebufferEXT(
3712 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
3713 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
3714 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:393715 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303716 SetGLError(GL_INVALID_OPERATION,
3717 "glBlitFramebufferEXT: function not available");
3718 }
[email protected]5094b0f2010-11-09 19:45:243719 if (IsAngle()) {
3720 glBlitFramebufferANGLE(
3721 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3722 } else {
3723 glBlitFramebufferEXT(
3724 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3725 }
[email protected]8e3e0662010-08-23 18:46:303726}
3727
3728void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
3729 GLenum target, GLsizei samples, GLenum internalformat,
3730 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:393731 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303732 SetGLError(GL_INVALID_OPERATION,
3733 "glRenderbufferStorageMultisampleEXT: function not available");
3734 return;
3735 }
[email protected]8e3e0662010-08-23 18:46:303736
[email protected]9edc6b22010-12-23 02:00:263737 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:303738 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:263739 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:303740 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:263741 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:303742 break;
3743 case GL_RGBA4:
3744 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:263745 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:303746 break;
3747 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:263748 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:303749 break;
3750 }
3751 }
3752
[email protected]9edc6b22010-12-23 02:00:263753 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:083754 if (IsAngle()) {
3755 glRenderbufferStorageMultisampleANGLE(
3756 target, samples, impl_format, width, height);
3757 } else {
3758 glRenderbufferStorageMultisampleEXT(
3759 target, samples, impl_format, width, height);
3760 }
[email protected]1002c2d2011-06-28 22:39:043761 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263762 if (error == GL_NO_ERROR) {
3763 bound_renderbuffer_->SetInfo(samples, internalformat, width, height);
3764 }
[email protected]8e3e0662010-08-23 18:46:303765}
3766
[email protected]36cef8ce2010-03-16 07:34:453767void GLES2DecoderImpl::DoRenderbufferStorage(
3768 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]051b1372010-04-12 02:42:083769 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293770 SetGLError(GL_INVALID_OPERATION,
3771 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453772 return;
3773 }
[email protected]876f6fee2010-08-02 23:10:323774
[email protected]9edc6b22010-12-23 02:00:263775 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:323776 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:263777 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:323778 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:263779 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:323780 break;
3781 case GL_RGBA4:
3782 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:263783 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:323784 break;
3785 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:263786 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:323787 break;
3788 }
[email protected]b71f52c2010-06-18 22:20:203789 }
[email protected]876f6fee2010-08-02 23:10:323790
[email protected]9edc6b22010-12-23 02:00:263791 CopyRealGLErrorsToWrapper();
3792 glRenderbufferStorageEXT(target, impl_format, width, height);
[email protected]1002c2d2011-06-28 22:39:043793 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263794 if (error == GL_NO_ERROR) {
3795 bound_renderbuffer_->SetInfo(0, internalformat, width, height);
3796 }
[email protected]36cef8ce2010-03-16 07:34:453797}
3798
[email protected]07f54fcc2009-12-22 02:46:303799void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]0c8fabf2011-06-14 19:35:223800 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]6b8cf1a2010-05-06 16:13:583801 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3802 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:473803 if (!info) {
[email protected]a93bb842010-02-16 23:03:473804 return;
3805 }
[email protected]05afda12011-01-20 00:17:343806
[email protected]d685a682011-04-29 16:19:573807 info->Link();
[email protected]07f54fcc2009-12-22 02:46:303808};
3809
[email protected]3916c97e2010-02-25 03:20:503810void GLES2DecoderImpl::DoTexParameterf(
3811 GLenum target, GLenum pname, GLfloat param) {
3812 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:303813 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293814 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243815 return;
[email protected]07f54fcc2009-12-22 02:46:303816 }
[email protected]cbb22e42011-05-12 23:36:243817
3818 if (!texture_manager()->SetParameter(
3819 feature_info_, info, pname, static_cast<GLint>(param))) {
3820 SetGLError(GL_INVALID_ENUM, "glTexParameterf: param GL_INVALID_ENUM");
3821 return;
3822 }
3823 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:303824}
3825
[email protected]3916c97e2010-02-25 03:20:503826void GLES2DecoderImpl::DoTexParameteri(
3827 GLenum target, GLenum pname, GLint param) {
3828 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3829 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293830 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243831 return;
[email protected]3916c97e2010-02-25 03:20:503832 }
[email protected]cbb22e42011-05-12 23:36:243833
3834 if (!texture_manager()->SetParameter(feature_info_, info, pname, param)) {
3835 SetGLError(GL_INVALID_ENUM, "glTexParameteri: param GL_INVALID_ENUM");
3836 return;
3837 }
3838 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:503839}
3840
3841void GLES2DecoderImpl::DoTexParameterfv(
3842 GLenum target, GLenum pname, const GLfloat* params) {
3843 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3844 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293845 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243846 return;
[email protected]3916c97e2010-02-25 03:20:503847 }
[email protected]cbb22e42011-05-12 23:36:243848
3849 if (!texture_manager()->SetParameter(
3850 feature_info_, info, pname, static_cast<GLint>(params[0]))) {
3851 SetGLError(GL_INVALID_ENUM, "glTexParameterfv: param GL_INVALID_ENUM");
3852 return;
3853 }
3854 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:503855}
3856
3857void GLES2DecoderImpl::DoTexParameteriv(
3858 GLenum target, GLenum pname, const GLint* params) {
3859 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3860 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293861 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243862 return;
[email protected]3916c97e2010-02-25 03:20:503863 }
[email protected]cbb22e42011-05-12 23:36:243864
3865 if (!texture_manager()->SetParameter(feature_info_, info, pname, *params)) {
3866 SetGLError(GL_INVALID_ENUM, "glTexParameteriv: param GL_INVALID_ENUM");
3867 return;
3868 }
3869 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:503870}
3871
[email protected]939e7362010-05-13 20:49:103872bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:143873 if (!current_program_) {
[email protected]939e7362010-05-13 20:49:103874 // The program does not exist.
3875 SetGLError(GL_INVALID_OPERATION,
3876 (std::string(function_name) + ": no program in use").c_str());
3877 return false;
3878 }
[email protected]ca488e12010-12-13 20:06:143879 if (!current_program_->InUse()) {
[email protected]939e7362010-05-13 20:49:103880 SetGLError(GL_INVALID_OPERATION,
3881 (std::string(function_name) + ": program not linked").c_str());
3882 return false;
3883 }
3884 return true;
3885}
3886
3887bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
3888 GLint location, const char* function_name) {
3889 if (!CheckCurrentProgram(function_name)) {
3890 return false;
3891 }
3892 return location != -1;
3893}
3894
[email protected]43c2f1f2011-03-25 18:35:363895bool GLES2DecoderImpl::PrepForSetUniformByLocation(
3896 GLint location, const char* function_name, GLenum* type, GLsizei* count) {
3897 DCHECK(type);
3898 DCHECK(count);
[email protected]939e7362010-05-13 20:49:103899 if (!CheckCurrentProgramForUniform(location, function_name)) {
3900 return false;
3901 }
[email protected]43c2f1f2011-03-25 18:35:363902 GLint array_index = -1;
3903 const ProgramManager::ProgramInfo::UniformInfo* info =
3904 current_program_->GetUniformInfoByLocation(location, &array_index);
3905 if (!info) {
[email protected]939e7362010-05-13 20:49:103906 SetGLError(GL_INVALID_OPERATION,
[email protected]43c2f1f2011-03-25 18:35:363907 (std::string(function_name) + ": unknown location").c_str());
[email protected]939e7362010-05-13 20:49:103908 return false;
3909 }
[email protected]43c2f1f2011-03-25 18:35:363910 if (*count > 1 && !info->is_array) {
3911 SetGLError(
3912 GL_INVALID_OPERATION,
3913 (std::string(function_name) + ": count > 1 for non-array").c_str());
3914 return false;
3915 }
3916 *count = std::min(info->size - array_index, *count);
3917 if (*count <= 0) {
3918 return false;
3919 }
3920 *type = info->type;
[email protected]939e7362010-05-13 20:49:103921 return true;
3922}
3923
[email protected]939e7362010-05-13 20:49:103924void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
3925 if (!CheckCurrentProgramForUniform(location, "glUniform1i")) {
[email protected]3916c97e2010-02-25 03:20:503926 return;
3927 }
3928 current_program_->SetSamplers(location, 1, &v0);
3929 glUniform1i(location, v0);
3930}
3931
3932void GLES2DecoderImpl::DoUniform1iv(
3933 GLint location, GLsizei count, const GLint *value) {
[email protected]939e7362010-05-13 20:49:103934 if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) {
[email protected]3916c97e2010-02-25 03:20:503935 return;
3936 }
[email protected]43c2f1f2011-03-25 18:35:363937 GLenum type = 0;
3938 if (!PrepForSetUniformByLocation(location, "glUniform1iv", &type, &count)) {
3939 return;
3940 }
[email protected]61eeb33f2011-07-26 15:30:313941 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
3942 type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]43c2f1f2011-03-25 18:35:363943 current_program_->SetSamplers(location, count, value);
3944 }
[email protected]3916c97e2010-02-25 03:20:503945 glUniform1iv(location, count, value);
3946}
3947
[email protected]939e7362010-05-13 20:49:103948void GLES2DecoderImpl::DoUniform1fv(
3949 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363950 GLenum type = 0;
3951 if (!PrepForSetUniformByLocation(location, "glUniform1fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103952 return;
3953 }
3954 if (type == GL_BOOL) {
3955 scoped_array<GLint> temp(new GLint[count]);
3956 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:533957 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103958 }
3959 DoUniform1iv(location, count, temp.get());
3960 } else {
3961 glUniform1fv(location, count, value);
3962 }
3963}
3964
3965void GLES2DecoderImpl::DoUniform2fv(
3966 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363967 GLenum type = 0;
3968 if (!PrepForSetUniformByLocation(location, "glUniform2fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103969 return;
3970 }
3971 if (type == GL_BOOL_VEC2) {
3972 GLsizei num_values = count * 2;
3973 scoped_array<GLint> temp(new GLint[num_values]);
3974 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533975 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103976 }
3977 glUniform2iv(location, count, temp.get());
3978 } else {
3979 glUniform2fv(location, count, value);
3980 }
3981}
3982
3983void GLES2DecoderImpl::DoUniform3fv(
3984 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363985 GLenum type = 0;
3986 if (!PrepForSetUniformByLocation(location, "glUniform3fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103987 return;
3988 }
3989 if (type == GL_BOOL_VEC3) {
3990 GLsizei num_values = count * 3;
3991 scoped_array<GLint> temp(new GLint[num_values]);
3992 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533993 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103994 }
3995 glUniform3iv(location, count, temp.get());
3996 } else {
3997 glUniform3fv(location, count, value);
3998 }
3999}
4000
4001void GLES2DecoderImpl::DoUniform4fv(
4002 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364003 GLenum type = 0;
4004 if (!PrepForSetUniformByLocation(location, "glUniform4fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104005 return;
4006 }
4007 if (type == GL_BOOL_VEC4) {
4008 GLsizei num_values = count * 4;
4009 scoped_array<GLint> temp(new GLint[num_values]);
4010 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534011 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104012 }
4013 glUniform4iv(location, count, temp.get());
4014 } else {
4015 glUniform4fv(location, count, value);
4016 }
4017}
4018
[email protected]43c2f1f2011-03-25 18:35:364019void GLES2DecoderImpl::DoUniform2iv(
4020 GLint location, GLsizei count, const GLint* value) {
4021 GLenum type = 0;
4022 if (!PrepForSetUniformByLocation(location, "glUniform2iv", &type, &count)) {
4023 return;
4024 }
4025 glUniform2iv(location, count, value);
4026}
4027
4028void GLES2DecoderImpl::DoUniform3iv(
4029 GLint location, GLsizei count, const GLint* value) {
4030 GLenum type = 0;
4031 if (!PrepForSetUniformByLocation(location, "glUniform3iv", &type, &count)) {
4032 return;
4033 }
4034 glUniform3iv(location, count, value);
4035}
4036
4037void GLES2DecoderImpl::DoUniform4iv(
4038 GLint location, GLsizei count, const GLint* value) {
4039 GLenum type = 0;
4040 if (!PrepForSetUniformByLocation(location, "glUniform4iv", &type, &count)) {
4041 return;
4042 }
4043 glUniform4iv(location, count, value);
4044}
4045
4046void GLES2DecoderImpl::DoUniformMatrix2fv(
4047 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4048 GLenum type = 0;
4049 if (!PrepForSetUniformByLocation(
4050 location, "glUniformMatrix2fv", &type, &count)) {
4051 return;
4052 }
4053 glUniformMatrix2fv (location, count, transpose, value);
4054}
4055
4056void GLES2DecoderImpl::DoUniformMatrix3fv(
4057 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4058 GLenum type = 0;
4059 if (!PrepForSetUniformByLocation(
4060 location, "glUniformMatrix3fv", &type, &count)) {
4061 return;
4062 }
4063 glUniformMatrix3fv (location, count, transpose, value);
4064}
4065
4066void GLES2DecoderImpl::DoUniformMatrix4fv(
4067 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4068 GLenum type = 0;
4069 if (!PrepForSetUniformByLocation(
4070 location, "glUniformMatrix4fv", &type, &count)) {
4071 return;
4072 }
4073 glUniformMatrix4fv (location, count, transpose, value);
4074}
4075
[email protected]3916c97e2010-02-25 03:20:504076void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:034077 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:504078 ProgramManager::ProgramInfo* info = NULL;
4079 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:584080 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:504081 if (!info) {
[email protected]ae51d192010-04-27 00:48:034082 return;
4083 }
4084 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:504085 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:294086 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:504087 return;
4088 }
[email protected]ae51d192010-04-27 00:48:034089 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:504090 }
[email protected]ca488e12010-12-13 20:06:144091 if (current_program_) {
4092 program_manager()->UnuseProgram(shader_manager(), current_program_);
4093 }
[email protected]3916c97e2010-02-25 03:20:504094 current_program_ = info;
[email protected]ca488e12010-12-13 20:06:144095 if (current_program_) {
4096 program_manager()->UseProgram(current_program_);
4097 }
[email protected]ae51d192010-04-27 00:48:034098 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:504099}
4100
[email protected]96449d2c2009-11-25 00:01:324101GLenum GLES2DecoderImpl::GetGLError() {
4102 // Check the GL error first, then our wrapped error.
4103 GLenum error = glGetError();
4104 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:374105 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:324106 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:294107 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:324108 break;
4109 }
4110 }
4111 }
4112
4113 if (error != GL_NO_ERROR) {
4114 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:294115 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324116 }
4117 return error;
4118}
4119
[email protected]1002c2d2011-06-28 22:39:044120GLenum GLES2DecoderImpl::PeekGLError() {
4121 GLenum error = glGetError();
4122 if (error != GL_NO_ERROR) {
4123 SetGLError(error, "");
4124 }
4125 return error;
4126}
4127
[email protected]8eee29c2010-04-29 03:38:294128void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
4129 if (msg) {
4130 last_error_ = msg;
[email protected]d0498742010-09-20 20:27:014131 LOG(ERROR) << last_error_;
[email protected]8eee29c2010-04-29 03:38:294132 }
[email protected]ddd968b82010-03-02 00:44:294133 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324134}
4135
[email protected]07f54fcc2009-12-22 02:46:304136void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
4137 GLenum error;
4138 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294139 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:304140 }
4141}
4142
[email protected]6217d392010-03-25 22:08:354143void GLES2DecoderImpl::ClearRealGLErrors() {
4144 GLenum error;
4145 while ((error = glGetError()) != GL_NO_ERROR) {
4146 NOTREACHED() << "GL error " << error << " was unhandled.";
4147 }
4148}
4149
[email protected]ef526492010-06-02 23:12:254150bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:504151 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:254152 // Only check if there are some unrenderable textures.
4153 if (!texture_manager()->HaveUnrenderableTextures()) {
4154 return false;
4155 }
4156 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:504157 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4158 current_program_->sampler_indices();
4159 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4160 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4161 current_program_->GetUniformInfo(sampler_indices[ii]);
4162 DCHECK(uniform_info);
4163 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4164 GLuint texture_unit_index = uniform_info->texture_units[jj];
4165 if (texture_unit_index < group_->max_texture_units()) {
4166 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4167 TextureManager::TextureInfo* texture_info =
[email protected]61eeb33f2011-07-26 15:30:314168 texture_unit.GetInfoForSamplerType(uniform_info->type);
[email protected]915a59a12010-09-30 21:29:114169 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]ef526492010-06-02 23:12:254170 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:504171 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4172 glBindTexture(
[email protected]61eeb33f2011-07-26 15:30:314173 GetBindTargetForSamplerType(uniform_info->type),
[email protected]00f893d2010-08-24 18:55:494174 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:504175 }
4176 }
4177 // else: should this be an error?
4178 }
4179 }
[email protected]ef526492010-06-02 23:12:254180 return textures_set;
[email protected]3916c97e2010-02-25 03:20:504181}
4182
4183void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
4184 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:504185 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4186 current_program_->sampler_indices();
4187 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4188 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4189 current_program_->GetUniformInfo(sampler_indices[ii]);
4190 DCHECK(uniform_info);
4191 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4192 GLuint texture_unit_index = uniform_info->texture_units[jj];
4193 if (texture_unit_index < group_->max_texture_units()) {
4194 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4195 TextureManager::TextureInfo* texture_info =
4196 uniform_info->type == GL_SAMPLER_2D ?
4197 texture_unit.bound_texture_2d :
4198 texture_unit.bound_texture_cube_map;
[email protected]915a59a12010-09-30 21:29:114199 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]3916c97e2010-02-25 03:20:504200 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4201 // Get the texture info that was previously bound here.
4202 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
4203 texture_unit.bound_texture_2d :
4204 texture_unit.bound_texture_cube_map;
4205 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:034206 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:504207 }
4208 }
4209 }
4210 }
4211 // Set the active texture back to whatever the user had it as.
4212 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:304213}
4214
4215bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]689fa1c52010-06-09 18:35:034216 // NOTE: We specifically do not check current_program->IsValid() because
4217 // it could never be invalid since glUseProgram would have failed. While
4218 // glLinkProgram could later mark the program as invalid the previous
4219 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:144220 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:504221 // The program does not exist.
4222 // But GL says no ERROR.
4223 return false;
4224 }
[email protected]f39f4b3f2010-05-12 17:04:084225 // Validate all attribs currently enabled. If they are used by the current
4226 // program then check that they have enough elements to handle the draw call.
4227 // If they are not used by the current program check that they have a buffer
4228 // assigned.
4229 const VertexAttribManager::VertexAttribInfoList& infos =
4230 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4231 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:404232 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:084233 const VertexAttribManager::VertexAttribInfo* info = *it;
4234 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4235 current_program_->GetAttribInfoByLocation(info->index());
4236 if (attrib_info) {
4237 // This attrib is used in the current program.
4238 if (!info->CanAccess(max_vertex_accessed)) {
4239 SetGLError(GL_INVALID_OPERATION,
4240 "glDrawXXX: attempt to access out of range vertices");
4241 return false;
4242 }
4243 } else {
4244 // This attrib is not used in the current program.
4245 if (!info->buffer() || info->buffer()->IsDeleted()) {
4246 SetGLError(
4247 GL_INVALID_OPERATION,
4248 "glDrawXXX: attempt to render with no buffer attached to enabled "
4249 "attrib");
4250 return false;
4251 }
[email protected]1d32bc82010-01-13 22:06:464252 }
[email protected]07f54fcc2009-12-22 02:46:304253 }
[email protected]3916c97e2010-02-25 03:20:504254 return true;
[email protected]b1122982010-05-17 23:04:244255}
4256
4257bool GLES2DecoderImpl::SimulateAttrib0(GLuint max_vertex_accessed) {
[email protected]876f6fee2010-08-02 23:10:324258 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4259 return false;
4260
[email protected]b1122982010-05-17 23:04:244261 const VertexAttribManager::VertexAttribInfo* info =
4262 vertex_attrib_manager_.GetVertexAttribInfo(0);
4263 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:494264 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
4265 if (info->enabled() && attrib_0_used) {
[email protected]b1122982010-05-17 23:04:244266 return false;
4267 }
4268
4269 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
4270
4271 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
4272
4273 // Make a buffer with a single repeated vec4 value enough to
4274 // simulate the constant value that is supposed to be here.
4275 // This is required to emulate GLES2 on GL.
4276 GLsizei num_vertices = max_vertex_accessed + 1;
4277 GLsizei size_needed = num_vertices * sizeof(Vec4); // NOLINT
[email protected]fc753442011-02-04 19:49:494278 if (size_needed > attrib_0_size_) {
4279 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
4280 // TODO(gman): check for error here?
4281 attrib_0_buffer_matches_value_ = false;
4282 }
4283 if (attrib_0_used &&
4284 (!attrib_0_buffer_matches_value_ ||
4285 (info->value().v[0] != attrib_0_value_.v[0] ||
4286 info->value().v[1] != attrib_0_value_.v[1] ||
4287 info->value().v[2] != attrib_0_value_.v[2] ||
4288 info->value().v[3] != attrib_0_value_.v[3]))) {
4289 std::vector<Vec4> temp(num_vertices, info->value());
4290 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
4291 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:244292 attrib_0_value_ = info->value();
4293 attrib_0_size_ = size_needed;
4294 }
4295
4296 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4297
4298 return true;
[email protected]b1122982010-05-17 23:04:244299}
4300
4301void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
4302 const VertexAttribManager::VertexAttribInfo* info =
4303 vertex_attrib_manager_.GetVertexAttribInfo(0);
4304 const void* ptr = reinterpret_cast<const void*>(info->offset());
4305 BufferManager::BufferInfo* buffer_info = info->buffer();
4306 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
4307 glVertexAttribPointer(
4308 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
4309 ptr);
4310 glBindBuffer(GL_ARRAY_BUFFER,
4311 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4312}
[email protected]07f54fcc2009-12-22 02:46:304313
[email protected]8fbedc02010-11-18 18:43:404314bool GLES2DecoderImpl::SimulateFixedAttribs(
4315 GLuint max_vertex_accessed, bool* simulated) {
4316 DCHECK(simulated);
4317 *simulated = false;
4318 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4319 return true;
4320
4321 if (!vertex_attrib_manager_.HaveFixedAttribs()) {
4322 return true;
4323 }
4324
4325 // NOTE: we could be smart and try to check if a buffer is used
4326 // twice in 2 different attribs, find the overlapping parts and therefore
4327 // duplicate the minimum amount of data but this whole code path is not meant
4328 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
4329 // tests so we just add to the buffer attrib used.
4330
4331 // Compute the number of elements needed.
4332 int num_vertices = max_vertex_accessed + 1;
4333 int elements_needed = 0;
4334 const VertexAttribManager::VertexAttribInfoList& infos =
4335 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4336 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4337 infos.begin(); it != infos.end(); ++it) {
4338 const VertexAttribManager::VertexAttribInfo* info = *it;
4339 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4340 current_program_->GetAttribInfoByLocation(info->index());
4341 if (attrib_info &&
4342 info->CanAccess(max_vertex_accessed) &&
4343 info->type() == GL_FIXED) {
4344 int elements_used = 0;
4345 if (!SafeMultiply(
4346 static_cast<int>(num_vertices),
4347 info->size(), &elements_used) ||
4348 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
4349 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4350 return false;
4351 }
4352 }
4353 }
4354
4355 const int kSizeOfFloat = sizeof(float); // NOLINT
4356 int size_needed = 0;
4357 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed)) {
4358 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4359 return false;
4360 }
4361
4362
4363 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
4364 if (size_needed > fixed_attrib_buffer_size_) {
4365 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
4366 }
4367
4368 // Copy the elements and convert to float
4369 GLintptr offset = 0;
4370 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4371 infos.begin(); it != infos.end(); ++it) {
4372 const VertexAttribManager::VertexAttribInfo* info = *it;
4373 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4374 current_program_->GetAttribInfoByLocation(info->index());
4375 if (attrib_info &&
4376 info->CanAccess(max_vertex_accessed) &&
4377 info->type() == GL_FIXED) {
4378 int num_elements = info->size() * kSizeOfFloat;
4379 int size = num_elements * num_vertices;
4380 scoped_array<float> data(new float[size]);
4381 const int32* src = reinterpret_cast<const int32 *>(
4382 info->buffer()->GetRange(info->offset(), size));
4383 const int32* end = src + num_elements;
4384 float* dst = data.get();
4385 while (src != end) {
4386 *dst++ = static_cast<float>(*src++) / 65536.0f;
4387 }
4388 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
4389 glVertexAttribPointer(
4390 info->index(), info->size(), GL_FLOAT, false, 0,
4391 reinterpret_cast<GLvoid*>(offset));
4392 offset += size;
4393 }
4394 }
4395 *simulated = true;
4396 return true;
4397}
4398
4399void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
4400 // There's no need to call glVertexAttribPointer because we shadow all the
4401 // settings and passing GL_FIXED to it will not work.
4402 glBindBuffer(GL_ARRAY_BUFFER,
4403 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4404}
4405
[email protected]38d139d2011-07-14 00:38:434406error::Error GLES2DecoderImpl::HandleDrawArrays(
4407 uint32 immediate_data_size, const gles2::DrawArrays& c) {
4408 GLenum mode = static_cast<GLenum>(c.mode);
4409 GLint first = static_cast<GLint>(c.first);
4410 GLsizei count = static_cast<GLsizei>(c.count);
4411 if (!validators_->draw_mode.IsValid(mode)) {
4412 SetGLError(GL_INVALID_ENUM, "glDrawArrays: mode GL_INVALID_ENUM");
4413 return error::kNoError;
4414 }
4415 if (count < 0) {
4416 SetGLError(GL_INVALID_VALUE, "glDrawArrays: count < 0");
4417 return error::kNoError;
4418 }
4419 if (!CheckFramebufferComplete("glDrawArrays")) {
4420 return error::kNoError;
4421 }
4422 // We have to check this here because the prototype for glDrawArrays
4423 // is GLint not GLsizei.
4424 if (first < 0) {
4425 SetGLError(GL_INVALID_VALUE, "glDrawArrays: first < 0");
4426 return error::kNoError;
4427 }
4428
4429 if (count == 0) {
4430 return error::kNoError;
4431 }
4432
4433 GLuint max_vertex_accessed = first + count - 1;
4434 if (IsDrawValid(max_vertex_accessed)) {
4435 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
4436 bool simulated_fixed_attribs = false;
4437 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
4438 bool textures_set = SetBlackTextureForNonRenderableTextures();
4439 ApplyDirtyState();
4440 glDrawArrays(mode, first, count);
4441 if (textures_set) {
4442 RestoreStateForNonRenderableTextures();
4443 }
4444 if (simulated_fixed_attribs) {
4445 RestoreStateForSimulatedFixedAttribs();
4446 }
4447 }
4448 if (simulated_attrib_0) {
4449 RestoreStateForSimulatedAttrib0();
4450 }
4451 if (WasContextLost()) {
4452 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawArrays.";
4453 return error::kLostContext;
4454 }
4455 }
4456 return error::kNoError;
4457}
4458
[email protected]f7a64ee2010-02-01 22:24:144459error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:194460 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:504461 if (!bound_element_array_buffer_ ||
4462 bound_element_array_buffer_->IsDeleted()) {
[email protected]8eee29c2010-04-29 03:38:294463 SetGLError(GL_INVALID_OPERATION,
4464 "glDrawElements: No element array buffer bound");
4465 return error::kNoError;
4466 }
4467
4468 GLenum mode = c.mode;
4469 GLsizei count = c.count;
4470 GLenum type = c.type;
4471 int32 offset = c.index_offset;
4472 if (count < 0) {
4473 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
4474 return error::kNoError;
4475 }
4476 if (offset < 0) {
4477 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
4478 return error::kNoError;
4479 }
[email protected]9438b012010-06-15 22:55:054480 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:294481 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
4482 return error::kNoError;
4483 }
[email protected]9438b012010-06-15 22:55:054484 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294485 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
4486 return error::kNoError;
4487 }
4488
[email protected]3a03a8f2011-03-19 00:51:274489 if (!CheckFramebufferComplete("glDrawElements")) {
4490 return error::kNoError;
4491 }
4492
[email protected]6c788fb72010-08-26 02:16:314493 if (count == 0) {
4494 return error::kNoError;
4495 }
4496
[email protected]8eee29c2010-04-29 03:38:294497 GLuint max_vertex_accessed;
4498 if (!bound_element_array_buffer_->GetMaxValueForRange(
4499 offset, count, type, &max_vertex_accessed)) {
4500 SetGLError(GL_INVALID_OPERATION,
4501 "glDrawElements: range out of bounds for buffer");
4502 return error::kNoError;
4503 }
4504
4505 if (IsDrawValid(max_vertex_accessed)) {
[email protected]b1122982010-05-17 23:04:244506 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
[email protected]8fbedc02010-11-18 18:43:404507 bool simulated_fixed_attribs = false;
4508 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
4509 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:464510 ApplyDirtyState();
[email protected]8fbedc02010-11-18 18:43:404511 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
4512 glDrawElements(mode, count, type, indices);
4513 if (textures_set) {
4514 RestoreStateForNonRenderableTextures();
4515 }
4516 if (simulated_fixed_attribs) {
4517 RestoreStateForSimulatedFixedAttribs();
4518 }
[email protected]ba3176a2009-12-16 18:19:464519 }
[email protected]b1122982010-05-17 23:04:244520 if (simulated_attrib_0) {
4521 RestoreStateForSimulatedAttrib0();
4522 }
[email protected]38d139d2011-07-14 00:38:434523 if (WasContextLost()) {
4524 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawElements.";
4525 return error::kLostContext;
4526 }
[email protected]96449d2c2009-11-25 00:01:324527 }
[email protected]f7a64ee2010-02-01 22:24:144528 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324529}
4530
[email protected]269200b12010-11-18 22:53:064531GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:234532 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
4533 GLuint max_vertex_accessed = 0;
4534 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:294535 if (!info) {
[email protected]ae51d192010-04-27 00:48:034536 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:294537 SetGLError(GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:064538 "GetMaxValueInBufferCHROMIUM: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:234539 } else {
4540 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:034541 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:064542 SetGLError(
4543 GL_INVALID_OPERATION,
4544 "GetMaxValueInBufferCHROMIUM: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:234545 }
4546 }
4547 return max_vertex_accessed;
4548}
4549
[email protected]96449d2c2009-11-25 00:01:324550// Calls glShaderSource for the various versions of the ShaderSource command.
4551// Assumes that data / data_size points to a piece of memory that is in range
4552// of whatever context it came from (shared memory, immediate memory, bucket
4553// memory.)
[email protected]45bf5152010-02-12 00:11:314554error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034555 GLuint client_id, const char* data, uint32 data_size) {
[email protected]6b8cf1a2010-05-06 16:13:584556 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4557 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:314558 if (!info) {
[email protected]45bf5152010-02-12 00:11:314559 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324560 }
[email protected]45bf5152010-02-12 00:11:314561 // Note: We don't actually call glShaderSource here. We wait until
4562 // the call to glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:524563 info->Update(std::string(data, data + data_size).c_str());
[email protected]f7a64ee2010-02-01 22:24:144564 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324565}
4566
[email protected]f7a64ee2010-02-01 22:24:144567error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:194568 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:324569 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314570 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:324571 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:464572 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144573 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324574 }
[email protected]ae51d192010-04-27 00:48:034575 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:324576}
4577
[email protected]f7a64ee2010-02-01 22:24:144578error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:194579 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:324580 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314581 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:304582 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:464583 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144584 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324585 }
[email protected]ae51d192010-04-27 00:48:034586 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:314587}
4588
[email protected]558847a2010-03-24 07:02:544589error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
4590 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:544591 Bucket* bucket = GetBucket(c.data_bucket_id);
4592 if (!bucket || bucket->size() == 0) {
4593 return error::kInvalidArguments;
4594 }
4595 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034596 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:544597 bucket->size() - 1);
4598}
4599
[email protected]ae51d192010-04-27 00:48:034600void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]0c8fabf2011-06-14 19:35:224601 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]6b8cf1a2010-05-06 16:13:584602 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4603 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:314604 if (!info) {
[email protected]45bf5152010-02-12 00:11:314605 return;
4606 }
[email protected]de17df392010-04-23 21:09:414607 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
4608 // glShaderSource and then glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:524609 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:344610 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:184611 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:344612 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:454613 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:234614
[email protected]a550584e2010-09-17 18:01:454615 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:344616 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:184617 return;
4618 }
[email protected]a550584e2010-09-17 18:01:454619 shader_src = translator->translated_shader();
[email protected]de17df392010-04-23 21:09:414620 }
[email protected]de17df392010-04-23 21:09:414621
[email protected]ae51d192010-04-27 00:48:034622 glShaderSource(info->service_id(), 1, &shader_src, NULL);
4623 glCompileShader(info->service_id());
[email protected]e5186162010-06-14 18:54:414624 GLint status = GL_FALSE;
4625 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
4626 if (status) {
[email protected]f57bb282010-11-12 00:51:344627 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:414628 } else {
[email protected]d9977d42010-09-01 20:27:024629 // We cannot reach here if we are using the shader translator.
4630 // All invalid shaders must be rejected by the translator.
4631 // All translated shaders must compile.
4632 LOG_IF(ERROR, use_shader_translator_)
4633 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:334634 GLint max_len = 0;
4635 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
4636 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:414637 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:334638 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
4639 DCHECK(max_len == 0 || len < max_len);
4640 DCHECK(len ==0 || temp[len] == '\0');
[email protected]df6cf1ad2011-01-29 01:20:524641 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
[email protected]e5186162010-06-14 18:54:414642 }
[email protected]45bf5152010-02-12 00:11:314643};
4644
[email protected]ddd968b82010-03-02 00:44:294645void GLES2DecoderImpl::DoGetShaderiv(
4646 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:584647 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4648 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:294649 if (!info) {
[email protected]ddd968b82010-03-02 00:44:294650 return;
4651 }
[email protected]8f1ccdac2010-05-19 21:01:484652 switch (pname) {
4653 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:524654 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:484655 return;
4656 case GL_COMPILE_STATUS:
[email protected]e5186162010-06-14 18:54:414657 *params = info->IsValid();
4658 return;
[email protected]8f1ccdac2010-05-19 21:01:484659 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:524660 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:414661 return;
[email protected]8f1ccdac2010-05-19 21:01:484662 default:
4663 break;
[email protected]ddd968b82010-03-02 00:44:294664 }
[email protected]8f1ccdac2010-05-19 21:01:484665 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:294666}
4667
[email protected]ae51d192010-04-27 00:48:034668error::Error GLES2DecoderImpl::HandleGetShaderSource(
4669 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
4670 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:034671 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4672 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:584673 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4674 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:524675 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:294676 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:294677 return error::kNoError;
4678 }
[email protected]df6cf1ad2011-01-29 01:20:524679 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:034680 return error::kNoError;
4681}
4682
4683error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
4684 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
4685 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:584686 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4687 Bucket* bucket = CreateBucket(bucket_id);
4688 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4689 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:524690 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:464691 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:034692 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:314693 }
[email protected]df6cf1ad2011-01-29 01:20:524694 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:034695 return error::kNoError;
4696}
4697
4698error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
4699 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
4700 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:584701 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4702 Bucket* bucket = CreateBucket(bucket_id);
4703 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4704 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:524705 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:464706 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:034707 return error::kNoError;
4708 }
[email protected]df6cf1ad2011-01-29 01:20:524709 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:034710 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324711}
4712
[email protected]1958e0e2010-04-22 05:17:154713bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364714 const BufferManager::BufferInfo* info = GetBufferInfo(client_id);
4715 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154716}
4717
4718bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364719 const FramebufferManager::FramebufferInfo* info =
4720 GetFramebufferInfo(client_id);
4721 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154722}
4723
4724bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364725 // IsProgram is true for programs as soon as they are created, until they are
4726 // deleted and no longer in use.
[email protected]ae51d192010-04-27 00:48:034727 return GetProgramInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154728}
4729
4730bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364731 const RenderbufferManager::RenderbufferInfo* info =
4732 GetRenderbufferInfo(client_id);
4733 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154734}
4735
4736bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364737 // IsShader is true for shaders as soon as they are created, until they
4738 // are deleted and not attached to any programs.
[email protected]ae51d192010-04-27 00:48:034739 return GetShaderInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154740}
4741
4742bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364743 const TextureManager::TextureInfo* info = GetTextureInfo(client_id);
4744 return info && info->IsValid();
[email protected]ae51d192010-04-27 00:48:034745}
4746
4747void GLES2DecoderImpl::DoAttachShader(
4748 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584749 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4750 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034751 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034752 return;
[email protected]1958e0e2010-04-22 05:17:154753 }
[email protected]6b8cf1a2010-05-06 16:13:584754 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4755 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034756 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034757 return;
4758 }
[email protected]ca488e12010-12-13 20:06:144759 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:314760 SetGLError(GL_INVALID_OPERATION,
4761 "glAttachShader: can not attach more than"
4762 " one shader of the same type.");
4763 return;
4764 }
[email protected]ae51d192010-04-27 00:48:034765 glAttachShader(program_info->service_id(), shader_info->service_id());
4766}
4767
4768void GLES2DecoderImpl::DoDetachShader(
4769 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584770 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4771 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034772 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034773 return;
4774 }
[email protected]6b8cf1a2010-05-06 16:13:584775 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4776 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034777 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034778 return;
4779 }
[email protected]9a0ccd42011-03-16 23:58:224780 if (!program_info->DetachShader(shader_manager(), shader_info)) {
4781 SetGLError(GL_INVALID_OPERATION,
4782 "glDetachShader: shader not attached to program");
4783 return;
4784 }
[email protected]ae51d192010-04-27 00:48:034785 glDetachShader(program_info->service_id(), shader_info->service_id());
4786}
4787
4788void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584789 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4790 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:034791 if (!info) {
[email protected]ae51d192010-04-27 00:48:034792 return;
4793 }
[email protected]d685a682011-04-29 16:19:574794 info->Validate();
[email protected]1958e0e2010-04-22 05:17:154795}
4796
[email protected]b1122982010-05-17 23:04:244797void GLES2DecoderImpl::DoGetVertexAttribfv(
4798 GLuint index, GLenum pname, GLfloat* params) {
4799 VertexAttribManager::VertexAttribInfo* info =
4800 vertex_attrib_manager_.GetVertexAttribInfo(index);
4801 if (!info) {
4802 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
4803 return;
4804 }
4805 switch (pname) {
4806 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4807 BufferManager::BufferInfo* buffer = info->buffer();
4808 if (buffer && !buffer->IsDeleted()) {
4809 GLuint client_id;
4810 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4811 *params = static_cast<GLfloat>(client_id);
4812 }
4813 break;
4814 }
4815 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4816 *params = static_cast<GLfloat>(info->enabled());
4817 break;
4818 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4819 *params = static_cast<GLfloat>(info->size());
4820 break;
4821 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4822 *params = static_cast<GLfloat>(info->gl_stride());
4823 break;
4824 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4825 *params = static_cast<GLfloat>(info->type());
4826 break;
4827 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4828 *params = static_cast<GLfloat>(info->normalized());
4829 break;
4830 case GL_CURRENT_VERTEX_ATTRIB:
4831 params[0] = info->value().v[0];
4832 params[1] = info->value().v[1];
4833 params[2] = info->value().v[2];
4834 params[3] = info->value().v[3];
4835 break;
4836 default:
4837 NOTREACHED();
4838 break;
4839 }
4840}
4841
4842void GLES2DecoderImpl::DoGetVertexAttribiv(
4843 GLuint index, GLenum pname, GLint* params) {
4844 VertexAttribManager::VertexAttribInfo* info =
4845 vertex_attrib_manager_.GetVertexAttribInfo(index);
4846 if (!info) {
4847 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
4848 return;
4849 }
4850 switch (pname) {
4851 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4852 BufferManager::BufferInfo* buffer = info->buffer();
4853 if (buffer && !buffer->IsDeleted()) {
4854 GLuint client_id;
4855 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4856 *params = client_id;
4857 }
4858 break;
4859 }
4860 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4861 *params = info->enabled();
4862 break;
4863 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4864 *params = info->size();
4865 break;
4866 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4867 *params = info->gl_stride();
4868 break;
4869 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4870 *params = info->type();
4871 break;
4872 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4873 *params = static_cast<GLint>(info->normalized());
4874 break;
4875 case GL_CURRENT_VERTEX_ATTRIB:
4876 params[0] = static_cast<GLint>(info->value().v[0]);
4877 params[1] = static_cast<GLint>(info->value().v[1]);
4878 params[2] = static_cast<GLint>(info->value().v[2]);
4879 params[3] = static_cast<GLint>(info->value().v[3]);
4880 break;
4881 default:
4882 NOTREACHED();
4883 break;
4884 }
4885}
4886
4887void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
4888 VertexAttribManager::VertexAttribInfo* info =
4889 vertex_attrib_manager_.GetVertexAttribInfo(index);
4890 if (!info) {
4891 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
4892 return;
4893 }
4894 VertexAttribManager::VertexAttribInfo::Vec4 value;
4895 value.v[0] = v0;
4896 value.v[1] = 0.0f;
4897 value.v[2] = 0.0f;
4898 value.v[3] = 1.0f;
4899 info->set_value(value);
4900 glVertexAttrib1f(index, v0);
4901}
4902
4903void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
4904 VertexAttribManager::VertexAttribInfo* info =
4905 vertex_attrib_manager_.GetVertexAttribInfo(index);
4906 if (!info) {
4907 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
4908 return;
4909 }
4910 VertexAttribManager::VertexAttribInfo::Vec4 value;
4911 value.v[0] = v0;
4912 value.v[1] = v1;
4913 value.v[2] = 0.0f;
4914 value.v[3] = 1.0f;
4915 info->set_value(value);
4916 glVertexAttrib2f(index, v0, v1);
4917}
4918
4919void GLES2DecoderImpl::DoVertexAttrib3f(
4920 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
4921 VertexAttribManager::VertexAttribInfo* info =
4922 vertex_attrib_manager_.GetVertexAttribInfo(index);
4923 if (!info) {
4924 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
4925 return;
4926 }
4927 VertexAttribManager::VertexAttribInfo::Vec4 value;
4928 value.v[0] = v0;
4929 value.v[1] = v1;
4930 value.v[2] = v2;
4931 value.v[3] = 1.0f;
4932 info->set_value(value);
4933 glVertexAttrib3f(index, v0, v1, v2);
4934}
4935
4936void GLES2DecoderImpl::DoVertexAttrib4f(
4937 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
4938 VertexAttribManager::VertexAttribInfo* info =
4939 vertex_attrib_manager_.GetVertexAttribInfo(index);
4940 if (!info) {
4941 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
4942 return;
4943 }
4944 VertexAttribManager::VertexAttribInfo::Vec4 value;
4945 value.v[0] = v0;
4946 value.v[1] = v1;
4947 value.v[2] = v2;
4948 value.v[3] = v3;
4949 info->set_value(value);
4950 glVertexAttrib4f(index, v0, v1, v2, v3);
4951}
4952
4953void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
4954 VertexAttribManager::VertexAttribInfo* info =
4955 vertex_attrib_manager_.GetVertexAttribInfo(index);
4956 if (!info) {
4957 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
4958 return;
4959 }
4960 VertexAttribManager::VertexAttribInfo::Vec4 value;
4961 value.v[0] = v[0];
4962 value.v[1] = 0.0f;
4963 value.v[2] = 0.0f;
4964 value.v[3] = 1.0f;
4965 info->set_value(value);
4966 glVertexAttrib1fv(index, v);
4967}
4968
4969void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
4970 VertexAttribManager::VertexAttribInfo* info =
4971 vertex_attrib_manager_.GetVertexAttribInfo(index);
4972 if (!info) {
4973 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
4974 return;
4975 }
4976 VertexAttribManager::VertexAttribInfo::Vec4 value;
4977 value.v[0] = v[0];
4978 value.v[1] = v[1];
4979 value.v[2] = 0.0f;
4980 value.v[3] = 1.0f;
4981 info->set_value(value);
4982 glVertexAttrib2fv(index, v);
4983}
4984
4985void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
4986 VertexAttribManager::VertexAttribInfo* info =
4987 vertex_attrib_manager_.GetVertexAttribInfo(index);
4988 if (!info) {
4989 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
4990 return;
4991 }
4992 VertexAttribManager::VertexAttribInfo::Vec4 value;
4993 value.v[0] = v[0];
4994 value.v[1] = v[1];
4995 value.v[2] = v[2];
4996 value.v[3] = 1.0f;
4997 info->set_value(value);
4998 glVertexAttrib3fv(index, v);
4999}
5000
5001void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
5002 VertexAttribManager::VertexAttribInfo* info =
5003 vertex_attrib_manager_.GetVertexAttribInfo(index);
5004 if (!info) {
5005 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
5006 return;
5007 }
5008 VertexAttribManager::VertexAttribInfo::Vec4 value;
5009 value.v[0] = v[0];
5010 value.v[1] = v[1];
5011 value.v[2] = v[2];
5012 value.v[3] = v[3];
5013 info->set_value(value);
5014 glVertexAttrib4fv(index, v);
5015}
5016
[email protected]f7a64ee2010-02-01 22:24:145017error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:195018 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:295019 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
5020 SetGLError(GL_INVALID_VALUE,
5021 "glVertexAttribPointer: no array buffer bound");
5022 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325023 }
[email protected]8eee29c2010-04-29 03:38:295024
5025 GLuint indx = c.indx;
5026 GLint size = c.size;
5027 GLenum type = c.type;
5028 GLboolean normalized = c.normalized;
5029 GLsizei stride = c.stride;
5030 GLsizei offset = c.offset;
5031 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:055032 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295033 SetGLError(GL_INVALID_ENUM,
5034 "glVertexAttribPointer: type GL_INVALID_ENUM");
5035 return error::kNoError;
5036 }
[email protected]9438b012010-06-15 22:55:055037 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:315038 SetGLError(GL_INVALID_VALUE,
[email protected]8eee29c2010-04-29 03:38:295039 "glVertexAttribPointer: size GL_INVALID_VALUE");
5040 return error::kNoError;
5041 }
5042 if (indx >= group_->max_vertex_attribs()) {
5043 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
5044 return error::kNoError;
5045 }
5046 if (stride < 0) {
5047 SetGLError(GL_INVALID_VALUE,
5048 "glVertexAttribPointer: stride < 0");
5049 return error::kNoError;
5050 }
5051 if (stride > 255) {
5052 SetGLError(GL_INVALID_VALUE,
5053 "glVertexAttribPointer: stride > 255");
5054 return error::kNoError;
5055 }
5056 if (offset < 0) {
5057 SetGLError(GL_INVALID_VALUE,
5058 "glVertexAttribPointer: offset < 0");
5059 return error::kNoError;
5060 }
5061 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:315062 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:295063 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:315064 SetGLError(GL_INVALID_OPERATION,
5065 "glVertexAttribPointer: offset not valid for type");
5066 return error::kNoError;
5067 }
5068 if (stride % component_size > 0) {
5069 SetGLError(GL_INVALID_OPERATION,
[email protected]8eee29c2010-04-29 03:38:295070 "glVertexAttribPointer: stride not valid for type");
5071 return error::kNoError;
5072 }
[email protected]8fbedc02010-11-18 18:43:405073 vertex_attrib_manager_.SetAttribInfo(
5074 indx,
[email protected]8eee29c2010-04-29 03:38:295075 bound_array_buffer_,
5076 size,
5077 type,
[email protected]b1122982010-05-17 23:04:245078 normalized,
5079 stride,
5080 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:295081 offset);
[email protected]8fbedc02010-11-18 18:43:405082 if (type != GL_FIXED) {
5083 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
5084 }
[email protected]f7a64ee2010-02-01 22:24:145085 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325086}
5087
[email protected]f7a64ee2010-02-01 22:24:145088error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:195089 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:315090 GLint x = c.x;
5091 GLint y = c.y;
5092 GLsizei width = c.width;
5093 GLsizei height = c.height;
5094 GLenum format = c.format;
5095 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:565096 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:295097 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:565098 return error::kNoError;
5099 }
[email protected]a51788e2010-02-24 21:54:255100 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:185101 uint32 pixels_size;
5102 if (!GLES2Util::ComputeImageDataSize(
5103 width, height, format, type, pack_alignment_, &pixels_size)) {
5104 return error::kOutOfBounds;
5105 }
[email protected]612d2f82009-12-08 20:49:315106 void* pixels = GetSharedMemoryAs<void*>(
5107 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:255108 Result* result = GetSharedMemoryAs<Result*>(
5109 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5110 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:145111 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465112 }
[email protected]a51788e2010-02-24 21:54:255113
[email protected]9438b012010-06-15 22:55:055114 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295115 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
5116 return error::kNoError;
5117 }
[email protected]9438b012010-06-15 22:55:055118 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295119 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125120 return error::kNoError;
5121 }
[email protected]57f223832010-03-19 01:57:565122 if (width == 0 || height == 0) {
5123 return error::kNoError;
5124 }
5125
5126 CopyRealGLErrorsToWrapper();
5127
[email protected]de26b3c2011-08-03 21:54:275128 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]34ff8b0c2010-10-01 20:06:025129
[email protected]57f223832010-03-19 01:57:565130 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:305131 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:565132
5133 GLint max_x;
5134 GLint max_y;
5135 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:295136 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:145137 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:315138 }
[email protected]57f223832010-03-19 01:57:565139
[email protected]d37231fa2010-04-09 21:16:025140 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:565141 // The user requested an out of range area. Get the results 1 line
5142 // at a time.
5143 uint32 temp_size;
5144 if (!GLES2Util::ComputeImageDataSize(
5145 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295146 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565147 return error::kNoError;
5148 }
5149 GLsizei unpadded_row_size = temp_size;
5150 if (!GLES2Util::ComputeImageDataSize(
5151 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295152 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565153 return error::kNoError;
5154 }
5155 GLsizei padded_row_size = temp_size - unpadded_row_size;
5156 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:295157 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565158 return error::kNoError;
5159 }
5160
5161 GLint dest_x_offset = std::max(-x, 0);
5162 uint32 dest_row_offset;
5163 if (!GLES2Util::ComputeImageDataSize(
5164 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:295165 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565166 return error::kNoError;
5167 }
5168
5169 // Copy each row into the larger dest rect.
5170 int8* dst = static_cast<int8*>(pixels);
5171 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:025172 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:565173 GLint read_width = read_end_x - read_x;
5174 for (GLint yy = 0; yy < height; ++yy) {
5175 GLint ry = y + yy;
5176
5177 // Clear the row.
5178 memset(dst, 0, unpadded_row_size);
5179
5180 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:025181 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:565182 glReadPixels(
5183 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
5184 }
5185 dst += padded_row_size;
5186 }
5187 } else {
5188 glReadPixels(x, y, width, height, format, type, pixels);
5189 }
[email protected]1002c2d2011-06-28 22:39:045190 GLenum error = PeekGLError();
[email protected]a51788e2010-02-24 21:54:255191 if (error == GL_NO_ERROR) {
5192 *result = true;
[email protected]4848b9f82011-03-10 18:37:565193
5194 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5195 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5196 if ((channels_exist & 0x0008) == 0) {
5197 // Set the alpha to 255 because some drivers are buggy in this regard.
5198 uint32 temp_size;
5199 if (!GLES2Util::ComputeImageDataSize(
5200 width, 1, format, type, pack_alignment_, &temp_size)) {
5201 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5202 return error::kNoError;
5203 }
5204 GLsizei unpadded_row_size = temp_size;
5205 if (!GLES2Util::ComputeImageDataSize(
5206 width, 2, format, type, pack_alignment_, &temp_size)) {
5207 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5208 return error::kNoError;
5209 }
5210 GLsizei padded_row_size = temp_size - unpadded_row_size;
5211 if (padded_row_size < 0 || unpadded_row_size < 0) {
5212 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5213 return error::kNoError;
5214 }
5215 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
5216 // of this implementation.
5217 if (type != GL_UNSIGNED_BYTE) {
5218 SetGLError(GL_INVALID_OPERATION, "unsupported readPixel format");
5219 return error::kNoError;
5220 }
5221 switch (format) {
5222 case GL_RGBA:
[email protected]297ca1c2011-06-20 23:08:465223 case GL_BGRA_EXT:
[email protected]4848b9f82011-03-10 18:37:565224 case GL_ALPHA: {
5225 int offset = (format == GL_ALPHA) ? 0 : 3;
5226 int step = (format == GL_ALPHA) ? 1 : 4;
5227 uint8* dst = static_cast<uint8*>(pixels) + offset;
5228 for (GLint yy = 0; yy < height; ++yy) {
5229 uint8* end = dst + unpadded_row_size;
5230 for (uint8* d = dst; d < end; d += step) {
5231 *d = 255;
5232 }
5233 dst += padded_row_size;
5234 }
5235 break;
5236 }
5237 default:
5238 break;
5239 }
5240 }
[email protected]a51788e2010-02-24 21:54:255241 }
[email protected]4848b9f82011-03-10 18:37:565242
[email protected]f7a64ee2010-02-01 22:24:145243 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325244}
5245
[email protected]f7a64ee2010-02-01 22:24:145246error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:195247 uint32 immediate_data_size, const gles2::PixelStorei& c) {
5248 GLenum pname = c.pname;
5249 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:055250 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:295251 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125252 return error::kNoError;
5253 }
[email protected]9438b012010-06-15 22:55:055254 if (!validators_->pixel_store_alignment.IsValid(param)) {
[email protected]8eee29c2010-04-29 03:38:295255 SetGLError(GL_INVALID_VALUE, "glPixelSTore: param GL_INVALID_VALUE");
[email protected]f7a64ee2010-02-01 22:24:145256 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195257 }
5258 glPixelStorei(pname, param);
5259 switch (pname) {
5260 case GL_PACK_ALIGNMENT:
5261 pack_alignment_ = param;
5262 break;
5263 case GL_UNPACK_ALIGNMENT:
5264 unpack_alignment_ = param;
5265 break;
5266 default:
5267 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:375268 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:195269 break;
5270 }
[email protected]f7a64ee2010-02-01 22:24:145271 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195272}
5273
[email protected]558847a2010-03-24 07:02:545274error::Error GLES2DecoderImpl::GetAttribLocationHelper(
5275 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5276 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:585277 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5278 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:035279 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145280 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195281 }
[email protected]ae51d192010-04-27 00:48:035282 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295283 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255284 return error::kNoError;
5285 }
[email protected]b9849abf2009-11-25 19:13:195286 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:545287 location_shm_id, location_shm_offset, sizeof(GLint));
5288 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:145289 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195290 }
[email protected]558847a2010-03-24 07:02:545291 // Require the client to init this incase the context is lost and we are no
5292 // longer executing commands.
5293 if (*location != -1) {
5294 return error::kGenericError;
5295 }
[email protected]0bfd9882010-02-05 23:02:255296 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:145297 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195298}
5299
[email protected]558847a2010-03-24 07:02:545300error::Error GLES2DecoderImpl::HandleGetAttribLocation(
5301 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
5302 uint32 name_size = c.data_size;
5303 const char* name = GetSharedMemoryAs<const char*>(
5304 c.name_shm_id, c.name_shm_offset, name_size);
5305 if (!name) {
5306 return error::kOutOfBounds;
5307 }
5308 String name_str(name, name_size);
5309 return GetAttribLocationHelper(
5310 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5311}
5312
[email protected]f7a64ee2010-02-01 22:24:145313error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:195314 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:545315 uint32 name_size = c.data_size;
5316 const char* name = GetImmediateDataAs<const char*>(
5317 c, name_size, immediate_data_size);
5318 if (!name) {
5319 return error::kOutOfBounds;
5320 }
5321 String name_str(name, name_size);
5322 return GetAttribLocationHelper(
5323 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5324}
5325
5326error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
5327 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
5328 Bucket* bucket = GetBucket(c.name_bucket_id);
5329 if (!bucket) {
5330 return error::kInvalidArguments;
5331 }
5332 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185333 if (!bucket->GetAsString(&name_str)) {
5334 return error::kInvalidArguments;
5335 }
[email protected]558847a2010-03-24 07:02:545336 return GetAttribLocationHelper(
5337 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5338}
5339
5340error::Error GLES2DecoderImpl::GetUniformLocationHelper(
5341 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5342 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:585343 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5344 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:035345 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145346 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195347 }
[email protected]ae51d192010-04-27 00:48:035348 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295349 SetGLError(GL_INVALID_OPERATION,
5350 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255351 return error::kNoError;
5352 }
[email protected]b9849abf2009-11-25 19:13:195353 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:545354 location_shm_id, location_shm_offset, sizeof(GLint));
5355 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:145356 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195357 }
[email protected]558847a2010-03-24 07:02:545358 // Require the client to init this incase the context is lost an we are no
5359 // longer executing commands.
5360 if (*location != -1) {
5361 return error::kGenericError;
5362 }
5363 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:145364 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195365}
5366
[email protected]f7a64ee2010-02-01 22:24:145367error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:195368 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:195369 uint32 name_size = c.data_size;
5370 const char* name = GetSharedMemoryAs<const char*>(
5371 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:545372 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:145373 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195374 }
5375 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:545376 return GetUniformLocationHelper(
5377 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195378}
5379
[email protected]f7a64ee2010-02-01 22:24:145380error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:195381 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:195382 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:305383 const char* name = GetImmediateDataAs<const char*>(
5384 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:545385 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:145386 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195387 }
5388 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:545389 return GetUniformLocationHelper(
5390 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5391}
5392
5393error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
5394 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
5395 Bucket* bucket = GetBucket(c.name_bucket_id);
5396 if (!bucket) {
5397 return error::kInvalidArguments;
5398 }
5399 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185400 if (!bucket->GetAsString(&name_str)) {
5401 return error::kInvalidArguments;
5402 }
[email protected]558847a2010-03-24 07:02:545403 return GetUniformLocationHelper(
5404 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195405}
5406
[email protected]ddd968b82010-03-02 00:44:295407error::Error GLES2DecoderImpl::HandleGetString(
5408 uint32 immediate_data_size, const gles2::GetString& c) {
5409 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:055410 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:295411 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:295412 return error::kNoError;
5413 }
[email protected]1958e0e2010-04-22 05:17:155414 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
5415 const char* str = NULL;
5416 switch (name) {
5417 case GL_VERSION:
5418 str = "OpenGL ES 2.0 Chromium";
5419 break;
5420 case GL_SHADING_LANGUAGE_VERSION:
5421 str = "OpenGL ES GLSL ES 1.0 Chromium";
5422 break;
5423 case GL_EXTENSIONS:
[email protected]915a59a12010-09-30 21:29:115424 str = feature_info_->extensions().c_str();
[email protected]1958e0e2010-04-22 05:17:155425 break;
5426 default:
5427 str = gl_str;
5428 break;
5429 }
[email protected]ddd968b82010-03-02 00:44:295430 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:155431 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:295432 return error::kNoError;
5433}
5434
[email protected]0c86dbf2010-03-05 08:14:115435void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:155436 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:055437 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295438 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
5439 return;
5440 }
[email protected]9438b012010-06-15 22:55:055441 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:295442 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:115443 return;
[email protected]3b6ec202010-03-05 05:16:235444 }
5445 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:295446 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:285447 return;
[email protected]3b6ec202010-03-05 05:16:235448 }
5449 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
5450 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295451 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285452 return;
[email protected]3b6ec202010-03-05 05:16:235453 }
5454 // Clear the buffer to 0 if no initial data was passed in.
5455 scoped_array<int8> zero;
5456 if (!data) {
5457 zero.reset(new int8[size]);
5458 memset(zero.get(), 0, size);
5459 data = zero.get();
5460 }
[email protected]473c01ccb2011-06-07 01:33:305461
5462 if (!bufferdata_faster_than_buffersubdata_ &&
5463 size == info->size() && usage == info->usage()) {
5464 glBufferSubData(target, 0, size, data);
5465 info->SetRange(0, size, data);
5466 return;
5467 }
5468
[email protected]3b6ec202010-03-05 05:16:235469 CopyRealGLErrorsToWrapper();
5470 glBufferData(target, size, data, usage);
[email protected]1002c2d2011-06-28 22:39:045471 GLenum error = PeekGLError();
5472 if (error == GL_NO_ERROR) {
[email protected]473c01ccb2011-06-07 01:33:305473 buffer_manager()->SetInfo(info, size, usage);
[email protected]0c86dbf2010-03-05 08:14:115474 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:235475 }
[email protected]0c86dbf2010-03-05 08:14:115476}
5477
5478error::Error GLES2DecoderImpl::HandleBufferData(
5479 uint32 immediate_data_size, const gles2::BufferData& c) {
5480 GLenum target = static_cast<GLenum>(c.target);
5481 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
5482 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5483 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5484 GLenum usage = static_cast<GLenum>(c.usage);
5485 const void* data = NULL;
5486 if (data_shm_id != 0 || data_shm_offset != 0) {
5487 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
5488 if (!data) {
5489 return error::kOutOfBounds;
5490 }
5491 }
5492 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:145493 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195494}
5495
[email protected]f7a64ee2010-02-01 22:24:145496error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:195497 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
5498 GLenum target = static_cast<GLenum>(c.target);
5499 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:305500 const void* data = GetImmediateDataAs<const void*>(
5501 c, size, immediate_data_size);
5502 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145503 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:305504 }
[email protected]b9849abf2009-11-25 19:13:195505 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:115506 DoBufferData(target, size, data, usage);
5507 return error::kNoError;
5508}
5509
5510void GLES2DecoderImpl::DoBufferSubData(
5511 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:505512 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475513 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295514 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285515 return;
[email protected]a93bb842010-02-16 23:03:475516 }
[email protected]0c86dbf2010-03-05 08:14:115517 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:295518 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]473c01ccb2011-06-07 01:33:305519 return;
[email protected]07f54fcc2009-12-22 02:46:305520 }
[email protected]473c01ccb2011-06-07 01:33:305521 if (bufferdata_faster_than_buffersubdata_ &&
5522 offset == 0 && size == info->size()) {
5523 glBufferData(target, size, data, info->usage());
5524 return;
5525 }
5526 glBufferSubData(target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:195527}
5528
[email protected]a93bb842010-02-16 23:03:475529error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
5530 GLenum target,
5531 GLint level,
5532 GLenum internal_format,
5533 GLsizei width,
5534 GLsizei height,
5535 GLint border,
5536 GLsizei image_size,
5537 const void* data) {
[email protected]a93bb842010-02-16 23:03:475538 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:055539 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295540 SetGLError(GL_INVALID_ENUM,
5541 "glCompressedTexImage2D: target GL_INVALID_ENUM");
5542 return error::kNoError;
5543 }
[email protected]9438b012010-06-15 22:55:055544 if (!validators_->compressed_texture_format.IsValid(
5545 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295546 SetGLError(GL_INVALID_ENUM,
5547 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:475548 return error::kNoError;
5549 }
[email protected]915a59a12010-09-30 21:29:115550 if (!texture_manager()->ValidForTarget(
5551 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475552 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295553 SetGLError(GL_INVALID_VALUE,
5554 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475555 return error::kNoError;
5556 }
[email protected]3916c97e2010-02-25 03:20:505557 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475558 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295559 SetGLError(GL_INVALID_VALUE,
5560 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:475561 return error::kNoError;
5562 }
5563 scoped_array<int8> zero;
5564 if (!data) {
5565 zero.reset(new int8[image_size]);
5566 memset(zero.get(), 0, image_size);
5567 data = zero.get();
5568 }
[email protected]cadde4a2010-07-31 17:10:435569 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:475570 glCompressedTexImage2D(
5571 target, level, internal_format, width, height, border, image_size, data);
[email protected]1002c2d2011-06-28 22:39:045572 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:435573 if (error == GL_NO_ERROR) {
5574 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:115575 feature_info_,
[email protected]cadde4a2010-07-31 17:10:435576 info, target, level, internal_format, width, height, 1, border, 0, 0);
5577 }
[email protected]a93bb842010-02-16 23:03:475578 return error::kNoError;
5579}
5580
[email protected]f7a64ee2010-02-01 22:24:145581error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195582 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
5583 GLenum target = static_cast<GLenum>(c.target);
5584 GLint level = static_cast<GLint>(c.level);
5585 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5586 GLsizei width = static_cast<GLsizei>(c.width);
5587 GLsizei height = static_cast<GLsizei>(c.height);
5588 GLint border = static_cast<GLint>(c.border);
5589 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
5590 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5591 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5592 const void* data = NULL;
5593 if (data_shm_id != 0 || data_shm_offset != 0) {
5594 data = GetSharedMemoryAs<const void*>(
5595 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:465596 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145597 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195598 }
5599 }
[email protected]a93bb842010-02-16 23:03:475600 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195601 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:195602}
5603
[email protected]f7a64ee2010-02-01 22:24:145604error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195605 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
5606 GLenum target = static_cast<GLenum>(c.target);
5607 GLint level = static_cast<GLint>(c.level);
5608 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5609 GLsizei width = static_cast<GLsizei>(c.width);
5610 GLsizei height = static_cast<GLsizei>(c.height);
5611 GLint border = static_cast<GLint>(c.border);
5612 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:305613 const void* data = GetImmediateDataAs<const void*>(
5614 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465615 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145616 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465617 }
[email protected]a93bb842010-02-16 23:03:475618 return DoCompressedTexImage2D(
5619 target, level, internal_format, width, height, border, image_size, data);
5620}
5621
[email protected]b6140d02010-05-17 14:47:165622error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
5623 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
5624 GLenum target = static_cast<GLenum>(c.target);
5625 GLint level = static_cast<GLint>(c.level);
5626 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5627 GLsizei width = static_cast<GLsizei>(c.width);
5628 GLsizei height = static_cast<GLsizei>(c.height);
5629 GLint border = static_cast<GLint>(c.border);
5630 Bucket* bucket = GetBucket(c.bucket_id);
5631 return DoCompressedTexImage2D(
5632 target, level, internal_format, width, height, border,
5633 bucket->size(), bucket->GetData(0, bucket->size()));
5634}
5635
5636error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
5637 uint32 immediate_data_size,
5638 const gles2::CompressedTexSubImage2DBucket& c) {
5639 GLenum target = static_cast<GLenum>(c.target);
5640 GLint level = static_cast<GLint>(c.level);
5641 GLint xoffset = static_cast<GLint>(c.xoffset);
5642 GLint yoffset = static_cast<GLint>(c.yoffset);
5643 GLsizei width = static_cast<GLsizei>(c.width);
5644 GLsizei height = static_cast<GLsizei>(c.height);
5645 GLenum format = static_cast<GLenum>(c.format);
5646 Bucket* bucket = GetBucket(c.bucket_id);
5647 uint32 data_size = bucket->size();
5648 GLsizei imageSize = data_size;
5649 const void* data = bucket->GetData(0, data_size);
[email protected]9438b012010-06-15 22:55:055650 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:165651 SetGLError(
5652 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
5653 return error::kNoError;
5654 }
[email protected]9438b012010-06-15 22:55:055655 if (!validators_->compressed_texture_format.IsValid(format)) {
5656 SetGLError(GL_INVALID_ENUM,
5657 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
5658 return error::kNoError;
5659 }
[email protected]b6140d02010-05-17 14:47:165660 if (width < 0) {
5661 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
5662 return error::kNoError;
5663 }
5664 if (height < 0) {
5665 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
5666 return error::kNoError;
5667 }
5668 if (imageSize < 0) {
5669 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
5670 return error::kNoError;
5671 }
[email protected]cadde4a2010-07-31 17:10:435672 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:165673 target, level, xoffset, yoffset, width, height, format, imageSize, data);
5674 return error::kNoError;
5675}
5676
[email protected]a93bb842010-02-16 23:03:475677error::Error GLES2DecoderImpl::DoTexImage2D(
5678 GLenum target,
5679 GLint level,
5680 GLenum internal_format,
5681 GLsizei width,
5682 GLsizei height,
5683 GLint border,
5684 GLenum format,
5685 GLenum type,
5686 const void* pixels,
5687 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:055688 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295689 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
5690 return error::kNoError;
5691 }
[email protected]9438b012010-06-15 22:55:055692 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295693 SetGLError(GL_INVALID_ENUM,
5694 "glTexImage2D: internal_format GL_INVALID_ENUM");
5695 return error::kNoError;
5696 }
[email protected]9438b012010-06-15 22:55:055697 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295698 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
5699 return error::kNoError;
5700 }
[email protected]9438b012010-06-15 22:55:055701 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295702 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:145703 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195704 }
[email protected]7b92c412010-07-20 17:48:255705 if (format != internal_format) {
5706 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
5707 return error::kNoError;
5708 }
[email protected]915a59a12010-09-30 21:29:115709 if (!texture_manager()->ValidForTarget(
5710 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475711 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295712 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475713 return error::kNoError;
5714 }
[email protected]3916c97e2010-02-25 03:20:505715 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475716 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295717 SetGLError(GL_INVALID_OPERATION,
5718 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:475719 return error::kNoError;
5720 }
[email protected]0226c112011-07-22 03:25:075721
5722 GLsizei tex_width = 0;
5723 GLsizei tex_height = 0;
5724 GLenum tex_type = 0;
5725 GLenum tex_format = 0;
5726 bool level_is_same =
5727 info->GetLevelSize(target, level, &tex_width, &tex_height) &&
5728 info->GetLevelType(target, level, &tex_type, &tex_format) &&
5729 width == tex_width && height == tex_height &&
5730 type == tex_type && format == tex_format;
5731
5732 if (level_is_same && !pixels) {
[email protected]ea72ed222011-08-17 18:58:435733 tex_image_2d_failed_ = false;
[email protected]0226c112011-07-22 03:25:075734 return error::kNoError;
5735 }
5736
[email protected]a93bb842010-02-16 23:03:475737 scoped_array<int8> zero;
5738 if (!pixels) {
5739 zero.reset(new int8[pixels_size]);
5740 memset(zero.get(), 0, pixels_size);
5741 pixels = zero.get();
5742 }
[email protected]876f6fee2010-08-02 23:10:325743
[email protected]297ca1c2011-06-20 23:08:465744 if (info->IsAttachedToFramebuffer()) {
5745 state_dirty_ = true;
5746 }
5747
[email protected]0226c112011-07-22 03:25:075748 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same) {
5749 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
5750 tex_image_2d_failed_ = false;
5751 return error::kNoError;
[email protected]7488d962010-07-16 02:41:585752 }
[email protected]876f6fee2010-08-02 23:10:325753
[email protected]cadde4a2010-07-31 17:10:435754 CopyRealGLErrorsToWrapper();
[email protected]473c01ccb2011-06-07 01:33:305755 WrappedTexImage2D(
5756 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475757 pixels);
[email protected]1002c2d2011-06-28 22:39:045758 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:435759 if (error == GL_NO_ERROR) {
[email protected]915a59a12010-09-30 21:29:115760 texture_manager()->SetLevelInfo(feature_info_, info,
[email protected]cadde4a2010-07-31 17:10:435761 target, level, internal_format, width, height, 1, border, format, type);
[email protected]b493ee622011-04-13 23:52:005762 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:435763 }
[email protected]f7a64ee2010-02-01 22:24:145764 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195765}
5766
[email protected]f7a64ee2010-02-01 22:24:145767error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195768 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]366ae242011-05-10 02:23:585769 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:005770 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:195771 GLenum target = static_cast<GLenum>(c.target);
5772 GLint level = static_cast<GLint>(c.level);
5773 GLint internal_format = static_cast<GLint>(c.internalformat);
5774 GLsizei width = static_cast<GLsizei>(c.width);
5775 GLsizei height = static_cast<GLsizei>(c.height);
5776 GLint border = static_cast<GLint>(c.border);
5777 GLenum format = static_cast<GLenum>(c.format);
5778 GLenum type = static_cast<GLenum>(c.type);
5779 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
5780 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:185781 uint32 pixels_size;
5782 if (!GLES2Util::ComputeImageDataSize(
5783 width, height, format, type, unpack_alignment_, &pixels_size)) {
5784 return error::kOutOfBounds;
5785 }
[email protected]b9849abf2009-11-25 19:13:195786 const void* pixels = NULL;
5787 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
5788 pixels = GetSharedMemoryAs<const void*>(
5789 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:465790 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145791 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195792 }
5793 }
[email protected]a93bb842010-02-16 23:03:475794 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195795 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475796 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:195797}
5798
[email protected]f7a64ee2010-02-01 22:24:145799error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195800 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
5801 GLenum target = static_cast<GLenum>(c.target);
5802 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:465803 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:195804 GLsizei width = static_cast<GLsizei>(c.width);
5805 GLsizei height = static_cast<GLsizei>(c.height);
5806 GLint border = static_cast<GLint>(c.border);
5807 GLenum format = static_cast<GLenum>(c.format);
5808 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:185809 uint32 size;
5810 if (!GLES2Util::ComputeImageDataSize(
5811 width, height, format, type, unpack_alignment_, &size)) {
5812 return error::kOutOfBounds;
5813 }
[email protected]07f54fcc2009-12-22 02:46:305814 const void* pixels = GetImmediateDataAs<const void*>(
5815 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465816 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145817 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465818 }
[email protected]a93bb842010-02-16 23:03:475819 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:465820 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475821 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:145822 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325823}
5824
[email protected]cadde4a2010-07-31 17:10:435825void GLES2DecoderImpl::DoCompressedTexSubImage2D(
5826 GLenum target,
5827 GLint level,
5828 GLint xoffset,
5829 GLint yoffset,
5830 GLsizei width,
5831 GLsizei height,
5832 GLenum format,
5833 GLsizei image_size,
5834 const void * data) {
5835 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5836 if (!info) {
5837 SetGLError(GL_INVALID_OPERATION,
5838 "glCompressedTexSubImage2D: unknown texture for target");
5839 return;
5840 }
5841 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:525842 GLenum internal_format = 0;
5843 if (!info->GetLevelType(target, level, &type, &internal_format)) {
5844 SetGLError(
5845 GL_INVALID_OPERATION,
5846 "glCompressdTexSubImage2D: level does not exist.");
5847 return;
5848 }
5849 if (internal_format != format) {
5850 SetGLError(
5851 GL_INVALID_OPERATION,
5852 "glCompressdTexSubImage2D: format does not match internal format.");
5853 return;
5854 }
5855 if (!info->ValidForTexture(
5856 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:435857 SetGLError(GL_INVALID_VALUE,
5858 "glCompressdTexSubImage2D: bad dimensions.");
5859 return;
5860 }
5861 glCompressedTexSubImage2D(
5862 target, level, xoffset, yoffset, width, height, format, image_size, data);
5863}
5864
[email protected]6e288612010-12-21 20:45:035865static void Clip(
5866 GLint start, GLint range, GLint sourceRange,
5867 GLint* out_start, GLint* out_range) {
5868 DCHECK(out_start);
5869 DCHECK(out_range);
5870 if (start < 0) {
5871 range += start;
5872 start = 0;
5873 }
5874 GLint end = start + range;
5875 if (end > sourceRange) {
5876 range -= end - sourceRange;
5877 }
5878 *out_start = start;
5879 *out_range = range;
5880}
5881
5882
[email protected]cadde4a2010-07-31 17:10:435883void GLES2DecoderImpl::DoCopyTexImage2D(
5884 GLenum target,
5885 GLint level,
5886 GLenum internal_format,
5887 GLint x,
5888 GLint y,
5889 GLsizei width,
5890 GLsizei height,
5891 GLint border) {
5892 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5893 if (!info) {
5894 SetGLError(GL_INVALID_OPERATION,
5895 "glCopyTexImage2D: unknown texture for target");
5896 return;
5897 }
[email protected]915a59a12010-09-30 21:29:115898 if (!texture_manager()->ValidForTarget(
5899 feature_info_, target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:185900 border != 0) {
5901 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
5902 return;
5903 }
5904
[email protected]9edc6b22010-12-23 02:00:265905 // Check we have compatible formats.
5906 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5907 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5908 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
5909
5910 if ((channels_needed & channels_exist) != channels_needed) {
5911 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
5912 return;
5913 }
5914
[email protected]cadde4a2010-07-31 17:10:435915 CopyRealGLErrorsToWrapper();
[email protected]de26b3c2011-08-03 21:54:275916 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:035917 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:265918
[email protected]297ca1c2011-06-20 23:08:465919 if (info->IsAttachedToFramebuffer()) {
5920 state_dirty_ = true;
5921 }
5922
[email protected]9edc6b22010-12-23 02:00:265923 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:035924 GLint copyX = 0;
5925 GLint copyY = 0;
5926 GLint copyWidth = 0;
5927 GLint copyHeight = 0;
5928 Clip(x, width, size.width(), &copyX, &copyWidth);
5929 Clip(y, height, size.height(), &copyY, &copyHeight);
5930
5931 if (copyX != x ||
5932 copyY != y ||
5933 copyWidth != width ||
5934 copyHeight != height) {
5935 // some part was clipped so clear the texture.
5936 uint32 pixels_size = 0;
5937 if (!GLES2Util::ComputeImageDataSize(
5938 width, height, internal_format, GL_UNSIGNED_BYTE,
5939 unpack_alignment_, &pixels_size)) {
5940 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions too large");
5941 return;
5942 }
5943 scoped_array<char> zero(new char[pixels_size]);
5944 memset(zero.get(), 0, pixels_size);
5945 glTexImage2D(target, level, internal_format, width, height, 0,
5946 internal_format, GL_UNSIGNED_BYTE, zero.get());
5947 if (copyHeight > 0 && copyWidth > 0) {
5948 GLint dx = copyX - x;
5949 GLint dy = copyY - y;
5950 GLint destX = dx;
5951 GLint destY = dy;
5952 glCopyTexSubImage2D(target, level,
5953 destX, destY, copyX, copyY,
5954 copyWidth, copyHeight);
5955 }
5956 } else {
5957 glCopyTexImage2D(target, level, internal_format,
5958 copyX, copyY, copyWidth, copyHeight, border);
5959 }
[email protected]1002c2d2011-06-28 22:39:045960 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:435961 if (error == GL_NO_ERROR) {
5962 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:115963 feature_info_, info, target, level, internal_format, width, height, 1,
5964 border, internal_format, GL_UNSIGNED_BYTE);
[email protected]cadde4a2010-07-31 17:10:435965 }
5966}
5967
5968void GLES2DecoderImpl::DoCopyTexSubImage2D(
5969 GLenum target,
5970 GLint level,
5971 GLint xoffset,
5972 GLint yoffset,
5973 GLint x,
5974 GLint y,
5975 GLsizei width,
5976 GLsizei height) {
5977 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5978 if (!info) {
5979 SetGLError(GL_INVALID_OPERATION,
5980 "glCopyTexSubImage2D: unknown texture for target");
5981 return;
5982 }
5983 GLenum type = 0;
5984 GLenum format = 0;
5985 if (!info->GetLevelType(target, level, &type, &format) ||
5986 !info->ValidForTexture(
5987 target, level, xoffset, yoffset, width, height, format, type)) {
5988 SetGLError(GL_INVALID_VALUE,
5989 "glCopyTexSubImage2D: bad dimensions.");
5990 return;
5991 }
[email protected]9edc6b22010-12-23 02:00:265992
5993 // Check we have compatible formats.
5994 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5995 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5996 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
5997
5998 if ((channels_needed & channels_exist) != channels_needed) {
5999 SetGLError(
6000 GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
6001 return;
6002 }
6003
[email protected]de26b3c2011-08-03 21:54:276004 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:036005 gfx::Size size = GetBoundReadFrameBufferSize();
6006 GLint copyX = 0;
6007 GLint copyY = 0;
6008 GLint copyWidth = 0;
6009 GLint copyHeight = 0;
6010 Clip(x, width, size.width(), &copyX, &copyWidth);
6011 Clip(y, height, size.height(), &copyY, &copyHeight);
6012 if (copyX != x ||
6013 copyY != y ||
6014 copyWidth != width ||
6015 copyHeight != height) {
6016 // some part was clipped so clear the texture.
6017 uint32 pixels_size = 0;
6018 if (!GLES2Util::ComputeImageDataSize(
6019 width, height, format, type, unpack_alignment_, &pixels_size)) {
6020 SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large");
6021 return;
6022 }
6023 scoped_array<char> zero(new char[pixels_size]);
6024 memset(zero.get(), 0, pixels_size);
6025 glTexSubImage2D(
6026 target, level, xoffset, yoffset, width, height,
6027 format, type, zero.get());
6028 }
6029 if (copyHeight > 0 && copyWidth > 0) {
6030 GLint dx = copyX - x;
6031 GLint dy = copyY - y;
6032 GLint destX = xoffset + dx;
6033 GLint destY = yoffset + dy;
6034 glCopyTexSubImage2D(target, level,
6035 destX, destY, copyX, copyY,
6036 copyWidth, copyHeight);
6037 }
[email protected]cadde4a2010-07-31 17:10:436038}
6039
6040void GLES2DecoderImpl::DoTexSubImage2D(
6041 GLenum target,
6042 GLint level,
6043 GLint xoffset,
6044 GLint yoffset,
6045 GLsizei width,
6046 GLsizei height,
6047 GLenum format,
6048 GLenum type,
6049 const void * data) {
6050 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6051 if (!info) {
6052 SetGLError(GL_INVALID_OPERATION,
6053 "glTexSubImage2D: unknown texture for target");
6054 return;
6055 }
[email protected]df6cf1ad2011-01-29 01:20:526056 GLenum current_type = 0;
6057 GLenum internal_format = 0;
6058 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
6059 SetGLError(
6060 GL_INVALID_OPERATION,
6061 "glTexSubImage2D: level does not exist.");
6062 return;
6063 }
6064 if (format != internal_format) {
6065 SetGLError(GL_INVALID_OPERATION,
6066 "glTexSubImage2D: format does not match internal format.");
6067 return;
6068 }
6069 if (type != current_type) {
6070 SetGLError(GL_INVALID_OPERATION,
6071 "glTexSubImage2D: type does not match type of texture.");
6072 return;
6073 }
6074
[email protected]cadde4a2010-07-31 17:10:436075 if (!info->ValidForTexture(
6076 target, level, xoffset, yoffset, width, height, format, type)) {
6077 SetGLError(GL_INVALID_VALUE,
6078 "glTexSubImage2D: bad dimensions.");
6079 return;
6080 }
[email protected]473c01ccb2011-06-07 01:33:306081
6082 // See if we can call glTexImage2D instead since it appears to be faster.
6083 if (teximage2d_faster_than_texsubimage2d_ && xoffset == 0 && yoffset == 0) {
6084 GLsizei tex_width = 0;
6085 GLsizei tex_height = 0;
6086 bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height);
6087 DCHECK(ok);
6088 if (width == tex_width && height == tex_height) {
6089 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
6090 // same as internal_foramt. If that changes we'll need to look them up.
6091 WrappedTexImage2D(
6092 target, level, format, width, height, 0, format, type, data);
6093 return;
6094 }
6095 }
[email protected]cadde4a2010-07-31 17:10:436096 glTexSubImage2D(
6097 target, level, xoffset, yoffset, width, height, format, type, data);
6098}
6099
[email protected]b493ee622011-04-13 23:52:006100error::Error GLES2DecoderImpl::HandleTexSubImage2D(
6101 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]366ae242011-05-10 02:23:586102 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:006103 GLboolean internal = static_cast<GLboolean>(c.internal);
6104 if (internal == GL_TRUE && tex_image_2d_failed_)
6105 return error::kNoError;
6106
6107 GLenum target = static_cast<GLenum>(c.target);
6108 GLint level = static_cast<GLint>(c.level);
6109 GLint xoffset = static_cast<GLint>(c.xoffset);
6110 GLint yoffset = static_cast<GLint>(c.yoffset);
6111 GLsizei width = static_cast<GLsizei>(c.width);
6112 GLsizei height = static_cast<GLsizei>(c.height);
6113 GLenum format = static_cast<GLenum>(c.format);
6114 GLenum type = static_cast<GLenum>(c.type);
6115 uint32 data_size;
6116 if (!GLES2Util::ComputeImageDataSize(
6117 width, height, format, type, unpack_alignment_, &data_size)) {
6118 return error::kOutOfBounds;
6119 }
6120 const void* pixels = GetSharedMemoryAs<const void*>(
6121 c.pixels_shm_id, c.pixels_shm_offset, data_size);
6122 if (!validators_->texture_target.IsValid(target)) {
6123 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
6124 return error::kNoError;
6125 }
6126 if (width < 0) {
6127 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
6128 return error::kNoError;
6129 }
6130 if (height < 0) {
6131 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
6132 return error::kNoError;
6133 }
6134 if (!validators_->texture_format.IsValid(format)) {
6135 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
6136 return error::kNoError;
6137 }
6138 if (!validators_->pixel_type.IsValid(type)) {
6139 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
6140 return error::kNoError;
6141 }
6142 if (pixels == NULL) {
6143 return error::kOutOfBounds;
6144 }
6145 DoTexSubImage2D(
6146 target, level, xoffset, yoffset, width, height, format, type, pixels);
6147 return error::kNoError;
6148}
6149
6150error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
6151 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
6152 GLboolean internal = static_cast<GLboolean>(c.internal);
6153 if (internal == GL_TRUE && tex_image_2d_failed_)
6154 return error::kNoError;
6155
6156 GLenum target = static_cast<GLenum>(c.target);
6157 GLint level = static_cast<GLint>(c.level);
6158 GLint xoffset = static_cast<GLint>(c.xoffset);
6159 GLint yoffset = static_cast<GLint>(c.yoffset);
6160 GLsizei width = static_cast<GLsizei>(c.width);
6161 GLsizei height = static_cast<GLsizei>(c.height);
6162 GLenum format = static_cast<GLenum>(c.format);
6163 GLenum type = static_cast<GLenum>(c.type);
6164 uint32 data_size;
6165 if (!GLES2Util::ComputeImageDataSize(
6166 width, height, format, type, unpack_alignment_, &data_size)) {
6167 return error::kOutOfBounds;
6168 }
6169 const void* pixels = GetImmediateDataAs<const void*>(
6170 c, data_size, immediate_data_size);
6171 if (!validators_->texture_target.IsValid(target)) {
6172 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
6173 return error::kNoError;
6174 }
6175 if (width < 0) {
6176 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
6177 return error::kNoError;
6178 }
6179 if (height < 0) {
6180 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
6181 return error::kNoError;
6182 }
6183 if (!validators_->texture_format.IsValid(format)) {
6184 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
6185 return error::kNoError;
6186 }
6187 if (!validators_->pixel_type.IsValid(type)) {
6188 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
6189 return error::kNoError;
6190 }
6191 if (pixels == NULL) {
6192 return error::kOutOfBounds;
6193 }
6194 DoTexSubImage2D(
6195 target, level, xoffset, yoffset, width, height, format, type, pixels);
6196 return error::kNoError;
6197}
6198
[email protected]f7a64ee2010-02-01 22:24:146199error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:196200 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:366201 GLuint index = static_cast<GLuint>(c.index);
6202 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:256203 typedef gles2::GetVertexAttribPointerv::Result Result;
6204 Result* result = GetSharedMemoryAs<Result*>(
6205 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:366206 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:146207 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:366208 }
[email protected]07d0cc82010-02-17 04:51:406209 // Check that the client initialized the result.
6210 if (result->size != 0) {
6211 return error::kInvalidArguments;
6212 }
[email protected]9438b012010-06-15 22:55:056213 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:296214 SetGLError(GL_INVALID_ENUM,
6215 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:146216 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:366217 }
[email protected]3916c97e2010-02-25 03:20:506218 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:296219 SetGLError(GL_INVALID_VALUE,
6220 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:146221 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:366222 }
[email protected]0bfd9882010-02-05 23:02:256223 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:086224 *result->GetData() =
6225 vertex_attrib_manager_.GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:146226 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326227}
6228
[email protected]f7b85372010-02-03 01:11:376229bool GLES2DecoderImpl::GetUniformSetup(
6230 GLuint program, GLint location,
6231 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:106232 error::Error* error, GLuint* service_id, void** result_pointer,
6233 GLenum* result_type) {
6234 DCHECK(error);
6235 DCHECK(service_id);
6236 DCHECK(result_pointer);
6237 DCHECK(result_type);
[email protected]f7b85372010-02-03 01:11:376238 *error = error::kNoError;
6239 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:256240 SizedResult<GLint>* result;
6241 result = GetSharedMemoryAs<SizedResult<GLint>*>(
6242 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
6243 if (!result) {
[email protected]f7b85372010-02-03 01:11:376244 *error = error::kOutOfBounds;
6245 return false;
6246 }
[email protected]0bfd9882010-02-05 23:02:256247 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:376248 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:256249 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:586250 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6251 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:376252 if (!info) {
[email protected]ae51d192010-04-27 00:48:036253 return false;
6254 }
6255 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:376256 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:296257 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:376258 return false;
6259 }
[email protected]ae51d192010-04-27 00:48:036260 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:366261 GLint array_index = -1;
6262 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
6263 info->GetUniformInfoByLocation(location, &array_index);
6264 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:376265 // No such location.
[email protected]8eee29c2010-04-29 03:38:296266 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:376267 return false;
6268 }
[email protected]43c2f1f2011-03-25 18:35:366269 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:506270 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:376271 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:296272 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:376273 return false;
6274 }
[email protected]0bfd9882010-02-05 23:02:256275 result = GetSharedMemoryAs<SizedResult<GLint>*>(
6276 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
6277 if (!result) {
[email protected]f7b85372010-02-03 01:11:376278 *error = error::kOutOfBounds;
6279 return false;
6280 }
[email protected]0bfd9882010-02-05 23:02:256281 result->size = size;
[email protected]939e7362010-05-13 20:49:106282 *result_type = type;
[email protected]f7b85372010-02-03 01:11:376283 return true;
6284}
6285
[email protected]f7a64ee2010-02-01 22:24:146286error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:196287 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:376288 GLuint program = c.program;
6289 GLint location = c.location;
6290 GLuint service_id;
[email protected]939e7362010-05-13 20:49:106291 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:376292 Error error;
[email protected]0bfd9882010-02-05 23:02:256293 void* result;
[email protected]f7b85372010-02-03 01:11:376294 if (GetUniformSetup(
6295 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:106296 &error, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:256297 glGetUniformiv(
6298 service_id, location,
6299 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:376300 }
6301 return error;
[email protected]96449d2c2009-11-25 00:01:326302}
6303
[email protected]f7a64ee2010-02-01 22:24:146304error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:196305 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:376306 GLuint program = c.program;
6307 GLint location = c.location;
6308 GLuint service_id;
6309 Error error;
[email protected]0bfd9882010-02-05 23:02:256310 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:106311 Result* result;
6312 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:376313 if (GetUniformSetup(
6314 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:106315 &error, &service_id, reinterpret_cast<void**>(&result), &result_type)) {
6316 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
6317 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
6318 GLsizei num_values = result->GetNumResults();
6319 scoped_array<GLint> temp(new GLint[num_values]);
6320 glGetUniformiv(service_id, location, temp.get());
6321 GLfloat* dst = result->GetData();
6322 for (GLsizei ii = 0; ii < num_values; ++ii) {
6323 dst[ii] = (temp[ii] != 0);
6324 }
6325 } else {
6326 glGetUniformfv(service_id, location, result->GetData());
6327 }
[email protected]f7b85372010-02-03 01:11:376328 }
6329 return error;
[email protected]96449d2c2009-11-25 00:01:326330}
6331
[email protected]f7a64ee2010-02-01 22:24:146332error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:196333 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:256334 GLenum shader_type = static_cast<GLenum>(c.shadertype);
6335 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
6336 typedef gles2::GetShaderPrecisionFormat::Result Result;
6337 Result* result = GetSharedMemoryAs<Result*>(
6338 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6339 if (!result) {
6340 return error::kOutOfBounds;
6341 }
[email protected]07d0cc82010-02-17 04:51:406342 // Check that the client initialized the result.
6343 if (result->success != 0) {
6344 return error::kInvalidArguments;
6345 }
[email protected]9438b012010-06-15 22:55:056346 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:296347 SetGLError(GL_INVALID_ENUM,
6348 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
6349 return error::kNoError;
6350 }
[email protected]9438b012010-06-15 22:55:056351 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:296352 SetGLError(GL_INVALID_ENUM,
6353 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
6354 return error::kNoError;
6355 }
6356
6357 result->success = 1; // true
6358 switch (precision_type) {
6359 case GL_LOW_INT:
6360 case GL_MEDIUM_INT:
6361 case GL_HIGH_INT:
6362 result->min_range = -31;
6363 result->max_range = 31;
6364 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:106365 break;
[email protected]8eee29c2010-04-29 03:38:296366 case GL_LOW_FLOAT:
6367 case GL_MEDIUM_FLOAT:
6368 case GL_HIGH_FLOAT:
6369 result->min_range = -62;
6370 result->max_range = 62;
6371 result->precision = -16;
6372 break;
6373 default:
6374 NOTREACHED();
6375 break;
[email protected]0bfd9882010-02-05 23:02:256376 }
[email protected]f7a64ee2010-02-01 22:24:146377 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326378}
6379
[email protected]f7a64ee2010-02-01 22:24:146380error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:196381 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:256382 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:586383 GLuint program = static_cast<GLuint>(c.program);
6384 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6385 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:036386 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256387 return error::kNoError;
6388 }
6389 typedef gles2::GetAttachedShaders::Result Result;
6390 uint32 max_count = Result::ComputeMaxResults(result_size);
6391 Result* result = GetSharedMemoryAs<Result*>(
6392 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
6393 if (!result) {
6394 return error::kOutOfBounds;
6395 }
[email protected]07d0cc82010-02-17 04:51:406396 // Check that the client initialized the result.
6397 if (result->size != 0) {
6398 return error::kInvalidArguments;
6399 }
[email protected]0bfd9882010-02-05 23:02:256400 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:036401 glGetAttachedShaders(
6402 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:256403 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:036404 if (!shader_manager()->GetClientId(result->GetData()[ii],
6405 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:256406 NOTREACHED();
6407 return error::kGenericError;
6408 }
6409 }
6410 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:146411 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326412}
6413
[email protected]f7a64ee2010-02-01 22:24:146414error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:196415 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:256416 GLuint program = c.program;
6417 GLuint index = c.index;
6418 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:256419 typedef gles2::GetActiveUniform::Result Result;
6420 Result* result = GetSharedMemoryAs<Result*>(
6421 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6422 if (!result) {
6423 return error::kOutOfBounds;
6424 }
[email protected]07d0cc82010-02-17 04:51:406425 // Check that the client initialized the result.
6426 if (result->success != 0) {
6427 return error::kInvalidArguments;
6428 }
[email protected]6b8cf1a2010-05-06 16:13:586429 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6430 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:036431 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256432 return error::kNoError;
6433 }
6434 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
6435 info->GetUniformInfo(index);
6436 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:296437 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:256438 return error::kNoError;
6439 }
6440 result->success = 1; // true.
6441 result->size = uniform_info->size;
6442 result->type = uniform_info->type;
6443 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:296444 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:146445 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326446}
6447
[email protected]f7a64ee2010-02-01 22:24:146448error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:196449 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:256450 GLuint program = c.program;
6451 GLuint index = c.index;
6452 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:256453 typedef gles2::GetActiveAttrib::Result Result;
6454 Result* result = GetSharedMemoryAs<Result*>(
6455 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6456 if (!result) {
6457 return error::kOutOfBounds;
6458 }
[email protected]07d0cc82010-02-17 04:51:406459 // Check that the client initialized the result.
6460 if (result->success != 0) {
6461 return error::kInvalidArguments;
6462 }
[email protected]6b8cf1a2010-05-06 16:13:586463 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6464 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:036465 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256466 return error::kNoError;
6467 }
6468 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
6469 info->GetAttribInfo(index);
6470 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:296471 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:256472 return error::kNoError;
6473 }
6474 result->success = 1; // true.
6475 result->size = attrib_info->size;
6476 result->type = attrib_info->type;
6477 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:296478 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:146479 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326480}
6481
[email protected]b273e432010-04-12 17:23:586482error::Error GLES2DecoderImpl::HandleShaderBinary(
6483 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
6484#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:296485 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:586486 return error::kNoError;
6487#else
6488 GLsizei n = static_cast<GLsizei>(c.n);
6489 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:296490 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:586491 return error::kNoError;
6492 }
6493 GLsizei length = static_cast<GLsizei>(c.length);
6494 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:296495 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:586496 return error::kNoError;
6497 }
6498 uint32 data_size;
6499 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
6500 return error::kOutOfBounds;
6501 }
6502 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
6503 c.shaders_shm_id, c.shaders_shm_offset, data_size);
6504 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
6505 const void* binary = GetSharedMemoryAs<const void*>(
6506 c.binary_shm_id, c.binary_shm_offset, length);
6507 if (shaders == NULL || binary == NULL) {
6508 return error::kOutOfBounds;
6509 }
6510 scoped_array<GLuint> service_ids(new GLuint[n]);
6511 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:036512 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
6513 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296514 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:586515 return error::kNoError;
6516 }
[email protected]ae51d192010-04-27 00:48:036517 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:586518 }
6519 // TODO(gman): call glShaderBinary
6520 return error::kNoError;
6521#endif
6522}
6523
[email protected]6217d392010-03-25 22:08:356524error::Error GLES2DecoderImpl::HandleSwapBuffers(
6525 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:496526 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
6527 int this_frame_number = frame_number_++;
6528 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
6529 "offscreen", is_offscreen,
6530 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:356531 // If offscreen then don't actually SwapBuffers to the display. Just copy
6532 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:496533 if (is_offscreen) {
[email protected]1fb8c482011-08-31 01:01:536534 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
6535 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
6536 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
6537 // fix this.
6538 if (needs_mac_nvidia_driver_workaround_) {
6539 offscreen_saved_frame_buffer_->Create();
6540 glFinish();
6541 }
6542
6543 // Allocate the offscreen saved color texture.
6544 DCHECK(offscreen_saved_color_format_);
6545 offscreen_saved_color_texture_->AllocateStorage(
6546 offscreen_size_, offscreen_saved_color_format_);
6547
6548 offscreen_saved_frame_buffer_->AttachRenderTexture(
6549 offscreen_saved_color_texture_.get());
6550 if (offscreen_saved_frame_buffer_->CheckStatus() !=
6551 GL_FRAMEBUFFER_COMPLETE) {
6552 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
6553 << "because offscreen saved FBO was incomplete.";
6554 return error::kLostContext;
6555 }
6556
[email protected]1fb8c482011-08-31 01:01:536557 // Clear the offscreen color texture.
6558 // TODO(piman): Is this still necessary?
6559 {
6560 ScopedFrameBufferBinder binder(this,
6561 offscreen_saved_frame_buffer_->id());
6562 glClearColor(0, 0, 0, 0);
6563 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6564 glDisable(GL_SCISSOR_TEST);
6565 glClear(GL_COLOR_BUFFER_BIT);
6566 RestoreClearState();
6567 }
6568
6569 UpdateParentTextureInfo();
6570 }
6571
[email protected]6217d392010-03-25 22:08:356572 ScopedGLErrorSuppressor suppressor(this);
6573
[email protected]34ff8b0c2010-10-01 20:06:026574 if (IsOffscreenBufferMultisampled()) {
6575 // For multisampled buffers, bind the resolved frame buffer so that
6576 // callbacks can call ReadPixels or CopyTexImage2D.
[email protected]de26b3c2011-08-03 21:54:276577 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]22f320a2011-08-30 01:17:006578#if defined(OS_MACOSX)
[email protected]34ff8b0c2010-10-01 20:06:026579 if (swap_buffers_callback_.get()) {
6580 swap_buffers_callback_->Run();
6581 }
[email protected]22f320a2011-08-30 01:17:006582#endif
[email protected]89d6ed02011-04-20 00:23:236583 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:486584 } else {
[email protected]0c8c9d22010-06-25 17:36:396585 ScopedFrameBufferBinder binder(this,
6586 offscreen_target_frame_buffer_->id());
[email protected]c007aa02010-09-02 22:22:406587
[email protected]9a5afa432011-07-22 18:16:396588 if (surface_->IsOffscreen()) {
[email protected]b86b14982010-10-11 18:45:486589 // Copy the target frame buffer to the saved offscreen texture.
6590 offscreen_saved_color_texture_->Copy(
[email protected]3a4d0c52011-06-29 23:11:586591 offscreen_saved_color_texture_->size(),
6592 offscreen_saved_color_format_);
[email protected]b86b14982010-10-11 18:45:486593
[email protected]a3ded6d2010-10-19 06:44:396594 // Ensure the side effects of the copy are visible to the parent
6595 // context. There is no need to do this for ANGLE because it uses a
6596 // single D3D device for all contexts.
[email protected]b86b14982010-10-11 18:45:486597 if (!IsAngle())
6598 glFlush();
6599 }
6600
6601 // Run the callback with |binder| in scope, so that the callback can call
6602 // ReadPixels or CopyTexImage2D.
[email protected]22f320a2011-08-30 01:17:006603#if defined(OS_MACOSX)
[email protected]b86b14982010-10-11 18:45:486604 if (swap_buffers_callback_.get()) {
6605 swap_buffers_callback_->Run();
6606 }
[email protected]22f320a2011-08-30 01:17:006607#endif
[email protected]89d6ed02011-04-20 00:23:236608 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:396609 }
[email protected]6217d392010-03-25 22:08:356610 } else {
[email protected]64ace852011-05-19 21:49:496611 TRACE_EVENT1("gpu", "GLContext::SwapBuffers", "frame", this_frame_number);
[email protected]f62a5ab2011-05-23 20:34:156612 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:016613 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:026614 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:016615 }
[email protected]6217d392010-03-25 22:08:356616 }
6617
[email protected]22f320a2011-08-30 01:17:006618#if defined(OS_MACOSX)
[email protected]6217d392010-03-25 22:08:356619 if (swap_buffers_callback_.get()) {
6620 swap_buffers_callback_->Run();
6621 }
[email protected]22f320a2011-08-30 01:17:006622#endif
[email protected]6217d392010-03-25 22:08:356623
[email protected]89d6ed02011-04-20 00:23:236624 return error::kNoError;
[email protected]6217d392010-03-25 22:08:356625}
6626
[email protected]d4239852011-08-12 04:51:226627error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
6628 uint32 immediate_data_size, const gles2::EnableFeatureCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:186629 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]d4239852011-08-12 04:51:226630 typedef gles2::EnableFeatureCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:186631 Result* result = GetSharedMemoryAs<Result*>(
6632 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6633 if (!result) {
6634 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:106635 }
[email protected]b1d2dcb2010-05-17 19:24:186636 // Check that the client initialized the result.
6637 if (*result != 0) {
6638 return error::kInvalidArguments;
6639 }
6640 std::string feature_str;
6641 if (!bucket->GetAsString(&feature_str)) {
6642 return error::kInvalidArguments;
6643 }
6644
6645 // TODO(gman): make this some kind of table to function pointer thingy.
[email protected]d4239852011-08-12 04:51:226646 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
[email protected]b1d2dcb2010-05-17 19:24:186647 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]d4239852011-08-12 04:51:226648 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
[email protected]8fbedc02010-11-18 18:43:406649 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
6650 // TODO(gman): decide how to remove the need for this const_cast.
6651 // I could make validators_ non const but that seems bad as this is the only
6652 // place it is needed. I could make some special friend class of validators
6653 // just to allow this to set them. That seems silly. I could refactor this
6654 // code to use the extension mechanism or the initialization attributes to
6655 // turn this feature on. Given that the only real point of this is to make
6656 // the conformance tests pass and given that there is lots of real work that
6657 // needs to be done it seems like refactoring for one to one of those
6658 // methods is a very low priority.
6659 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]b1d2dcb2010-05-17 19:24:186660 } else {
6661 return error::kNoError;
6662 }
6663
6664 *result = 1; // true.
6665 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:106666}
6667
[email protected]c2f8c8402010-12-06 18:07:246668error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
6669 uint32 immediate_data_size,
6670 const gles2::GetRequestableExtensionsCHROMIUM& c) {
6671 Bucket* bucket = CreateBucket(c.bucket_id);
6672 scoped_ptr<FeatureInfo> info(new FeatureInfo());
[email protected]c410da802011-03-14 19:17:416673 info->Initialize(disallowed_extensions_, NULL);
[email protected]c2f8c8402010-12-06 18:07:246674 bucket->SetFromString(info->extensions().c_str());
6675 return error::kNoError;
6676}
6677
6678error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
6679 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
6680 Bucket* bucket = GetBucket(c.bucket_id);
6681 std::string feature_str;
6682 if (!bucket->GetAsString(&feature_str)) {
6683 return error::kInvalidArguments;
6684 }
6685
6686 bool std_derivatives_enabled =
6687 feature_info_->feature_flags().oes_standard_derivatives;
6688 bool webglsl_enabled =
6689 feature_info_->feature_flags().chromium_webglsl;
6690
6691 feature_info_->AddFeatures(feature_str.c_str());
6692
6693 // If we just enabled a feature which affects the shader translator,
6694 // we may need to re-initialize it.
6695 if (std_derivatives_enabled !=
6696 feature_info_->feature_flags().oes_standard_derivatives ||
6697 webglsl_enabled !=
6698 feature_info_->feature_flags().chromium_webglsl) {
6699 InitializeShaderTranslator();
6700 }
6701
[email protected]302ce6d2011-07-07 23:28:116702 UpdateCapabilities();
6703
[email protected]c2f8c8402010-12-06 18:07:246704 return error::kNoError;
6705}
6706
[email protected]372e0412011-06-28 16:08:566707error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
6708 uint32 immediate_data_size, const gles2::GetMultipleIntegervCHROMIUM& c) {
6709 GLuint count = c.count;
6710 uint32 pnames_size;
6711 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
6712 return error::kOutOfBounds;
6713 }
6714 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
6715 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
6716 if (pnames == NULL) {
6717 return error::kOutOfBounds;
6718 }
6719
6720 // We have to copy them since we use them twice so the client
6721 // can't change them between the time we validate them and the time we use
6722 // them.
6723 scoped_array<GLenum> enums(new GLenum[count]);
6724 memcpy(enums.get(), pnames, pnames_size);
6725
6726 // Count up the space needed for the result.
6727 uint32 num_results = 0;
6728 for (GLuint ii = 0; ii < count; ++ii) {
6729 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
6730 if (num == 0) {
6731 SetGLError(GL_INVALID_ENUM,
6732 "glGetMulitpleCHROMIUM: pname GL_INVALID_ENUM");
6733 return error::kNoError;
6734 }
6735 // Num will never be more than 4.
6736 DCHECK_LE(num, 4u);
6737 if (!SafeAdd(num_results, num, &num_results)) {
6738 return error::kOutOfBounds;
6739 }
6740 }
6741
6742 uint32 result_size = 0;
6743 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
6744 return error::kOutOfBounds;
6745 }
6746
6747 if (result_size != static_cast<uint32>(c.size)) {
6748 SetGLError(GL_INVALID_VALUE,
6749 "glGetMulitpleCHROMIUM: bad size GL_INVALID_VALUE");
6750 return error::kNoError;
6751 }
6752
6753 GLint* results = GetSharedMemoryAs<GLint*>(
6754 c.results_shm_id, c.results_shm_offset, result_size);
6755 if (results == NULL) {
6756 return error::kOutOfBounds;
6757 }
6758
6759 // Check the results have been cleared in case the context was lost.
6760 for (uint32 ii = 0; ii < num_results; ++ii) {
6761 if (results[ii]) {
6762 return error::kInvalidArguments;
6763 }
6764 }
6765
6766 // Get each result.
6767 GLint* start = results;
6768 for (GLuint ii = 0; ii < count; ++ii) {
6769 GLsizei num_written = 0;
6770 if (!GetHelper(enums[ii], results, &num_written)) {
6771 glGetIntegerv(enums[ii], results);
6772 }
6773 results += num_written;
6774 }
6775
6776 // Just to verify. Should this be a DCHECK?
6777 if (static_cast<uint32>(results - start) != num_results) {
6778 return error::kOutOfBounds;
6779 }
6780
6781 return error::kNoError;
6782}
6783
[email protected]2318d342011-07-11 22:27:426784error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
6785 uint32 immediate_data_size, const gles2::GetProgramInfoCHROMIUM& c) {
6786 GLuint program = static_cast<GLuint>(c.program);
6787 uint32 bucket_id = c.bucket_id;
6788 Bucket* bucket = CreateBucket(bucket_id);
6789 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
6790 ProgramManager::ProgramInfo* info = NULL;
[email protected]9a14ae612011-08-08 17:51:466791 info = GetProgramInfo(program);
6792 if (!info || !info->IsValid()) {
6793 return error::kNoError;
[email protected]2318d342011-07-11 22:27:426794 }
6795 info->GetProgramInfo(bucket);
6796 return error::kNoError;
6797}
6798
[email protected]38d139d2011-07-14 00:38:436799error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
6800 switch (reset_status_) {
6801 case GL_NO_ERROR:
6802 // TODO(kbr): improve the precision of the error code in this case.
6803 // Consider delegating to context for error code if MakeCurrent fails.
6804 return error::kUnknown;
6805 case GL_GUILTY_CONTEXT_RESET_ARB:
6806 return error::kGuilty;
6807 case GL_INNOCENT_CONTEXT_RESET_ARB:
6808 return error::kInnocent;
6809 case GL_UNKNOWN_CONTEXT_RESET_ARB:
6810 return error::kUnknown;
6811 }
6812
6813 NOTREACHED();
6814 return error::kUnknown;
6815}
6816
6817bool GLES2DecoderImpl::WasContextLost() {
6818 if (context_->WasAllocatedUsingARBRobustness() && has_arb_robustness_) {
6819 GLenum status = glGetGraphicsResetStatusARB();
6820 if (status != GL_NO_ERROR) {
6821 // The graphics card was reset. Signal a lost context to the application.
6822 reset_status_ = status;
6823 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
6824 << " context lost via ARB_robustness. Reset status = 0x"
6825 << std::hex << status << std::dec;
6826 return true;
6827 }
6828 }
6829 return false;
6830}
6831
[email protected]96449d2c2009-11-25 00:01:326832// Include the auto-generated part of this file. We split this because it means
6833// we can easily edit the non-auto generated parts right here in this file
6834// instead of having to edit some template or the code generator.
6835#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
6836
6837} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:256838} // namespace gpu