blob: 63f73a9aef2c79d4310d40dcf5491980c2cc856f [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]fbe20372011-06-01 01:46:3837#include "gpu/command_buffer/service/surface_manager.h"
[email protected]a93bb842010-02-16 23:03:4738#include "gpu/command_buffer/service/texture_manager.h"
[email protected]d8ea9772011-07-11 18:11:4339#include "gpu/command_buffer/service/vertex_attrib_manager.h"
[email protected]4e8a5b122010-05-08 22:00:1040#include "gpu/GLES2/gles2_command_buffer.h"
[email protected]5ae0b282011-03-28 19:24:4941#include "ui/gfx/gl/gl_context.h"
42#include "ui/gfx/gl/gl_implementation.h"
[email protected]f62a5ab2011-05-23 20:34:1543#include "ui/gfx/gl/gl_surface.h"
[email protected]de17df392010-04-23 21:09:4144
[email protected]6217d392010-03-25 22:08:3545#if !defined(GL_DEPTH24_STENCIL8)
46#define GL_DEPTH24_STENCIL8 0x88F0
47#endif
48
[email protected]a7a27ace2009-12-12 00:11:2549namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3250namespace gles2 {
51
[email protected]6217d392010-03-25 22:08:3552class GLES2DecoderImpl;
53
[email protected]07f54fcc2009-12-22 02:46:3054// Check that certain assumptions the code makes are true. There are places in
55// the code where shared memory is passed direclty to GL. Example, glUniformiv,
56// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
57// a few others) are 32bits. If they are not 32bits the code will have to change
58// to call those GL functions with service side memory and then copy the results
59// to shared memory, converting the sizes.
60COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
61 GLint_not_same_size_as_uint32);
62COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
63 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3764COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
65 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3066
[email protected]43f28f832010-02-03 02:28:4867// TODO(kbr): the use of this anonymous namespace core dumps the
68// linker on Mac OS X 10.6 when the symbol ordering file is used
69// namespace {
[email protected]96449d2c2009-11-25 00:01:3270
71// Returns the address of the first byte after a struct.
72template <typename T>
73const void* AddressAfterStruct(const T& pod) {
74 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
75}
76
[email protected]07f54fcc2009-12-22 02:46:3077// Returns the address of the frst byte after the struct or NULL if size >
78// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3279template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3080RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
81 uint32 size,
82 uint32 immediate_data_size) {
83 return (size <= immediate_data_size) ?
84 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
85 NULL;
[email protected]96449d2c2009-11-25 00:01:3286}
87
[email protected]07f54fcc2009-12-22 02:46:3088// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1889bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3290 GLuint count,
91 size_t size,
[email protected]a76b0052010-03-05 00:33:1892 unsigned int elements_per_unit,
93 uint32* dst) {
94 uint32 value;
95 if (!SafeMultiplyUint32(count, size, &value)) {
96 return false;
97 }
98 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
99 return false;
100 }
101 *dst = value;
102 return true;
[email protected]96449d2c2009-11-25 00:01:32103}
104
105// A struct to hold info about each command.
106struct CommandInfo {
107 int arg_flags; // How to handle the arguments for this command
108 int arg_count; // How many arguments are expected for this command.
109};
110
111// A table of CommandInfo for all the commands.
112const CommandInfo g_command_info[] = {
113 #define GLES2_CMD_OP(name) { \
114 name::kArgFlags, \
115 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
116
117 GLES2_COMMAND_LIST(GLES2_CMD_OP)
118
119 #undef GLES2_CMD_OP
120};
121
[email protected]34ff8b0c2010-10-01 20:06:02122static bool IsAngle() {
123#if defined(OS_WIN)
124 return gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
125#else
126 return false;
127#endif
128}
129
[email protected]297ca1c2011-06-20 23:08:46130static void WrappedTexImage2D(
[email protected]473c01ccb2011-06-07 01:33:30131 GLenum target,
132 GLint level,
133 GLenum internal_format,
134 GLsizei width,
135 GLsizei height,
136 GLint border,
137 GLenum format,
138 GLenum type,
139 const void* pixels) {
140 GLenum gl_internal_format = internal_format;
141 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
142 if (format == GL_BGRA_EXT && internal_format == GL_BGRA_EXT) {
143 gl_internal_format = GL_RGBA;
144 } else if (type == GL_FLOAT) {
145 if (format == GL_RGBA) {
146 gl_internal_format = GL_RGBA32F_ARB;
147 } else if (format == GL_RGB) {
148 gl_internal_format = GL_RGB32F_ARB;
149 }
150 } else if (type == GL_HALF_FLOAT_OES) {
151 if (format == GL_RGBA) {
152 gl_internal_format = GL_RGBA16F_ARB;
153 } else if (format == GL_RGB) {
154 gl_internal_format = GL_RGB16F_ARB;
155 }
156 }
157 }
158 glTexImage2D(
159 target, level, gl_internal_format, width, height, border, format, type,
160 pixels);
161}
162
[email protected]297ca1c2011-06-20 23:08:46163// Wrapper for glEnable/glDisable that doesn't suck.
164static void EnableDisable(GLenum pname, bool enable) {
165 if (enable) {
166 glEnable(pname);
167 } else {
168 glDisable(pname);
169 }
170}
171
[email protected]6217d392010-03-25 22:08:35172// This class prevents any GL errors that occur when it is in scope from
173// being reported to the client.
174class ScopedGLErrorSuppressor {
175 public:
176 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
177 ~ScopedGLErrorSuppressor();
178 private:
179 GLES2DecoderImpl* decoder_;
180 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
181};
182
183// Temporarily changes a decoder's bound 2D texture and restore it when this
184// object goes out of scope. Also temporarily switches to using active texture
185// unit zero in case the client has changed that to something invalid.
186class ScopedTexture2DBinder {
187 public:
188 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
189 ~ScopedTexture2DBinder();
190
191 private:
192 GLES2DecoderImpl* decoder_;
193 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
194};
195
196// Temporarily changes a decoder's bound render buffer and restore it when this
197// object goes out of scope.
198class ScopedRenderBufferBinder {
199 public:
200 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
201 ~ScopedRenderBufferBinder();
202
203 private:
204 GLES2DecoderImpl* decoder_;
205 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
206};
207
208// Temporarily changes a decoder's bound frame buffer and restore it when this
209// object goes out of scope.
210class ScopedFrameBufferBinder {
211 public:
212 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
213 ~ScopedFrameBufferBinder();
214
215 private:
216 GLES2DecoderImpl* decoder_;
217 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
218};
219
[email protected]34ff8b0c2010-10-01 20:06:02220// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52221// the multisampled offscreen render buffer if that buffer is multisampled, and,
222// if it is bound or enforce_internal_framebuffer is true.
[email protected]34ff8b0c2010-10-01 20:06:02223class ScopedResolvedFrameBufferBinder {
224 public:
[email protected]c0701082011-04-20 00:34:52225 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
226 bool enforce_internal_framebuffer);
[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]fbe20372011-06-01 01:46:38450 explicit GLES2DecoderImpl(SurfaceManager* surface_manager,
451 ContextGroup* group);
[email protected]f39f4b3f2010-05-12 17:04:08452
[email protected]96449d2c2009-11-25 00:01:32453 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14454 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50455 unsigned int arg_count,
456 const void* args);
[email protected]96449d2c2009-11-25 00:01:32457
458 // Overridden from AsyncAPIInterface.
459 virtual const char* GetCommandName(unsigned int command_id) const;
460
461 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38462 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
463 const scoped_refptr<gfx::GLContext>& context,
[email protected]6217d392010-03-25 22:08:35464 const gfx::Size& size,
[email protected]c410da802011-03-14 19:17:41465 const DisallowedExtensions& disallowed_extensions,
[email protected]a3ded6d2010-10-19 06:44:39466 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:24467 const std::vector<int32>& attribs);
[email protected]96449d2c2009-11-25 00:01:32468 virtual void Destroy();
[email protected]3c644d82011-06-20 19:58:24469 virtual bool SetParent(GLES2Decoder* parent_decoder,
470 uint32 parent_texture_id);
[email protected]6217d392010-03-25 22:08:35471 virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]c71caa82010-06-02 23:25:45472 virtual bool UpdateOffscreenFrameBufferSize();
[email protected]9a5afa432011-07-22 18:16:39473 void UpdateParentTextureInfo();
[email protected]eb54a562010-01-20 21:55:18474 virtual bool MakeCurrent();
[email protected]56ac89b2010-03-17 21:16:55475 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30476 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]f62a5ab2011-05-23 20:34:15477 virtual gfx::GLSurface* GetGLSurface() { return surface_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39478 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]43f28f832010-02-03 02:28:48479
[email protected]7ff86b92010-11-25 17:50:00480 virtual void SetResizeCallback(Callback1<gfx::Size>::Type* callback);
[email protected]43f28f832010-02-03 02:28:48481 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
[email protected]1318e922010-09-17 22:03:16482 virtual bool GetServiceTextureId(uint32 client_texture_id,
483 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48484
[email protected]8e3e0662010-08-23 18:46:30485 // Restores the current state to the user's settings.
486 void RestoreCurrentFramebufferBindings();
487 void RestoreCurrentRenderbufferBindings();
488 void RestoreCurrentTexture2DBindings();
489
[email protected]297ca1c2011-06-20 23:08:46490 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
491 void ApplyDirtyState();
492
493 // These check the state of the currently bound framebuffer or the
494 // backbuffer if no framebuffer is bound.
495 bool BoundFramebufferHasColorAttachmentWithAlpha();
496 bool BoundFramebufferHasDepthAttachment();
497 bool BoundFramebufferHasStencilAttachment();
498
[email protected]38d139d2011-07-14 00:38:43499 virtual error::ContextLostReason GetContextLostReason();
500
[email protected]96449d2c2009-11-25 00:01:32501 private:
[email protected]6217d392010-03-25 22:08:35502 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02503 friend class ScopedResolvedFrameBufferBinder;
[email protected]6217d392010-03-25 22:08:35504 friend class RenderBuffer;
505 friend class FrameBuffer;
506
[email protected]3916c97e2010-02-25 03:20:50507 // State associated with each texture unit.
508 struct TextureUnit {
509 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
510
511 // The last target that was bound to this texture unit.
512 GLenum bind_target;
513
514 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
515 TextureManager::TextureInfo::Ref bound_texture_2d;
516
517 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
518 // glBindTexture
519 TextureManager::TextureInfo::Ref bound_texture_cube_map;
520 };
521
[email protected]c2f8c8402010-12-06 18:07:24522 // Initialize or re-initialize the shader translator.
523 bool InitializeShaderTranslator();
524
[email protected]302ce6d2011-07-07 23:28:11525 void UpdateCapabilities();
526
[email protected]ae51d192010-04-27 00:48:03527 // Helpers for the glGen and glDelete functions.
528 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
529 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
530 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
531 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
532 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
533 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
534 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
535 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47536
[email protected]3916c97e2010-02-25 03:20:50537 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50538 BufferManager* buffer_manager() {
539 return group_->buffer_manager();
540 }
541
[email protected]a25fa872010-03-25 02:57:58542 RenderbufferManager* renderbuffer_manager() {
543 return group_->renderbuffer_manager();
544 }
545
546 FramebufferManager* framebuffer_manager() {
547 return group_->framebuffer_manager();
548 }
549
[email protected]3916c97e2010-02-25 03:20:50550 ProgramManager* program_manager() {
551 return group_->program_manager();
552 }
553
554 ShaderManager* shader_manager() {
555 return group_->shader_manager();
556 }
557
558 TextureManager* texture_manager() {
559 return group_->texture_manager();
560 }
561
[email protected]34ff8b0c2010-10-01 20:06:02562 bool IsOffscreenBufferMultisampled() const {
563 return offscreen_target_samples_ > 1;
564 }
565
[email protected]a93bb842010-02-16 23:03:47566 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03567 TextureManager::TextureInfo* CreateTextureInfo(
568 GLuint client_id, GLuint service_id) {
[email protected]915a59a12010-09-30 21:29:11569 return texture_manager()->CreateTextureInfo(
570 feature_info_, client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47571 }
572
573 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03574 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50575 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03576 texture_manager()->GetTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50577 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47578 }
579
580 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03581 void RemoveTextureInfo(GLuint client_id) {
[email protected]915a59a12010-09-30 21:29:11582 texture_manager()->RemoveTextureInfo(feature_info_, client_id);
[email protected]3916c97e2010-02-25 03:20:50583 }
[email protected]a93bb842010-02-16 23:03:47584
[email protected]d37231fa2010-04-09 21:16:02585 // Get the size (in pixels) of the currently bound frame buffer (either FBO
586 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30587 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02588
[email protected]9edc6b22010-12-23 02:00:26589 // Get the format of the currently bound frame buffer (either FBO or regular
590 // back buffer)
591 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46592 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26593
[email protected]a93bb842010-02-16 23:03:47594 // Wrapper for CompressedTexImage2D commands.
595 error::Error DoCompressedTexImage2D(
596 GLenum target,
597 GLint level,
598 GLenum internal_format,
599 GLsizei width,
600 GLsizei height,
601 GLint border,
602 GLsizei image_size,
603 const void* data);
604
[email protected]cadde4a2010-07-31 17:10:43605 // Wrapper for CompressedTexSubImage2D.
606 void DoCompressedTexSubImage2D(
607 GLenum target,
608 GLint level,
609 GLint xoffset,
610 GLint yoffset,
611 GLsizei width,
612 GLsizei height,
613 GLenum format,
614 GLsizei imageSize,
615 const void * data);
616
617 // Wrapper for CopyTexImage2D.
618 void DoCopyTexImage2D(
619 GLenum target,
620 GLint level,
621 GLenum internal_format,
622 GLint x,
623 GLint y,
624 GLsizei width,
625 GLsizei height,
626 GLint border);
627
628 // Wrapper for CopyTexSubImage2D.
629 void DoCopyTexSubImage2D(
630 GLenum target,
631 GLint level,
632 GLint xoffset,
633 GLint yoffset,
634 GLint x,
635 GLint y,
636 GLsizei width,
637 GLsizei height);
638
[email protected]a93bb842010-02-16 23:03:47639 // Wrapper for TexImage2D commands.
640 error::Error DoTexImage2D(
641 GLenum target,
642 GLint level,
643 GLenum internal_format,
644 GLsizei width,
645 GLsizei height,
646 GLint border,
647 GLenum format,
648 GLenum type,
649 const void* pixels,
650 uint32 pixels_size);
651
[email protected]cadde4a2010-07-31 17:10:43652 // Wrapper for TexSubImage2D.
653 void DoTexSubImage2D(
654 GLenum target,
655 GLint level,
656 GLint xoffset,
657 GLint yoffset,
658 GLsizei width,
659 GLsizei height,
660 GLenum format,
661 GLenum type,
662 const void * data);
663
[email protected]a93bb842010-02-16 23:03:47664 // Creates a ProgramInfo for the given program.
[email protected]d685a682011-04-29 16:19:57665 ProgramManager::ProgramInfo* CreateProgramInfo(
666 GLuint client_id, GLuint service_id) {
667 return program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47668 }
669
[email protected]07f54fcc2009-12-22 02:46:30670 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03671 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14672 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46673 }
[email protected]07f54fcc2009-12-22 02:46:30674
[email protected]6b8cf1a2010-05-06 16:13:58675 // Gets the program info for the given program. If it's not a program
676 // generates a GL error. Returns NULL if not program.
677 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
678 GLuint client_id, const char* function_name) {
679 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
680 if (!info) {
681 if (GetShaderInfo(client_id)) {
682 SetGLError(GL_INVALID_OPERATION,
683 (std::string(function_name) +
684 ": shader passed for program").c_str());
685 } else {
686 SetGLError(GL_INVALID_VALUE,
687 (std::string(function_name) + ": unknown program").c_str());
688 }
689 }
690 return info;
691 }
692
693
[email protected]45bf5152010-02-12 00:11:31694 // Creates a ShaderInfo for the given shader.
[email protected]d685a682011-04-29 16:19:57695 ShaderManager::ShaderInfo* CreateShaderInfo(
696 GLuint client_id,
697 GLuint service_id,
698 GLenum shader_type) {
699 return shader_manager()->CreateShaderInfo(
700 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31701 }
702
703 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03704 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14705 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31706 }
707
[email protected]6b8cf1a2010-05-06 16:13:58708 // Gets the shader info for the given shader. If it's not a shader generates a
709 // GL error. Returns NULL if not shader.
710 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
711 GLuint client_id, const char* function_name) {
712 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
713 if (!info) {
714 if (GetProgramInfo(client_id)) {
715 SetGLError(
716 GL_INVALID_OPERATION,
717 (std::string(function_name) +
718 ": program passed for shader").c_str());
719 } else {
720 SetGLError(GL_INVALID_VALUE,
721 (std::string(function_name) + ": unknown shader").c_str());
722 }
723 }
724 return info;
725 }
726
[email protected]a93bb842010-02-16 23:03:47727 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03728 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
729 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47730 }
731
[email protected]07f54fcc2009-12-22 02:46:30732 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03733 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
734 BufferManager::BufferInfo* info =
735 buffer_manager()->GetBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50736 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46737 }
[email protected]07f54fcc2009-12-22 02:46:30738
[email protected]a93bb842010-02-16 23:03:47739 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
740 // on glDeleteBuffers so we can make sure the user does not try to render
741 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03742 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47743
[email protected]a25fa872010-03-25 02:57:58744 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03745 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
746 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58747 }
748
749 // Gets the framebuffer info for the given framebuffer.
750 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03751 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58752 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03753 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58754 return (info && !info->IsDeleted()) ? info : NULL;
755 }
756
757 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03758 void RemoveFramebufferInfo(GLuint client_id) {
759 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58760 }
761
762 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03763 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
764 return renderbuffer_manager()->CreateRenderbufferInfo(
765 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58766 }
767
768 // Gets the renderbuffer info for the given renderbuffer.
769 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03770 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58771 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03772 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58773 return (info && !info->IsDeleted()) ? info : NULL;
774 }
775
776 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03777 void RemoveRenderbufferInfo(GLuint client_id) {
778 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58779 }
780
[email protected]558847a2010-03-24 07:02:54781 error::Error GetAttribLocationHelper(
782 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
783 const std::string& name_str);
784
785 error::Error GetUniformLocationHelper(
786 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
787 const std::string& name_str);
788
[email protected]3916c97e2010-02-25 03:20:50789 // Helper for glShaderSource.
790 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03791 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30792
[email protected]3a2e7c7b2010-08-06 01:12:28793 // Clears any uncleared render buffers attached to the given frame buffer.
[email protected]8e3e0662010-08-23 18:46:30794 void ClearUnclearedRenderbuffers(
795 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28796
[email protected]c007aa02010-09-02 22:22:40797 // Restore all GL state that affects clearing.
798 void RestoreClearState();
799
[email protected]3a2e7c7b2010-08-06 01:12:28800 // Remembers the state of some capabilities.
[email protected]297ca1c2011-06-20 23:08:46801 // Returns: true if glEnable/glDisable should actually be called.
802 bool SetCapabilityState(GLenum cap, bool enabled);
[email protected]3a2e7c7b2010-08-06 01:12:28803
[email protected]3a03a8f2011-03-19 00:51:27804 // Check that the current frame buffer is complete. Generates error if not.
805 bool CheckFramebufferComplete(const char* func_name);
806
[email protected]939e7362010-05-13 20:49:10807 // Checks if the current program exists and is valid. If not generates the
808 // appropriate GL error. Returns true if the current program is in a usable
809 // state.
810 bool CheckCurrentProgram(const char* function_name);
811
812 // Checks if the current program exists and is valid and that location is not
813 // -1. If the current program is not valid generates the appropriate GL
814 // error. Returns true if the current program is in a usable state and
815 // location is not -1.
816 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
817
818 // Gets the type of a uniform for a location in the current program. Sets GL
819 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:36820 // program is valid and the location exists. Adjusts count so it
821 // does not overflow the uniform.
822 bool PrepForSetUniformByLocation(
823 GLint location, const char* function_name, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:10824
[email protected]b273e432010-04-12 17:23:58825 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
826 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
827
[email protected]96449d2c2009-11-25 00:01:32828 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03829 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32830
831 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03832 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32833
[email protected]3916c97e2010-02-25 03:20:50834 // Wrapper for glActiveTexture
835 void DoActiveTexture(GLenum texture_unit);
836
[email protected]ae51d192010-04-27 00:48:03837 // Wrapper for glAttachShader
838 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
839
[email protected]96449d2c2009-11-25 00:01:32840 // Wrapper for glBindBuffer since we need to track the current targets.
841 void DoBindBuffer(GLenum target, GLuint buffer);
842
[email protected]86093972010-03-11 00:13:56843 // Wrapper for glBindFramebuffer since we need to track the current targets.
844 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
845
846 // Wrapper for glBindRenderbuffer since we need to track the current targets.
847 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
848
[email protected]a93bb842010-02-16 23:03:47849 // Wrapper for glBindTexture since we need to track the current targets.
850 void DoBindTexture(GLenum target, GLuint texture);
851
[email protected]8e3e0662010-08-23 18:46:30852 // Wrapper for glBlitFramebufferEXT.
853 void DoBlitFramebufferEXT(
854 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
855 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
856 GLbitfield mask, GLenum filter);
857
[email protected]36cef8ce2010-03-16 07:34:45858 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:11859 void DoBufferData(
860 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
861
[email protected]36cef8ce2010-03-16 07:34:45862 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:11863 void DoBufferSubData(
864 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
865
[email protected]36cef8ce2010-03-16 07:34:45866 // Wrapper for glCheckFramebufferStatus
867 GLenum DoCheckFramebufferStatus(GLenum target);
868
[email protected]3a03a8f2011-03-19 00:51:27869 // Wrapper for glClear
870 void DoClear(GLbitfield mask);
871
[email protected]3a2e7c7b2010-08-06 01:12:28872 // Wrappers for clear and mask settings functions.
873 void DoClearColor(
874 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
875 void DoClearDepthf(GLclampf depth);
876 void DoClearStencil(GLint s);
877 void DoColorMask(
878 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
879 void DoDepthMask(GLboolean depth);
880 void DoStencilMask(GLuint mask);
881 void DoStencilMaskSeparate(GLenum face, GLuint mask);
882
[email protected]45bf5152010-02-12 00:11:31883 // Wrapper for glCompileShader.
884 void DoCompileShader(GLuint shader);
885
[email protected]269200b12010-11-18 22:53:06886 // Helper for DeleteSharedIdsCHROMIUM commands.
887 void DoDeleteSharedIdsCHROMIUM(
888 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:10889
[email protected]ae51d192010-04-27 00:48:03890 // Wrapper for glDetachShader
891 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
892
[email protected]3a2e7c7b2010-08-06 01:12:28893 // Wrapper for glDisable
894 void DoDisable(GLenum cap);
895
[email protected]07f54fcc2009-12-22 02:46:30896 // Wrapper for glDisableVertexAttribArray.
897 void DoDisableVertexAttribArray(GLuint index);
898
[email protected]3a2e7c7b2010-08-06 01:12:28899 // Wrapper for glEnable
900 void DoEnable(GLenum cap);
901
[email protected]07f54fcc2009-12-22 02:46:30902 // Wrapper for glEnableVertexAttribArray.
903 void DoEnableVertexAttribArray(GLuint index);
904
[email protected]36cef8ce2010-03-16 07:34:45905 // Wrapper for glFramebufferRenderbufffer.
906 void DoFramebufferRenderbuffer(
907 GLenum target, GLenum attachment, GLenum renderbuffertarget,
908 GLuint renderbuffer);
909
910 // Wrapper for glFramebufferTexture2D.
911 void DoFramebufferTexture2D(
912 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
913 GLint level);
914
[email protected]a93bb842010-02-16 23:03:47915 // Wrapper for glGenerateMipmap
916 void DoGenerateMipmap(GLenum target);
917
[email protected]269200b12010-11-18 22:53:06918 // Helper for GenSharedIdsCHROMIUM commands.
919 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:10920 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
921
[email protected]b273e432010-04-12 17:23:58922 // Wrapper for DoGetBooleanv.
923 void DoGetBooleanv(GLenum pname, GLboolean* params);
924
925 // Wrapper for DoGetFloatv.
926 void DoGetFloatv(GLenum pname, GLfloat* params);
927
[email protected]36cef8ce2010-03-16 07:34:45928 // Wrapper for glGetFramebufferAttachmentParameteriv.
929 void DoGetFramebufferAttachmentParameteriv(
930 GLenum target, GLenum attachment, GLenum pname, GLint* params);
931
[email protected]a0c3e972010-04-21 00:49:13932 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:58933 void DoGetIntegerv(GLenum pname, GLint* params);
934
[email protected]29a9eb52010-04-13 09:04:23935 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:06936 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:23937 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
938
[email protected]a0c3e972010-04-21 00:49:13939 // Wrapper for glGetProgramiv.
940 void DoGetProgramiv(
941 GLuint program_id, GLenum pname, GLint* params);
942
[email protected]36cef8ce2010-03-16 07:34:45943 // Wrapper for glRenderbufferParameteriv.
944 void DoGetRenderbufferParameteriv(
945 GLenum target, GLenum pname, GLint* params);
946
[email protected]ddd968b82010-03-02 00:44:29947 // Wrapper for glGetShaderiv
948 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
949
[email protected]b1122982010-05-17 23:04:24950 // Wrappers for glGetVertexAttrib.
951 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
952 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
953
[email protected]1958e0e2010-04-22 05:17:15954 // Wrappers for glIsXXX functions.
955 bool DoIsBuffer(GLuint client_id);
956 bool DoIsFramebuffer(GLuint client_id);
957 bool DoIsProgram(GLuint client_id);
958 bool DoIsRenderbuffer(GLuint client_id);
959 bool DoIsShader(GLuint client_id);
960 bool DoIsTexture(GLuint client_id);
961
[email protected]07f54fcc2009-12-22 02:46:30962 // Wrapper for glLinkProgram
963 void DoLinkProgram(GLuint program);
964
[email protected]269200b12010-11-18 22:53:06965 // Helper for RegisterSharedIdsCHROMIUM.
966 void DoRegisterSharedIdsCHROMIUM(
967 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:10968
[email protected]36cef8ce2010-03-16 07:34:45969 // Wrapper for glRenderbufferStorage.
970 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:03971 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:45972
[email protected]8e3e0662010-08-23 18:46:30973 // Wrapper for glRenderbufferStorageMultisampleEXT.
974 void DoRenderbufferStorageMultisample(
975 GLenum target, GLsizei samples, GLenum internalformat,
976 GLsizei width, GLsizei height);
977
[email protected]b273e432010-04-12 17:23:58978 // Wrapper for glReleaseShaderCompiler.
979 void DoReleaseShaderCompiler() { }
980
[email protected]3916c97e2010-02-25 03:20:50981 // Wrappers for glTexParameter functions.
982 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
983 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
984 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
985 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
986
987 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
988 // spec only these 2 functions can be used to set sampler uniforms.
989 void DoUniform1i(GLint location, GLint v0);
[email protected]939e7362010-05-13 20:49:10990 void DoUniform1iv(GLint location, GLsizei count, const GLint* value);
[email protected]43c2f1f2011-03-25 18:35:36991 void DoUniform2iv(GLint location, GLsizei count, const GLint* value);
992 void DoUniform3iv(GLint location, GLsizei count, const GLint* value);
993 void DoUniform4iv(GLint location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:10994
995 // Wrappers for glUniformfv because some drivers don't correctly accept
996 // bool uniforms.
997 void DoUniform1fv(GLint location, GLsizei count, const GLfloat* value);
998 void DoUniform2fv(GLint location, GLsizei count, const GLfloat* value);
999 void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value);
1000 void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501001
[email protected]43c2f1f2011-03-25 18:35:361002 void DoUniformMatrix2fv(
1003 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1004 void DoUniformMatrix3fv(
1005 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1006 void DoUniformMatrix4fv(
1007 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1008
[email protected]b1122982010-05-17 23:04:241009 // Wrappers for glVertexAttrib??
1010 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1011 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1012 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1013 void DoVertexAttrib4f(
1014 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1015 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1016 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1017 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1018 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1019
[email protected]07f54fcc2009-12-22 02:46:301020 // Wrapper for glUseProgram
1021 void DoUseProgram(GLuint program);
1022
[email protected]ae51d192010-04-27 00:48:031023 // Wrapper for glValidateProgram.
1024 void DoValidateProgram(GLuint program_client_id);
1025
[email protected]297ca1c2011-06-20 23:08:461026 void DoCopyTextureToParentTextureCHROMIUM(
1027 GLuint client_texture_id, GLuint parent_client_texture_id);
[email protected]a3a93e7b2010-08-28 00:48:561028
[email protected]43ecf372010-11-16 19:19:391029 void DoResizeCHROMIUM(GLuint width, GLuint height);
1030
[email protected]fbe20372011-06-01 01:46:381031 void DoSetSurfaceCHROMIUM(GLint surface_id);
1032
[email protected]4e8a5b122010-05-08 22:00:101033 // Gets the number of values that will be returned by glGetXXX. Returns
1034 // false if pname is unknown.
1035 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1036
[email protected]96449d2c2009-11-25 00:01:321037 // Gets the GLError through our wrapper.
1038 GLenum GetGLError();
1039
[email protected]1002c2d2011-06-28 22:39:041040 // Gets the GLError and stores it in our wrapper. Effectively
1041 // this lets us peek at the error without losing it.
1042 GLenum PeekGLError();
1043
[email protected]96449d2c2009-11-25 00:01:321044 // Sets our wrapper for the GLError.
[email protected]8eee29c2010-04-29 03:38:291045 void SetGLError(GLenum error, const char* msg);
[email protected]96449d2c2009-11-25 00:01:321046
[email protected]07f54fcc2009-12-22 02:46:301047 // Copies the real GL errors to the wrapper. This is so we can
1048 // make sure there are no native GL errors before calling some GL function
1049 // so that on return we know any error generated was for that specific
1050 // command.
1051 void CopyRealGLErrorsToWrapper();
1052
[email protected]6217d392010-03-25 22:08:351053 // Clear all real GL errors. This is to prevent the client from seeing any
1054 // errors caused by GL calls that it was not responsible for issuing.
1055 void ClearRealGLErrors();
1056
[email protected]07f54fcc2009-12-22 02:46:301057 // Checks if the current program and vertex attributes are valid for drawing.
1058 bool IsDrawValid(GLuint max_vertex_accessed);
1059
[email protected]b1122982010-05-17 23:04:241060 // Returns true if attrib0 was simulated.
1061 bool SimulateAttrib0(GLuint max_vertex_accessed);
1062 void RestoreStateForSimulatedAttrib0();
1063
[email protected]ef526492010-06-02 23:12:251064 // Returns true if textures were set.
1065 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501066 void RestoreStateForNonRenderableTextures();
1067
[email protected]8fbedc02010-11-18 18:43:401068 // Returns true if GL_FIXED attribs were simulated.
1069 bool SimulateFixedAttribs(GLuint max_vertex_accessed, bool* simulated);
1070 void RestoreStateForSimulatedFixedAttribs();
1071
[email protected]07f54fcc2009-12-22 02:46:301072 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501073 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301074 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501075 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1076 bound_array_buffer_ : bound_element_array_buffer_;
1077 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:301078 }
1079
[email protected]a93bb842010-02-16 23:03:471080 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501081 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1082 TextureUnit& unit = texture_units_[active_texture_unit_];
1083 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471084 switch (target) {
1085 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501086 info = unit.bound_texture_2d;
1087 break;
[email protected]a93bb842010-02-16 23:03:471088 case GL_TEXTURE_CUBE_MAP:
1089 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1090 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1091 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1092 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1093 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1094 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501095 info = unit.bound_texture_cube_map;
1096 break;
[email protected]1aef98132010-02-23 18:00:071097 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
1098 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
1099 // because |texture_| is used by the FBO rendering mechanism for readback
1100 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:471101 default:
1102 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501103 return NULL;
[email protected]a93bb842010-02-16 23:03:471104 }
[email protected]3916c97e2010-02-25 03:20:501105 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:471106 }
1107
[email protected]8e3e0662010-08-23 18:46:301108 // Gets the framebuffer info for a particular target.
1109 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1110 GLenum target) {
1111 FramebufferManager::FramebufferInfo* info = NULL;
1112 switch (target) {
1113 case GL_FRAMEBUFFER:
1114 case GL_DRAW_FRAMEBUFFER:
1115 info = bound_draw_framebuffer_;
1116 break;
1117 case GL_READ_FRAMEBUFFER:
1118 info = bound_read_framebuffer_;
1119 break;
1120 default:
1121 NOTREACHED();
1122 break;
1123 }
1124 return (info && !info->IsDeleted()) ? info : NULL;
1125 }
1126
[email protected]f7b85372010-02-03 01:11:371127 // Validates the program and location for a glGetUniform call and returns
1128 // a SizeResult setup to receive the result. Returns true if glGetUniform
1129 // should be called.
1130 bool GetUniformSetup(
1131 GLuint program, GLint location,
1132 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:101133 error::Error* error, GLuint* service_id, void** result,
1134 GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371135
[email protected]38d139d2011-07-14 00:38:431136 // Returns true if the context was just lost due to e.g. GL_ARB_robustness.
1137 bool WasContextLost();
1138
[email protected]96449d2c2009-11-25 00:01:321139 // Generate a member function prototype for each command in an automated and
1140 // typesafe way.
1141 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141142 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191143 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321144 const gles2::name& args); \
1145
1146 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1147
1148 #undef GLES2_CMD_OP
1149
[email protected]fbe20372011-06-01 01:46:381150 // Maps surface IDs to GLSurface.
1151 gpu::SurfaceManager* surface_manager_;
1152
[email protected]2f2d7042010-04-14 21:45:581153 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381154 scoped_refptr<gfx::GLSurface> surface_;
1155 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021156
[email protected]a3ded6d2010-10-19 06:44:391157 // The ContextGroup for this decoder uses to track resources.
1158 ContextGroup::Ref group_;
1159
[email protected]6217d392010-03-25 22:08:351160 // A parent decoder can access this decoders saved offscreen frame buffer.
1161 // The parent pointer is reset if the parent is destroyed.
1162 base::WeakPtr<GLES2DecoderImpl> parent_;
1163
1164 // Width and height to which an offscreen frame buffer should be resized on
1165 // the next call to SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:021166 gfx::Size pending_offscreen_size_;
[email protected]6217d392010-03-25 22:08:351167
[email protected]34ff8b0c2010-10-01 20:06:021168 // Current width and height of the offscreen frame buffer.
1169 gfx::Size offscreen_size_;
1170
[email protected]96449d2c2009-11-25 00:01:321171 // Current GL error bits.
1172 uint32 error_bits_;
1173
[email protected]96449d2c2009-11-25 00:01:321174 // Util to help with GL.
1175 GLES2Util util_;
1176
1177 // pack alignment as last set by glPixelStorei
1178 GLint pack_alignment_;
1179
1180 // unpack alignment as last set by glPixelStorei
1181 GLint unpack_alignment_;
1182
1183 // The currently bound array buffer. If this is 0 it is illegal to call
1184 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501185 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321186
1187 // The currently bound element array buffer. If this is 0 it is illegal
1188 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501189 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301190
[email protected]f39f4b3f2010-05-12 17:04:081191 // Class that manages vertex attribs.
1192 VertexAttribManager vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301193
[email protected]b1122982010-05-17 23:04:241194 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1195 GLuint attrib_0_buffer_id_;
1196
1197 // The value currently in attrib_0.
1198 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1199
[email protected]fc753442011-02-04 19:49:491200 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1201 bool attrib_0_buffer_matches_value_;
1202
[email protected]b1122982010-05-17 23:04:241203 // The size of attrib 0.
1204 GLsizei attrib_0_size_;
1205
[email protected]8fbedc02010-11-18 18:43:401206 // The buffer used to simulate GL_FIXED attribs.
1207 GLuint fixed_attrib_buffer_id_;
1208
1209 // The size of fiixed attrib buffer.
1210 GLsizei fixed_attrib_buffer_size_;
1211
[email protected]3916c97e2010-02-25 03:20:501212 // Current active texture by 0 - n index.
1213 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1214 // be 2.
1215 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301216
[email protected]3916c97e2010-02-25 03:20:501217 // Which textures are bound to texture units through glActiveTexture.
1218 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471219
[email protected]3a2e7c7b2010-08-06 01:12:281220 // state saved for clearing so we can clear render buffers and then
1221 // restore to these values.
1222 GLclampf clear_red_;
1223 GLclampf clear_green_;
1224 GLclampf clear_blue_;
1225 GLclampf clear_alpha_;
1226 GLboolean mask_red_;
1227 GLboolean mask_green_;
1228 GLboolean mask_blue_;
1229 GLboolean mask_alpha_;
1230 GLint clear_stencil_;
1231 GLuint mask_stencil_front_;
1232 GLuint mask_stencil_back_;
1233 GLclampf clear_depth_;
1234 GLboolean mask_depth_;
1235 bool enable_scissor_test_;
[email protected]297ca1c2011-06-20 23:08:461236 bool enable_depth_test_;
1237 bool enable_stencil_test_;
1238 bool state_dirty_;
[email protected]3a2e7c7b2010-08-06 01:12:281239
[email protected]1d32bc82010-01-13 22:06:461240 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501241 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301242
[email protected]8e3e0662010-08-23 18:46:301243 // The currently bound framebuffers
1244 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1245 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561246
1247 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081248 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561249
[email protected]b9363b22010-06-09 22:06:151250 // The offscreen frame buffer that the client renders to. With EGL, the
1251 // depth and stencil buffers are separate. With regular GL there is a single
1252 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1253 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351254 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1255 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021256 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151257 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1258 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021259 GLenum offscreen_target_color_format_;
1260 GLenum offscreen_target_depth_format_;
1261 GLenum offscreen_target_stencil_format_;
1262 GLsizei offscreen_target_samples_;
[email protected]6217d392010-03-25 22:08:351263
[email protected]a3a93e7b2010-08-28 00:48:561264 GLuint copy_texture_to_parent_texture_fb_;
1265
[email protected]34ff8b0c2010-10-01 20:06:021266 // The copy that is saved when SwapBuffers is called. It is also
1267 // used as the destination for multi-sample resolves.
1268 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351269 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]97872062010-11-03 19:07:051270 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351271
[email protected]7ff86b92010-11-25 17:50:001272 scoped_ptr<Callback1<gfx::Size>::Type> resize_callback_;
[email protected]43f28f832010-02-03 02:28:481273 scoped_ptr<Callback0::Type> swap_buffers_callback_;
[email protected]43f28f832010-02-03 02:28:481274
[email protected]32fe9aa2011-01-21 23:47:131275 // The format of the back buffer_
1276 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461277 bool back_buffer_has_depth_;
1278 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131279
[email protected]473c01ccb2011-06-07 01:33:301280 bool teximage2d_faster_than_texsubimage2d_;
1281 bool bufferdata_faster_than_buffersubdata_;
1282
[email protected]8eee29c2010-04-29 03:38:291283 // The last error message set.
1284 std::string last_error_;
1285
[email protected]a3a93e7b2010-08-28 00:48:561286 // The current decoder error.
1287 error::Error current_decoder_error_;
1288
[email protected]b1d2dcb2010-05-17 19:24:181289 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451290 scoped_ptr<ShaderTranslator> vertex_translator_;
1291 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181292
[email protected]c410da802011-03-14 19:17:411293 DisallowedExtensions disallowed_extensions_;
1294
[email protected]915a59a12010-09-30 21:29:111295 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051296 const Validators* validators_;
[email protected]915a59a12010-09-30 21:29:111297 FeatureInfo* feature_info_;
[email protected]9438b012010-06-15 22:55:051298
[email protected]b493ee622011-04-13 23:52:001299 // This indicates all the following texSubImage2D calls that are part of the
1300 // failed texImage2D call should be ignored.
1301 bool tex_image_2d_failed_;
1302
[email protected]65225772011-05-12 21:10:241303 int frame_number_;
1304
[email protected]38d139d2011-07-14 00:38:431305 bool has_arb_robustness_;
1306 GLenum reset_status_;
1307
[email protected]96449d2c2009-11-25 00:01:321308 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1309};
1310
[email protected]6217d392010-03-25 22:08:351311ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1312 : decoder_(decoder) {
1313 decoder_->CopyRealGLErrorsToWrapper();
1314}
1315
1316ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1317 decoder_->ClearRealGLErrors();
1318}
1319
1320ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1321 GLuint id)
1322 : decoder_(decoder) {
1323 ScopedGLErrorSuppressor suppressor(decoder_);
1324
1325 // TODO(apatrick): Check if there are any other states that need to be reset
1326 // before binding a new texture.
1327 glActiveTexture(GL_TEXTURE0);
1328 glBindTexture(GL_TEXTURE_2D, id);
1329}
1330
1331ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1332 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301333 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351334}
1335
1336ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1337 GLuint id)
1338 : decoder_(decoder) {
1339 ScopedGLErrorSuppressor suppressor(decoder_);
1340 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1341}
1342
1343ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1344 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301345 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351346}
1347
1348ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1349 GLuint id)
1350 : decoder_(decoder) {
1351 ScopedGLErrorSuppressor suppressor(decoder_);
1352 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1353}
1354
1355ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1356 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301357 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351358}
1359
[email protected]34ff8b0c2010-10-01 20:06:021360ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]c0701082011-04-20 00:34:521361 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer)
1362 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021363 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1364 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]c0701082011-04-20 00:34:521365 (!decoder_->bound_read_framebuffer_.get() ||
1366 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021367 if (!resolve_and_bind_)
1368 return;
1369
1370 ScopedGLErrorSuppressor suppressor(decoder_);
1371 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1372 decoder_->offscreen_target_frame_buffer_->id());
1373 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT,
1374 decoder_->offscreen_saved_frame_buffer_->id());
1375 const int width = decoder_->offscreen_size_.width();
1376 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181377 glDisable(GL_SCISSOR_TEST);
[email protected]34ff8b0c2010-10-01 20:06:021378 if (IsAngle()) {
1379 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1380 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1381 } else {
1382 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1383 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1384 }
1385 glBindFramebufferEXT(GL_FRAMEBUFFER,
1386 decoder_->offscreen_saved_frame_buffer_->id());
1387}
1388
1389ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1390 if (!resolve_and_bind_)
1391 return;
1392
1393 ScopedGLErrorSuppressor suppressor(decoder_);
1394 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181395 if (decoder_->enable_scissor_test_) {
1396 glEnable(GL_SCISSOR_TEST);
1397 }
[email protected]34ff8b0c2010-10-01 20:06:021398}
1399
[email protected]6217d392010-03-25 22:08:351400Texture::Texture(GLES2DecoderImpl* decoder)
1401 : decoder_(decoder),
[email protected]3a4d0c52011-06-29 23:11:581402 id_(0) {
[email protected]6217d392010-03-25 22:08:351403}
1404
1405Texture::~Texture() {
1406 // This does not destroy the render texture because that would require that
1407 // the associated GL context was current. Just check that it was explicitly
1408 // destroyed.
1409 DCHECK_EQ(id_, 0u);
1410}
1411
1412void Texture::Create() {
1413 ScopedGLErrorSuppressor suppressor(decoder_);
1414 Destroy();
1415 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581416 ScopedTexture2DBinder binder(decoder_, id_);
1417 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1418 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1419 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1420 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]6217d392010-03-25 22:08:351421}
1422
[email protected]34ff8b0c2010-10-01 20:06:021423bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351424 DCHECK_NE(id_, 0u);
1425 ScopedGLErrorSuppressor suppressor(decoder_);
1426 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]6217d392010-03-25 22:08:351427
1428 glTexImage2D(GL_TEXTURE_2D,
1429 0, // mip level
[email protected]34ff8b0c2010-10-01 20:06:021430 format,
[email protected]6217d392010-03-25 22:08:351431 size.width(),
1432 size.height(),
1433 0, // border
[email protected]34ff8b0c2010-10-01 20:06:021434 format,
[email protected]6217d392010-03-25 22:08:351435 GL_UNSIGNED_BYTE,
1436 NULL);
1437
[email protected]d37231fa2010-04-09 21:16:021438 size_ = size;
1439
[email protected]6217d392010-03-25 22:08:351440 return glGetError() == GL_NO_ERROR;
1441}
1442
[email protected]3a4d0c52011-06-29 23:11:581443void Texture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351444 DCHECK_NE(id_, 0u);
1445 ScopedGLErrorSuppressor suppressor(decoder_);
1446 ScopedTexture2DBinder binder(decoder_, id_);
1447 glCopyTexImage2D(GL_TEXTURE_2D,
1448 0, // level
[email protected]3a4d0c52011-06-29 23:11:581449 format,
[email protected]6217d392010-03-25 22:08:351450 0, 0,
1451 size.width(),
1452 size.height(),
1453 0); // border
1454}
1455
1456void Texture::Destroy() {
1457 if (id_ != 0) {
1458 ScopedGLErrorSuppressor suppressor(decoder_);
1459 glDeleteTextures(1, &id_);
1460 id_ = 0;
1461 }
1462}
1463
[email protected]97872062010-11-03 19:07:051464void Texture::Invalidate() {
1465 id_ = 0;
1466}
1467
[email protected]6217d392010-03-25 22:08:351468RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1469 : decoder_(decoder),
1470 id_(0) {
1471}
1472
1473RenderBuffer::~RenderBuffer() {
1474 // This does not destroy the render buffer because that would require that
1475 // the associated GL context was current. Just check that it was explicitly
1476 // destroyed.
1477 DCHECK_EQ(id_, 0u);
1478}
1479
1480void RenderBuffer::Create() {
1481 ScopedGLErrorSuppressor suppressor(decoder_);
1482 Destroy();
1483 glGenRenderbuffersEXT(1, &id_);
1484}
1485
[email protected]34ff8b0c2010-10-01 20:06:021486bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1487 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351488 ScopedGLErrorSuppressor suppressor(decoder_);
1489 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021490 if (samples <= 1) {
1491 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1492 format,
1493 size.width(),
1494 size.height());
1495 } else {
1496 if (IsAngle()) {
1497 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1498 samples,
1499 format,
1500 size.width(),
1501 size.height());
1502 } else {
1503 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1504 samples,
1505 format,
1506 size.width(),
1507 size.height());
1508 }
1509 }
[email protected]6217d392010-03-25 22:08:351510 return glGetError() == GL_NO_ERROR;
1511}
1512
1513void RenderBuffer::Destroy() {
1514 if (id_ != 0) {
1515 ScopedGLErrorSuppressor suppressor(decoder_);
1516 glDeleteRenderbuffersEXT(1, &id_);
1517 id_ = 0;
1518 }
1519}
1520
[email protected]97872062010-11-03 19:07:051521void RenderBuffer::Invalidate() {
1522 id_ = 0;
1523}
1524
[email protected]6217d392010-03-25 22:08:351525FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1526 : decoder_(decoder),
1527 id_(0) {
1528}
1529
1530FrameBuffer::~FrameBuffer() {
1531 // This does not destroy the frame buffer because that would require that
1532 // the associated GL context was current. Just check that it was explicitly
1533 // destroyed.
1534 DCHECK_EQ(id_, 0u);
1535}
1536
1537void FrameBuffer::Create() {
1538 ScopedGLErrorSuppressor suppressor(decoder_);
1539 Destroy();
1540 glGenFramebuffersEXT(1, &id_);
1541}
1542
1543void FrameBuffer::AttachRenderTexture(Texture* texture) {
1544 DCHECK_NE(id_, 0u);
1545 ScopedGLErrorSuppressor suppressor(decoder_);
1546 ScopedFrameBufferBinder binder(decoder_, id_);
1547 GLuint attach_id = texture ? texture->id() : 0;
1548 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1549 GL_COLOR_ATTACHMENT0,
1550 GL_TEXTURE_2D,
1551 attach_id,
1552 0);
1553}
1554
[email protected]b9363b22010-06-09 22:06:151555void FrameBuffer::AttachRenderBuffer(GLenum target,
1556 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351557 DCHECK_NE(id_, 0u);
1558 ScopedGLErrorSuppressor suppressor(decoder_);
1559 ScopedFrameBufferBinder binder(decoder_, id_);
1560 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1561 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151562 target,
[email protected]6217d392010-03-25 22:08:351563 GL_RENDERBUFFER,
1564 attach_id);
1565}
1566
1567void FrameBuffer::Clear(GLbitfield buffers) {
1568 ScopedGLErrorSuppressor suppressor(decoder_);
1569 ScopedFrameBufferBinder binder(decoder_, id_);
1570 glClear(buffers);
1571}
1572
1573void FrameBuffer::Destroy() {
1574 if (id_ != 0) {
1575 ScopedGLErrorSuppressor suppressor(decoder_);
1576 glDeleteFramebuffersEXT(1, &id_);
1577 id_ = 0;
1578 }
1579}
1580
[email protected]97872062010-11-03 19:07:051581void FrameBuffer::Invalidate() {
1582 id_ = 0;
1583}
1584
[email protected]6217d392010-03-25 22:08:351585GLenum FrameBuffer::CheckStatus() {
1586 DCHECK_NE(id_, 0u);
1587 ScopedGLErrorSuppressor suppressor(decoder_);
1588 ScopedFrameBufferBinder binder(decoder_, id_);
1589 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1590}
1591
[email protected]fbe20372011-06-01 01:46:381592GLES2Decoder* GLES2Decoder::Create(SurfaceManager* surface_manager,
1593 ContextGroup* group) {
1594 return new GLES2DecoderImpl(surface_manager, group);
[email protected]96449d2c2009-11-25 00:01:321595}
1596
[email protected]fbe20372011-06-01 01:46:381597GLES2DecoderImpl::GLES2DecoderImpl(SurfaceManager* surface_manager,
1598 ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391599 : GLES2Decoder(),
[email protected]fbe20372011-06-01 01:46:381600 surface_manager_(surface_manager),
[email protected]a3ded6d2010-10-19 06:44:391601 group_(ContextGroup::Ref(group ? group : new ContextGroup())),
[email protected]96449d2c2009-11-25 00:01:321602 error_bits_(0),
[email protected]96449d2c2009-11-25 00:01:321603 pack_alignment_(4),
1604 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241605 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491606 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241607 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401608 fixed_attrib_buffer_id_(0),
1609 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501610 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281611 clear_red_(0),
1612 clear_green_(0),
1613 clear_blue_(0),
1614 clear_alpha_(0),
1615 mask_red_(true),
1616 mask_green_(true),
1617 mask_blue_(true),
1618 mask_alpha_(true),
1619 clear_stencil_(0),
1620 mask_stencil_front_(-1),
1621 mask_stencil_back_(-1),
1622 clear_depth_(1.0f),
1623 mask_depth_(true),
1624 enable_scissor_test_(false),
[email protected]297ca1c2011-06-20 23:08:461625 enable_depth_test_(false),
1626 enable_stencil_test_(false),
1627 state_dirty_(true),
[email protected]34ff8b0c2010-10-01 20:06:021628 offscreen_target_color_format_(0),
1629 offscreen_target_depth_format_(0),
1630 offscreen_target_stencil_format_(0),
1631 offscreen_target_samples_(0),
[email protected]5ea88812011-03-28 10:45:391632 copy_texture_to_parent_texture_fb_(0),
[email protected]97872062010-11-03 19:07:051633 offscreen_saved_color_format_(0),
[email protected]32fe9aa2011-01-21 23:47:131634 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:461635 back_buffer_has_depth_(false),
1636 back_buffer_has_stencil_(false),
[email protected]473c01ccb2011-06-07 01:33:301637 teximage2d_faster_than_texsubimage2d_(true),
1638 bufferdata_faster_than_buffersubdata_(true),
[email protected]a3a93e7b2010-08-28 00:48:561639 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051640 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111641 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001642 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241643 tex_image_2d_failed_(false),
[email protected]38d139d2011-07-14 00:38:431644 frame_number_(0),
1645 has_arb_robustness_(false),
1646 reset_status_(GL_NO_ERROR) {
[email protected]b1122982010-05-17 23:04:241647 attrib_0_value_.v[0] = 0.0f;
1648 attrib_0_value_.v[1] = 0.0f;
1649 attrib_0_value_.v[2] = 0.0f;
1650 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151651
[email protected]c2f8c8402010-12-06 18:07:241652 // The shader translator is used for WebGL even when running on EGL
1653 // because additional restrictions are needed (like only enabling
1654 // GL_OES_standard_derivatives on demand). It is used for the unit
1655 // tests because
1656 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1657 // empty string to CompileShader and this is not a valid shader.
1658 // TODO(apatrick): fix this test.
1659 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
1660 !feature_info_->feature_flags().chromium_webglsl) ||
[email protected]b9363b22010-06-09 22:06:151661 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) {
1662 use_shader_translator_ = false;
1663 }
[email protected]473c01ccb2011-06-07 01:33:301664
1665 // TODO(gman): Consider setting these based on GPU and/or driver.
1666 if (IsAngle()) {
1667 teximage2d_faster_than_texsubimage2d_ = false;
1668 bufferdata_faster_than_buffersubdata_ = false;
1669 }
[email protected]96449d2c2009-11-25 00:01:321670}
1671
[email protected]c410da802011-03-14 19:17:411672bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:381673 const scoped_refptr<gfx::GLSurface>& surface,
1674 const scoped_refptr<gfx::GLContext>& context,
[email protected]c410da802011-03-14 19:17:411675 const gfx::Size& size,
1676 const DisallowedExtensions& disallowed_extensions,
1677 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:241678 const std::vector<int32>& attribs) {
[email protected]4bedba72010-04-20 22:08:541679 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301680 DCHECK(!context_.get());
1681
[email protected]fbe20372011-06-01 01:46:381682 // Take ownership of the GLSurface. TODO(apatrick): once the parent / child
1683 // context is retired, the decoder should not take an initial surface as
1684 // an argument to this function.
1685 // Maybe create a short lived offscreen GLSurface for the purpose of
1686 // initializing the decoder's GLContext.
1687 surface_ = surface;
[email protected]f62a5ab2011-05-23 20:34:151688
[email protected]66791e382010-07-14 20:48:301689 // Take ownership of the GLContext.
[email protected]fbe20372011-06-01 01:46:381690 context_ = context;
[email protected]d37231fa2010-04-09 21:16:021691
[email protected]246a70452010-03-05 21:53:501692 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:011693 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
1694 << "MakeCurrent failed.";
[email protected]246a70452010-03-05 21:53:501695 Destroy();
1696 return false;
[email protected]eb54a562010-01-20 21:55:181697 }
1698
[email protected]c410da802011-03-14 19:17:411699 if (!group_->Initialize(disallowed_extensions, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:221700 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:391701 << "failed to initialize.";
1702 Destroy();
[email protected]ae1741092010-11-17 19:16:031703 return false;
[email protected]a3ded6d2010-10-19 06:44:391704 }
1705
[email protected]246a70452010-03-05 21:53:501706 CHECK_GL_ERROR();
[email protected]c410da802011-03-14 19:17:411707 disallowed_extensions_ = disallowed_extensions;
[email protected]246a70452010-03-05 21:53:501708
[email protected]f39f4b3f2010-05-12 17:04:081709 vertex_attrib_manager_.Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:321710
[email protected]302ce6d2011-07-07 23:28:111711 util_.set_num_compressed_texture_formats(
1712 validators_->compressed_texture_format.GetValues().size());
1713
[email protected]1071e572011-02-09 20:00:121714 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1715 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
1716 // OpenGL ES 2.0 does not have this issue.
1717 glEnableVertexAttribArray(0);
1718 }
[email protected]b1122982010-05-17 23:04:241719 glGenBuffersARB(1, &attrib_0_buffer_id_);
1720 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
1721 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
1722 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:401723 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:081724
[email protected]246a70452010-03-05 21:53:501725 texture_units_.reset(
1726 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:151727 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:491728 glActiveTexture(GL_TEXTURE0 + tt);
1729 // Do cube map first because we want the last bind to be 2D.
1730 TextureManager::TextureInfo* info =
[email protected]1958e0e2010-04-22 05:17:151731 texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:491732 texture_units_[tt].bound_texture_cube_map = info;
1733 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
1734 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
1735 texture_units_[tt].bound_texture_2d = info;
1736 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:151737 }
[email protected]00f893d2010-08-24 18:55:491738 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:501739 CHECK_GL_ERROR();
1740
[email protected]297ca1c2011-06-20 23:08:461741 ContextCreationAttribParser attrib_parser;
1742 if (!attrib_parser.Parse(attribs))
1743 return false;
[email protected]41c56362011-06-14 16:47:431744
[email protected]297ca1c2011-06-20 23:08:461745 // These are NOT if the back buffer has these proprorties. They are
1746 // if we want the command buffer to enforce them regardless of what
1747 // the real backbuffer is assuming the real back buffer gives us more than
1748 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
1749 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
1750 // can't do anything about that.
1751
1752 GLint v = 0;
1753 glGetIntegerv(GL_ALPHA_BITS, &v);
1754 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
1755 // user requested RGB then RGB. If the user did not specify a preference than
1756 // use whatever we were given. Same for DEPTH and STENCIL.
1757 back_buffer_color_format_ =
1758 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
1759 glGetIntegerv(GL_DEPTH_BITS, &v);
1760 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
1761 glGetIntegerv(GL_STENCIL_BITS, &v);
1762 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
1763
1764 if (surface_->IsOffscreen()) {
[email protected]34ff8b0c2010-10-01 20:06:021765 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:541766 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:021767 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
1768 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:431769 // max_sample_count must be initialized to a sane value. If
1770 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
1771 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:021772 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
1773 offscreen_target_samples_ = std::min(attrib_parser.samples_,
1774 max_sample_count);
1775 } else {
1776 offscreen_target_samples_ = 1;
1777 }
1778
1779 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
1780 const bool rgb8_supported =
1781 context_->HasExtension("GL_OES_rgb8_rgba8");
1782 // The only available default render buffer formats in GLES2 have very
1783 // little precision. Don't enable multisampling unless 8-bit render
1784 // buffer formats are available--instead fall back to 8-bit textures.
1785 if (rgb8_supported && offscreen_target_samples_ > 1) {
1786 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1787 GL_RGBA8 : GL_RGB8;
1788 } else {
1789 offscreen_target_samples_ = 1;
1790 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1791 GL_RGBA : GL_RGB;
1792 }
1793
1794 // ANGLE only supports packed depth/stencil formats, so use it if it is
1795 // available.
1796 const bool depth24_stencil8_supported =
1797 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271798 VLOG(1) << "GL_OES_packed_depth_stencil "
1799 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:001800 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1801 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021802 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1803 offscreen_target_stencil_format_ = 0;
1804 } else {
1805 // It may be the case that this depth/stencil combination is not
1806 // supported, but this will be checked later by CheckFramebufferStatus.
1807 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1808 GL_DEPTH_COMPONENT16 : 0;
1809 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1810 GL_STENCIL_INDEX8 : 0;
1811 }
1812 } else {
1813 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1814 GL_RGBA : GL_RGB;
1815
1816 // If depth is requested at all, use the packed depth stencil format if
1817 // it's available, as some desktop GL drivers don't support any non-packed
1818 // formats for depth attachments.
1819 const bool depth24_stencil8_supported =
1820 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271821 VLOG(1) << "GL_EXT_packed_depth_stencil "
1822 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:021823
[email protected]71ee3642010-10-14 18:08:001824 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1825 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021826 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1827 offscreen_target_stencil_format_ = 0;
1828 } else {
1829 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1830 GL_DEPTH_COMPONENT : 0;
1831 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1832 GL_STENCIL_INDEX : 0;
1833 }
1834 }
1835
[email protected]97872062010-11-03 19:07:051836 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
1837 GL_RGBA : GL_RGB;
1838
[email protected]6217d392010-03-25 22:08:351839 // Create the target frame buffer. This is the one that the client renders
1840 // directly to.
1841 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
1842 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021843 // Due to GLES2 format limitations, either the color texture (for
1844 // non-multisampling) or the color render buffer (for multisampling) will be
1845 // attached to the offscreen frame buffer. The render buffer has more
1846 // limited formats available to it, but the texture can't do multisampling.
1847 if (IsOffscreenBufferMultisampled()) {
1848 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
1849 offscreen_target_color_render_buffer_->Create();
1850 } else {
1851 offscreen_target_color_texture_.reset(new Texture(this));
1852 offscreen_target_color_texture_->Create();
1853 }
1854 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151855 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021856 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151857 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:351858
1859 // Create the saved offscreen texture. The target frame buffer is copied
1860 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021861 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
1862 offscreen_saved_frame_buffer_->Create();
1863 //
[email protected]6217d392010-03-25 22:08:351864 offscreen_saved_color_texture_.reset(new Texture(this));
1865 offscreen_saved_color_texture_->Create();
1866
[email protected]6217d392010-03-25 22:08:351867 // Allocate the render buffers at their initial size and check the status
1868 // of the frame buffers is okay.
[email protected]d37231fa2010-04-09 21:16:021869 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:351870 if (!UpdateOffscreenFrameBufferSize()) {
[email protected]d0498742010-09-20 20:27:011871 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:351872 Destroy();
1873 return false;
1874 }
1875
1876 // Bind to the new default frame buffer (the offscreen target frame buffer).
1877 // This should now be associated with ID zero.
1878 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
[email protected]a3a93e7b2010-08-28 00:48:561879
1880 glGenFramebuffersEXT(1, &copy_texture_to_parent_texture_fb_);
[email protected]6217d392010-03-25 22:08:351881 }
1882
[email protected]76a0ee102010-04-07 21:03:041883 // OpenGL ES 2.0 implicitly enables the desktop GL capability
1884 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
1885 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:371886 // mailing list archives. It also implicitly enables the desktop GL
1887 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
1888 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:151889 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1890 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:371891 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:151892 }
[email protected]de17df392010-04-23 21:09:411893
[email protected]38d139d2011-07-14 00:38:431894 has_arb_robustness_ = context->HasExtension("GL_ARB_robustness");
1895
[email protected]c2f8c8402010-12-06 18:07:241896 if (!InitializeShaderTranslator()) {
1897 return false;
[email protected]de17df392010-04-23 21:09:411898 }
[email protected]76a0ee102010-04-07 21:03:041899
[email protected]246a70452010-03-05 21:53:501900 return true;
[email protected]96449d2c2009-11-25 00:01:321901}
1902
[email protected]302ce6d2011-07-07 23:28:111903void GLES2DecoderImpl::UpdateCapabilities() {
1904 util_.set_num_compressed_texture_formats(
1905 validators_->compressed_texture_format.GetValues().size());
1906 util_.set_num_shader_binary_formats(
1907 validators_->shader_binary_format.GetValues().size());
1908}
1909
[email protected]c2f8c8402010-12-06 18:07:241910bool GLES2DecoderImpl::InitializeShaderTranslator() {
1911 // Re-check the state of use_shader_translator_ each time this is called.
1912 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
1913 feature_info_->feature_flags().chromium_webglsl &&
1914 !use_shader_translator_) {
1915 use_shader_translator_ = true;
1916 }
1917 if (!use_shader_translator_) {
1918 return true;
1919 }
1920 ShBuiltInResources resources;
1921 ShInitBuiltInResources(&resources);
1922 resources.MaxVertexAttribs = group_->max_vertex_attribs();
1923 resources.MaxVertexUniformVectors =
1924 group_->max_vertex_uniform_vectors();
1925 resources.MaxVaryingVectors = group_->max_varying_vectors();
1926 resources.MaxVertexTextureImageUnits =
1927 group_->max_vertex_texture_image_units();
1928 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
1929 resources.MaxTextureImageUnits = group_->max_texture_image_units();
1930 resources.MaxFragmentUniformVectors =
1931 group_->max_fragment_uniform_vectors();
1932 resources.MaxDrawBuffers = 1;
1933 resources.OES_standard_derivatives =
1934 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
1935 vertex_translator_.reset(new ShaderTranslator);
1936 ShShaderSpec shader_spec = feature_info_->feature_flags().chromium_webglsl ?
1937 SH_WEBGL_SPEC : SH_GLES2_SPEC;
1938 bool is_glsl_es =
1939 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
1940 if (!vertex_translator_->Init(
1941 SH_VERTEX_SHADER, shader_spec, &resources, is_glsl_es)) {
1942 LOG(ERROR) << "Could not initialize vertex shader translator.";
1943 Destroy();
1944 return false;
1945 }
1946 fragment_translator_.reset(new ShaderTranslator);
1947 if (!fragment_translator_->Init(
1948 SH_FRAGMENT_SHADER, shader_spec, &resources, is_glsl_es)) {
1949 LOG(ERROR) << "Could not initialize fragment shader translator.";
1950 Destroy();
1951 return false;
1952 }
1953 return true;
1954}
1955
[email protected]ae51d192010-04-27 00:48:031956bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:471957 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:031958 if (GetBufferInfo(client_ids[ii])) {
1959 return false;
1960 }
1961 }
1962 scoped_array<GLuint> service_ids(new GLuint[n]);
1963 glGenBuffersARB(n, service_ids.get());
1964 for (GLsizei ii = 0; ii < n; ++ii) {
1965 CreateBufferInfo(client_ids[ii], service_ids[ii]);
1966 }
1967 return true;
1968}
1969
1970bool GLES2DecoderImpl::GenFramebuffersHelper(
1971 GLsizei n, const GLuint* client_ids) {
1972 for (GLsizei ii = 0; ii < n; ++ii) {
1973 if (GetFramebufferInfo(client_ids[ii])) {
1974 return false;
1975 }
1976 }
1977 scoped_array<GLuint> service_ids(new GLuint[n]);
1978 glGenFramebuffersEXT(n, service_ids.get());
1979 for (GLsizei ii = 0; ii < n; ++ii) {
1980 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
1981 }
1982 return true;
1983}
1984
1985bool GLES2DecoderImpl::GenRenderbuffersHelper(
1986 GLsizei n, const GLuint* client_ids) {
1987 for (GLsizei ii = 0; ii < n; ++ii) {
1988 if (GetRenderbufferInfo(client_ids[ii])) {
1989 return false;
1990 }
1991 }
1992 scoped_array<GLuint> service_ids(new GLuint[n]);
1993 glGenRenderbuffersEXT(n, service_ids.get());
1994 for (GLsizei ii = 0; ii < n; ++ii) {
1995 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
1996 }
1997 return true;
1998}
1999
2000bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2001 for (GLsizei ii = 0; ii < n; ++ii) {
2002 if (GetTextureInfo(client_ids[ii])) {
2003 return false;
2004 }
2005 }
2006 scoped_array<GLuint> service_ids(new GLuint[n]);
2007 glGenTextures(n, service_ids.get());
2008 for (GLsizei ii = 0; ii < n; ++ii) {
2009 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2010 }
2011 return true;
2012}
2013
2014void GLES2DecoderImpl::DeleteBuffersHelper(
2015 GLsizei n, const GLuint* client_ids) {
2016 for (GLsizei ii = 0; ii < n; ++ii) {
2017 BufferManager::BufferInfo* info = GetBufferInfo(client_ids[ii]);
2018 if (info) {
2019 GLuint service_id = info->service_id();
2020 glDeleteBuffersARB(1, &service_id);
2021 RemoveBufferInfo(client_ids[ii]);
2022 }
[email protected]a93bb842010-02-16 23:03:472023 }
[email protected]07f54fcc2009-12-22 02:46:302024}
2025
[email protected]ae51d192010-04-27 00:48:032026void GLES2DecoderImpl::DeleteFramebuffersHelper(
2027 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582028 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032029 FramebufferManager::FramebufferInfo* info =
2030 GetFramebufferInfo(client_ids[ii]);
2031 if (info) {
[email protected]297ca1c2011-06-20 23:08:462032 if (info == bound_draw_framebuffer_) {
2033 bound_draw_framebuffer_ = NULL;
2034 state_dirty_ = true;
2035 }
[email protected]ae51d192010-04-27 00:48:032036 GLuint service_id = info->service_id();
2037 glDeleteFramebuffersEXT(1, &service_id);
2038 RemoveFramebufferInfo(client_ids[ii]);
2039 }
[email protected]a25fa872010-03-25 02:57:582040 }
[email protected]07f54fcc2009-12-22 02:46:302041}
2042
[email protected]ae51d192010-04-27 00:48:032043void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2044 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582045 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032046 RenderbufferManager::RenderbufferInfo* info =
2047 GetRenderbufferInfo(client_ids[ii]);
2048 if (info) {
[email protected]297ca1c2011-06-20 23:08:462049 state_dirty_ = true;
[email protected]ae51d192010-04-27 00:48:032050 GLuint service_id = info->service_id();
2051 glDeleteRenderbuffersEXT(1, &service_id);
2052 RemoveRenderbufferInfo(client_ids[ii]);
2053 }
[email protected]a25fa872010-03-25 02:57:582054 }
[email protected]07f54fcc2009-12-22 02:46:302055}
2056
[email protected]ae51d192010-04-27 00:48:032057void GLES2DecoderImpl::DeleteTexturesHelper(
2058 GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472059 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032060 TextureManager::TextureInfo* info = GetTextureInfo(client_ids[ii]);
2061 if (info) {
[email protected]297ca1c2011-06-20 23:08:462062 if (info->IsAttachedToFramebuffer()) {
2063 state_dirty_ = true;
2064 }
[email protected]ae51d192010-04-27 00:48:032065 GLuint service_id = info->service_id();
2066 glDeleteTextures(1, &service_id);
2067 RemoveTextureInfo(client_ids[ii]);
2068 }
[email protected]a93bb842010-02-16 23:03:472069 }
[email protected]07f54fcc2009-12-22 02:46:302070}
2071
[email protected]43f28f832010-02-03 02:28:482072// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322073
[email protected]eb54a562010-01-20 21:55:182074bool GLES2DecoderImpl::MakeCurrent() {
[email protected]38d139d2011-07-14 00:38:432075 bool result = context_.get() ? context_->MakeCurrent(surface_.get()) : false;
2076 if (result && WasContextLost()) {
2077 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2078 result = false;
2079 }
2080
2081 return result;
[email protected]eb54a562010-01-20 21:55:182082}
2083
[email protected]8e3e0662010-08-23 18:46:302084void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
2085 glBindRenderbufferEXT(
2086 GL_RENDERBUFFER,
2087 bound_renderbuffer_ ? bound_renderbuffer_->service_id() : 0);
2088}
2089
2090static void RebindCurrentFramebuffer(
2091 GLenum target,
2092 FramebufferManager::FramebufferInfo* info,
2093 FrameBuffer* offscreen_frame_buffer) {
2094 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462095
[email protected]8e3e0662010-08-23 18:46:302096 if (framebuffer_id == 0 && offscreen_frame_buffer) {
2097 framebuffer_id = offscreen_frame_buffer->id();
2098 }
[email protected]297ca1c2011-06-20 23:08:462099
[email protected]8e3e0662010-08-23 18:46:302100 glBindFramebufferEXT(target, framebuffer_id);
2101}
2102
2103void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]297ca1c2011-06-20 23:08:462104 state_dirty_ = true;
2105
[email protected]a3ded6d2010-10-19 06:44:392106 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302107 RebindCurrentFramebuffer(
2108 GL_FRAMEBUFFER,
2109 bound_draw_framebuffer_.get(),
2110 offscreen_target_frame_buffer_.get());
2111 } else {
2112 RebindCurrentFramebuffer(
2113 GL_READ_FRAMEBUFFER_EXT,
2114 bound_read_framebuffer_.get(),
2115 offscreen_target_frame_buffer_.get());
2116 RebindCurrentFramebuffer(
2117 GL_DRAW_FRAMEBUFFER_EXT,
2118 bound_draw_framebuffer_.get(),
2119 offscreen_target_frame_buffer_.get());
2120 }
2121}
2122
2123void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2124 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2125 GLuint last_id;
2126 if (info.bound_texture_2d) {
2127 last_id = info.bound_texture_2d->service_id();
2128 } else {
2129 last_id = 0;
2130 }
2131
2132 glBindTexture(GL_TEXTURE_2D, last_id);
2133 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2134}
2135
[email protected]3a03a8f2011-03-19 00:51:272136bool GLES2DecoderImpl::CheckFramebufferComplete(const char* func_name) {
2137 if (bound_draw_framebuffer_ && bound_draw_framebuffer_->IsNotComplete()) {
[email protected]be45d7c2011-04-15 18:03:352138 SetGLError(GL_INVALID_FRAMEBUFFER_OPERATION,
[email protected]3a03a8f2011-03-19 00:51:272139 (std::string(func_name) + " framebuffer incomplete").c_str());
2140 return false;
2141 }
2142 return true;
2143}
2144
[email protected]8e3e0662010-08-23 18:46:302145gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
2146 if (bound_read_framebuffer_ != 0) {
[email protected]9edc6b22010-12-23 02:00:262147 const FramebufferManager::FramebufferInfo::Attachment* attachment =
2148 bound_read_framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
2149 if (attachment) {
2150 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502151 }
[email protected]9edc6b22010-12-23 02:00:262152 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022153 } else if (offscreen_target_frame_buffer_.get()) {
2154 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352155 } else {
[email protected]f62a5ab2011-05-23 20:34:152156 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022157 }
[email protected]246a70452010-03-05 21:53:502158}
2159
[email protected]9edc6b22010-12-23 02:00:262160GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
2161 if (bound_read_framebuffer_ != 0) {
[email protected]297ca1c2011-06-20 23:08:462162 return bound_read_framebuffer_->GetColorAttachmentFormat();
2163 } else if (offscreen_target_frame_buffer_.get()) {
2164 return offscreen_target_color_format_;
2165 } else {
2166 return back_buffer_color_format_;
2167 }
2168}
2169
2170GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
2171 if (bound_draw_framebuffer_ != 0) {
2172 return bound_draw_framebuffer_->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262173 } else if (offscreen_target_frame_buffer_.get()) {
2174 return offscreen_target_color_format_;
2175 } else {
[email protected]32fe9aa2011-01-21 23:47:132176 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262177 }
2178}
2179
[email protected]6217d392010-03-25 22:08:352180bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
[email protected]34ff8b0c2010-10-01 20:06:022181 if (offscreen_size_ == pending_offscreen_size_)
[email protected]6217d392010-03-25 22:08:352182 return true;
2183
[email protected]34ff8b0c2010-10-01 20:06:022184 offscreen_size_ = pending_offscreen_size_;
[email protected]a470d612011-02-25 04:15:002185 int w = offscreen_size_.width();
2186 int h = offscreen_size_.height();
2187 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
2188 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2189 << "to allocate storage due to excessive dimensions.";
2190 return false;
2191 }
[email protected]34ff8b0c2010-10-01 20:06:022192
[email protected]6217d392010-03-25 22:08:352193 // Reallocate the offscreen target buffers.
[email protected]34ff8b0c2010-10-01 20:06:022194 DCHECK(offscreen_target_color_format_);
2195 if (IsOffscreenBufferMultisampled()) {
2196 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2197 pending_offscreen_size_, offscreen_target_color_format_,
2198 offscreen_target_samples_)) {
2199 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2200 << "to allocate storage for offscreen target color buffer.";
2201 return false;
2202 }
2203 } else {
2204 if (!offscreen_target_color_texture_->AllocateStorage(
2205 pending_offscreen_size_, offscreen_target_color_format_)) {
2206 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2207 << "to allocate storage for offscreen target color texture.";
2208 return false;
2209 }
2210 }
2211 if (offscreen_target_depth_format_ &&
2212 !offscreen_target_depth_render_buffer_->AllocateStorage(
2213 pending_offscreen_size_, offscreen_target_depth_format_,
2214 offscreen_target_samples_)) {
[email protected]d0498742010-09-20 20:27:012215 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
[email protected]34ff8b0c2010-10-01 20:06:022216 << "to allocate storage for offscreen target depth buffer.";
2217 return false;
2218 }
2219 if (offscreen_target_stencil_format_ &&
2220 !offscreen_target_stencil_render_buffer_->AllocateStorage(
2221 pending_offscreen_size_, offscreen_target_stencil_format_,
2222 offscreen_target_samples_)) {
2223 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2224 << "to allocate storage for offscreen target stencil buffer.";
[email protected]6217d392010-03-25 22:08:352225 return false;
2226 }
2227
[email protected]2f2d7042010-04-14 21:45:582228 // Attach the offscreen target buffers to the target frame buffer.
[email protected]34ff8b0c2010-10-01 20:06:022229 if (IsOffscreenBufferMultisampled()) {
[email protected]b9363b22010-06-09 22:06:152230 offscreen_target_frame_buffer_->AttachRenderBuffer(
[email protected]34ff8b0c2010-10-01 20:06:022231 GL_COLOR_ATTACHMENT0,
2232 offscreen_target_color_render_buffer_.get());
[email protected]b9363b22010-06-09 22:06:152233 } else {
[email protected]34ff8b0c2010-10-01 20:06:022234 offscreen_target_frame_buffer_->AttachRenderTexture(
2235 offscreen_target_color_texture_.get());
2236 }
2237 if (offscreen_target_depth_format_) {
2238 offscreen_target_frame_buffer_->AttachRenderBuffer(
2239 GL_DEPTH_ATTACHMENT,
2240 offscreen_target_depth_render_buffer_.get());
2241 }
2242 const bool packed_depth_stencil =
2243 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2244 if (packed_depth_stencil) {
[email protected]b9363b22010-06-09 22:06:152245 offscreen_target_frame_buffer_->AttachRenderBuffer(
2246 GL_STENCIL_ATTACHMENT,
2247 offscreen_target_depth_render_buffer_.get());
[email protected]34ff8b0c2010-10-01 20:06:022248 } else if (offscreen_target_stencil_format_) {
2249 offscreen_target_frame_buffer_->AttachRenderBuffer(
2250 GL_STENCIL_ATTACHMENT,
2251 offscreen_target_stencil_render_buffer_.get());
[email protected]b9363b22010-06-09 22:06:152252 }
[email protected]34ff8b0c2010-10-01 20:06:022253
[email protected]6217d392010-03-25 22:08:352254 if (offscreen_target_frame_buffer_->CheckStatus() !=
2255 GL_FRAMEBUFFER_COMPLETE) {
[email protected]d0498742010-09-20 20:27:012256 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2257 << "because offscreen FBO was incomplete.";
[email protected]6217d392010-03-25 22:08:352258 return false;
2259 }
2260
[email protected]c007aa02010-09-02 22:22:402261 // Clear the target frame buffer.
2262 {
2263 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
[email protected]297ca1c2011-06-20 23:08:462264 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2265 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
[email protected]c007aa02010-09-02 22:22:402266 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2267 glClearStencil(0);
[email protected]297ca1c2011-06-20 23:08:462268 glStencilMaskSeparate(GL_FRONT, -1);
2269 glStencilMaskSeparate(GL_BACK, -1);
[email protected]c007aa02010-09-02 22:22:402270 glClearDepth(0);
2271 glDepthMask(GL_TRUE);
2272 glDisable(GL_SCISSOR_TEST);
[email protected]2f2d7042010-04-14 21:45:582273 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
[email protected]c007aa02010-09-02 22:22:402274 RestoreClearState();
[email protected]2f2d7042010-04-14 21:45:582275 }
[email protected]2f2d7042010-04-14 21:45:582276
[email protected]9a5afa432011-07-22 18:16:392277 // Allocate the offscreen saved color texture.
2278 DCHECK(offscreen_saved_color_format_);
2279 offscreen_saved_color_texture_->AllocateStorage(
2280 pending_offscreen_size_, offscreen_saved_color_format_);
[email protected]d37231fa2010-04-09 21:16:022281
[email protected]9a5afa432011-07-22 18:16:392282 offscreen_saved_frame_buffer_->AttachRenderTexture(
2283 offscreen_saved_color_texture_.get());
2284 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2285 GL_FRAMEBUFFER_COMPLETE) {
2286 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2287 << "because offscreen saved FBO was incomplete.";
2288 return false;
[email protected]34ff8b0c2010-10-01 20:06:022289 }
2290
[email protected]9a5afa432011-07-22 18:16:392291 // Clear the offscreen color texture.
2292 {
2293 ScopedFrameBufferBinder binder(this, offscreen_saved_frame_buffer_->id());
2294 glClearColor(0, 0, 0, 0);
2295 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2296 glDisable(GL_SCISSOR_TEST);
2297 glClear(GL_COLOR_BUFFER_BIT);
2298 RestoreClearState();
2299 }
2300
2301 UpdateParentTextureInfo();
2302
2303 return true;
2304}
2305
2306void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]34ff8b0c2010-10-01 20:06:022307 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582308 // Update the info about the offscreen saved color texture in the parent.
2309 // The reference to the parent is a weak pointer and will become null if the
2310 // parent is later destroyed.
[email protected]6217d392010-03-25 22:08:352311 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]8d25d042010-06-16 19:48:142312 GLuint client_id;
[email protected]262d7aa2010-12-03 22:07:292313 TextureManager* parent_texture_manager = parent_->texture_manager();
2314 CHECK(parent_texture_manager->GetClientId(service_id, &client_id));
[email protected]8d25d042010-06-16 19:48:142315 TextureManager::TextureInfo* info = parent_->GetTextureInfo(client_id);
[email protected]6217d392010-03-25 22:08:352316 DCHECK(info);
2317
[email protected]262d7aa2010-12-03 22:07:292318 parent_texture_manager->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:112319 feature_info_,
[email protected]ef526492010-06-02 23:12:252320 info,
2321 GL_TEXTURE_2D,
2322 0, // level
2323 GL_RGBA,
2324 pending_offscreen_size_.width(),
2325 pending_offscreen_size_.height(),
2326 1, // depth
2327 0, // border
2328 GL_RGBA,
2329 GL_UNSIGNED_BYTE);
[email protected]262d7aa2010-12-03 22:07:292330 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042331 feature_info_,
2332 info,
2333 GL_TEXTURE_MAG_FILTER,
2334 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292335 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042336 feature_info_,
2337 info,
2338 GL_TEXTURE_MIN_FILTER,
2339 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292340 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042341 feature_info_,
2342 info,
2343 GL_TEXTURE_WRAP_S,
2344 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292345 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042346 feature_info_,
2347 info,
2348 GL_TEXTURE_WRAP_T,
2349 GL_CLAMP_TO_EDGE);
[email protected]0c8c9d22010-06-25 17:36:392350 }
[email protected]6217d392010-03-25 22:08:352351}
2352
[email protected]7ff86b92010-11-25 17:50:002353void GLES2DecoderImpl::SetResizeCallback(Callback1<gfx::Size>::Type* callback) {
2354 resize_callback_.reset(callback);
2355}
2356
[email protected]43f28f832010-02-03 02:28:482357void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
2358 swap_buffers_callback_.reset(callback);
2359}
2360
[email protected]1318e922010-09-17 22:03:162361bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2362 uint32* service_texture_id) {
2363 TextureManager::TextureInfo* texture =
2364 texture_manager()->GetTextureInfo(client_texture_id);
2365 if (texture) {
2366 *service_texture_id = texture->service_id();
2367 return true;
2368 }
2369 return false;
2370}
2371
[email protected]96449d2c2009-11-25 00:01:322372void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392373 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052374
2375 if (group_.get())
2376 group_->set_have_context(have_context);
2377
[email protected]3c644d82011-06-20 19:58:242378 SetParent(NULL, 0);
2379
[email protected]eadc96792010-10-27 19:39:392380 if (have_context) {
[email protected]ca488e12010-12-13 20:06:142381 if (current_program_) {
2382 program_manager()->UnuseProgram(shader_manager(), current_program_);
2383 current_program_ = NULL;
2384 }
2385
[email protected]b1122982010-05-17 23:04:242386 if (attrib_0_buffer_id_) {
2387 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2388 }
[email protected]8fbedc02010-11-18 18:43:402389 if (fixed_attrib_buffer_id_) {
2390 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2391 }
[email protected]b1122982010-05-17 23:04:242392
[email protected]3c644d82011-06-20 19:58:242393 if (copy_texture_to_parent_texture_fb_)
[email protected]a3a93e7b2010-08-28 00:48:562394 glDeleteFramebuffersEXT(1, &copy_texture_to_parent_texture_fb_);
[email protected]6217d392010-03-25 22:08:352395
[email protected]97872062010-11-03 19:07:052396 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542397 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052398 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542399 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052400 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022401 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052402 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152403 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052404 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152405 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052406 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022407 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052408 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542409 offscreen_saved_color_texture_->Destroy();
[email protected]66791e382010-07-14 20:48:302410
[email protected]eadc96792010-10-27 19:39:392411 // must release the ContextGroup before destroying the context as its
2412 // destructor uses GL.
2413 group_ = NULL;
[email protected]97872062010-11-03 19:07:052414 } else {
2415 if (offscreen_target_frame_buffer_.get())
2416 offscreen_target_frame_buffer_->Invalidate();
2417 if (offscreen_target_color_texture_.get())
2418 offscreen_target_color_texture_->Invalidate();
2419 if (offscreen_target_color_render_buffer_.get())
2420 offscreen_target_color_render_buffer_->Invalidate();
2421 if (offscreen_target_depth_render_buffer_.get())
2422 offscreen_target_depth_render_buffer_->Invalidate();
2423 if (offscreen_target_stencil_render_buffer_.get())
2424 offscreen_target_stencil_render_buffer_->Invalidate();
2425 if (offscreen_saved_frame_buffer_.get())
2426 offscreen_saved_frame_buffer_->Invalidate();
2427 if (offscreen_saved_color_texture_.get())
2428 offscreen_saved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022429 }
[email protected]97872062010-11-03 19:07:052430
[email protected]fe871662011-06-16 20:43:052431 if (context_.get()) {
2432 context_->ReleaseCurrent(NULL);
[email protected]0fc35742011-04-13 17:57:542433 context_->Destroy();
[email protected]fe871662011-06-16 20:43:052434 }
[email protected]fbe20372011-06-01 01:46:382435 context_ = NULL;
[email protected]0fc35742011-04-13 17:57:542436
[email protected]97872062010-11-03 19:07:052437 offscreen_target_frame_buffer_.reset();
2438 offscreen_target_color_texture_.reset();
2439 offscreen_target_color_render_buffer_.reset();
2440 offscreen_target_depth_render_buffer_.reset();
2441 offscreen_target_stencil_render_buffer_.reset();
2442 offscreen_saved_frame_buffer_.reset();
2443 offscreen_saved_color_texture_.reset();
[email protected]96449d2c2009-11-25 00:01:322444}
2445
[email protected]3c644d82011-06-20 19:58:242446bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
2447 uint32 new_parent_texture_id) {
[email protected]9a5afa432011-07-22 18:16:392448 if (!offscreen_saved_color_texture_.get())
2449 return false;
2450
[email protected]3c644d82011-06-20 19:58:242451 // Remove the saved frame buffer mapping from the parent decoder. The
2452 // parent pointer is a weak pointer so it will be null if the parent has
2453 // already been destroyed.
2454 if (parent_) {
2455 // First check the texture has been mapped into the parent. This might not
2456 // be the case if initialization failed midway through.
2457 GLuint service_id = offscreen_saved_color_texture_->id();
2458 GLuint client_id = 0;
2459 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
2460 parent_->texture_manager()->RemoveTextureInfo(feature_info_, client_id);
2461 }
2462 }
2463
2464 GLES2DecoderImpl* new_parent_impl = static_cast<GLES2DecoderImpl*>(
2465 new_parent);
2466 if (new_parent_impl) {
2467 // Map the ID of the saved offscreen texture into the parent so that
2468 // it can reference it.
2469 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]98687862011-07-11 23:31:302470
2471 // Replace texture info when ID is already in use by parent.
2472 if (new_parent_impl->texture_manager()->GetTextureInfo(
2473 new_parent_texture_id))
2474 new_parent_impl->texture_manager()->RemoveTextureInfo(
2475 feature_info_, new_parent_texture_id);
2476
[email protected]3c644d82011-06-20 19:58:242477 TextureManager::TextureInfo* info =
2478 new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id);
2479 info->SetNotOwned();
2480 new_parent_impl->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
2481
2482 parent_ = new_parent_impl->AsWeakPtr();
[email protected]9a5afa432011-07-22 18:16:392483
2484 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:242485 } else {
2486 parent_.reset();
2487 }
2488
2489 return true;
2490}
2491
[email protected]6217d392010-03-25 22:08:352492void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2493 // We can't resize the render buffers immediately because there might be a
2494 // partial frame rendered into them and we don't want the tail end of that
2495 // rendered into the reallocated storage. Defer until the next SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:022496 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:352497}
2498
[email protected]269200b12010-11-18 22:53:062499void GLES2DecoderImpl::DoCopyTextureToParentTextureCHROMIUM(
[email protected]c007aa02010-09-02 22:22:402500 GLuint client_texture_id,
2501 GLuint parent_client_texture_id) {
[email protected]a3a93e7b2010-08-28 00:48:562502 if (parent_) {
[email protected]c007aa02010-09-02 22:22:402503 TextureManager::TextureInfo* texture = texture_manager()->GetTextureInfo(
2504 client_texture_id);
2505 TextureManager::TextureInfo* parent_texture =
2506 parent_->texture_manager()->GetTextureInfo(parent_client_texture_id);
[email protected]a3a93e7b2010-08-28 00:48:562507 if (!texture || !parent_texture) {
2508 current_decoder_error_ = error::kInvalidArguments;
2509 return;
2510 }
2511 ScopedFrameBufferBinder fb_binder(this, copy_texture_to_parent_texture_fb_);
2512 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2513 GL_COLOR_ATTACHMENT0,
2514 GL_TEXTURE_2D,
2515 texture->service_id(),
2516 0);
2517 ScopedTexture2DBinder tex_binder(this, parent_texture->service_id());
2518 GLsizei width, height;
2519 parent_texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height);
2520 glCopyTexImage2D(GL_TEXTURE_2D,
2521 0, // level
2522 GL_RGBA,
[email protected]c007aa02010-09-02 22:22:402523 0, 0, // x, y
[email protected]a3a93e7b2010-08-28 00:48:562524 width,
2525 height,
2526 0); // border
2527 }
2528}
2529
[email protected]43ecf372010-11-16 19:19:392530void GLES2DecoderImpl::DoResizeCHROMIUM(GLuint width, GLuint height) {
[email protected]2e7bbf22011-07-22 18:41:292531#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(TOUCH_UI)
[email protected]7ff86b92010-11-25 17:50:002532 // Make sure that we are done drawing to the back buffer before resizing.
2533 glFinish();
2534#endif
2535 if (resize_callback_.get()) {
2536 gfx::Size size(width, height);
2537 resize_callback_->Run(size);
2538 }
[email protected]43ecf372010-11-16 19:19:392539}
2540
[email protected]fbe20372011-06-01 01:46:382541void GLES2DecoderImpl::DoSetSurfaceCHROMIUM(GLint surface_id) {
2542 gfx::GLSurface* surface = surface_manager_->LookupSurface(surface_id);
2543 if (!surface)
2544 return;
2545
2546 surface_ = surface;
2547}
2548
[email protected]96449d2c2009-11-25 00:01:322549const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
2550 if (command_id > kStartPoint && command_id < kNumCommands) {
2551 return gles2::GetCommandName(static_cast<CommandId>(command_id));
2552 }
2553 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
2554}
2555
2556// Decode command with its arguments, and call the corresponding GL function.
2557// Note: args is a pointer to the command buffer. As such, it could be changed
2558// by a (malicious) client at any time, so if validation has to happen, it
2559// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:142560error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:322561 unsigned int command,
2562 unsigned int arg_count,
2563 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:142564 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192565 if (debug()) {
2566 // TODO(gman): Change output to something useful for NaCl.
[email protected]8e1b98a2011-06-14 23:39:532567 DLOG(INFO) << "[" << this << "]" << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192568 }
[email protected]96449d2c2009-11-25 00:01:322569 unsigned int command_index = command - kStartPoint - 1;
2570 if (command_index < arraysize(g_command_info)) {
2571 const CommandInfo& info = g_command_info[command_index];
2572 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
2573 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
2574 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:192575 uint32 immediate_data_size =
2576 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:322577 switch (command) {
2578 #define GLES2_CMD_OP(name) \
2579 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:192580 result = Handle ## name( \
2581 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:322582 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:192583 break; \
[email protected]96449d2c2009-11-25 00:01:322584
2585 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:322586 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:382587 }
2588 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:302589 GLenum error;
2590 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:382591 // TODO(gman): Change output to something useful for NaCl.
[email protected]8eee29c2010-04-29 03:38:292592 SetGLError(error, NULL);
[email protected]8e1b98a2011-06-14 23:39:532593 DLOG(INFO) << "[" << this << "]"
2594 << "GL ERROR: " << error << " : " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192595 }
[email protected]96449d2c2009-11-25 00:01:322596 }
2597 } else {
[email protected]f7a64ee2010-02-01 22:24:142598 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:322599 }
[email protected]b9849abf2009-11-25 19:13:192600 } else {
2601 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:322602 }
[email protected]a3a93e7b2010-08-28 00:48:562603 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
2604 result = current_decoder_error_;
2605 current_decoder_error_ = error::kNoError;
2606 }
[email protected]b9849abf2009-11-25 19:13:192607 return result;
[email protected]96449d2c2009-11-25 00:01:322608}
2609
[email protected]ae51d192010-04-27 00:48:032610void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
2611 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:502612}
2613
[email protected]ae51d192010-04-27 00:48:032614bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
2615 if (GetProgramInfo(client_id)) {
2616 return false;
2617 }
[email protected]96449d2c2009-11-25 00:01:322618 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:032619 if (service_id != 0) {
2620 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:322621 }
[email protected]ae51d192010-04-27 00:48:032622 return true;
[email protected]96449d2c2009-11-25 00:01:322623}
2624
[email protected]ae51d192010-04-27 00:48:032625bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
2626 if (GetShaderInfo(client_id)) {
2627 return false;
[email protected]96449d2c2009-11-25 00:01:322628 }
[email protected]ae51d192010-04-27 00:48:032629 GLuint service_id = glCreateShader(type);
2630 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:382631 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:032632 }
2633 return true;
[email protected]96449d2c2009-11-25 00:01:322634}
2635
[email protected]3916c97e2010-02-25 03:20:502636void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:452637 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]660858b2011-07-13 23:16:142638 if (texture_index >= group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:292639 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:502640 return;
2641 }
[email protected]36cef8ce2010-03-16 07:34:452642 active_texture_unit_ = texture_index;
2643 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:502644}
2645
[email protected]051b1372010-04-12 02:42:082646void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:502647 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082648 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032649 if (client_id != 0) {
2650 info = GetBufferInfo(client_id);
2651 if (!info) {
2652 // It's a new id so make a buffer info for it.
2653 glGenBuffersARB(1, &service_id);
2654 CreateBufferInfo(client_id, service_id);
2655 info = GetBufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102656 IdAllocator* id_allocator =
2657 group_->GetIdAllocator(id_namespaces::kBuffers);
2658 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032659 }
[email protected]051b1372010-04-12 02:42:082660 }
[email protected]ae51d192010-04-27 00:48:032661 if (info) {
[email protected]4e8a5b122010-05-08 22:00:102662 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:292663 SetGLError(GL_INVALID_OPERATION,
2664 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:472665 return;
2666 }
[email protected]ae51d192010-04-27 00:48:032667 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:472668 }
[email protected]96449d2c2009-11-25 00:01:322669 switch (target) {
2670 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502671 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322672 break;
2673 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502674 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322675 break;
2676 default:
[email protected]a93bb842010-02-16 23:03:472677 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:322678 break;
2679 }
[email protected]051b1372010-04-12 02:42:082680 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:322681}
2682
[email protected]297ca1c2011-06-20 23:08:462683bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
2684 return (GLES2Util::GetChannelsForFormat(
2685 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
2686}
2687
2688bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
2689 if (bound_draw_framebuffer_) {
2690 return bound_draw_framebuffer_->HasDepthAttachment();
2691 }
2692 if (offscreen_target_frame_buffer_.get()) {
2693 return offscreen_target_depth_format_ != 0;
2694 }
2695 return back_buffer_has_depth_;
2696}
2697
2698bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
2699 if (bound_draw_framebuffer_) {
2700 return bound_draw_framebuffer_->HasStencilAttachment();
2701 }
2702 if (offscreen_target_frame_buffer_.get()) {
2703 return offscreen_target_stencil_format_ != 0 ||
2704 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2705 }
2706 return back_buffer_has_stencil_;
2707}
2708
2709void GLES2DecoderImpl::ApplyDirtyState() {
2710 if (state_dirty_) {
2711 glColorMask(
2712 mask_red_, mask_green_, mask_blue_,
2713 mask_alpha_ && BoundFramebufferHasColorAttachmentWithAlpha());
2714 bool have_depth = BoundFramebufferHasDepthAttachment();
2715 glDepthMask(mask_depth_ && have_depth);
2716 EnableDisable(GL_DEPTH_TEST, enable_depth_test_ && have_depth);
2717 bool have_stencil = BoundFramebufferHasStencilAttachment();
2718 glStencilMaskSeparate(GL_FRONT, have_stencil ? mask_stencil_front_ : 0);
2719 glStencilMaskSeparate(GL_BACK, have_stencil ? mask_stencil_back_ : 0);
2720 EnableDisable(GL_STENCIL_TEST, enable_stencil_test_ && have_stencil);
2721 state_dirty_ = false;
2722 }
2723}
2724
[email protected]051b1372010-04-12 02:42:082725void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
2726 FramebufferManager::FramebufferInfo* info = NULL;
2727 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032728 if (client_id != 0) {
2729 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082730 if (!info) {
[email protected]ae51d192010-04-27 00:48:032731 // It's a new id so make a framebuffer info for it.
2732 glGenFramebuffersEXT(1, &service_id);
2733 CreateFramebufferInfo(client_id, service_id);
2734 info = GetFramebufferInfo(client_id);
[email protected]066849e32010-05-03 19:14:102735 IdAllocator* id_allocator =
2736 group_->GetIdAllocator(id_namespaces::kFramebuffers);
2737 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032738 } else {
2739 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082740 }
[email protected]06c8b082011-01-05 18:00:362741 info->MarkAsValid();
[email protected]eff9a222010-12-21 21:48:562742 } else {
[email protected]2e7bbf22011-07-22 18:41:292743 service_id = surface_->GetBackingFrameBufferObject();
[email protected]051b1372010-04-12 02:42:082744 }
[email protected]8e3e0662010-08-23 18:46:302745
2746 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
2747 bound_draw_framebuffer_ = info;
2748 }
2749 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
2750 bound_read_framebuffer_ = info;
2751 }
[email protected]6217d392010-03-25 22:08:352752
[email protected]297ca1c2011-06-20 23:08:462753 state_dirty_ = true;
2754
[email protected]6217d392010-03-25 22:08:352755 // When rendering to an offscreen frame buffer, instead of unbinding from
2756 // the current frame buffer, bind to the offscreen target frame buffer.
[email protected]297ca1c2011-06-20 23:08:462757 if (info == NULL && offscreen_target_frame_buffer_.get()) {
[email protected]051b1372010-04-12 02:42:082758 service_id = offscreen_target_frame_buffer_->id();
[email protected]297ca1c2011-06-20 23:08:462759 }
[email protected]6217d392010-03-25 22:08:352760
[email protected]051b1372010-04-12 02:42:082761 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562762}
2763
[email protected]051b1372010-04-12 02:42:082764void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
2765 RenderbufferManager::RenderbufferInfo* info = NULL;
2766 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032767 if (client_id != 0) {
2768 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082769 if (!info) {
[email protected]ae51d192010-04-27 00:48:032770 // It's a new id so make a renderbuffer info for it.
2771 glGenRenderbuffersEXT(1, &service_id);
2772 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:102773 info = GetRenderbufferInfo(client_id);
2774 IdAllocator* id_allocator =
2775 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
2776 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032777 } else {
2778 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082779 }
[email protected]06c8b082011-01-05 18:00:362780 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:082781 }
2782 bound_renderbuffer_ = info;
2783 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562784}
2785
[email protected]051b1372010-04-12 02:42:082786void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032787 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082788 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032789 if (client_id != 0) {
2790 info = GetTextureInfo(client_id);
2791 if (!info) {
2792 // It's a new id so make a texture info for it.
2793 glGenTextures(1, &service_id);
2794 CreateTextureInfo(client_id, service_id);
2795 info = GetTextureInfo(client_id);
[email protected]066849e32010-05-03 19:14:102796 IdAllocator* id_allocator =
2797 group_->GetIdAllocator(id_namespaces::kTextures);
2798 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032799 }
2800 } else {
2801 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:082802 }
[email protected]ae51d192010-04-27 00:48:032803
[email protected]1958e0e2010-04-22 05:17:152804 // Check the texture exists
2805 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:032806 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:292807 SetGLError(GL_INVALID_OPERATION,
2808 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:152809 return;
2810 }
2811 if (info->target() == 0) {
2812 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:472813 }
[email protected]ae51d192010-04-27 00:48:032814 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:502815 TextureUnit& unit = texture_units_[active_texture_unit_];
2816 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:472817 switch (target) {
2818 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:502819 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:472820 break;
2821 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:502822 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:472823 break;
2824 default:
2825 NOTREACHED(); // Validation should prevent us getting here.
2826 break;
2827 }
2828}
2829
[email protected]07f54fcc2009-12-22 02:46:302830void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082831 if (vertex_attrib_manager_.Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:122832 if (index != 0 ||
2833 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:242834 glDisableVertexAttribArray(index);
2835 }
[email protected]07f54fcc2009-12-22 02:46:302836 } else {
[email protected]8eee29c2010-04-29 03:38:292837 SetGLError(GL_INVALID_VALUE,
2838 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302839 }
2840}
2841
2842void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082843 if (vertex_attrib_manager_.Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:302844 glEnableVertexAttribArray(index);
2845 } else {
[email protected]8eee29c2010-04-29 03:38:292846 SetGLError(GL_INVALID_VALUE,
2847 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302848 }
2849}
2850
[email protected]a93bb842010-02-16 23:03:472851void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:502852 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]915a59a12010-09-30 21:29:112853 if (!info || !texture_manager()->MarkMipmapsGenerated(feature_info_, info)) {
[email protected]8eee29c2010-04-29 03:38:292854 SetGLError(GL_INVALID_OPERATION,
2855 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:472856 return;
2857 }
[email protected]59f3ca02011-03-26 22:24:192858 // Workaround for Mac driver bug. In the large scheme of things setting
2859 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
2860 // hit so there's probably no need to make this conditional.
2861 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
[email protected]a93bb842010-02-16 23:03:472862 glGenerateMipmapEXT(target);
[email protected]59f3ca02011-03-26 22:24:192863 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
[email protected]a93bb842010-02-16 23:03:472864}
2865
[email protected]b273e432010-04-12 17:23:582866bool GLES2DecoderImpl::GetHelper(
2867 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:582868 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:152869 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2870 switch (pname) {
[email protected]b273e432010-04-12 17:23:582871 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2872 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102873 if (params) {
[email protected]5094b0f2010-11-09 19:45:242874 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:102875 }
[email protected]b273e432010-04-12 17:23:582876 return true;
2877 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2878 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102879 if (params) {
[email protected]5094b0f2010-11-09 19:45:242880 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:102881 }
[email protected]b273e432010-04-12 17:23:582882 return true;
2883 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
2884 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102885 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482886 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102887 }
[email protected]b273e432010-04-12 17:23:582888 return true;
2889 case GL_MAX_VARYING_VECTORS:
2890 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102891 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482892 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:102893 }
[email protected]b273e432010-04-12 17:23:582894 return true;
2895 case GL_MAX_VERTEX_UNIFORM_VECTORS:
2896 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102897 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482898 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102899 }
[email protected]b273e432010-04-12 17:23:582900 return true;
[email protected]5094b0f2010-11-09 19:45:242901 case GL_MAX_VIEWPORT_DIMS:
2902 if (offscreen_target_frame_buffer_.get()) {
2903 *num_written = 2;
2904 if (params) {
2905 params[0] = renderbuffer_manager()->max_renderbuffer_size();
2906 params[1] = renderbuffer_manager()->max_renderbuffer_size();
2907 }
2908 return true;
2909 }
[email protected]b9363b22010-06-09 22:06:152910 }
2911 }
2912 switch (pname) {
[email protected]297ca1c2011-06-20 23:08:462913 case GL_COLOR_WRITEMASK:
2914 *num_written = 4;
2915 if (params) {
2916 params[0] = mask_red_;
2917 params[1] = mask_green_;
2918 params[2] = mask_blue_;
2919 params[3] = mask_alpha_;
2920 }
2921 return true;
2922 case GL_DEPTH_WRITEMASK:
2923 *num_written = 1;
2924 if (params) {
2925 params[0] = mask_depth_;
2926 }
2927 return true;
2928 case GL_STENCIL_BACK_WRITEMASK:
2929 *num_written = 1;
2930 if (params) {
2931 params[0] = mask_stencil_back_;
2932 }
2933 return true;
2934 case GL_STENCIL_WRITEMASK:
2935 *num_written = 1;
2936 if (params) {
2937 params[0] = mask_stencil_front_;
2938 }
2939 return true;
2940 case GL_DEPTH_TEST:
2941 *num_written = 1;
2942 if (params) {
2943 params[0] = enable_depth_test_;
2944 }
2945 return true;
2946 case GL_STENCIL_TEST:
2947 *num_written = 1;
2948 if (params) {
2949 params[0] = enable_stencil_test_;
2950 }
2951 return true;
2952 case GL_ALPHA_BITS:
2953 *num_written = 1;
2954 if (params) {
2955 GLint v = 0;
2956 glGetIntegerv(GL_ALPHA_BITS, &v);
2957 params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0;
2958 }
2959 return true;
2960 case GL_DEPTH_BITS:
2961 *num_written = 1;
2962 if (params) {
2963 GLint v = 0;
2964 glGetIntegerv(GL_DEPTH_BITS, &v);
2965 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
2966 }
2967 return true;
2968 case GL_STENCIL_BITS:
2969 *num_written = 1;
2970 if (params) {
2971 GLint v = 0;
2972 glGetIntegerv(GL_STENCIL_BITS, &v);
2973 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
2974 }
2975 return true;
[email protected]656dcaad2010-05-07 17:18:372976 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:112977 *num_written = validators_->compressed_texture_format.GetValues().size();
2978 if (params) {
2979 for (GLint ii = 0; ii < *num_written; ++ii) {
2980 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
2981 }
2982 }
[email protected]656dcaad2010-05-07 17:18:372983 return true;
[email protected]b273e432010-04-12 17:23:582984 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
2985 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102986 if (params) {
[email protected]302ce6d2011-07-07 23:28:112987 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:102988 }
[email protected]b273e432010-04-12 17:23:582989 return true;
2990 case GL_NUM_SHADER_BINARY_FORMATS:
2991 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102992 if (params) {
[email protected]302ce6d2011-07-07 23:28:112993 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:102994 }
[email protected]b273e432010-04-12 17:23:582995 return true;
2996 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:112997 *num_written = validators_->shader_binary_format.GetValues().size();
2998 if (params) {
2999 for (GLint ii = 0; ii < *num_written; ++ii) {
3000 params[ii] = validators_->shader_binary_format.GetValues()[ii];
3001 }
3002 }
3003 return true;
[email protected]b273e432010-04-12 17:23:583004 case GL_SHADER_COMPILER:
3005 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103006 if (params) {
3007 *params = GL_TRUE;
3008 }
[email protected]b273e432010-04-12 17:23:583009 return true;
[email protected]6b8cf1a2010-05-06 16:13:583010 case GL_ARRAY_BUFFER_BINDING:
3011 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103012 if (params) {
3013 if (bound_array_buffer_) {
3014 GLuint client_id = 0;
3015 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
3016 &client_id);
3017 *params = client_id;
3018 } else {
3019 *params = 0;
3020 }
[email protected]6b8cf1a2010-05-06 16:13:583021 }
3022 return true;
3023 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3024 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103025 if (params) {
3026 if (bound_element_array_buffer_) {
3027 GLuint client_id = 0;
3028 buffer_manager()->GetClientId(
3029 bound_element_array_buffer_->service_id(),
3030 &client_id);
3031 *params = client_id;
3032 } else {
3033 *params = 0;
3034 }
[email protected]6b8cf1a2010-05-06 16:13:583035 }
3036 return true;
3037 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:303038 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:583039 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103040 if (params) {
[email protected]8e3e0662010-08-23 18:46:303041 if (bound_draw_framebuffer_) {
[email protected]4e8a5b122010-05-08 22:00:103042 GLuint client_id = 0;
3043 framebuffer_manager()->GetClientId(
[email protected]8e3e0662010-08-23 18:46:303044 bound_draw_framebuffer_->service_id(), &client_id);
3045 *params = client_id;
3046 } else {
3047 *params = 0;
3048 }
3049 }
3050 return true;
3051 case GL_READ_FRAMEBUFFER_BINDING:
3052 *num_written = 1;
3053 if (params) {
3054 if (bound_read_framebuffer_) {
3055 GLuint client_id = 0;
3056 framebuffer_manager()->GetClientId(
3057 bound_read_framebuffer_->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103058 *params = client_id;
3059 } else {
3060 *params = 0;
3061 }
[email protected]6b8cf1a2010-05-06 16:13:583062 }
3063 return true;
3064 case GL_RENDERBUFFER_BINDING:
3065 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103066 if (params) {
3067 if (bound_renderbuffer_) {
3068 GLuint client_id = 0;
3069 renderbuffer_manager()->GetClientId(
3070 bound_renderbuffer_->service_id(), &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_CURRENT_PROGRAM:
3078 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103079 if (params) {
3080 if (current_program_) {
3081 GLuint client_id = 0;
3082 program_manager()->GetClientId(
3083 current_program_->service_id(), &client_id);
3084 *params = client_id;
3085 } else {
3086 *params = 0;
3087 }
[email protected]6b8cf1a2010-05-06 16:13:583088 }
3089 return true;
[email protected]4e8a5b122010-05-08 22:00:103090 case GL_TEXTURE_BINDING_2D:
3091 *num_written = 1;
3092 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583093 TextureUnit& unit = texture_units_[active_texture_unit_];
3094 if (unit.bound_texture_2d) {
3095 GLuint client_id = 0;
3096 texture_manager()->GetClientId(
3097 unit.bound_texture_2d->service_id(), &client_id);
3098 *params = client_id;
3099 } else {
3100 *params = 0;
3101 }
[email protected]6b8cf1a2010-05-06 16:13:583102 }
[email protected]4e8a5b122010-05-08 22:00:103103 return true;
3104 case GL_TEXTURE_BINDING_CUBE_MAP:
3105 *num_written = 1;
3106 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583107 TextureUnit& unit = texture_units_[active_texture_unit_];
3108 if (unit.bound_texture_cube_map) {
3109 GLuint client_id = 0;
3110 texture_manager()->GetClientId(
3111 unit.bound_texture_cube_map->service_id(), &client_id);
3112 *params = client_id;
3113 } else {
3114 *params = 0;
3115 }
[email protected]6b8cf1a2010-05-06 16:13:583116 }
[email protected]4e8a5b122010-05-08 22:00:103117 return true;
[email protected]b273e432010-04-12 17:23:583118 default:
[email protected]4e8a5b122010-05-08 22:00:103119 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533120 return false;
[email protected]b273e432010-04-12 17:23:583121 }
3122}
3123
[email protected]4e8a5b122010-05-08 22:00:103124bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3125 GLenum pname, GLsizei* num_values) {
3126 return GetHelper(pname, NULL, num_values);
3127}
3128
[email protected]b273e432010-04-12 17:23:583129void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3130 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103131 GLsizei num_written = 0;
3132 if (GetHelper(pname, NULL, &num_written)) {
3133 scoped_array<GLint> values(new GLint[num_written]);
3134 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583135 for (GLsizei ii = 0; ii < num_written; ++ii) {
3136 params[ii] = static_cast<GLboolean>(values[ii]);
3137 }
3138 } else {
3139 glGetBooleanv(pname, params);
3140 }
3141}
3142
3143void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3144 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103145 GLsizei num_written = 0;
3146 if (GetHelper(pname, NULL, &num_written)) {
3147 scoped_array<GLint> values(new GLint[num_written]);
3148 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583149 for (GLsizei ii = 0; ii < num_written; ++ii) {
3150 params[ii] = static_cast<GLfloat>(values[ii]);
3151 }
3152 } else {
3153 glGetFloatv(pname, params);
3154 }
3155}
3156
3157void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3158 DCHECK(params);
3159 GLsizei num_written;
3160 if (!GetHelper(pname, params, &num_written)) {
3161 glGetIntegerv(pname, params);
3162 }
3163}
3164
[email protected]a0c3e972010-04-21 00:49:133165void GLES2DecoderImpl::DoGetProgramiv(
3166 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583167 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3168 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133169 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133170 return;
3171 }
3172 info->GetProgramiv(pname, params);
3173}
3174
[email protected]558847a2010-03-24 07:02:543175error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3176 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
[email protected]6b8cf1a2010-05-06 16:13:583177 GLuint program = static_cast<GLuint>(c.program);
3178 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3179 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033180 if (!info) {
[email protected]558847a2010-03-24 07:02:543181 return error::kNoError;
3182 }
3183 GLuint index = static_cast<GLuint>(c.index);
3184 uint32 name_size = c.data_size;
3185 const char* name = GetSharedMemoryAs<const char*>(
3186 c.name_shm_id, c.name_shm_offset, name_size);
3187 if (name == NULL) {
3188 return error::kOutOfBounds;
3189 }
3190 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033191 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543192 return error::kNoError;
3193}
3194
3195error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3196 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583197 GLuint program = static_cast<GLuint>(c.program);
3198 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3199 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033200 if (!info) {
[email protected]558847a2010-03-24 07:02:543201 return error::kNoError;
3202 }
3203 GLuint index = static_cast<GLuint>(c.index);
3204 uint32 name_size = c.data_size;
3205 const char* name = GetImmediateDataAs<const char*>(
3206 c, name_size, immediate_data_size);
3207 if (name == NULL) {
3208 return error::kOutOfBounds;
3209 }
3210 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033211 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543212 return error::kNoError;
3213}
3214
3215error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3216 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583217 GLuint program = static_cast<GLuint>(c.program);
3218 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3219 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033220 if (!info) {
[email protected]558847a2010-03-24 07:02:543221 return error::kNoError;
3222 }
3223 GLuint index = static_cast<GLuint>(c.index);
3224 Bucket* bucket = GetBucket(c.name_bucket_id);
3225 if (!bucket || bucket->size() == 0) {
3226 return error::kInvalidArguments;
3227 }
3228 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183229 if (!bucket->GetAsString(&name_str)) {
3230 return error::kInvalidArguments;
3231 }
[email protected]ae51d192010-04-27 00:48:033232 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543233 return error::kNoError;
3234}
3235
[email protected]f7a64ee2010-02-01 22:24:143236error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463237 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033238 GLuint client_id = c.shader;
3239 if (client_id) {
3240 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3241 if (info) {
[email protected]ca488e12010-12-13 20:06:143242 if (!info->IsDeleted()) {
3243 glDeleteShader(info->service_id());
3244 shader_manager()->MarkAsDeleted(info);
3245 }
[email protected]ae51d192010-04-27 00:48:033246 } else {
[email protected]8eee29c2010-04-29 03:38:293247 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033248 }
[email protected]96449d2c2009-11-25 00:01:323249 }
[email protected]f7a64ee2010-02-01 22:24:143250 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323251}
3252
[email protected]f7a64ee2010-02-01 22:24:143253error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463254 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033255 GLuint client_id = c.program;
3256 if (client_id) {
3257 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3258 if (info) {
[email protected]ca488e12010-12-13 20:06:143259 if (!info->IsDeleted()) {
3260 glDeleteProgram(info->service_id());
3261 program_manager()->MarkAsDeleted(shader_manager(), info);
3262 }
[email protected]ae51d192010-04-27 00:48:033263 } else {
[email protected]8eee29c2010-04-29 03:38:293264 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033265 }
[email protected]96449d2c2009-11-25 00:01:323266 }
[email protected]f7a64ee2010-02-01 22:24:143267 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323268}
3269
[email protected]269200b12010-11-18 22:53:063270void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103271 GLuint namespace_id, GLsizei n, const GLuint* ids) {
3272 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3273 for (GLsizei ii = 0; ii < n; ++ii) {
3274 id_allocator->FreeID(ids[ii]);
3275 }
3276}
3277
[email protected]269200b12010-11-18 22:53:063278error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
3279 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103280 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3281 GLsizei n = static_cast<GLsizei>(c.n);
3282 uint32 data_size;
3283 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3284 return error::kOutOfBounds;
3285 }
3286 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3287 c.ids_shm_id, c.ids_shm_offset, data_size);
3288 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063289 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103290 return error::kNoError;
3291 }
3292 if (ids == NULL) {
3293 return error::kOutOfBounds;
3294 }
[email protected]269200b12010-11-18 22:53:063295 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103296 return error::kNoError;
3297}
3298
[email protected]269200b12010-11-18 22:53:063299void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103300 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
3301 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3302 if (id_offset == 0) {
3303 for (GLsizei ii = 0; ii < n; ++ii) {
3304 ids[ii] = id_allocator->AllocateID();
3305 }
3306 } else {
3307 for (GLsizei ii = 0; ii < n; ++ii) {
3308 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
3309 id_offset = ids[ii] + 1;
3310 }
3311 }
3312}
3313
[email protected]269200b12010-11-18 22:53:063314error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
3315 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103316 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3317 GLuint id_offset = static_cast<GLuint>(c.id_offset);
3318 GLsizei n = static_cast<GLsizei>(c.n);
3319 uint32 data_size;
3320 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3321 return error::kOutOfBounds;
3322 }
3323 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3324 c.ids_shm_id, c.ids_shm_offset, data_size);
3325 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063326 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103327 return error::kNoError;
3328 }
3329 if (ids == NULL) {
3330 return error::kOutOfBounds;
3331 }
[email protected]269200b12010-11-18 22:53:063332 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:103333 return error::kNoError;
3334}
3335
[email protected]269200b12010-11-18 22:53:063336void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103337 GLuint namespace_id, GLsizei n, const GLuint* ids) {
3338 IdAllocator* id_allocator = group_->GetIdAllocator(namespace_id);
3339 for (GLsizei ii = 0; ii < n; ++ii) {
3340 if (!id_allocator->MarkAsUsed(ids[ii])) {
3341 for (GLsizei jj = 0; jj < ii; ++jj) {
3342 id_allocator->FreeID(ids[jj]);
3343 }
3344 SetGLError(
3345 GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:063346 "RegisterSharedIdsCHROMIUM: attempt to register "
3347 "id that already exists");
[email protected]066849e32010-05-03 19:14:103348 return;
3349 }
3350 }
3351}
3352
[email protected]269200b12010-11-18 22:53:063353error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
3354 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103355 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3356 GLsizei n = static_cast<GLsizei>(c.n);
3357 uint32 data_size;
3358 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3359 return error::kOutOfBounds;
3360 }
3361 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3362 c.ids_shm_id, c.ids_shm_offset, data_size);
3363 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063364 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103365 return error::kNoError;
3366 }
3367 if (ids == NULL) {
3368 return error::kOutOfBounds;
3369 }
[email protected]269200b12010-11-18 22:53:063370 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103371 return error::kNoError;
3372}
3373
[email protected]3a03a8f2011-03-19 00:51:273374void GLES2DecoderImpl::DoClear(GLbitfield mask) {
3375 if (CheckFramebufferComplete("glClear")) {
[email protected]297ca1c2011-06-20 23:08:463376 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:273377 glClear(mask);
3378 }
3379}
3380
[email protected]36cef8ce2010-03-16 07:34:453381void GLES2DecoderImpl::DoFramebufferRenderbuffer(
3382 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:033383 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:303384 FramebufferManager::FramebufferInfo* framebuffer_info =
3385 GetFramebufferInfoForTarget(target);
3386 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293387 SetGLError(GL_INVALID_OPERATION,
3388 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453389 return;
3390 }
[email protected]ae51d192010-04-27 00:48:033391 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283392 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033393 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283394 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:033395 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293396 SetGLError(GL_INVALID_OPERATION,
3397 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:033398 return;
3399 }
3400 service_id = info->service_id();
3401 }
[email protected]9edc6b22010-12-23 02:00:263402 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033403 glFramebufferRenderbufferEXT(
3404 target, attachment, renderbuffertarget, service_id);
[email protected]1002c2d2011-06-28 22:39:043405 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263406 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:303407 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]9edc6b22010-12-23 02:00:263408 if (service_id == 0 ||
3409 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
3410 if (info) {
3411 ClearUnclearedRenderbuffers(target, framebuffer_info);
3412 }
[email protected]3a2e7c7b2010-08-06 01:12:283413 }
3414 }
[email protected]297ca1c2011-06-20 23:08:463415 if (framebuffer_info == bound_draw_framebuffer_) {
3416 state_dirty_ = true;
3417 }
[email protected]3a2e7c7b2010-08-06 01:12:283418}
3419
[email protected]297ca1c2011-06-20 23:08:463420bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
[email protected]3a2e7c7b2010-08-06 01:12:283421 switch (cap) {
3422 case GL_SCISSOR_TEST:
3423 enable_scissor_test_ = enabled;
[email protected]297ca1c2011-06-20 23:08:463424 return true;
3425 case GL_DEPTH_TEST: {
3426 if (enable_depth_test_ != enabled) {
3427 enable_depth_test_ = enabled;
3428 state_dirty_ = true;
3429 }
3430 return false;
3431 }
3432 case GL_STENCIL_TEST:
3433 if (enable_stencil_test_ != enabled) {
3434 enable_stencil_test_ = enabled;
3435 state_dirty_ = true;
3436 }
3437 return false;
[email protected]3a2e7c7b2010-08-06 01:12:283438 default:
[email protected]297ca1c2011-06-20 23:08:463439 return true;
[email protected]3a2e7c7b2010-08-06 01:12:283440 }
3441}
3442
3443void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:463444 if (SetCapabilityState(cap, false)) {
3445 glDisable(cap);
3446 }
[email protected]3a2e7c7b2010-08-06 01:12:283447}
3448
3449void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:463450 if (SetCapabilityState(cap, true)) {
3451 glEnable(cap);
3452 }
[email protected]3a2e7c7b2010-08-06 01:12:283453}
3454
3455void GLES2DecoderImpl::DoClearColor(
3456 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
3457 clear_red_ = red;
3458 clear_green_ = green;
3459 clear_blue_ = blue;
3460 clear_alpha_ = alpha;
3461 glClearColor(red, green, blue, alpha);
3462}
3463
3464void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
3465 clear_depth_ = depth;
3466 glClearDepth(depth);
3467}
3468
3469void GLES2DecoderImpl::DoClearStencil(GLint s) {
3470 clear_stencil_ = s;
3471 glClearStencil(s);
3472}
3473
3474void GLES2DecoderImpl::DoColorMask(
3475 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
3476 mask_red_ = red;
3477 mask_green_ = green;
3478 mask_blue_ = blue;
3479 mask_alpha_ = alpha;
[email protected]297ca1c2011-06-20 23:08:463480 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283481}
3482
3483void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
3484 mask_depth_ = depth;
[email protected]297ca1c2011-06-20 23:08:463485 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283486}
3487
3488void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
3489 mask_stencil_front_ = mask;
3490 mask_stencil_back_ = mask;
[email protected]297ca1c2011-06-20 23:08:463491 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283492}
3493
3494void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
[email protected]297ca1c2011-06-20 23:08:463495 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:283496 mask_stencil_front_ = mask;
[email protected]297ca1c2011-06-20 23:08:463497 }
3498 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:283499 mask_stencil_back_ = mask;
3500 }
[email protected]297ca1c2011-06-20 23:08:463501 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283502}
3503
3504// NOTE: There's an assumption here that Texture attachments
3505// are cleared because they are textures so we only need to clear
3506// the renderbuffers.
3507void GLES2DecoderImpl::ClearUnclearedRenderbuffers(
[email protected]8e3e0662010-08-23 18:46:303508 GLenum target, FramebufferManager::FramebufferInfo* info) {
3509 if (target == GL_READ_FRAMEBUFFER_EXT) {
3510 // TODO(gman): bind this to the DRAW point, clear then bind back to READ
3511 }
[email protected]3a2e7c7b2010-08-06 01:12:283512 GLbitfield clear_bits = 0;
3513 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:463514 glClearColor(
3515 0, 0, 0,
3516 (GLES2Util::GetChannelsForFormat(
3517 info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0 : 1);
[email protected]3a2e7c7b2010-08-06 01:12:283518 glColorMask(true, true, true, true);
3519 clear_bits |= GL_COLOR_BUFFER_BIT;
3520 }
3521
3522 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
3523 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3524 glClearStencil(0);
3525 glStencilMask(-1);
3526 clear_bits |= GL_STENCIL_BUFFER_BIT;
3527 }
3528
3529 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
3530 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3531 glClearDepth(1.0f);
3532 glDepthMask(true);
3533 clear_bits |= GL_DEPTH_BUFFER_BIT;
3534 }
3535
3536 glDisable(GL_SCISSOR_TEST);
3537 glClear(clear_bits);
3538
3539 info->MarkAttachedRenderbuffersAsCleared();
3540
[email protected]c007aa02010-09-02 22:22:403541 RestoreClearState();
3542
3543 if (target == GL_READ_FRAMEBUFFER_EXT) {
3544 // TODO(gman): rebind draw.
3545 }
3546}
3547
3548void GLES2DecoderImpl::RestoreClearState() {
[email protected]297ca1c2011-06-20 23:08:463549 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283550 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
[email protected]3a2e7c7b2010-08-06 01:12:283551 glClearStencil(clear_stencil_);
[email protected]3a2e7c7b2010-08-06 01:12:283552 glClearDepth(clear_depth_);
[email protected]3a2e7c7b2010-08-06 01:12:283553 if (enable_scissor_test_) {
3554 glEnable(GL_SCISSOR_TEST);
3555 }
[email protected]36cef8ce2010-03-16 07:34:453556}
3557
3558GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]8e3e0662010-08-23 18:46:303559 FramebufferManager::FramebufferInfo* info =
3560 GetFramebufferInfoForTarget(target);
3561 if (!info) {
[email protected]36cef8ce2010-03-16 07:34:453562 return GL_FRAMEBUFFER_COMPLETE;
3563 }
3564 return glCheckFramebufferStatusEXT(target);
3565}
3566
3567void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:033568 GLenum target, GLenum attachment, GLenum textarget,
3569 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:303570 FramebufferManager::FramebufferInfo* framebuffer_info =
3571 GetFramebufferInfoForTarget(target);
3572 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293573 SetGLError(GL_INVALID_OPERATION,
3574 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:453575 return;
3576 }
[email protected]ae51d192010-04-27 00:48:033577 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283578 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033579 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283580 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:033581 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293582 SetGLError(GL_INVALID_OPERATION,
3583 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:033584 return;
3585 }
3586 service_id = info->service_id();
3587 }
[email protected]9edc6b22010-12-23 02:00:263588 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033589 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]1002c2d2011-06-28 22:39:043590 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263591 if (error == GL_NO_ERROR) {
3592 framebuffer_info->AttachTexture(attachment, info, textarget, level);
3593 if (service_id != 0 &&
3594 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
3595 ClearUnclearedRenderbuffers(target, framebuffer_info);
3596 }
[email protected]3a2e7c7b2010-08-06 01:12:283597 }
[email protected]297ca1c2011-06-20 23:08:463598 if (framebuffer_info == bound_draw_framebuffer_) {
3599 state_dirty_ = true;
3600 }
[email protected]36cef8ce2010-03-16 07:34:453601}
3602
3603void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
3604 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:303605 FramebufferManager::FramebufferInfo* framebuffer_info =
3606 GetFramebufferInfoForTarget(target);
3607 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293608 SetGLError(GL_INVALID_OPERATION,
3609 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453610 return;
3611 }
3612 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:573613 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
3614 GLint type = 0;
3615 GLuint client_id = 0;
3616 glGetFramebufferAttachmentParameterivEXT(
3617 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
3618 switch (type) {
3619 case GL_RENDERBUFFER: {
3620 renderbuffer_manager()->GetClientId(*params, &client_id);
3621 break;
3622 }
3623 case GL_TEXTURE: {
3624 texture_manager()->GetClientId(*params, &client_id);
3625 break;
3626 }
3627 default:
3628 break;
3629 }
3630 *params = client_id;
3631 }
[email protected]36cef8ce2010-03-16 07:34:453632}
3633
3634void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
3635 GLenum target, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:083636 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293637 SetGLError(GL_INVALID_OPERATION,
3638 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453639 return;
3640 }
[email protected]3a03a8f2011-03-19 00:51:273641 switch (pname) {
3642 case GL_RENDERBUFFER_INTERNAL_FORMAT:
[email protected]b71f52c2010-06-18 22:20:203643 *params = bound_renderbuffer_->internal_format();
[email protected]3a03a8f2011-03-19 00:51:273644 break;
3645 case GL_RENDERBUFFER_WIDTH:
3646 *params = bound_renderbuffer_->width();
3647 break;
3648 case GL_RENDERBUFFER_HEIGHT:
3649 *params = bound_renderbuffer_->height();
3650 break;
3651 default:
3652 glGetRenderbufferParameterivEXT(target, pname, params);
3653 break;
[email protected]b71f52c2010-06-18 22:20:203654 }
[email protected]36cef8ce2010-03-16 07:34:453655}
3656
[email protected]8e3e0662010-08-23 18:46:303657void GLES2DecoderImpl::DoBlitFramebufferEXT(
3658 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
3659 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
3660 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:393661 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303662 SetGLError(GL_INVALID_OPERATION,
3663 "glBlitFramebufferEXT: function not available");
3664 }
[email protected]5094b0f2010-11-09 19:45:243665 if (IsAngle()) {
3666 glBlitFramebufferANGLE(
3667 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3668 } else {
3669 glBlitFramebufferEXT(
3670 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3671 }
[email protected]8e3e0662010-08-23 18:46:303672}
3673
3674void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
3675 GLenum target, GLsizei samples, GLenum internalformat,
3676 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:393677 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303678 SetGLError(GL_INVALID_OPERATION,
3679 "glRenderbufferStorageMultisampleEXT: function not available");
3680 return;
3681 }
[email protected]8e3e0662010-08-23 18:46:303682
[email protected]9edc6b22010-12-23 02:00:263683 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:303684 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:263685 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:303686 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:263687 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:303688 break;
3689 case GL_RGBA4:
3690 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:263691 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:303692 break;
3693 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:263694 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:303695 break;
3696 }
3697 }
3698
[email protected]9edc6b22010-12-23 02:00:263699 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:083700 if (IsAngle()) {
3701 glRenderbufferStorageMultisampleANGLE(
3702 target, samples, impl_format, width, height);
3703 } else {
3704 glRenderbufferStorageMultisampleEXT(
3705 target, samples, impl_format, width, height);
3706 }
[email protected]1002c2d2011-06-28 22:39:043707 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263708 if (error == GL_NO_ERROR) {
3709 bound_renderbuffer_->SetInfo(samples, internalformat, width, height);
3710 }
[email protected]8e3e0662010-08-23 18:46:303711}
3712
[email protected]36cef8ce2010-03-16 07:34:453713void GLES2DecoderImpl::DoRenderbufferStorage(
3714 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]051b1372010-04-12 02:42:083715 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293716 SetGLError(GL_INVALID_OPERATION,
3717 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453718 return;
3719 }
[email protected]876f6fee2010-08-02 23:10:323720
[email protected]9edc6b22010-12-23 02:00:263721 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:323722 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:263723 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:323724 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:263725 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:323726 break;
3727 case GL_RGBA4:
3728 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:263729 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:323730 break;
3731 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:263732 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:323733 break;
3734 }
[email protected]b71f52c2010-06-18 22:20:203735 }
[email protected]876f6fee2010-08-02 23:10:323736
[email protected]9edc6b22010-12-23 02:00:263737 CopyRealGLErrorsToWrapper();
3738 glRenderbufferStorageEXT(target, impl_format, width, height);
[email protected]1002c2d2011-06-28 22:39:043739 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263740 if (error == GL_NO_ERROR) {
3741 bound_renderbuffer_->SetInfo(0, internalformat, width, height);
3742 }
[email protected]36cef8ce2010-03-16 07:34:453743}
3744
[email protected]07f54fcc2009-12-22 02:46:303745void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]0c8fabf2011-06-14 19:35:223746 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]6b8cf1a2010-05-06 16:13:583747 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3748 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:473749 if (!info) {
[email protected]a93bb842010-02-16 23:03:473750 return;
3751 }
[email protected]05afda12011-01-20 00:17:343752
[email protected]d685a682011-04-29 16:19:573753 info->Link();
[email protected]07f54fcc2009-12-22 02:46:303754};
3755
[email protected]3916c97e2010-02-25 03:20:503756void GLES2DecoderImpl::DoTexParameterf(
3757 GLenum target, GLenum pname, GLfloat param) {
3758 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:303759 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293760 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243761 return;
[email protected]07f54fcc2009-12-22 02:46:303762 }
[email protected]cbb22e42011-05-12 23:36:243763
3764 if (!texture_manager()->SetParameter(
3765 feature_info_, info, pname, static_cast<GLint>(param))) {
3766 SetGLError(GL_INVALID_ENUM, "glTexParameterf: param GL_INVALID_ENUM");
3767 return;
3768 }
3769 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:303770}
3771
[email protected]3916c97e2010-02-25 03:20:503772void GLES2DecoderImpl::DoTexParameteri(
3773 GLenum target, GLenum pname, GLint param) {
3774 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3775 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293776 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243777 return;
[email protected]3916c97e2010-02-25 03:20:503778 }
[email protected]cbb22e42011-05-12 23:36:243779
3780 if (!texture_manager()->SetParameter(feature_info_, info, pname, param)) {
3781 SetGLError(GL_INVALID_ENUM, "glTexParameteri: param GL_INVALID_ENUM");
3782 return;
3783 }
3784 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:503785}
3786
3787void GLES2DecoderImpl::DoTexParameterfv(
3788 GLenum target, GLenum pname, const GLfloat* params) {
3789 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3790 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293791 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243792 return;
[email protected]3916c97e2010-02-25 03:20:503793 }
[email protected]cbb22e42011-05-12 23:36:243794
3795 if (!texture_manager()->SetParameter(
3796 feature_info_, info, pname, static_cast<GLint>(params[0]))) {
3797 SetGLError(GL_INVALID_ENUM, "glTexParameterfv: param GL_INVALID_ENUM");
3798 return;
3799 }
3800 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:503801}
3802
3803void GLES2DecoderImpl::DoTexParameteriv(
3804 GLenum target, GLenum pname, const GLint* params) {
3805 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3806 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293807 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243808 return;
[email protected]3916c97e2010-02-25 03:20:503809 }
[email protected]cbb22e42011-05-12 23:36:243810
3811 if (!texture_manager()->SetParameter(feature_info_, info, pname, *params)) {
3812 SetGLError(GL_INVALID_ENUM, "glTexParameteriv: param GL_INVALID_ENUM");
3813 return;
3814 }
3815 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:503816}
3817
[email protected]939e7362010-05-13 20:49:103818bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:143819 if (!current_program_) {
[email protected]939e7362010-05-13 20:49:103820 // The program does not exist.
3821 SetGLError(GL_INVALID_OPERATION,
3822 (std::string(function_name) + ": no program in use").c_str());
3823 return false;
3824 }
[email protected]ca488e12010-12-13 20:06:143825 if (!current_program_->InUse()) {
[email protected]939e7362010-05-13 20:49:103826 SetGLError(GL_INVALID_OPERATION,
3827 (std::string(function_name) + ": program not linked").c_str());
3828 return false;
3829 }
3830 return true;
3831}
3832
3833bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
3834 GLint location, const char* function_name) {
3835 if (!CheckCurrentProgram(function_name)) {
3836 return false;
3837 }
3838 return location != -1;
3839}
3840
[email protected]43c2f1f2011-03-25 18:35:363841bool GLES2DecoderImpl::PrepForSetUniformByLocation(
3842 GLint location, const char* function_name, GLenum* type, GLsizei* count) {
3843 DCHECK(type);
3844 DCHECK(count);
[email protected]939e7362010-05-13 20:49:103845 if (!CheckCurrentProgramForUniform(location, function_name)) {
3846 return false;
3847 }
[email protected]43c2f1f2011-03-25 18:35:363848 GLint array_index = -1;
3849 const ProgramManager::ProgramInfo::UniformInfo* info =
3850 current_program_->GetUniformInfoByLocation(location, &array_index);
3851 if (!info) {
[email protected]939e7362010-05-13 20:49:103852 SetGLError(GL_INVALID_OPERATION,
[email protected]43c2f1f2011-03-25 18:35:363853 (std::string(function_name) + ": unknown location").c_str());
[email protected]939e7362010-05-13 20:49:103854 return false;
3855 }
[email protected]43c2f1f2011-03-25 18:35:363856 if (*count > 1 && !info->is_array) {
3857 SetGLError(
3858 GL_INVALID_OPERATION,
3859 (std::string(function_name) + ": count > 1 for non-array").c_str());
3860 return false;
3861 }
3862 *count = std::min(info->size - array_index, *count);
3863 if (*count <= 0) {
3864 return false;
3865 }
3866 *type = info->type;
[email protected]939e7362010-05-13 20:49:103867 return true;
3868}
3869
[email protected]939e7362010-05-13 20:49:103870void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
3871 if (!CheckCurrentProgramForUniform(location, "glUniform1i")) {
[email protected]3916c97e2010-02-25 03:20:503872 return;
3873 }
3874 current_program_->SetSamplers(location, 1, &v0);
3875 glUniform1i(location, v0);
3876}
3877
3878void GLES2DecoderImpl::DoUniform1iv(
3879 GLint location, GLsizei count, const GLint *value) {
[email protected]939e7362010-05-13 20:49:103880 if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) {
[email protected]3916c97e2010-02-25 03:20:503881 return;
3882 }
[email protected]43c2f1f2011-03-25 18:35:363883 GLenum type = 0;
3884 if (!PrepForSetUniformByLocation(location, "glUniform1iv", &type, &count)) {
3885 return;
3886 }
3887 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE) {
3888 current_program_->SetSamplers(location, count, value);
3889 }
[email protected]3916c97e2010-02-25 03:20:503890 glUniform1iv(location, count, value);
3891}
3892
[email protected]939e7362010-05-13 20:49:103893void GLES2DecoderImpl::DoUniform1fv(
3894 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363895 GLenum type = 0;
3896 if (!PrepForSetUniformByLocation(location, "glUniform1fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103897 return;
3898 }
3899 if (type == GL_BOOL) {
3900 scoped_array<GLint> temp(new GLint[count]);
3901 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:533902 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103903 }
3904 DoUniform1iv(location, count, temp.get());
3905 } else {
3906 glUniform1fv(location, count, value);
3907 }
3908}
3909
3910void GLES2DecoderImpl::DoUniform2fv(
3911 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363912 GLenum type = 0;
3913 if (!PrepForSetUniformByLocation(location, "glUniform2fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103914 return;
3915 }
3916 if (type == GL_BOOL_VEC2) {
3917 GLsizei num_values = count * 2;
3918 scoped_array<GLint> temp(new GLint[num_values]);
3919 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533920 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103921 }
3922 glUniform2iv(location, count, temp.get());
3923 } else {
3924 glUniform2fv(location, count, value);
3925 }
3926}
3927
3928void GLES2DecoderImpl::DoUniform3fv(
3929 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363930 GLenum type = 0;
3931 if (!PrepForSetUniformByLocation(location, "glUniform3fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103932 return;
3933 }
3934 if (type == GL_BOOL_VEC3) {
3935 GLsizei num_values = count * 3;
3936 scoped_array<GLint> temp(new GLint[num_values]);
3937 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533938 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103939 }
3940 glUniform3iv(location, count, temp.get());
3941 } else {
3942 glUniform3fv(location, count, value);
3943 }
3944}
3945
3946void GLES2DecoderImpl::DoUniform4fv(
3947 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363948 GLenum type = 0;
3949 if (!PrepForSetUniformByLocation(location, "glUniform4fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103950 return;
3951 }
3952 if (type == GL_BOOL_VEC4) {
3953 GLsizei num_values = count * 4;
3954 scoped_array<GLint> temp(new GLint[num_values]);
3955 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:533956 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103957 }
3958 glUniform4iv(location, count, temp.get());
3959 } else {
3960 glUniform4fv(location, count, value);
3961 }
3962}
3963
[email protected]43c2f1f2011-03-25 18:35:363964void GLES2DecoderImpl::DoUniform2iv(
3965 GLint location, GLsizei count, const GLint* value) {
3966 GLenum type = 0;
3967 if (!PrepForSetUniformByLocation(location, "glUniform2iv", &type, &count)) {
3968 return;
3969 }
3970 glUniform2iv(location, count, value);
3971}
3972
3973void GLES2DecoderImpl::DoUniform3iv(
3974 GLint location, GLsizei count, const GLint* value) {
3975 GLenum type = 0;
3976 if (!PrepForSetUniformByLocation(location, "glUniform3iv", &type, &count)) {
3977 return;
3978 }
3979 glUniform3iv(location, count, value);
3980}
3981
3982void GLES2DecoderImpl::DoUniform4iv(
3983 GLint location, GLsizei count, const GLint* value) {
3984 GLenum type = 0;
3985 if (!PrepForSetUniformByLocation(location, "glUniform4iv", &type, &count)) {
3986 return;
3987 }
3988 glUniform4iv(location, count, value);
3989}
3990
3991void GLES2DecoderImpl::DoUniformMatrix2fv(
3992 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
3993 GLenum type = 0;
3994 if (!PrepForSetUniformByLocation(
3995 location, "glUniformMatrix2fv", &type, &count)) {
3996 return;
3997 }
3998 glUniformMatrix2fv (location, count, transpose, value);
3999}
4000
4001void GLES2DecoderImpl::DoUniformMatrix3fv(
4002 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4003 GLenum type = 0;
4004 if (!PrepForSetUniformByLocation(
4005 location, "glUniformMatrix3fv", &type, &count)) {
4006 return;
4007 }
4008 glUniformMatrix3fv (location, count, transpose, value);
4009}
4010
4011void GLES2DecoderImpl::DoUniformMatrix4fv(
4012 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4013 GLenum type = 0;
4014 if (!PrepForSetUniformByLocation(
4015 location, "glUniformMatrix4fv", &type, &count)) {
4016 return;
4017 }
4018 glUniformMatrix4fv (location, count, transpose, value);
4019}
4020
[email protected]3916c97e2010-02-25 03:20:504021void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:034022 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:504023 ProgramManager::ProgramInfo* info = NULL;
4024 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:584025 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:504026 if (!info) {
[email protected]ae51d192010-04-27 00:48:034027 return;
4028 }
4029 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:504030 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:294031 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:504032 return;
4033 }
[email protected]ae51d192010-04-27 00:48:034034 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:504035 }
[email protected]ca488e12010-12-13 20:06:144036 if (current_program_) {
4037 program_manager()->UnuseProgram(shader_manager(), current_program_);
4038 }
[email protected]3916c97e2010-02-25 03:20:504039 current_program_ = info;
[email protected]ca488e12010-12-13 20:06:144040 if (current_program_) {
4041 program_manager()->UseProgram(current_program_);
4042 }
[email protected]ae51d192010-04-27 00:48:034043 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:504044}
4045
[email protected]96449d2c2009-11-25 00:01:324046GLenum GLES2DecoderImpl::GetGLError() {
4047 // Check the GL error first, then our wrapped error.
4048 GLenum error = glGetError();
4049 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:374050 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:324051 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:294052 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:324053 break;
4054 }
4055 }
4056 }
4057
4058 if (error != GL_NO_ERROR) {
4059 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:294060 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324061 }
4062 return error;
4063}
4064
[email protected]1002c2d2011-06-28 22:39:044065GLenum GLES2DecoderImpl::PeekGLError() {
4066 GLenum error = glGetError();
4067 if (error != GL_NO_ERROR) {
4068 SetGLError(error, "");
4069 }
4070 return error;
4071}
4072
[email protected]8eee29c2010-04-29 03:38:294073void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
4074 if (msg) {
4075 last_error_ = msg;
[email protected]d0498742010-09-20 20:27:014076 LOG(ERROR) << last_error_;
[email protected]8eee29c2010-04-29 03:38:294077 }
[email protected]ddd968b82010-03-02 00:44:294078 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324079}
4080
[email protected]07f54fcc2009-12-22 02:46:304081void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
4082 GLenum error;
4083 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294084 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:304085 }
4086}
4087
[email protected]6217d392010-03-25 22:08:354088void GLES2DecoderImpl::ClearRealGLErrors() {
4089 GLenum error;
4090 while ((error = glGetError()) != GL_NO_ERROR) {
4091 NOTREACHED() << "GL error " << error << " was unhandled.";
4092 }
4093}
4094
[email protected]ef526492010-06-02 23:12:254095bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:504096 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:254097 // Only check if there are some unrenderable textures.
4098 if (!texture_manager()->HaveUnrenderableTextures()) {
4099 return false;
4100 }
4101 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:504102 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4103 current_program_->sampler_indices();
4104 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4105 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4106 current_program_->GetUniformInfo(sampler_indices[ii]);
4107 DCHECK(uniform_info);
4108 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4109 GLuint texture_unit_index = uniform_info->texture_units[jj];
4110 if (texture_unit_index < group_->max_texture_units()) {
4111 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4112 TextureManager::TextureInfo* texture_info =
4113 uniform_info->type == GL_SAMPLER_2D ?
4114 texture_unit.bound_texture_2d :
4115 texture_unit.bound_texture_cube_map;
[email protected]915a59a12010-09-30 21:29:114116 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]ef526492010-06-02 23:12:254117 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:504118 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4119 glBindTexture(
4120 uniform_info->type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
4121 GL_TEXTURE_CUBE_MAP,
[email protected]00f893d2010-08-24 18:55:494122 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:504123 }
4124 }
4125 // else: should this be an error?
4126 }
4127 }
[email protected]ef526492010-06-02 23:12:254128 return textures_set;
[email protected]3916c97e2010-02-25 03:20:504129}
4130
4131void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
4132 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:504133 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4134 current_program_->sampler_indices();
4135 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4136 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4137 current_program_->GetUniformInfo(sampler_indices[ii]);
4138 DCHECK(uniform_info);
4139 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4140 GLuint texture_unit_index = uniform_info->texture_units[jj];
4141 if (texture_unit_index < group_->max_texture_units()) {
4142 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4143 TextureManager::TextureInfo* texture_info =
4144 uniform_info->type == GL_SAMPLER_2D ?
4145 texture_unit.bound_texture_2d :
4146 texture_unit.bound_texture_cube_map;
[email protected]915a59a12010-09-30 21:29:114147 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]3916c97e2010-02-25 03:20:504148 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4149 // Get the texture info that was previously bound here.
4150 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
4151 texture_unit.bound_texture_2d :
4152 texture_unit.bound_texture_cube_map;
4153 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:034154 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:504155 }
4156 }
4157 }
4158 }
4159 // Set the active texture back to whatever the user had it as.
4160 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:304161}
4162
4163bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]689fa1c52010-06-09 18:35:034164 // NOTE: We specifically do not check current_program->IsValid() because
4165 // it could never be invalid since glUseProgram would have failed. While
4166 // glLinkProgram could later mark the program as invalid the previous
4167 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:144168 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:504169 // The program does not exist.
4170 // But GL says no ERROR.
4171 return false;
4172 }
[email protected]f39f4b3f2010-05-12 17:04:084173 // Validate all attribs currently enabled. If they are used by the current
4174 // program then check that they have enough elements to handle the draw call.
4175 // If they are not used by the current program check that they have a buffer
4176 // assigned.
4177 const VertexAttribManager::VertexAttribInfoList& infos =
4178 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4179 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:404180 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:084181 const VertexAttribManager::VertexAttribInfo* info = *it;
4182 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4183 current_program_->GetAttribInfoByLocation(info->index());
4184 if (attrib_info) {
4185 // This attrib is used in the current program.
4186 if (!info->CanAccess(max_vertex_accessed)) {
4187 SetGLError(GL_INVALID_OPERATION,
4188 "glDrawXXX: attempt to access out of range vertices");
4189 return false;
4190 }
4191 } else {
4192 // This attrib is not used in the current program.
4193 if (!info->buffer() || info->buffer()->IsDeleted()) {
4194 SetGLError(
4195 GL_INVALID_OPERATION,
4196 "glDrawXXX: attempt to render with no buffer attached to enabled "
4197 "attrib");
4198 return false;
4199 }
[email protected]1d32bc82010-01-13 22:06:464200 }
[email protected]07f54fcc2009-12-22 02:46:304201 }
[email protected]3916c97e2010-02-25 03:20:504202 return true;
[email protected]b1122982010-05-17 23:04:244203}
4204
4205bool GLES2DecoderImpl::SimulateAttrib0(GLuint max_vertex_accessed) {
[email protected]876f6fee2010-08-02 23:10:324206 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4207 return false;
4208
[email protected]b1122982010-05-17 23:04:244209 const VertexAttribManager::VertexAttribInfo* info =
4210 vertex_attrib_manager_.GetVertexAttribInfo(0);
4211 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:494212 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
4213 if (info->enabled() && attrib_0_used) {
[email protected]b1122982010-05-17 23:04:244214 return false;
4215 }
4216
4217 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
4218
4219 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
4220
4221 // Make a buffer with a single repeated vec4 value enough to
4222 // simulate the constant value that is supposed to be here.
4223 // This is required to emulate GLES2 on GL.
4224 GLsizei num_vertices = max_vertex_accessed + 1;
4225 GLsizei size_needed = num_vertices * sizeof(Vec4); // NOLINT
[email protected]fc753442011-02-04 19:49:494226 if (size_needed > attrib_0_size_) {
4227 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
4228 // TODO(gman): check for error here?
4229 attrib_0_buffer_matches_value_ = false;
4230 }
4231 if (attrib_0_used &&
4232 (!attrib_0_buffer_matches_value_ ||
4233 (info->value().v[0] != attrib_0_value_.v[0] ||
4234 info->value().v[1] != attrib_0_value_.v[1] ||
4235 info->value().v[2] != attrib_0_value_.v[2] ||
4236 info->value().v[3] != attrib_0_value_.v[3]))) {
4237 std::vector<Vec4> temp(num_vertices, info->value());
4238 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
4239 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:244240 attrib_0_value_ = info->value();
4241 attrib_0_size_ = size_needed;
4242 }
4243
4244 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4245
4246 return true;
[email protected]b1122982010-05-17 23:04:244247}
4248
4249void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
4250 const VertexAttribManager::VertexAttribInfo* info =
4251 vertex_attrib_manager_.GetVertexAttribInfo(0);
4252 const void* ptr = reinterpret_cast<const void*>(info->offset());
4253 BufferManager::BufferInfo* buffer_info = info->buffer();
4254 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
4255 glVertexAttribPointer(
4256 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
4257 ptr);
4258 glBindBuffer(GL_ARRAY_BUFFER,
4259 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4260}
[email protected]07f54fcc2009-12-22 02:46:304261
[email protected]8fbedc02010-11-18 18:43:404262bool GLES2DecoderImpl::SimulateFixedAttribs(
4263 GLuint max_vertex_accessed, bool* simulated) {
4264 DCHECK(simulated);
4265 *simulated = false;
4266 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4267 return true;
4268
4269 if (!vertex_attrib_manager_.HaveFixedAttribs()) {
4270 return true;
4271 }
4272
4273 // NOTE: we could be smart and try to check if a buffer is used
4274 // twice in 2 different attribs, find the overlapping parts and therefore
4275 // duplicate the minimum amount of data but this whole code path is not meant
4276 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
4277 // tests so we just add to the buffer attrib used.
4278
4279 // Compute the number of elements needed.
4280 int num_vertices = max_vertex_accessed + 1;
4281 int elements_needed = 0;
4282 const VertexAttribManager::VertexAttribInfoList& infos =
4283 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4284 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4285 infos.begin(); it != infos.end(); ++it) {
4286 const VertexAttribManager::VertexAttribInfo* info = *it;
4287 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4288 current_program_->GetAttribInfoByLocation(info->index());
4289 if (attrib_info &&
4290 info->CanAccess(max_vertex_accessed) &&
4291 info->type() == GL_FIXED) {
4292 int elements_used = 0;
4293 if (!SafeMultiply(
4294 static_cast<int>(num_vertices),
4295 info->size(), &elements_used) ||
4296 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
4297 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4298 return false;
4299 }
4300 }
4301 }
4302
4303 const int kSizeOfFloat = sizeof(float); // NOLINT
4304 int size_needed = 0;
4305 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed)) {
4306 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4307 return false;
4308 }
4309
4310
4311 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
4312 if (size_needed > fixed_attrib_buffer_size_) {
4313 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
4314 }
4315
4316 // Copy the elements and convert to float
4317 GLintptr offset = 0;
4318 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4319 infos.begin(); it != infos.end(); ++it) {
4320 const VertexAttribManager::VertexAttribInfo* info = *it;
4321 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4322 current_program_->GetAttribInfoByLocation(info->index());
4323 if (attrib_info &&
4324 info->CanAccess(max_vertex_accessed) &&
4325 info->type() == GL_FIXED) {
4326 int num_elements = info->size() * kSizeOfFloat;
4327 int size = num_elements * num_vertices;
4328 scoped_array<float> data(new float[size]);
4329 const int32* src = reinterpret_cast<const int32 *>(
4330 info->buffer()->GetRange(info->offset(), size));
4331 const int32* end = src + num_elements;
4332 float* dst = data.get();
4333 while (src != end) {
4334 *dst++ = static_cast<float>(*src++) / 65536.0f;
4335 }
4336 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
4337 glVertexAttribPointer(
4338 info->index(), info->size(), GL_FLOAT, false, 0,
4339 reinterpret_cast<GLvoid*>(offset));
4340 offset += size;
4341 }
4342 }
4343 *simulated = true;
4344 return true;
4345}
4346
4347void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
4348 // There's no need to call glVertexAttribPointer because we shadow all the
4349 // settings and passing GL_FIXED to it will not work.
4350 glBindBuffer(GL_ARRAY_BUFFER,
4351 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4352}
4353
[email protected]38d139d2011-07-14 00:38:434354error::Error GLES2DecoderImpl::HandleDrawArrays(
4355 uint32 immediate_data_size, const gles2::DrawArrays& c) {
4356 GLenum mode = static_cast<GLenum>(c.mode);
4357 GLint first = static_cast<GLint>(c.first);
4358 GLsizei count = static_cast<GLsizei>(c.count);
4359 if (!validators_->draw_mode.IsValid(mode)) {
4360 SetGLError(GL_INVALID_ENUM, "glDrawArrays: mode GL_INVALID_ENUM");
4361 return error::kNoError;
4362 }
4363 if (count < 0) {
4364 SetGLError(GL_INVALID_VALUE, "glDrawArrays: count < 0");
4365 return error::kNoError;
4366 }
4367 if (!CheckFramebufferComplete("glDrawArrays")) {
4368 return error::kNoError;
4369 }
4370 // We have to check this here because the prototype for glDrawArrays
4371 // is GLint not GLsizei.
4372 if (first < 0) {
4373 SetGLError(GL_INVALID_VALUE, "glDrawArrays: first < 0");
4374 return error::kNoError;
4375 }
4376
4377 if (count == 0) {
4378 return error::kNoError;
4379 }
4380
4381 GLuint max_vertex_accessed = first + count - 1;
4382 if (IsDrawValid(max_vertex_accessed)) {
4383 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
4384 bool simulated_fixed_attribs = false;
4385 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
4386 bool textures_set = SetBlackTextureForNonRenderableTextures();
4387 ApplyDirtyState();
4388 glDrawArrays(mode, first, count);
4389 if (textures_set) {
4390 RestoreStateForNonRenderableTextures();
4391 }
4392 if (simulated_fixed_attribs) {
4393 RestoreStateForSimulatedFixedAttribs();
4394 }
4395 }
4396 if (simulated_attrib_0) {
4397 RestoreStateForSimulatedAttrib0();
4398 }
4399 if (WasContextLost()) {
4400 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawArrays.";
4401 return error::kLostContext;
4402 }
4403 }
4404 return error::kNoError;
4405}
4406
[email protected]f7a64ee2010-02-01 22:24:144407error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:194408 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:504409 if (!bound_element_array_buffer_ ||
4410 bound_element_array_buffer_->IsDeleted()) {
[email protected]8eee29c2010-04-29 03:38:294411 SetGLError(GL_INVALID_OPERATION,
4412 "glDrawElements: No element array buffer bound");
4413 return error::kNoError;
4414 }
4415
4416 GLenum mode = c.mode;
4417 GLsizei count = c.count;
4418 GLenum type = c.type;
4419 int32 offset = c.index_offset;
4420 if (count < 0) {
4421 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
4422 return error::kNoError;
4423 }
4424 if (offset < 0) {
4425 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
4426 return error::kNoError;
4427 }
[email protected]9438b012010-06-15 22:55:054428 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:294429 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
4430 return error::kNoError;
4431 }
[email protected]9438b012010-06-15 22:55:054432 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294433 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
4434 return error::kNoError;
4435 }
4436
[email protected]3a03a8f2011-03-19 00:51:274437 if (!CheckFramebufferComplete("glDrawElements")) {
4438 return error::kNoError;
4439 }
4440
[email protected]6c788fb72010-08-26 02:16:314441 if (count == 0) {
4442 return error::kNoError;
4443 }
4444
[email protected]8eee29c2010-04-29 03:38:294445 GLuint max_vertex_accessed;
4446 if (!bound_element_array_buffer_->GetMaxValueForRange(
4447 offset, count, type, &max_vertex_accessed)) {
4448 SetGLError(GL_INVALID_OPERATION,
4449 "glDrawElements: range out of bounds for buffer");
4450 return error::kNoError;
4451 }
4452
4453 if (IsDrawValid(max_vertex_accessed)) {
[email protected]b1122982010-05-17 23:04:244454 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
[email protected]8fbedc02010-11-18 18:43:404455 bool simulated_fixed_attribs = false;
4456 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
4457 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:464458 ApplyDirtyState();
[email protected]8fbedc02010-11-18 18:43:404459 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
4460 glDrawElements(mode, count, type, indices);
4461 if (textures_set) {
4462 RestoreStateForNonRenderableTextures();
4463 }
4464 if (simulated_fixed_attribs) {
4465 RestoreStateForSimulatedFixedAttribs();
4466 }
[email protected]ba3176a2009-12-16 18:19:464467 }
[email protected]b1122982010-05-17 23:04:244468 if (simulated_attrib_0) {
4469 RestoreStateForSimulatedAttrib0();
4470 }
[email protected]38d139d2011-07-14 00:38:434471 if (WasContextLost()) {
4472 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawElements.";
4473 return error::kLostContext;
4474 }
[email protected]96449d2c2009-11-25 00:01:324475 }
[email protected]f7a64ee2010-02-01 22:24:144476 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324477}
4478
[email protected]269200b12010-11-18 22:53:064479GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:234480 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
4481 GLuint max_vertex_accessed = 0;
4482 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:294483 if (!info) {
[email protected]ae51d192010-04-27 00:48:034484 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:294485 SetGLError(GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:064486 "GetMaxValueInBufferCHROMIUM: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:234487 } else {
4488 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:034489 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:064490 SetGLError(
4491 GL_INVALID_OPERATION,
4492 "GetMaxValueInBufferCHROMIUM: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:234493 }
4494 }
4495 return max_vertex_accessed;
4496}
4497
[email protected]96449d2c2009-11-25 00:01:324498// Calls glShaderSource for the various versions of the ShaderSource command.
4499// Assumes that data / data_size points to a piece of memory that is in range
4500// of whatever context it came from (shared memory, immediate memory, bucket
4501// memory.)
[email protected]45bf5152010-02-12 00:11:314502error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034503 GLuint client_id, const char* data, uint32 data_size) {
[email protected]6b8cf1a2010-05-06 16:13:584504 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4505 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:314506 if (!info) {
[email protected]45bf5152010-02-12 00:11:314507 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324508 }
[email protected]45bf5152010-02-12 00:11:314509 // Note: We don't actually call glShaderSource here. We wait until
4510 // the call to glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:524511 info->Update(std::string(data, data + data_size).c_str());
[email protected]f7a64ee2010-02-01 22:24:144512 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324513}
4514
[email protected]f7a64ee2010-02-01 22:24:144515error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:194516 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:324517 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314518 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:324519 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:464520 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144521 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324522 }
[email protected]ae51d192010-04-27 00:48:034523 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:324524}
4525
[email protected]f7a64ee2010-02-01 22:24:144526error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:194527 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:324528 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314529 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:304530 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:464531 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144532 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324533 }
[email protected]ae51d192010-04-27 00:48:034534 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:314535}
4536
[email protected]558847a2010-03-24 07:02:544537error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
4538 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:544539 Bucket* bucket = GetBucket(c.data_bucket_id);
4540 if (!bucket || bucket->size() == 0) {
4541 return error::kInvalidArguments;
4542 }
4543 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034544 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:544545 bucket->size() - 1);
4546}
4547
[email protected]ae51d192010-04-27 00:48:034548void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]0c8fabf2011-06-14 19:35:224549 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]6b8cf1a2010-05-06 16:13:584550 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4551 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:314552 if (!info) {
[email protected]45bf5152010-02-12 00:11:314553 return;
4554 }
[email protected]de17df392010-04-23 21:09:414555 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
4556 // glShaderSource and then glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:524557 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:344558 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:184559 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:344560 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:454561 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:234562
[email protected]a550584e2010-09-17 18:01:454563 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:344564 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:184565 return;
4566 }
[email protected]a550584e2010-09-17 18:01:454567 shader_src = translator->translated_shader();
[email protected]de17df392010-04-23 21:09:414568 }
[email protected]de17df392010-04-23 21:09:414569
[email protected]ae51d192010-04-27 00:48:034570 glShaderSource(info->service_id(), 1, &shader_src, NULL);
4571 glCompileShader(info->service_id());
[email protected]e5186162010-06-14 18:54:414572 GLint status = GL_FALSE;
4573 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
4574 if (status) {
[email protected]f57bb282010-11-12 00:51:344575 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:414576 } else {
[email protected]d9977d42010-09-01 20:27:024577 // We cannot reach here if we are using the shader translator.
4578 // All invalid shaders must be rejected by the translator.
4579 // All translated shaders must compile.
4580 LOG_IF(ERROR, use_shader_translator_)
4581 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:334582 GLint max_len = 0;
4583 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
4584 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:414585 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:334586 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
4587 DCHECK(max_len == 0 || len < max_len);
4588 DCHECK(len ==0 || temp[len] == '\0');
[email protected]df6cf1ad2011-01-29 01:20:524589 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
[email protected]e5186162010-06-14 18:54:414590 }
[email protected]45bf5152010-02-12 00:11:314591};
4592
[email protected]ddd968b82010-03-02 00:44:294593void GLES2DecoderImpl::DoGetShaderiv(
4594 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:584595 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4596 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:294597 if (!info) {
[email protected]ddd968b82010-03-02 00:44:294598 return;
4599 }
[email protected]8f1ccdac2010-05-19 21:01:484600 switch (pname) {
4601 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:524602 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:484603 return;
4604 case GL_COMPILE_STATUS:
[email protected]e5186162010-06-14 18:54:414605 *params = info->IsValid();
4606 return;
[email protected]8f1ccdac2010-05-19 21:01:484607 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:524608 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:414609 return;
[email protected]8f1ccdac2010-05-19 21:01:484610 default:
4611 break;
[email protected]ddd968b82010-03-02 00:44:294612 }
[email protected]8f1ccdac2010-05-19 21:01:484613 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:294614}
4615
[email protected]ae51d192010-04-27 00:48:034616error::Error GLES2DecoderImpl::HandleGetShaderSource(
4617 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
4618 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:034619 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4620 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:584621 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4622 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:524623 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:294624 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:294625 return error::kNoError;
4626 }
[email protected]df6cf1ad2011-01-29 01:20:524627 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:034628 return error::kNoError;
4629}
4630
4631error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
4632 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
4633 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:584634 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4635 Bucket* bucket = CreateBucket(bucket_id);
4636 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4637 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:524638 if (!info || !info->log_info()) {
4639 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:034640 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:314641 }
[email protected]df6cf1ad2011-01-29 01:20:524642 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:034643 return error::kNoError;
4644}
4645
4646error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
4647 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
4648 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:584649 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4650 Bucket* bucket = CreateBucket(bucket_id);
4651 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4652 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:524653 if (!info || !info->log_info()) {
[email protected]6b8cf1a2010-05-06 16:13:584654 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:034655 return error::kNoError;
4656 }
[email protected]df6cf1ad2011-01-29 01:20:524657 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:034658 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324659}
4660
[email protected]1958e0e2010-04-22 05:17:154661bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364662 const BufferManager::BufferInfo* info = GetBufferInfo(client_id);
4663 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154664}
4665
4666bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364667 const FramebufferManager::FramebufferInfo* info =
4668 GetFramebufferInfo(client_id);
4669 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154670}
4671
4672bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364673 // IsProgram is true for programs as soon as they are created, until they are
4674 // deleted and no longer in use.
[email protected]ae51d192010-04-27 00:48:034675 return GetProgramInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154676}
4677
4678bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364679 const RenderbufferManager::RenderbufferInfo* info =
4680 GetRenderbufferInfo(client_id);
4681 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154682}
4683
4684bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364685 // IsShader is true for shaders as soon as they are created, until they
4686 // are deleted and not attached to any programs.
[email protected]ae51d192010-04-27 00:48:034687 return GetShaderInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154688}
4689
4690bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364691 const TextureManager::TextureInfo* info = GetTextureInfo(client_id);
4692 return info && info->IsValid();
[email protected]ae51d192010-04-27 00:48:034693}
4694
4695void GLES2DecoderImpl::DoAttachShader(
4696 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584697 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4698 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034699 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034700 return;
[email protected]1958e0e2010-04-22 05:17:154701 }
[email protected]6b8cf1a2010-05-06 16:13:584702 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4703 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034704 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034705 return;
4706 }
[email protected]ca488e12010-12-13 20:06:144707 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:314708 SetGLError(GL_INVALID_OPERATION,
4709 "glAttachShader: can not attach more than"
4710 " one shader of the same type.");
4711 return;
4712 }
[email protected]ae51d192010-04-27 00:48:034713 glAttachShader(program_info->service_id(), shader_info->service_id());
4714}
4715
4716void GLES2DecoderImpl::DoDetachShader(
4717 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584718 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4719 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034720 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034721 return;
4722 }
[email protected]6b8cf1a2010-05-06 16:13:584723 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4724 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034725 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034726 return;
4727 }
[email protected]9a0ccd42011-03-16 23:58:224728 if (!program_info->DetachShader(shader_manager(), shader_info)) {
4729 SetGLError(GL_INVALID_OPERATION,
4730 "glDetachShader: shader not attached to program");
4731 return;
4732 }
[email protected]ae51d192010-04-27 00:48:034733 glDetachShader(program_info->service_id(), shader_info->service_id());
4734}
4735
4736void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584737 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4738 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:034739 if (!info) {
[email protected]ae51d192010-04-27 00:48:034740 return;
4741 }
[email protected]d685a682011-04-29 16:19:574742 info->Validate();
[email protected]1958e0e2010-04-22 05:17:154743}
4744
[email protected]b1122982010-05-17 23:04:244745void GLES2DecoderImpl::DoGetVertexAttribfv(
4746 GLuint index, GLenum pname, GLfloat* params) {
4747 VertexAttribManager::VertexAttribInfo* info =
4748 vertex_attrib_manager_.GetVertexAttribInfo(index);
4749 if (!info) {
4750 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
4751 return;
4752 }
4753 switch (pname) {
4754 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4755 BufferManager::BufferInfo* buffer = info->buffer();
4756 if (buffer && !buffer->IsDeleted()) {
4757 GLuint client_id;
4758 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4759 *params = static_cast<GLfloat>(client_id);
4760 }
4761 break;
4762 }
4763 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4764 *params = static_cast<GLfloat>(info->enabled());
4765 break;
4766 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4767 *params = static_cast<GLfloat>(info->size());
4768 break;
4769 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4770 *params = static_cast<GLfloat>(info->gl_stride());
4771 break;
4772 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4773 *params = static_cast<GLfloat>(info->type());
4774 break;
4775 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4776 *params = static_cast<GLfloat>(info->normalized());
4777 break;
4778 case GL_CURRENT_VERTEX_ATTRIB:
4779 params[0] = info->value().v[0];
4780 params[1] = info->value().v[1];
4781 params[2] = info->value().v[2];
4782 params[3] = info->value().v[3];
4783 break;
4784 default:
4785 NOTREACHED();
4786 break;
4787 }
4788}
4789
4790void GLES2DecoderImpl::DoGetVertexAttribiv(
4791 GLuint index, GLenum pname, GLint* params) {
4792 VertexAttribManager::VertexAttribInfo* info =
4793 vertex_attrib_manager_.GetVertexAttribInfo(index);
4794 if (!info) {
4795 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
4796 return;
4797 }
4798 switch (pname) {
4799 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4800 BufferManager::BufferInfo* buffer = info->buffer();
4801 if (buffer && !buffer->IsDeleted()) {
4802 GLuint client_id;
4803 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4804 *params = client_id;
4805 }
4806 break;
4807 }
4808 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4809 *params = info->enabled();
4810 break;
4811 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4812 *params = info->size();
4813 break;
4814 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4815 *params = info->gl_stride();
4816 break;
4817 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4818 *params = info->type();
4819 break;
4820 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4821 *params = static_cast<GLint>(info->normalized());
4822 break;
4823 case GL_CURRENT_VERTEX_ATTRIB:
4824 params[0] = static_cast<GLint>(info->value().v[0]);
4825 params[1] = static_cast<GLint>(info->value().v[1]);
4826 params[2] = static_cast<GLint>(info->value().v[2]);
4827 params[3] = static_cast<GLint>(info->value().v[3]);
4828 break;
4829 default:
4830 NOTREACHED();
4831 break;
4832 }
4833}
4834
4835void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
4836 VertexAttribManager::VertexAttribInfo* info =
4837 vertex_attrib_manager_.GetVertexAttribInfo(index);
4838 if (!info) {
4839 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
4840 return;
4841 }
4842 VertexAttribManager::VertexAttribInfo::Vec4 value;
4843 value.v[0] = v0;
4844 value.v[1] = 0.0f;
4845 value.v[2] = 0.0f;
4846 value.v[3] = 1.0f;
4847 info->set_value(value);
4848 glVertexAttrib1f(index, v0);
4849}
4850
4851void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
4852 VertexAttribManager::VertexAttribInfo* info =
4853 vertex_attrib_manager_.GetVertexAttribInfo(index);
4854 if (!info) {
4855 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
4856 return;
4857 }
4858 VertexAttribManager::VertexAttribInfo::Vec4 value;
4859 value.v[0] = v0;
4860 value.v[1] = v1;
4861 value.v[2] = 0.0f;
4862 value.v[3] = 1.0f;
4863 info->set_value(value);
4864 glVertexAttrib2f(index, v0, v1);
4865}
4866
4867void GLES2DecoderImpl::DoVertexAttrib3f(
4868 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
4869 VertexAttribManager::VertexAttribInfo* info =
4870 vertex_attrib_manager_.GetVertexAttribInfo(index);
4871 if (!info) {
4872 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
4873 return;
4874 }
4875 VertexAttribManager::VertexAttribInfo::Vec4 value;
4876 value.v[0] = v0;
4877 value.v[1] = v1;
4878 value.v[2] = v2;
4879 value.v[3] = 1.0f;
4880 info->set_value(value);
4881 glVertexAttrib3f(index, v0, v1, v2);
4882}
4883
4884void GLES2DecoderImpl::DoVertexAttrib4f(
4885 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
4886 VertexAttribManager::VertexAttribInfo* info =
4887 vertex_attrib_manager_.GetVertexAttribInfo(index);
4888 if (!info) {
4889 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
4890 return;
4891 }
4892 VertexAttribManager::VertexAttribInfo::Vec4 value;
4893 value.v[0] = v0;
4894 value.v[1] = v1;
4895 value.v[2] = v2;
4896 value.v[3] = v3;
4897 info->set_value(value);
4898 glVertexAttrib4f(index, v0, v1, v2, v3);
4899}
4900
4901void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
4902 VertexAttribManager::VertexAttribInfo* info =
4903 vertex_attrib_manager_.GetVertexAttribInfo(index);
4904 if (!info) {
4905 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
4906 return;
4907 }
4908 VertexAttribManager::VertexAttribInfo::Vec4 value;
4909 value.v[0] = v[0];
4910 value.v[1] = 0.0f;
4911 value.v[2] = 0.0f;
4912 value.v[3] = 1.0f;
4913 info->set_value(value);
4914 glVertexAttrib1fv(index, v);
4915}
4916
4917void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
4918 VertexAttribManager::VertexAttribInfo* info =
4919 vertex_attrib_manager_.GetVertexAttribInfo(index);
4920 if (!info) {
4921 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
4922 return;
4923 }
4924 VertexAttribManager::VertexAttribInfo::Vec4 value;
4925 value.v[0] = v[0];
4926 value.v[1] = v[1];
4927 value.v[2] = 0.0f;
4928 value.v[3] = 1.0f;
4929 info->set_value(value);
4930 glVertexAttrib2fv(index, v);
4931}
4932
4933void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
4934 VertexAttribManager::VertexAttribInfo* info =
4935 vertex_attrib_manager_.GetVertexAttribInfo(index);
4936 if (!info) {
4937 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
4938 return;
4939 }
4940 VertexAttribManager::VertexAttribInfo::Vec4 value;
4941 value.v[0] = v[0];
4942 value.v[1] = v[1];
4943 value.v[2] = v[2];
4944 value.v[3] = 1.0f;
4945 info->set_value(value);
4946 glVertexAttrib3fv(index, v);
4947}
4948
4949void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
4950 VertexAttribManager::VertexAttribInfo* info =
4951 vertex_attrib_manager_.GetVertexAttribInfo(index);
4952 if (!info) {
4953 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
4954 return;
4955 }
4956 VertexAttribManager::VertexAttribInfo::Vec4 value;
4957 value.v[0] = v[0];
4958 value.v[1] = v[1];
4959 value.v[2] = v[2];
4960 value.v[3] = v[3];
4961 info->set_value(value);
4962 glVertexAttrib4fv(index, v);
4963}
4964
[email protected]f7a64ee2010-02-01 22:24:144965error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:194966 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:294967 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
4968 SetGLError(GL_INVALID_VALUE,
4969 "glVertexAttribPointer: no array buffer bound");
4970 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324971 }
[email protected]8eee29c2010-04-29 03:38:294972
4973 GLuint indx = c.indx;
4974 GLint size = c.size;
4975 GLenum type = c.type;
4976 GLboolean normalized = c.normalized;
4977 GLsizei stride = c.stride;
4978 GLsizei offset = c.offset;
4979 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:054980 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294981 SetGLError(GL_INVALID_ENUM,
4982 "glVertexAttribPointer: type GL_INVALID_ENUM");
4983 return error::kNoError;
4984 }
[email protected]9438b012010-06-15 22:55:054985 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:314986 SetGLError(GL_INVALID_VALUE,
[email protected]8eee29c2010-04-29 03:38:294987 "glVertexAttribPointer: size GL_INVALID_VALUE");
4988 return error::kNoError;
4989 }
4990 if (indx >= group_->max_vertex_attribs()) {
4991 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
4992 return error::kNoError;
4993 }
4994 if (stride < 0) {
4995 SetGLError(GL_INVALID_VALUE,
4996 "glVertexAttribPointer: stride < 0");
4997 return error::kNoError;
4998 }
4999 if (stride > 255) {
5000 SetGLError(GL_INVALID_VALUE,
5001 "glVertexAttribPointer: stride > 255");
5002 return error::kNoError;
5003 }
5004 if (offset < 0) {
5005 SetGLError(GL_INVALID_VALUE,
5006 "glVertexAttribPointer: offset < 0");
5007 return error::kNoError;
5008 }
5009 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:315010 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:295011 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:315012 SetGLError(GL_INVALID_OPERATION,
5013 "glVertexAttribPointer: offset not valid for type");
5014 return error::kNoError;
5015 }
5016 if (stride % component_size > 0) {
5017 SetGLError(GL_INVALID_OPERATION,
[email protected]8eee29c2010-04-29 03:38:295018 "glVertexAttribPointer: stride not valid for type");
5019 return error::kNoError;
5020 }
[email protected]8fbedc02010-11-18 18:43:405021 vertex_attrib_manager_.SetAttribInfo(
5022 indx,
[email protected]8eee29c2010-04-29 03:38:295023 bound_array_buffer_,
5024 size,
5025 type,
[email protected]b1122982010-05-17 23:04:245026 normalized,
5027 stride,
5028 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:295029 offset);
[email protected]8fbedc02010-11-18 18:43:405030 if (type != GL_FIXED) {
5031 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
5032 }
[email protected]f7a64ee2010-02-01 22:24:145033 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325034}
5035
[email protected]f7a64ee2010-02-01 22:24:145036error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:195037 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:315038 GLint x = c.x;
5039 GLint y = c.y;
5040 GLsizei width = c.width;
5041 GLsizei height = c.height;
5042 GLenum format = c.format;
5043 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:565044 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:295045 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:565046 return error::kNoError;
5047 }
[email protected]a51788e2010-02-24 21:54:255048 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:185049 uint32 pixels_size;
5050 if (!GLES2Util::ComputeImageDataSize(
5051 width, height, format, type, pack_alignment_, &pixels_size)) {
5052 return error::kOutOfBounds;
5053 }
[email protected]612d2f82009-12-08 20:49:315054 void* pixels = GetSharedMemoryAs<void*>(
5055 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:255056 Result* result = GetSharedMemoryAs<Result*>(
5057 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5058 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:145059 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465060 }
[email protected]a51788e2010-02-24 21:54:255061
[email protected]9438b012010-06-15 22:55:055062 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295063 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
5064 return error::kNoError;
5065 }
[email protected]9438b012010-06-15 22:55:055066 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295067 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125068 return error::kNoError;
5069 }
[email protected]57f223832010-03-19 01:57:565070 if (width == 0 || height == 0) {
5071 return error::kNoError;
5072 }
5073
5074 CopyRealGLErrorsToWrapper();
5075
[email protected]c0701082011-04-20 00:34:525076 ScopedResolvedFrameBufferBinder binder(this, false);
[email protected]34ff8b0c2010-10-01 20:06:025077
[email protected]57f223832010-03-19 01:57:565078 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:305079 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:565080
5081 GLint max_x;
5082 GLint max_y;
5083 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:295084 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:145085 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:315086 }
[email protected]57f223832010-03-19 01:57:565087
[email protected]d37231fa2010-04-09 21:16:025088 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:565089 // The user requested an out of range area. Get the results 1 line
5090 // at a time.
5091 uint32 temp_size;
5092 if (!GLES2Util::ComputeImageDataSize(
5093 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295094 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565095 return error::kNoError;
5096 }
5097 GLsizei unpadded_row_size = temp_size;
5098 if (!GLES2Util::ComputeImageDataSize(
5099 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295100 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565101 return error::kNoError;
5102 }
5103 GLsizei padded_row_size = temp_size - unpadded_row_size;
5104 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:295105 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565106 return error::kNoError;
5107 }
5108
5109 GLint dest_x_offset = std::max(-x, 0);
5110 uint32 dest_row_offset;
5111 if (!GLES2Util::ComputeImageDataSize(
5112 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:295113 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565114 return error::kNoError;
5115 }
5116
5117 // Copy each row into the larger dest rect.
5118 int8* dst = static_cast<int8*>(pixels);
5119 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:025120 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:565121 GLint read_width = read_end_x - read_x;
5122 for (GLint yy = 0; yy < height; ++yy) {
5123 GLint ry = y + yy;
5124
5125 // Clear the row.
5126 memset(dst, 0, unpadded_row_size);
5127
5128 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:025129 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:565130 glReadPixels(
5131 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
5132 }
5133 dst += padded_row_size;
5134 }
5135 } else {
5136 glReadPixels(x, y, width, height, format, type, pixels);
5137 }
[email protected]1002c2d2011-06-28 22:39:045138 GLenum error = PeekGLError();
[email protected]a51788e2010-02-24 21:54:255139 if (error == GL_NO_ERROR) {
5140 *result = true;
[email protected]4848b9f82011-03-10 18:37:565141
5142 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5143 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5144 if ((channels_exist & 0x0008) == 0) {
5145 // Set the alpha to 255 because some drivers are buggy in this regard.
5146 uint32 temp_size;
5147 if (!GLES2Util::ComputeImageDataSize(
5148 width, 1, format, type, pack_alignment_, &temp_size)) {
5149 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5150 return error::kNoError;
5151 }
5152 GLsizei unpadded_row_size = temp_size;
5153 if (!GLES2Util::ComputeImageDataSize(
5154 width, 2, format, type, pack_alignment_, &temp_size)) {
5155 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5156 return error::kNoError;
5157 }
5158 GLsizei padded_row_size = temp_size - unpadded_row_size;
5159 if (padded_row_size < 0 || unpadded_row_size < 0) {
5160 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5161 return error::kNoError;
5162 }
5163 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
5164 // of this implementation.
5165 if (type != GL_UNSIGNED_BYTE) {
5166 SetGLError(GL_INVALID_OPERATION, "unsupported readPixel format");
5167 return error::kNoError;
5168 }
5169 switch (format) {
5170 case GL_RGBA:
[email protected]297ca1c2011-06-20 23:08:465171 case GL_BGRA_EXT:
[email protected]4848b9f82011-03-10 18:37:565172 case GL_ALPHA: {
5173 int offset = (format == GL_ALPHA) ? 0 : 3;
5174 int step = (format == GL_ALPHA) ? 1 : 4;
5175 uint8* dst = static_cast<uint8*>(pixels) + offset;
5176 for (GLint yy = 0; yy < height; ++yy) {
5177 uint8* end = dst + unpadded_row_size;
5178 for (uint8* d = dst; d < end; d += step) {
5179 *d = 255;
5180 }
5181 dst += padded_row_size;
5182 }
5183 break;
5184 }
5185 default:
5186 break;
5187 }
5188 }
[email protected]a51788e2010-02-24 21:54:255189 }
[email protected]4848b9f82011-03-10 18:37:565190
[email protected]f7a64ee2010-02-01 22:24:145191 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325192}
5193
[email protected]f7a64ee2010-02-01 22:24:145194error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:195195 uint32 immediate_data_size, const gles2::PixelStorei& c) {
5196 GLenum pname = c.pname;
5197 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:055198 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:295199 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125200 return error::kNoError;
5201 }
[email protected]9438b012010-06-15 22:55:055202 if (!validators_->pixel_store_alignment.IsValid(param)) {
[email protected]8eee29c2010-04-29 03:38:295203 SetGLError(GL_INVALID_VALUE, "glPixelSTore: param GL_INVALID_VALUE");
[email protected]f7a64ee2010-02-01 22:24:145204 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195205 }
5206 glPixelStorei(pname, param);
5207 switch (pname) {
5208 case GL_PACK_ALIGNMENT:
5209 pack_alignment_ = param;
5210 break;
5211 case GL_UNPACK_ALIGNMENT:
5212 unpack_alignment_ = param;
5213 break;
5214 default:
5215 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:375216 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:195217 break;
5218 }
[email protected]f7a64ee2010-02-01 22:24:145219 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195220}
5221
[email protected]558847a2010-03-24 07:02:545222error::Error GLES2DecoderImpl::GetAttribLocationHelper(
5223 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5224 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:585225 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5226 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:035227 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145228 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195229 }
[email protected]ae51d192010-04-27 00:48:035230 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295231 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255232 return error::kNoError;
5233 }
[email protected]b9849abf2009-11-25 19:13:195234 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:545235 location_shm_id, location_shm_offset, sizeof(GLint));
5236 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:145237 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195238 }
[email protected]558847a2010-03-24 07:02:545239 // Require the client to init this incase the context is lost and we are no
5240 // longer executing commands.
5241 if (*location != -1) {
5242 return error::kGenericError;
5243 }
[email protected]0bfd9882010-02-05 23:02:255244 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:145245 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195246}
5247
[email protected]558847a2010-03-24 07:02:545248error::Error GLES2DecoderImpl::HandleGetAttribLocation(
5249 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
5250 uint32 name_size = c.data_size;
5251 const char* name = GetSharedMemoryAs<const char*>(
5252 c.name_shm_id, c.name_shm_offset, name_size);
5253 if (!name) {
5254 return error::kOutOfBounds;
5255 }
5256 String name_str(name, name_size);
5257 return GetAttribLocationHelper(
5258 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5259}
5260
[email protected]f7a64ee2010-02-01 22:24:145261error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:195262 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:545263 uint32 name_size = c.data_size;
5264 const char* name = GetImmediateDataAs<const char*>(
5265 c, name_size, immediate_data_size);
5266 if (!name) {
5267 return error::kOutOfBounds;
5268 }
5269 String name_str(name, name_size);
5270 return GetAttribLocationHelper(
5271 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5272}
5273
5274error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
5275 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
5276 Bucket* bucket = GetBucket(c.name_bucket_id);
5277 if (!bucket) {
5278 return error::kInvalidArguments;
5279 }
5280 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185281 if (!bucket->GetAsString(&name_str)) {
5282 return error::kInvalidArguments;
5283 }
[email protected]558847a2010-03-24 07:02:545284 return GetAttribLocationHelper(
5285 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5286}
5287
5288error::Error GLES2DecoderImpl::GetUniformLocationHelper(
5289 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5290 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:585291 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5292 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:035293 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145294 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195295 }
[email protected]ae51d192010-04-27 00:48:035296 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295297 SetGLError(GL_INVALID_OPERATION,
5298 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255299 return error::kNoError;
5300 }
[email protected]b9849abf2009-11-25 19:13:195301 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:545302 location_shm_id, location_shm_offset, sizeof(GLint));
5303 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:145304 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195305 }
[email protected]558847a2010-03-24 07:02:545306 // Require the client to init this incase the context is lost an we are no
5307 // longer executing commands.
5308 if (*location != -1) {
5309 return error::kGenericError;
5310 }
5311 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:145312 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195313}
5314
[email protected]f7a64ee2010-02-01 22:24:145315error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:195316 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:195317 uint32 name_size = c.data_size;
5318 const char* name = GetSharedMemoryAs<const char*>(
5319 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:545320 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:145321 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195322 }
5323 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:545324 return GetUniformLocationHelper(
5325 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195326}
5327
[email protected]f7a64ee2010-02-01 22:24:145328error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:195329 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:195330 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:305331 const char* name = GetImmediateDataAs<const char*>(
5332 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:545333 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:145334 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195335 }
5336 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:545337 return GetUniformLocationHelper(
5338 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5339}
5340
5341error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
5342 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
5343 Bucket* bucket = GetBucket(c.name_bucket_id);
5344 if (!bucket) {
5345 return error::kInvalidArguments;
5346 }
5347 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185348 if (!bucket->GetAsString(&name_str)) {
5349 return error::kInvalidArguments;
5350 }
[email protected]558847a2010-03-24 07:02:545351 return GetUniformLocationHelper(
5352 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195353}
5354
[email protected]ddd968b82010-03-02 00:44:295355error::Error GLES2DecoderImpl::HandleGetString(
5356 uint32 immediate_data_size, const gles2::GetString& c) {
5357 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:055358 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:295359 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:295360 return error::kNoError;
5361 }
[email protected]1958e0e2010-04-22 05:17:155362 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
5363 const char* str = NULL;
5364 switch (name) {
5365 case GL_VERSION:
5366 str = "OpenGL ES 2.0 Chromium";
5367 break;
5368 case GL_SHADING_LANGUAGE_VERSION:
5369 str = "OpenGL ES GLSL ES 1.0 Chromium";
5370 break;
5371 case GL_EXTENSIONS:
[email protected]915a59a12010-09-30 21:29:115372 str = feature_info_->extensions().c_str();
[email protected]1958e0e2010-04-22 05:17:155373 break;
5374 default:
5375 str = gl_str;
5376 break;
5377 }
[email protected]ddd968b82010-03-02 00:44:295378 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:155379 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:295380 return error::kNoError;
5381}
5382
[email protected]0c86dbf2010-03-05 08:14:115383void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:155384 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:055385 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295386 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
5387 return;
5388 }
[email protected]9438b012010-06-15 22:55:055389 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:295390 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:115391 return;
[email protected]3b6ec202010-03-05 05:16:235392 }
5393 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:295394 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:285395 return;
[email protected]3b6ec202010-03-05 05:16:235396 }
5397 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
5398 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295399 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285400 return;
[email protected]3b6ec202010-03-05 05:16:235401 }
5402 // Clear the buffer to 0 if no initial data was passed in.
5403 scoped_array<int8> zero;
5404 if (!data) {
5405 zero.reset(new int8[size]);
5406 memset(zero.get(), 0, size);
5407 data = zero.get();
5408 }
[email protected]473c01ccb2011-06-07 01:33:305409
5410 if (!bufferdata_faster_than_buffersubdata_ &&
5411 size == info->size() && usage == info->usage()) {
5412 glBufferSubData(target, 0, size, data);
5413 info->SetRange(0, size, data);
5414 return;
5415 }
5416
[email protected]3b6ec202010-03-05 05:16:235417 CopyRealGLErrorsToWrapper();
5418 glBufferData(target, size, data, usage);
[email protected]1002c2d2011-06-28 22:39:045419 GLenum error = PeekGLError();
5420 if (error == GL_NO_ERROR) {
[email protected]473c01ccb2011-06-07 01:33:305421 buffer_manager()->SetInfo(info, size, usage);
[email protected]0c86dbf2010-03-05 08:14:115422 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:235423 }
[email protected]0c86dbf2010-03-05 08:14:115424}
5425
5426error::Error GLES2DecoderImpl::HandleBufferData(
5427 uint32 immediate_data_size, const gles2::BufferData& c) {
5428 GLenum target = static_cast<GLenum>(c.target);
5429 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
5430 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5431 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5432 GLenum usage = static_cast<GLenum>(c.usage);
5433 const void* data = NULL;
5434 if (data_shm_id != 0 || data_shm_offset != 0) {
5435 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
5436 if (!data) {
5437 return error::kOutOfBounds;
5438 }
5439 }
5440 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:145441 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195442}
5443
[email protected]f7a64ee2010-02-01 22:24:145444error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:195445 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
5446 GLenum target = static_cast<GLenum>(c.target);
5447 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:305448 const void* data = GetImmediateDataAs<const void*>(
5449 c, size, immediate_data_size);
5450 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145451 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:305452 }
[email protected]b9849abf2009-11-25 19:13:195453 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:115454 DoBufferData(target, size, data, usage);
5455 return error::kNoError;
5456}
5457
5458void GLES2DecoderImpl::DoBufferSubData(
5459 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:505460 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475461 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295462 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285463 return;
[email protected]a93bb842010-02-16 23:03:475464 }
[email protected]0c86dbf2010-03-05 08:14:115465 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:295466 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]473c01ccb2011-06-07 01:33:305467 return;
[email protected]07f54fcc2009-12-22 02:46:305468 }
[email protected]473c01ccb2011-06-07 01:33:305469 if (bufferdata_faster_than_buffersubdata_ &&
5470 offset == 0 && size == info->size()) {
5471 glBufferData(target, size, data, info->usage());
5472 return;
5473 }
5474 glBufferSubData(target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:195475}
5476
[email protected]a93bb842010-02-16 23:03:475477error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
5478 GLenum target,
5479 GLint level,
5480 GLenum internal_format,
5481 GLsizei width,
5482 GLsizei height,
5483 GLint border,
5484 GLsizei image_size,
5485 const void* data) {
[email protected]a93bb842010-02-16 23:03:475486 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:055487 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295488 SetGLError(GL_INVALID_ENUM,
5489 "glCompressedTexImage2D: target GL_INVALID_ENUM");
5490 return error::kNoError;
5491 }
[email protected]9438b012010-06-15 22:55:055492 if (!validators_->compressed_texture_format.IsValid(
5493 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295494 SetGLError(GL_INVALID_ENUM,
5495 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:475496 return error::kNoError;
5497 }
[email protected]915a59a12010-09-30 21:29:115498 if (!texture_manager()->ValidForTarget(
5499 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475500 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295501 SetGLError(GL_INVALID_VALUE,
5502 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475503 return error::kNoError;
5504 }
[email protected]3916c97e2010-02-25 03:20:505505 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475506 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295507 SetGLError(GL_INVALID_VALUE,
5508 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:475509 return error::kNoError;
5510 }
5511 scoped_array<int8> zero;
5512 if (!data) {
5513 zero.reset(new int8[image_size]);
5514 memset(zero.get(), 0, image_size);
5515 data = zero.get();
5516 }
[email protected]cadde4a2010-07-31 17:10:435517 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:475518 glCompressedTexImage2D(
5519 target, level, internal_format, width, height, border, image_size, data);
[email protected]1002c2d2011-06-28 22:39:045520 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:435521 if (error == GL_NO_ERROR) {
5522 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:115523 feature_info_,
[email protected]cadde4a2010-07-31 17:10:435524 info, target, level, internal_format, width, height, 1, border, 0, 0);
5525 }
[email protected]a93bb842010-02-16 23:03:475526 return error::kNoError;
5527}
5528
[email protected]f7a64ee2010-02-01 22:24:145529error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195530 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
5531 GLenum target = static_cast<GLenum>(c.target);
5532 GLint level = static_cast<GLint>(c.level);
5533 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5534 GLsizei width = static_cast<GLsizei>(c.width);
5535 GLsizei height = static_cast<GLsizei>(c.height);
5536 GLint border = static_cast<GLint>(c.border);
5537 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
5538 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5539 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5540 const void* data = NULL;
5541 if (data_shm_id != 0 || data_shm_offset != 0) {
5542 data = GetSharedMemoryAs<const void*>(
5543 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:465544 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145545 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195546 }
5547 }
[email protected]a93bb842010-02-16 23:03:475548 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195549 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:195550}
5551
[email protected]f7a64ee2010-02-01 22:24:145552error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195553 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
5554 GLenum target = static_cast<GLenum>(c.target);
5555 GLint level = static_cast<GLint>(c.level);
5556 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5557 GLsizei width = static_cast<GLsizei>(c.width);
5558 GLsizei height = static_cast<GLsizei>(c.height);
5559 GLint border = static_cast<GLint>(c.border);
5560 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:305561 const void* data = GetImmediateDataAs<const void*>(
5562 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465563 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145564 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465565 }
[email protected]a93bb842010-02-16 23:03:475566 return DoCompressedTexImage2D(
5567 target, level, internal_format, width, height, border, image_size, data);
5568}
5569
[email protected]b6140d02010-05-17 14:47:165570error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
5571 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
5572 GLenum target = static_cast<GLenum>(c.target);
5573 GLint level = static_cast<GLint>(c.level);
5574 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5575 GLsizei width = static_cast<GLsizei>(c.width);
5576 GLsizei height = static_cast<GLsizei>(c.height);
5577 GLint border = static_cast<GLint>(c.border);
5578 Bucket* bucket = GetBucket(c.bucket_id);
5579 return DoCompressedTexImage2D(
5580 target, level, internal_format, width, height, border,
5581 bucket->size(), bucket->GetData(0, bucket->size()));
5582}
5583
5584error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
5585 uint32 immediate_data_size,
5586 const gles2::CompressedTexSubImage2DBucket& c) {
5587 GLenum target = static_cast<GLenum>(c.target);
5588 GLint level = static_cast<GLint>(c.level);
5589 GLint xoffset = static_cast<GLint>(c.xoffset);
5590 GLint yoffset = static_cast<GLint>(c.yoffset);
5591 GLsizei width = static_cast<GLsizei>(c.width);
5592 GLsizei height = static_cast<GLsizei>(c.height);
5593 GLenum format = static_cast<GLenum>(c.format);
5594 Bucket* bucket = GetBucket(c.bucket_id);
5595 uint32 data_size = bucket->size();
5596 GLsizei imageSize = data_size;
5597 const void* data = bucket->GetData(0, data_size);
[email protected]9438b012010-06-15 22:55:055598 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:165599 SetGLError(
5600 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
5601 return error::kNoError;
5602 }
[email protected]9438b012010-06-15 22:55:055603 if (!validators_->compressed_texture_format.IsValid(format)) {
5604 SetGLError(GL_INVALID_ENUM,
5605 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
5606 return error::kNoError;
5607 }
[email protected]b6140d02010-05-17 14:47:165608 if (width < 0) {
5609 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
5610 return error::kNoError;
5611 }
5612 if (height < 0) {
5613 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
5614 return error::kNoError;
5615 }
5616 if (imageSize < 0) {
5617 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
5618 return error::kNoError;
5619 }
[email protected]cadde4a2010-07-31 17:10:435620 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:165621 target, level, xoffset, yoffset, width, height, format, imageSize, data);
5622 return error::kNoError;
5623}
5624
[email protected]a93bb842010-02-16 23:03:475625error::Error GLES2DecoderImpl::DoTexImage2D(
5626 GLenum target,
5627 GLint level,
5628 GLenum internal_format,
5629 GLsizei width,
5630 GLsizei height,
5631 GLint border,
5632 GLenum format,
5633 GLenum type,
5634 const void* pixels,
5635 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:055636 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295637 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
5638 return error::kNoError;
5639 }
[email protected]9438b012010-06-15 22:55:055640 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295641 SetGLError(GL_INVALID_ENUM,
5642 "glTexImage2D: internal_format GL_INVALID_ENUM");
5643 return error::kNoError;
5644 }
[email protected]9438b012010-06-15 22:55:055645 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295646 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
5647 return error::kNoError;
5648 }
[email protected]9438b012010-06-15 22:55:055649 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295650 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:145651 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195652 }
[email protected]7b92c412010-07-20 17:48:255653 if (format != internal_format) {
5654 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
5655 return error::kNoError;
5656 }
[email protected]915a59a12010-09-30 21:29:115657 if (!texture_manager()->ValidForTarget(
5658 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475659 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295660 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475661 return error::kNoError;
5662 }
[email protected]3916c97e2010-02-25 03:20:505663 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475664 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295665 SetGLError(GL_INVALID_OPERATION,
5666 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:475667 return error::kNoError;
5668 }
[email protected]0226c112011-07-22 03:25:075669
5670 GLsizei tex_width = 0;
5671 GLsizei tex_height = 0;
5672 GLenum tex_type = 0;
5673 GLenum tex_format = 0;
5674 bool level_is_same =
5675 info->GetLevelSize(target, level, &tex_width, &tex_height) &&
5676 info->GetLevelType(target, level, &tex_type, &tex_format) &&
5677 width == tex_width && height == tex_height &&
5678 type == tex_type && format == tex_format;
5679
5680 if (level_is_same && !pixels) {
5681 return error::kNoError;
5682 }
5683
[email protected]a93bb842010-02-16 23:03:475684 scoped_array<int8> zero;
5685 if (!pixels) {
5686 zero.reset(new int8[pixels_size]);
5687 memset(zero.get(), 0, pixels_size);
5688 pixels = zero.get();
5689 }
[email protected]876f6fee2010-08-02 23:10:325690
[email protected]297ca1c2011-06-20 23:08:465691 if (info->IsAttachedToFramebuffer()) {
5692 state_dirty_ = true;
5693 }
5694
[email protected]0226c112011-07-22 03:25:075695 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same) {
5696 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
5697 tex_image_2d_failed_ = false;
5698 return error::kNoError;
[email protected]7488d962010-07-16 02:41:585699 }
[email protected]876f6fee2010-08-02 23:10:325700
[email protected]cadde4a2010-07-31 17:10:435701 CopyRealGLErrorsToWrapper();
[email protected]473c01ccb2011-06-07 01:33:305702 WrappedTexImage2D(
5703 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475704 pixels);
[email protected]1002c2d2011-06-28 22:39:045705 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:435706 if (error == GL_NO_ERROR) {
[email protected]915a59a12010-09-30 21:29:115707 texture_manager()->SetLevelInfo(feature_info_, info,
[email protected]cadde4a2010-07-31 17:10:435708 target, level, internal_format, width, height, 1, border, format, type);
[email protected]b493ee622011-04-13 23:52:005709 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:435710 }
[email protected]f7a64ee2010-02-01 22:24:145711 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195712}
5713
[email protected]f7a64ee2010-02-01 22:24:145714error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195715 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]366ae242011-05-10 02:23:585716 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:005717 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:195718 GLenum target = static_cast<GLenum>(c.target);
5719 GLint level = static_cast<GLint>(c.level);
5720 GLint internal_format = static_cast<GLint>(c.internalformat);
5721 GLsizei width = static_cast<GLsizei>(c.width);
5722 GLsizei height = static_cast<GLsizei>(c.height);
5723 GLint border = static_cast<GLint>(c.border);
5724 GLenum format = static_cast<GLenum>(c.format);
5725 GLenum type = static_cast<GLenum>(c.type);
5726 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
5727 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:185728 uint32 pixels_size;
5729 if (!GLES2Util::ComputeImageDataSize(
5730 width, height, format, type, unpack_alignment_, &pixels_size)) {
5731 return error::kOutOfBounds;
5732 }
[email protected]b9849abf2009-11-25 19:13:195733 const void* pixels = NULL;
5734 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
5735 pixels = GetSharedMemoryAs<const void*>(
5736 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:465737 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145738 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195739 }
5740 }
[email protected]a93bb842010-02-16 23:03:475741 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195742 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475743 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:195744}
5745
[email protected]f7a64ee2010-02-01 22:24:145746error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195747 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
5748 GLenum target = static_cast<GLenum>(c.target);
5749 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:465750 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:195751 GLsizei width = static_cast<GLsizei>(c.width);
5752 GLsizei height = static_cast<GLsizei>(c.height);
5753 GLint border = static_cast<GLint>(c.border);
5754 GLenum format = static_cast<GLenum>(c.format);
5755 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:185756 uint32 size;
5757 if (!GLES2Util::ComputeImageDataSize(
5758 width, height, format, type, unpack_alignment_, &size)) {
5759 return error::kOutOfBounds;
5760 }
[email protected]07f54fcc2009-12-22 02:46:305761 const void* pixels = GetImmediateDataAs<const void*>(
5762 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465763 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145764 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465765 }
[email protected]a93bb842010-02-16 23:03:475766 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:465767 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475768 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:145769 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325770}
5771
[email protected]cadde4a2010-07-31 17:10:435772void GLES2DecoderImpl::DoCompressedTexSubImage2D(
5773 GLenum target,
5774 GLint level,
5775 GLint xoffset,
5776 GLint yoffset,
5777 GLsizei width,
5778 GLsizei height,
5779 GLenum format,
5780 GLsizei image_size,
5781 const void * data) {
5782 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5783 if (!info) {
5784 SetGLError(GL_INVALID_OPERATION,
5785 "glCompressedTexSubImage2D: unknown texture for target");
5786 return;
5787 }
5788 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:525789 GLenum internal_format = 0;
5790 if (!info->GetLevelType(target, level, &type, &internal_format)) {
5791 SetGLError(
5792 GL_INVALID_OPERATION,
5793 "glCompressdTexSubImage2D: level does not exist.");
5794 return;
5795 }
5796 if (internal_format != format) {
5797 SetGLError(
5798 GL_INVALID_OPERATION,
5799 "glCompressdTexSubImage2D: format does not match internal format.");
5800 return;
5801 }
5802 if (!info->ValidForTexture(
5803 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:435804 SetGLError(GL_INVALID_VALUE,
5805 "glCompressdTexSubImage2D: bad dimensions.");
5806 return;
5807 }
5808 glCompressedTexSubImage2D(
5809 target, level, xoffset, yoffset, width, height, format, image_size, data);
5810}
5811
[email protected]6e288612010-12-21 20:45:035812static void Clip(
5813 GLint start, GLint range, GLint sourceRange,
5814 GLint* out_start, GLint* out_range) {
5815 DCHECK(out_start);
5816 DCHECK(out_range);
5817 if (start < 0) {
5818 range += start;
5819 start = 0;
5820 }
5821 GLint end = start + range;
5822 if (end > sourceRange) {
5823 range -= end - sourceRange;
5824 }
5825 *out_start = start;
5826 *out_range = range;
5827}
5828
5829
[email protected]cadde4a2010-07-31 17:10:435830void GLES2DecoderImpl::DoCopyTexImage2D(
5831 GLenum target,
5832 GLint level,
5833 GLenum internal_format,
5834 GLint x,
5835 GLint y,
5836 GLsizei width,
5837 GLsizei height,
5838 GLint border) {
5839 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5840 if (!info) {
5841 SetGLError(GL_INVALID_OPERATION,
5842 "glCopyTexImage2D: unknown texture for target");
5843 return;
5844 }
[email protected]915a59a12010-09-30 21:29:115845 if (!texture_manager()->ValidForTarget(
5846 feature_info_, target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:185847 border != 0) {
5848 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
5849 return;
5850 }
5851
[email protected]9edc6b22010-12-23 02:00:265852 // Check we have compatible formats.
5853 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5854 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5855 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
5856
5857 if ((channels_needed & channels_exist) != channels_needed) {
5858 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
5859 return;
5860 }
5861
[email protected]cadde4a2010-07-31 17:10:435862 CopyRealGLErrorsToWrapper();
[email protected]c0701082011-04-20 00:34:525863 ScopedResolvedFrameBufferBinder binder(this, false);
[email protected]6e288612010-12-21 20:45:035864 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:265865
[email protected]297ca1c2011-06-20 23:08:465866 if (info->IsAttachedToFramebuffer()) {
5867 state_dirty_ = true;
5868 }
5869
[email protected]9edc6b22010-12-23 02:00:265870 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:035871 GLint copyX = 0;
5872 GLint copyY = 0;
5873 GLint copyWidth = 0;
5874 GLint copyHeight = 0;
5875 Clip(x, width, size.width(), &copyX, &copyWidth);
5876 Clip(y, height, size.height(), &copyY, &copyHeight);
5877
5878 if (copyX != x ||
5879 copyY != y ||
5880 copyWidth != width ||
5881 copyHeight != height) {
5882 // some part was clipped so clear the texture.
5883 uint32 pixels_size = 0;
5884 if (!GLES2Util::ComputeImageDataSize(
5885 width, height, internal_format, GL_UNSIGNED_BYTE,
5886 unpack_alignment_, &pixels_size)) {
5887 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions too large");
5888 return;
5889 }
5890 scoped_array<char> zero(new char[pixels_size]);
5891 memset(zero.get(), 0, pixels_size);
5892 glTexImage2D(target, level, internal_format, width, height, 0,
5893 internal_format, GL_UNSIGNED_BYTE, zero.get());
5894 if (copyHeight > 0 && copyWidth > 0) {
5895 GLint dx = copyX - x;
5896 GLint dy = copyY - y;
5897 GLint destX = dx;
5898 GLint destY = dy;
5899 glCopyTexSubImage2D(target, level,
5900 destX, destY, copyX, copyY,
5901 copyWidth, copyHeight);
5902 }
5903 } else {
5904 glCopyTexImage2D(target, level, internal_format,
5905 copyX, copyY, copyWidth, copyHeight, border);
5906 }
[email protected]1002c2d2011-06-28 22:39:045907 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:435908 if (error == GL_NO_ERROR) {
5909 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:115910 feature_info_, info, target, level, internal_format, width, height, 1,
5911 border, internal_format, GL_UNSIGNED_BYTE);
[email protected]cadde4a2010-07-31 17:10:435912 }
5913}
5914
5915void GLES2DecoderImpl::DoCopyTexSubImage2D(
5916 GLenum target,
5917 GLint level,
5918 GLint xoffset,
5919 GLint yoffset,
5920 GLint x,
5921 GLint y,
5922 GLsizei width,
5923 GLsizei height) {
5924 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5925 if (!info) {
5926 SetGLError(GL_INVALID_OPERATION,
5927 "glCopyTexSubImage2D: unknown texture for target");
5928 return;
5929 }
5930 GLenum type = 0;
5931 GLenum format = 0;
5932 if (!info->GetLevelType(target, level, &type, &format) ||
5933 !info->ValidForTexture(
5934 target, level, xoffset, yoffset, width, height, format, type)) {
5935 SetGLError(GL_INVALID_VALUE,
5936 "glCopyTexSubImage2D: bad dimensions.");
5937 return;
5938 }
[email protected]9edc6b22010-12-23 02:00:265939
5940 // Check we have compatible formats.
5941 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5942 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5943 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
5944
5945 if ((channels_needed & channels_exist) != channels_needed) {
5946 SetGLError(
5947 GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
5948 return;
5949 }
5950
[email protected]c0701082011-04-20 00:34:525951 ScopedResolvedFrameBufferBinder binder(this, false);
[email protected]6e288612010-12-21 20:45:035952 gfx::Size size = GetBoundReadFrameBufferSize();
5953 GLint copyX = 0;
5954 GLint copyY = 0;
5955 GLint copyWidth = 0;
5956 GLint copyHeight = 0;
5957 Clip(x, width, size.width(), &copyX, &copyWidth);
5958 Clip(y, height, size.height(), &copyY, &copyHeight);
5959 if (copyX != x ||
5960 copyY != y ||
5961 copyWidth != width ||
5962 copyHeight != height) {
5963 // some part was clipped so clear the texture.
5964 uint32 pixels_size = 0;
5965 if (!GLES2Util::ComputeImageDataSize(
5966 width, height, format, type, unpack_alignment_, &pixels_size)) {
5967 SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large");
5968 return;
5969 }
5970 scoped_array<char> zero(new char[pixels_size]);
5971 memset(zero.get(), 0, pixels_size);
5972 glTexSubImage2D(
5973 target, level, xoffset, yoffset, width, height,
5974 format, type, zero.get());
5975 }
5976 if (copyHeight > 0 && copyWidth > 0) {
5977 GLint dx = copyX - x;
5978 GLint dy = copyY - y;
5979 GLint destX = xoffset + dx;
5980 GLint destY = yoffset + dy;
5981 glCopyTexSubImage2D(target, level,
5982 destX, destY, copyX, copyY,
5983 copyWidth, copyHeight);
5984 }
[email protected]cadde4a2010-07-31 17:10:435985}
5986
5987void GLES2DecoderImpl::DoTexSubImage2D(
5988 GLenum target,
5989 GLint level,
5990 GLint xoffset,
5991 GLint yoffset,
5992 GLsizei width,
5993 GLsizei height,
5994 GLenum format,
5995 GLenum type,
5996 const void * data) {
5997 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5998 if (!info) {
5999 SetGLError(GL_INVALID_OPERATION,
6000 "glTexSubImage2D: unknown texture for target");
6001 return;
6002 }
[email protected]df6cf1ad2011-01-29 01:20:526003 GLenum current_type = 0;
6004 GLenum internal_format = 0;
6005 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
6006 SetGLError(
6007 GL_INVALID_OPERATION,
6008 "glTexSubImage2D: level does not exist.");
6009 return;
6010 }
6011 if (format != internal_format) {
6012 SetGLError(GL_INVALID_OPERATION,
6013 "glTexSubImage2D: format does not match internal format.");
6014 return;
6015 }
6016 if (type != current_type) {
6017 SetGLError(GL_INVALID_OPERATION,
6018 "glTexSubImage2D: type does not match type of texture.");
6019 return;
6020 }
6021
[email protected]cadde4a2010-07-31 17:10:436022 if (!info->ValidForTexture(
6023 target, level, xoffset, yoffset, width, height, format, type)) {
6024 SetGLError(GL_INVALID_VALUE,
6025 "glTexSubImage2D: bad dimensions.");
6026 return;
6027 }
[email protected]473c01ccb2011-06-07 01:33:306028
6029 // See if we can call glTexImage2D instead since it appears to be faster.
6030 if (teximage2d_faster_than_texsubimage2d_ && xoffset == 0 && yoffset == 0) {
6031 GLsizei tex_width = 0;
6032 GLsizei tex_height = 0;
6033 bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height);
6034 DCHECK(ok);
6035 if (width == tex_width && height == tex_height) {
6036 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
6037 // same as internal_foramt. If that changes we'll need to look them up.
6038 WrappedTexImage2D(
6039 target, level, format, width, height, 0, format, type, data);
6040 return;
6041 }
6042 }
[email protected]cadde4a2010-07-31 17:10:436043 glTexSubImage2D(
6044 target, level, xoffset, yoffset, width, height, format, type, data);
6045}
6046
[email protected]b493ee622011-04-13 23:52:006047error::Error GLES2DecoderImpl::HandleTexSubImage2D(
6048 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]366ae242011-05-10 02:23:586049 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:006050 GLboolean internal = static_cast<GLboolean>(c.internal);
6051 if (internal == GL_TRUE && tex_image_2d_failed_)
6052 return error::kNoError;
6053
6054 GLenum target = static_cast<GLenum>(c.target);
6055 GLint level = static_cast<GLint>(c.level);
6056 GLint xoffset = static_cast<GLint>(c.xoffset);
6057 GLint yoffset = static_cast<GLint>(c.yoffset);
6058 GLsizei width = static_cast<GLsizei>(c.width);
6059 GLsizei height = static_cast<GLsizei>(c.height);
6060 GLenum format = static_cast<GLenum>(c.format);
6061 GLenum type = static_cast<GLenum>(c.type);
6062 uint32 data_size;
6063 if (!GLES2Util::ComputeImageDataSize(
6064 width, height, format, type, unpack_alignment_, &data_size)) {
6065 return error::kOutOfBounds;
6066 }
6067 const void* pixels = GetSharedMemoryAs<const void*>(
6068 c.pixels_shm_id, c.pixels_shm_offset, data_size);
6069 if (!validators_->texture_target.IsValid(target)) {
6070 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
6071 return error::kNoError;
6072 }
6073 if (width < 0) {
6074 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
6075 return error::kNoError;
6076 }
6077 if (height < 0) {
6078 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
6079 return error::kNoError;
6080 }
6081 if (!validators_->texture_format.IsValid(format)) {
6082 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
6083 return error::kNoError;
6084 }
6085 if (!validators_->pixel_type.IsValid(type)) {
6086 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
6087 return error::kNoError;
6088 }
6089 if (pixels == NULL) {
6090 return error::kOutOfBounds;
6091 }
6092 DoTexSubImage2D(
6093 target, level, xoffset, yoffset, width, height, format, type, pixels);
6094 return error::kNoError;
6095}
6096
6097error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
6098 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
6099 GLboolean internal = static_cast<GLboolean>(c.internal);
6100 if (internal == GL_TRUE && tex_image_2d_failed_)
6101 return error::kNoError;
6102
6103 GLenum target = static_cast<GLenum>(c.target);
6104 GLint level = static_cast<GLint>(c.level);
6105 GLint xoffset = static_cast<GLint>(c.xoffset);
6106 GLint yoffset = static_cast<GLint>(c.yoffset);
6107 GLsizei width = static_cast<GLsizei>(c.width);
6108 GLsizei height = static_cast<GLsizei>(c.height);
6109 GLenum format = static_cast<GLenum>(c.format);
6110 GLenum type = static_cast<GLenum>(c.type);
6111 uint32 data_size;
6112 if (!GLES2Util::ComputeImageDataSize(
6113 width, height, format, type, unpack_alignment_, &data_size)) {
6114 return error::kOutOfBounds;
6115 }
6116 const void* pixels = GetImmediateDataAs<const void*>(
6117 c, data_size, immediate_data_size);
6118 if (!validators_->texture_target.IsValid(target)) {
6119 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
6120 return error::kNoError;
6121 }
6122 if (width < 0) {
6123 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
6124 return error::kNoError;
6125 }
6126 if (height < 0) {
6127 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
6128 return error::kNoError;
6129 }
6130 if (!validators_->texture_format.IsValid(format)) {
6131 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
6132 return error::kNoError;
6133 }
6134 if (!validators_->pixel_type.IsValid(type)) {
6135 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
6136 return error::kNoError;
6137 }
6138 if (pixels == NULL) {
6139 return error::kOutOfBounds;
6140 }
6141 DoTexSubImage2D(
6142 target, level, xoffset, yoffset, width, height, format, type, pixels);
6143 return error::kNoError;
6144}
6145
[email protected]f7a64ee2010-02-01 22:24:146146error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:196147 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:366148 GLuint index = static_cast<GLuint>(c.index);
6149 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:256150 typedef gles2::GetVertexAttribPointerv::Result Result;
6151 Result* result = GetSharedMemoryAs<Result*>(
6152 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:366153 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:146154 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:366155 }
[email protected]07d0cc82010-02-17 04:51:406156 // Check that the client initialized the result.
6157 if (result->size != 0) {
6158 return error::kInvalidArguments;
6159 }
[email protected]9438b012010-06-15 22:55:056160 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:296161 SetGLError(GL_INVALID_ENUM,
6162 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:146163 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:366164 }
[email protected]3916c97e2010-02-25 03:20:506165 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:296166 SetGLError(GL_INVALID_VALUE,
6167 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:146168 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:366169 }
[email protected]0bfd9882010-02-05 23:02:256170 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:086171 *result->GetData() =
6172 vertex_attrib_manager_.GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:146173 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326174}
6175
[email protected]f7b85372010-02-03 01:11:376176bool GLES2DecoderImpl::GetUniformSetup(
6177 GLuint program, GLint location,
6178 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:106179 error::Error* error, GLuint* service_id, void** result_pointer,
6180 GLenum* result_type) {
6181 DCHECK(error);
6182 DCHECK(service_id);
6183 DCHECK(result_pointer);
6184 DCHECK(result_type);
[email protected]f7b85372010-02-03 01:11:376185 *error = error::kNoError;
6186 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:256187 SizedResult<GLint>* result;
6188 result = GetSharedMemoryAs<SizedResult<GLint>*>(
6189 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
6190 if (!result) {
[email protected]f7b85372010-02-03 01:11:376191 *error = error::kOutOfBounds;
6192 return false;
6193 }
[email protected]0bfd9882010-02-05 23:02:256194 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:376195 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:256196 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:586197 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6198 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:376199 if (!info) {
[email protected]ae51d192010-04-27 00:48:036200 return false;
6201 }
6202 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:376203 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:296204 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:376205 return false;
6206 }
[email protected]ae51d192010-04-27 00:48:036207 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:366208 GLint array_index = -1;
6209 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
6210 info->GetUniformInfoByLocation(location, &array_index);
6211 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:376212 // No such location.
[email protected]8eee29c2010-04-29 03:38:296213 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:376214 return false;
6215 }
[email protected]43c2f1f2011-03-25 18:35:366216 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:506217 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:376218 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:296219 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:376220 return false;
6221 }
[email protected]0bfd9882010-02-05 23:02:256222 result = GetSharedMemoryAs<SizedResult<GLint>*>(
6223 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
6224 if (!result) {
[email protected]f7b85372010-02-03 01:11:376225 *error = error::kOutOfBounds;
6226 return false;
6227 }
[email protected]0bfd9882010-02-05 23:02:256228 result->size = size;
[email protected]939e7362010-05-13 20:49:106229 *result_type = type;
[email protected]f7b85372010-02-03 01:11:376230 return true;
6231}
6232
[email protected]f7a64ee2010-02-01 22:24:146233error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:196234 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:376235 GLuint program = c.program;
6236 GLint location = c.location;
6237 GLuint service_id;
[email protected]939e7362010-05-13 20:49:106238 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:376239 Error error;
[email protected]0bfd9882010-02-05 23:02:256240 void* result;
[email protected]f7b85372010-02-03 01:11:376241 if (GetUniformSetup(
6242 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:106243 &error, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:256244 glGetUniformiv(
6245 service_id, location,
6246 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:376247 }
6248 return error;
[email protected]96449d2c2009-11-25 00:01:326249}
6250
[email protected]f7a64ee2010-02-01 22:24:146251error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:196252 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:376253 GLuint program = c.program;
6254 GLint location = c.location;
6255 GLuint service_id;
6256 Error error;
[email protected]0bfd9882010-02-05 23:02:256257 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:106258 Result* result;
6259 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:376260 if (GetUniformSetup(
6261 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:106262 &error, &service_id, reinterpret_cast<void**>(&result), &result_type)) {
6263 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
6264 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
6265 GLsizei num_values = result->GetNumResults();
6266 scoped_array<GLint> temp(new GLint[num_values]);
6267 glGetUniformiv(service_id, location, temp.get());
6268 GLfloat* dst = result->GetData();
6269 for (GLsizei ii = 0; ii < num_values; ++ii) {
6270 dst[ii] = (temp[ii] != 0);
6271 }
6272 } else {
6273 glGetUniformfv(service_id, location, result->GetData());
6274 }
[email protected]f7b85372010-02-03 01:11:376275 }
6276 return error;
[email protected]96449d2c2009-11-25 00:01:326277}
6278
[email protected]f7a64ee2010-02-01 22:24:146279error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:196280 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:256281 GLenum shader_type = static_cast<GLenum>(c.shadertype);
6282 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
6283 typedef gles2::GetShaderPrecisionFormat::Result Result;
6284 Result* result = GetSharedMemoryAs<Result*>(
6285 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6286 if (!result) {
6287 return error::kOutOfBounds;
6288 }
[email protected]07d0cc82010-02-17 04:51:406289 // Check that the client initialized the result.
6290 if (result->success != 0) {
6291 return error::kInvalidArguments;
6292 }
[email protected]9438b012010-06-15 22:55:056293 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:296294 SetGLError(GL_INVALID_ENUM,
6295 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
6296 return error::kNoError;
6297 }
[email protected]9438b012010-06-15 22:55:056298 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:296299 SetGLError(GL_INVALID_ENUM,
6300 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
6301 return error::kNoError;
6302 }
6303
6304 result->success = 1; // true
6305 switch (precision_type) {
6306 case GL_LOW_INT:
6307 case GL_MEDIUM_INT:
6308 case GL_HIGH_INT:
6309 result->min_range = -31;
6310 result->max_range = 31;
6311 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:106312 break;
[email protected]8eee29c2010-04-29 03:38:296313 case GL_LOW_FLOAT:
6314 case GL_MEDIUM_FLOAT:
6315 case GL_HIGH_FLOAT:
6316 result->min_range = -62;
6317 result->max_range = 62;
6318 result->precision = -16;
6319 break;
6320 default:
6321 NOTREACHED();
6322 break;
[email protected]0bfd9882010-02-05 23:02:256323 }
[email protected]f7a64ee2010-02-01 22:24:146324 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326325}
6326
[email protected]f7a64ee2010-02-01 22:24:146327error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:196328 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:256329 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:586330 GLuint program = static_cast<GLuint>(c.program);
6331 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6332 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:036333 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256334 return error::kNoError;
6335 }
6336 typedef gles2::GetAttachedShaders::Result Result;
6337 uint32 max_count = Result::ComputeMaxResults(result_size);
6338 Result* result = GetSharedMemoryAs<Result*>(
6339 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
6340 if (!result) {
6341 return error::kOutOfBounds;
6342 }
[email protected]07d0cc82010-02-17 04:51:406343 // Check that the client initialized the result.
6344 if (result->size != 0) {
6345 return error::kInvalidArguments;
6346 }
[email protected]0bfd9882010-02-05 23:02:256347 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:036348 glGetAttachedShaders(
6349 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:256350 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:036351 if (!shader_manager()->GetClientId(result->GetData()[ii],
6352 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:256353 NOTREACHED();
6354 return error::kGenericError;
6355 }
6356 }
6357 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:146358 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326359}
6360
[email protected]f7a64ee2010-02-01 22:24:146361error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:196362 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:256363 GLuint program = c.program;
6364 GLuint index = c.index;
6365 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:256366 typedef gles2::GetActiveUniform::Result Result;
6367 Result* result = GetSharedMemoryAs<Result*>(
6368 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6369 if (!result) {
6370 return error::kOutOfBounds;
6371 }
[email protected]07d0cc82010-02-17 04:51:406372 // Check that the client initialized the result.
6373 if (result->success != 0) {
6374 return error::kInvalidArguments;
6375 }
[email protected]6b8cf1a2010-05-06 16:13:586376 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6377 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:036378 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256379 return error::kNoError;
6380 }
6381 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
6382 info->GetUniformInfo(index);
6383 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:296384 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:256385 return error::kNoError;
6386 }
6387 result->success = 1; // true.
6388 result->size = uniform_info->size;
6389 result->type = uniform_info->type;
6390 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:296391 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:146392 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326393}
6394
[email protected]f7a64ee2010-02-01 22:24:146395error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:196396 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:256397 GLuint program = c.program;
6398 GLuint index = c.index;
6399 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:256400 typedef gles2::GetActiveAttrib::Result Result;
6401 Result* result = GetSharedMemoryAs<Result*>(
6402 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6403 if (!result) {
6404 return error::kOutOfBounds;
6405 }
[email protected]07d0cc82010-02-17 04:51:406406 // Check that the client initialized the result.
6407 if (result->success != 0) {
6408 return error::kInvalidArguments;
6409 }
[email protected]6b8cf1a2010-05-06 16:13:586410 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6411 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:036412 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256413 return error::kNoError;
6414 }
6415 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
6416 info->GetAttribInfo(index);
6417 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:296418 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:256419 return error::kNoError;
6420 }
6421 result->success = 1; // true.
6422 result->size = attrib_info->size;
6423 result->type = attrib_info->type;
6424 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:296425 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:146426 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326427}
6428
[email protected]b273e432010-04-12 17:23:586429error::Error GLES2DecoderImpl::HandleShaderBinary(
6430 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
6431#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:296432 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:586433 return error::kNoError;
6434#else
6435 GLsizei n = static_cast<GLsizei>(c.n);
6436 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:296437 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:586438 return error::kNoError;
6439 }
6440 GLsizei length = static_cast<GLsizei>(c.length);
6441 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:296442 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:586443 return error::kNoError;
6444 }
6445 uint32 data_size;
6446 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
6447 return error::kOutOfBounds;
6448 }
6449 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
6450 c.shaders_shm_id, c.shaders_shm_offset, data_size);
6451 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
6452 const void* binary = GetSharedMemoryAs<const void*>(
6453 c.binary_shm_id, c.binary_shm_offset, length);
6454 if (shaders == NULL || binary == NULL) {
6455 return error::kOutOfBounds;
6456 }
6457 scoped_array<GLuint> service_ids(new GLuint[n]);
6458 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:036459 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
6460 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296461 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:586462 return error::kNoError;
6463 }
[email protected]ae51d192010-04-27 00:48:036464 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:586465 }
6466 // TODO(gman): call glShaderBinary
6467 return error::kNoError;
6468#endif
6469}
6470
[email protected]6217d392010-03-25 22:08:356471error::Error GLES2DecoderImpl::HandleSwapBuffers(
6472 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:496473 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
6474 int this_frame_number = frame_number_++;
6475 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
6476 "offscreen", is_offscreen,
6477 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:356478 // If offscreen then don't actually SwapBuffers to the display. Just copy
6479 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:496480 if (is_offscreen) {
[email protected]6217d392010-03-25 22:08:356481 ScopedGLErrorSuppressor suppressor(this);
6482
6483 // First check to see if a deferred offscreen render buffer resize is
6484 // pending.
[email protected]d0498742010-09-20 20:27:016485 if (!UpdateOffscreenFrameBufferSize()) {
6486 LOG(ERROR) << "Context lost because reallocation of offscreen FBO "
6487 << "failed.";
[email protected]6217d392010-03-25 22:08:356488 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:016489 }
[email protected]6217d392010-03-25 22:08:356490
[email protected]34ff8b0c2010-10-01 20:06:026491 if (IsOffscreenBufferMultisampled()) {
6492 // For multisampled buffers, bind the resolved frame buffer so that
6493 // callbacks can call ReadPixels or CopyTexImage2D.
[email protected]c0701082011-04-20 00:34:526494 ScopedResolvedFrameBufferBinder binder(this, true);
[email protected]34ff8b0c2010-10-01 20:06:026495 if (swap_buffers_callback_.get()) {
6496 swap_buffers_callback_->Run();
6497 }
[email protected]89d6ed02011-04-20 00:23:236498 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:486499 } else {
[email protected]0c8c9d22010-06-25 17:36:396500 ScopedFrameBufferBinder binder(this,
6501 offscreen_target_frame_buffer_->id());
[email protected]c007aa02010-09-02 22:22:406502
[email protected]9a5afa432011-07-22 18:16:396503 if (surface_->IsOffscreen()) {
[email protected]b86b14982010-10-11 18:45:486504 // Copy the target frame buffer to the saved offscreen texture.
6505 offscreen_saved_color_texture_->Copy(
[email protected]3a4d0c52011-06-29 23:11:586506 offscreen_saved_color_texture_->size(),
6507 offscreen_saved_color_format_);
[email protected]b86b14982010-10-11 18:45:486508
[email protected]a3ded6d2010-10-19 06:44:396509 // Ensure the side effects of the copy are visible to the parent
6510 // context. There is no need to do this for ANGLE because it uses a
6511 // single D3D device for all contexts.
[email protected]b86b14982010-10-11 18:45:486512 if (!IsAngle())
6513 glFlush();
6514 }
6515
6516 // Run the callback with |binder| in scope, so that the callback can call
6517 // ReadPixels or CopyTexImage2D.
6518 if (swap_buffers_callback_.get()) {
6519 swap_buffers_callback_->Run();
6520 }
[email protected]89d6ed02011-04-20 00:23:236521 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:396522 }
[email protected]6217d392010-03-25 22:08:356523 } else {
[email protected]64ace852011-05-19 21:49:496524 TRACE_EVENT1("gpu", "GLContext::SwapBuffers", "frame", this_frame_number);
[email protected]f62a5ab2011-05-23 20:34:156525 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:016526 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:026527 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:016528 }
[email protected]6217d392010-03-25 22:08:356529 }
6530
6531 if (swap_buffers_callback_.get()) {
6532 swap_buffers_callback_->Run();
6533 }
6534
[email protected]89d6ed02011-04-20 00:23:236535 return error::kNoError;
[email protected]6217d392010-03-25 22:08:356536}
6537
[email protected]269200b12010-11-18 22:53:066538error::Error GLES2DecoderImpl::HandleCommandBufferEnableCHROMIUM(
6539 uint32 immediate_data_size, const gles2::CommandBufferEnableCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:186540 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]269200b12010-11-18 22:53:066541 typedef gles2::CommandBufferEnableCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:186542 Result* result = GetSharedMemoryAs<Result*>(
6543 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6544 if (!result) {
6545 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:106546 }
[email protected]b1d2dcb2010-05-17 19:24:186547 // Check that the client initialized the result.
6548 if (*result != 0) {
6549 return error::kInvalidArguments;
6550 }
6551 std::string feature_str;
6552 if (!bucket->GetAsString(&feature_str)) {
6553 return error::kInvalidArguments;
6554 }
6555
6556 // TODO(gman): make this some kind of table to function pointer thingy.
6557 if (feature_str.compare(PEPPER3D_ALLOW_BUFFERS_ON_MULTIPLE_TARGETS) == 0) {
6558 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]8fbedc02010-11-18 18:43:406559 } else if (feature_str.compare(PEPPER3D_SUPPORT_FIXED_ATTRIBS) == 0) {
6560 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
6561 // TODO(gman): decide how to remove the need for this const_cast.
6562 // I could make validators_ non const but that seems bad as this is the only
6563 // place it is needed. I could make some special friend class of validators
6564 // just to allow this to set them. That seems silly. I could refactor this
6565 // code to use the extension mechanism or the initialization attributes to
6566 // turn this feature on. Given that the only real point of this is to make
6567 // the conformance tests pass and given that there is lots of real work that
6568 // needs to be done it seems like refactoring for one to one of those
6569 // methods is a very low priority.
6570 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]b1d2dcb2010-05-17 19:24:186571 } else if (feature_str.compare(PEPPER3D_SKIP_GLSL_TRANSLATION) == 0) {
6572 use_shader_translator_ = false;
6573 } else {
6574 return error::kNoError;
6575 }
6576
6577 *result = 1; // true.
6578 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:106579}
6580
[email protected]c2f8c8402010-12-06 18:07:246581error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
6582 uint32 immediate_data_size,
6583 const gles2::GetRequestableExtensionsCHROMIUM& c) {
6584 Bucket* bucket = CreateBucket(c.bucket_id);
6585 scoped_ptr<FeatureInfo> info(new FeatureInfo());
[email protected]c410da802011-03-14 19:17:416586 info->Initialize(disallowed_extensions_, NULL);
[email protected]c2f8c8402010-12-06 18:07:246587 bucket->SetFromString(info->extensions().c_str());
6588 return error::kNoError;
6589}
6590
6591error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
6592 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
6593 Bucket* bucket = GetBucket(c.bucket_id);
6594 std::string feature_str;
6595 if (!bucket->GetAsString(&feature_str)) {
6596 return error::kInvalidArguments;
6597 }
6598
6599 bool std_derivatives_enabled =
6600 feature_info_->feature_flags().oes_standard_derivatives;
6601 bool webglsl_enabled =
6602 feature_info_->feature_flags().chromium_webglsl;
6603
6604 feature_info_->AddFeatures(feature_str.c_str());
6605
6606 // If we just enabled a feature which affects the shader translator,
6607 // we may need to re-initialize it.
6608 if (std_derivatives_enabled !=
6609 feature_info_->feature_flags().oes_standard_derivatives ||
6610 webglsl_enabled !=
6611 feature_info_->feature_flags().chromium_webglsl) {
6612 InitializeShaderTranslator();
6613 }
6614
[email protected]302ce6d2011-07-07 23:28:116615 UpdateCapabilities();
6616
[email protected]c2f8c8402010-12-06 18:07:246617 return error::kNoError;
6618}
6619
[email protected]372e0412011-06-28 16:08:566620error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
6621 uint32 immediate_data_size, const gles2::GetMultipleIntegervCHROMIUM& c) {
6622 GLuint count = c.count;
6623 uint32 pnames_size;
6624 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
6625 return error::kOutOfBounds;
6626 }
6627 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
6628 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
6629 if (pnames == NULL) {
6630 return error::kOutOfBounds;
6631 }
6632
6633 // We have to copy them since we use them twice so the client
6634 // can't change them between the time we validate them and the time we use
6635 // them.
6636 scoped_array<GLenum> enums(new GLenum[count]);
6637 memcpy(enums.get(), pnames, pnames_size);
6638
6639 // Count up the space needed for the result.
6640 uint32 num_results = 0;
6641 for (GLuint ii = 0; ii < count; ++ii) {
6642 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
6643 if (num == 0) {
6644 SetGLError(GL_INVALID_ENUM,
6645 "glGetMulitpleCHROMIUM: pname GL_INVALID_ENUM");
6646 return error::kNoError;
6647 }
6648 // Num will never be more than 4.
6649 DCHECK_LE(num, 4u);
6650 if (!SafeAdd(num_results, num, &num_results)) {
6651 return error::kOutOfBounds;
6652 }
6653 }
6654
6655 uint32 result_size = 0;
6656 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
6657 return error::kOutOfBounds;
6658 }
6659
6660 if (result_size != static_cast<uint32>(c.size)) {
6661 SetGLError(GL_INVALID_VALUE,
6662 "glGetMulitpleCHROMIUM: bad size GL_INVALID_VALUE");
6663 return error::kNoError;
6664 }
6665
6666 GLint* results = GetSharedMemoryAs<GLint*>(
6667 c.results_shm_id, c.results_shm_offset, result_size);
6668 if (results == NULL) {
6669 return error::kOutOfBounds;
6670 }
6671
6672 // Check the results have been cleared in case the context was lost.
6673 for (uint32 ii = 0; ii < num_results; ++ii) {
6674 if (results[ii]) {
6675 return error::kInvalidArguments;
6676 }
6677 }
6678
6679 // Get each result.
6680 GLint* start = results;
6681 for (GLuint ii = 0; ii < count; ++ii) {
6682 GLsizei num_written = 0;
6683 if (!GetHelper(enums[ii], results, &num_written)) {
6684 glGetIntegerv(enums[ii], results);
6685 }
6686 results += num_written;
6687 }
6688
6689 // Just to verify. Should this be a DCHECK?
6690 if (static_cast<uint32>(results - start) != num_results) {
6691 return error::kOutOfBounds;
6692 }
6693
6694 return error::kNoError;
6695}
6696
[email protected]2318d342011-07-11 22:27:426697error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
6698 uint32 immediate_data_size, const gles2::GetProgramInfoCHROMIUM& c) {
6699 GLuint program = static_cast<GLuint>(c.program);
6700 uint32 bucket_id = c.bucket_id;
6701 Bucket* bucket = CreateBucket(bucket_id);
6702 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
6703 ProgramManager::ProgramInfo* info = NULL;
6704 if (program) {
6705 info = GetProgramInfoNotShader(program, "glGetProgramInfoCHROMIUM");
6706 if (!info) {
6707 return error::kNoError;
6708 }
6709 if (!info->IsValid()) {
6710 // Program was not linked successfully. (ie, glLinkProgram)
6711 SetGLError(GL_INVALID_OPERATION,
6712 "glGetProgramInfoCHROMIUM: program not linked");
6713 return error::kNoError;
6714 }
6715 }
6716 info->GetProgramInfo(bucket);
6717 return error::kNoError;
6718}
6719
[email protected]38d139d2011-07-14 00:38:436720error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
6721 switch (reset_status_) {
6722 case GL_NO_ERROR:
6723 // TODO(kbr): improve the precision of the error code in this case.
6724 // Consider delegating to context for error code if MakeCurrent fails.
6725 return error::kUnknown;
6726 case GL_GUILTY_CONTEXT_RESET_ARB:
6727 return error::kGuilty;
6728 case GL_INNOCENT_CONTEXT_RESET_ARB:
6729 return error::kInnocent;
6730 case GL_UNKNOWN_CONTEXT_RESET_ARB:
6731 return error::kUnknown;
6732 }
6733
6734 NOTREACHED();
6735 return error::kUnknown;
6736}
6737
6738bool GLES2DecoderImpl::WasContextLost() {
6739 if (context_->WasAllocatedUsingARBRobustness() && has_arb_robustness_) {
6740 GLenum status = glGetGraphicsResetStatusARB();
6741 if (status != GL_NO_ERROR) {
6742 // The graphics card was reset. Signal a lost context to the application.
6743 reset_status_ = status;
6744 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
6745 << " context lost via ARB_robustness. Reset status = 0x"
6746 << std::hex << status << std::dec;
6747 return true;
6748 }
6749 }
6750 return false;
6751}
6752
[email protected]96449d2c2009-11-25 00:01:326753// Include the auto-generated part of this file. We split this because it means
6754// we can easily edit the non-auto generated parts right here in this file
6755// instead of having to edit some template or the code generator.
6756#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
6757
6758} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:256759} // namespace gpu