blob: 1dd1bfdee5b7a6948de1566c18705ab32892c0af [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,
[email protected]de26b3c2011-08-03 21:54:27222// if it is bound or enforce_internal_framebuffer is true. If internal is
223// true, the resolved framebuffer is not visible to the parent.
[email protected]34ff8b0c2010-10-01 20:06:02224class ScopedResolvedFrameBufferBinder {
225 public:
[email protected]e7e38032011-07-26 17:25:25226 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
[email protected]de26b3c2011-08-03 21:54:27227 bool enforce_internal_framebuffer,
228 bool internal);
[email protected]34ff8b0c2010-10-01 20:06:02229 ~ScopedResolvedFrameBufferBinder();
230
231 private:
232 GLES2DecoderImpl* decoder_;
233 bool resolve_and_bind_;
234 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
235};
236
[email protected]6217d392010-03-25 22:08:35237// Encapsulates an OpenGL texture.
238class Texture {
239 public:
240 explicit Texture(GLES2DecoderImpl* decoder);
241 ~Texture();
242
243 // Create a new render texture.
244 void Create();
245
246 // Set the initial size and format of a render texture or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02247 bool AllocateStorage(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35248
249 // Copy the contents of the currently bound frame buffer.
[email protected]3a4d0c52011-06-29 23:11:58250 void Copy(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35251
252 // Destroy the render texture. This must be explicitly called before
253 // destroying this object.
254 void Destroy();
255
[email protected]97872062010-11-03 19:07:05256 // Invalidate the texture. This can be used when a context is lost and it is
257 // not possible to make it current in order to free the resource.
258 void Invalidate();
259
[email protected]6217d392010-03-25 22:08:35260 GLuint id() const {
261 return id_;
262 }
263
[email protected]d37231fa2010-04-09 21:16:02264 gfx::Size size() const {
265 return size_;
266 }
267
[email protected]6217d392010-03-25 22:08:35268 private:
269 GLES2DecoderImpl* decoder_;
270 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02271 gfx::Size size_;
[email protected]6217d392010-03-25 22:08:35272 DISALLOW_COPY_AND_ASSIGN(Texture);
273};
274
275// Encapsulates an OpenGL render buffer of any format.
276class RenderBuffer {
277 public:
278 explicit RenderBuffer(GLES2DecoderImpl* decoder);
279 ~RenderBuffer();
280
281 // Create a new render buffer.
282 void Create();
283
284 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02285 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35286
287 // Destroy the render buffer. This must be explicitly called before destroying
288 // this object.
289 void Destroy();
290
[email protected]97872062010-11-03 19:07:05291 // Invalidate the render buffer. This can be used when a context is lost and
292 // it is not possible to make it current in order to free the resource.
293 void Invalidate();
294
[email protected]6217d392010-03-25 22:08:35295 GLuint id() const {
296 return id_;
297 }
298
299 private:
300 GLES2DecoderImpl* decoder_;
301 GLuint id_;
302 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
303};
304
305// Encapsulates an OpenGL frame buffer.
306class FrameBuffer {
307 public:
308 explicit FrameBuffer(GLES2DecoderImpl* decoder);
309 ~FrameBuffer();
310
311 // Create a new frame buffer.
312 void Create();
313
314 // Attach a color render buffer to a frame buffer.
315 void AttachRenderTexture(Texture* texture);
316
[email protected]b9363b22010-06-09 22:06:15317 // Attach a render buffer to a frame buffer. Note that this unbinds any
318 // currently bound frame buffer.
319 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35320
321 // Clear the given attached buffers.
322 void Clear(GLbitfield buffers);
323
324 // Destroy the frame buffer. This must be explicitly called before destroying
325 // this object.
326 void Destroy();
327
[email protected]97872062010-11-03 19:07:05328 // Invalidate the frame buffer. This can be used when a context is lost and it
329 // is not possible to make it current in order to free the resource.
330 void Invalidate();
331
[email protected]6217d392010-03-25 22:08:35332 // See glCheckFramebufferStatusEXT.
333 GLenum CheckStatus();
334
335 GLuint id() const {
336 return id_;
337 }
338
339 private:
340 GLES2DecoderImpl* decoder_;
341 GLuint id_;
342 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
343};
[email protected]34ff8b0c2010-10-01 20:06:02344
345class ContextCreationAttribParser {
346 public:
347 ContextCreationAttribParser();
348 bool Parse(const std::vector<int32>& attribs);
349
350 // -1 if invalid or unspecified.
351 int32 alpha_size_;
352 int32 blue_size_;
353 int32 green_size_;
354 int32 red_size_;
355 int32 depth_size_;
356 int32 stencil_size_;
357 int32 samples_;
358 int32 sample_buffers_;
359};
360
361ContextCreationAttribParser::ContextCreationAttribParser()
362 : alpha_size_(-1),
363 blue_size_(-1),
364 green_size_(-1),
365 red_size_(-1),
366 depth_size_(-1),
367 stencil_size_(-1),
368 samples_(-1),
369 sample_buffers_(-1) {
370}
371
372bool ContextCreationAttribParser::Parse(const std::vector<int32>& attribs) {
373 // From <EGL/egl.h>.
374 const int32 EGL_ALPHA_SIZE = 0x3021;
375 const int32 EGL_BLUE_SIZE = 0x3022;
376 const int32 EGL_GREEN_SIZE = 0x3023;
377 const int32 EGL_RED_SIZE = 0x3024;
378 const int32 EGL_DEPTH_SIZE = 0x3025;
379 const int32 EGL_STENCIL_SIZE = 0x3026;
380 const int32 EGL_SAMPLES = 0x3031;
381 const int32 EGL_SAMPLE_BUFFERS = 0x3032;
382 const int32 EGL_NONE = 0x3038;
383
384 for (size_t i = 0; i < attribs.size(); i += 2) {
385 const int32 attrib = attribs[i];
386 if (i + 1 >= attribs.size()) {
387 if (attrib == EGL_NONE)
388 return true;
389
390 DLOG(ERROR) << "Missing value after context creation attribute: "
391 << attrib;
392 return false;
393 }
394
395 const int32 value = attribs[i+1];
396 switch (attrib) {
397 case EGL_ALPHA_SIZE:
398 alpha_size_ = value;
399 break;
400 case EGL_BLUE_SIZE:
401 blue_size_ = value;
402 break;
403 case EGL_GREEN_SIZE:
404 green_size_ = value;
405 break;
406 case EGL_RED_SIZE:
407 red_size_ = value;
408 break;
409 case EGL_DEPTH_SIZE:
410 depth_size_ = value;
411 break;
412 case EGL_STENCIL_SIZE:
413 stencil_size_ = value;
414 break;
415 case EGL_SAMPLES:
416 samples_ = value;
417 break;
418 case EGL_SAMPLE_BUFFERS:
419 sample_buffers_ = value;
420 break;
421 case EGL_NONE:
422 // Terminate list, even if more attributes.
423 return true;
424 default:
425 DLOG(ERROR) << "Invalid context creation attribute: " << attrib;
426 return false;
427 }
428 }
429
430 return true;
431}
432
[email protected]43f28f832010-02-03 02:28:48433// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32434
[email protected]ddb1e5a2010-12-13 20:10:45435bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
436 uint32* service_texture_id) {
437 return false;
438}
439
[email protected]a3ded6d2010-10-19 06:44:39440GLES2Decoder::GLES2Decoder()
441 : debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32442}
443
[email protected]3916c97e2010-02-25 03:20:50444GLES2Decoder::~GLES2Decoder() {
445}
446
[email protected]f39f4b3f2010-05-12 17:04:08447// This class implements GLES2Decoder so we don't have to expose all the GLES2
448// cmd stuff to outside this class.
449class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
450 public GLES2Decoder {
451 public:
[email protected]e7e38032011-07-26 17:25:25452 GLES2DecoderImpl(SurfaceManager* surface_manager, ContextGroup* group);
[email protected]f39f4b3f2010-05-12 17:04:08453
[email protected]96449d2c2009-11-25 00:01:32454 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14455 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50456 unsigned int arg_count,
457 const void* args);
[email protected]96449d2c2009-11-25 00:01:32458
459 // Overridden from AsyncAPIInterface.
460 virtual const char* GetCommandName(unsigned int command_id) const;
461
462 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38463 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
464 const scoped_refptr<gfx::GLContext>& context,
[email protected]6217d392010-03-25 22:08:35465 const gfx::Size& size,
[email protected]c410da802011-03-14 19:17:41466 const DisallowedExtensions& disallowed_extensions,
[email protected]a3ded6d2010-10-19 06:44:39467 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:24468 const std::vector<int32>& attribs);
[email protected]96449d2c2009-11-25 00:01:32469 virtual void Destroy();
[email protected]3c644d82011-06-20 19:58:24470 virtual bool SetParent(GLES2Decoder* parent_decoder,
471 uint32 parent_texture_id);
[email protected]6217d392010-03-25 22:08:35472 virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]c71caa82010-06-02 23:25:45473 virtual bool UpdateOffscreenFrameBufferSize();
[email protected]9a5afa432011-07-22 18:16:39474 void UpdateParentTextureInfo();
[email protected]eb54a562010-01-20 21:55:18475 virtual bool MakeCurrent();
[email protected]56ac89b2010-03-17 21:16:55476 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30477 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]f62a5ab2011-05-23 20:34:15478 virtual gfx::GLSurface* GetGLSurface() { return surface_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39479 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]43f28f832010-02-03 02:28:48480
[email protected]7ff86b92010-11-25 17:50:00481 virtual void SetResizeCallback(Callback1<gfx::Size>::Type* callback);
[email protected]43f28f832010-02-03 02:28:48482 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
[email protected]1318e922010-09-17 22:03:16483 virtual bool GetServiceTextureId(uint32 client_texture_id,
484 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48485
[email protected]8e3e0662010-08-23 18:46:30486 // Restores the current state to the user's settings.
487 void RestoreCurrentFramebufferBindings();
488 void RestoreCurrentRenderbufferBindings();
489 void RestoreCurrentTexture2DBindings();
490
[email protected]297ca1c2011-06-20 23:08:46491 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
492 void ApplyDirtyState();
493
494 // These check the state of the currently bound framebuffer or the
495 // backbuffer if no framebuffer is bound.
496 bool BoundFramebufferHasColorAttachmentWithAlpha();
497 bool BoundFramebufferHasDepthAttachment();
498 bool BoundFramebufferHasStencilAttachment();
499
[email protected]38d139d2011-07-14 00:38:43500 virtual error::ContextLostReason GetContextLostReason();
501
[email protected]96449d2c2009-11-25 00:01:32502 private:
[email protected]6217d392010-03-25 22:08:35503 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02504 friend class ScopedResolvedFrameBufferBinder;
[email protected]6217d392010-03-25 22:08:35505 friend class RenderBuffer;
506 friend class FrameBuffer;
507
[email protected]3916c97e2010-02-25 03:20:50508 // State associated with each texture unit.
509 struct TextureUnit {
510 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
511
512 // The last target that was bound to this texture unit.
513 GLenum bind_target;
514
515 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
516 TextureManager::TextureInfo::Ref bound_texture_2d;
517
518 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
519 // glBindTexture
520 TextureManager::TextureInfo::Ref bound_texture_cube_map;
[email protected]61eeb33f2011-07-26 15:30:31521
522 // texture currently bound to this unit's GL_TEXTURE_EXTERNAL_OES with
523 // glBindTexture
524 TextureManager::TextureInfo::Ref bound_texture_external_oes;
525
526 TextureManager::TextureInfo::Ref GetInfoForSamplerType(GLenum type) {
527 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
528 type == GL_SAMPLER_EXTERNAL_OES);
529 return type == GL_SAMPLER_2D ? bound_texture_2d :
530 (type == GL_SAMPLER_EXTERNAL_OES ? bound_texture_external_oes :
531 bound_texture_cube_map);
532 }
[email protected]3916c97e2010-02-25 03:20:50533 };
534
[email protected]c2f8c8402010-12-06 18:07:24535 // Initialize or re-initialize the shader translator.
536 bool InitializeShaderTranslator();
537
[email protected]302ce6d2011-07-07 23:28:11538 void UpdateCapabilities();
539
[email protected]ae51d192010-04-27 00:48:03540 // Helpers for the glGen and glDelete functions.
541 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
542 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
543 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
544 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
545 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
546 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
547 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
548 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47549
[email protected]3916c97e2010-02-25 03:20:50550 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50551 BufferManager* buffer_manager() {
552 return group_->buffer_manager();
553 }
554
[email protected]a25fa872010-03-25 02:57:58555 RenderbufferManager* renderbuffer_manager() {
556 return group_->renderbuffer_manager();
557 }
558
559 FramebufferManager* framebuffer_manager() {
560 return group_->framebuffer_manager();
561 }
562
[email protected]3916c97e2010-02-25 03:20:50563 ProgramManager* program_manager() {
564 return group_->program_manager();
565 }
566
567 ShaderManager* shader_manager() {
568 return group_->shader_manager();
569 }
570
571 TextureManager* texture_manager() {
572 return group_->texture_manager();
573 }
574
[email protected]34ff8b0c2010-10-01 20:06:02575 bool IsOffscreenBufferMultisampled() const {
576 return offscreen_target_samples_ > 1;
577 }
578
[email protected]a93bb842010-02-16 23:03:47579 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03580 TextureManager::TextureInfo* CreateTextureInfo(
581 GLuint client_id, GLuint service_id) {
[email protected]915a59a12010-09-30 21:29:11582 return texture_manager()->CreateTextureInfo(
583 feature_info_, client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47584 }
585
586 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03587 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50588 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03589 texture_manager()->GetTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50590 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47591 }
592
593 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03594 void RemoveTextureInfo(GLuint client_id) {
[email protected]915a59a12010-09-30 21:29:11595 texture_manager()->RemoveTextureInfo(feature_info_, client_id);
[email protected]3916c97e2010-02-25 03:20:50596 }
[email protected]a93bb842010-02-16 23:03:47597
[email protected]d37231fa2010-04-09 21:16:02598 // Get the size (in pixels) of the currently bound frame buffer (either FBO
599 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30600 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02601
[email protected]9edc6b22010-12-23 02:00:26602 // Get the format of the currently bound frame buffer (either FBO or regular
603 // back buffer)
604 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46605 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26606
[email protected]a93bb842010-02-16 23:03:47607 // Wrapper for CompressedTexImage2D commands.
608 error::Error DoCompressedTexImage2D(
609 GLenum target,
610 GLint level,
611 GLenum internal_format,
612 GLsizei width,
613 GLsizei height,
614 GLint border,
615 GLsizei image_size,
616 const void* data);
617
[email protected]cadde4a2010-07-31 17:10:43618 // Wrapper for CompressedTexSubImage2D.
619 void DoCompressedTexSubImage2D(
620 GLenum target,
621 GLint level,
622 GLint xoffset,
623 GLint yoffset,
624 GLsizei width,
625 GLsizei height,
626 GLenum format,
627 GLsizei imageSize,
628 const void * data);
629
630 // Wrapper for CopyTexImage2D.
631 void DoCopyTexImage2D(
632 GLenum target,
633 GLint level,
634 GLenum internal_format,
635 GLint x,
636 GLint y,
637 GLsizei width,
638 GLsizei height,
639 GLint border);
640
641 // Wrapper for CopyTexSubImage2D.
642 void DoCopyTexSubImage2D(
643 GLenum target,
644 GLint level,
645 GLint xoffset,
646 GLint yoffset,
647 GLint x,
648 GLint y,
649 GLsizei width,
650 GLsizei height);
651
[email protected]a93bb842010-02-16 23:03:47652 // Wrapper for TexImage2D commands.
653 error::Error DoTexImage2D(
654 GLenum target,
655 GLint level,
656 GLenum internal_format,
657 GLsizei width,
658 GLsizei height,
659 GLint border,
660 GLenum format,
661 GLenum type,
662 const void* pixels,
663 uint32 pixels_size);
664
[email protected]cadde4a2010-07-31 17:10:43665 // Wrapper for TexSubImage2D.
666 void DoTexSubImage2D(
667 GLenum target,
668 GLint level,
669 GLint xoffset,
670 GLint yoffset,
671 GLsizei width,
672 GLsizei height,
673 GLenum format,
674 GLenum type,
675 const void * data);
676
[email protected]a93bb842010-02-16 23:03:47677 // Creates a ProgramInfo for the given program.
[email protected]d685a682011-04-29 16:19:57678 ProgramManager::ProgramInfo* CreateProgramInfo(
679 GLuint client_id, GLuint service_id) {
680 return program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47681 }
682
[email protected]07f54fcc2009-12-22 02:46:30683 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03684 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14685 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46686 }
[email protected]07f54fcc2009-12-22 02:46:30687
[email protected]6b8cf1a2010-05-06 16:13:58688 // Gets the program info for the given program. If it's not a program
689 // generates a GL error. Returns NULL if not program.
690 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
691 GLuint client_id, const char* function_name) {
692 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
693 if (!info) {
694 if (GetShaderInfo(client_id)) {
695 SetGLError(GL_INVALID_OPERATION,
696 (std::string(function_name) +
697 ": shader passed for program").c_str());
698 } else {
699 SetGLError(GL_INVALID_VALUE,
700 (std::string(function_name) + ": unknown program").c_str());
701 }
702 }
703 return info;
704 }
705
706
[email protected]45bf5152010-02-12 00:11:31707 // Creates a ShaderInfo for the given shader.
[email protected]d685a682011-04-29 16:19:57708 ShaderManager::ShaderInfo* CreateShaderInfo(
709 GLuint client_id,
710 GLuint service_id,
711 GLenum shader_type) {
712 return shader_manager()->CreateShaderInfo(
713 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31714 }
715
716 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03717 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14718 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31719 }
720
[email protected]6b8cf1a2010-05-06 16:13:58721 // Gets the shader info for the given shader. If it's not a shader generates a
722 // GL error. Returns NULL if not shader.
723 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
724 GLuint client_id, const char* function_name) {
725 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
726 if (!info) {
727 if (GetProgramInfo(client_id)) {
728 SetGLError(
729 GL_INVALID_OPERATION,
730 (std::string(function_name) +
731 ": program passed for shader").c_str());
732 } else {
733 SetGLError(GL_INVALID_VALUE,
734 (std::string(function_name) + ": unknown shader").c_str());
735 }
736 }
737 return info;
738 }
739
[email protected]a93bb842010-02-16 23:03:47740 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03741 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
742 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47743 }
744
[email protected]07f54fcc2009-12-22 02:46:30745 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03746 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
747 BufferManager::BufferInfo* info =
748 buffer_manager()->GetBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50749 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46750 }
[email protected]07f54fcc2009-12-22 02:46:30751
[email protected]a93bb842010-02-16 23:03:47752 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
753 // on glDeleteBuffers so we can make sure the user does not try to render
754 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03755 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47756
[email protected]a25fa872010-03-25 02:57:58757 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03758 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
759 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58760 }
761
762 // Gets the framebuffer info for the given framebuffer.
763 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03764 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58765 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03766 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58767 return (info && !info->IsDeleted()) ? info : NULL;
768 }
769
770 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03771 void RemoveFramebufferInfo(GLuint client_id) {
772 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58773 }
774
775 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03776 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
777 return renderbuffer_manager()->CreateRenderbufferInfo(
778 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58779 }
780
781 // Gets the renderbuffer info for the given renderbuffer.
782 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03783 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58784 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03785 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58786 return (info && !info->IsDeleted()) ? info : NULL;
787 }
788
789 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03790 void RemoveRenderbufferInfo(GLuint client_id) {
791 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58792 }
793
[email protected]558847a2010-03-24 07:02:54794 error::Error GetAttribLocationHelper(
795 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
796 const std::string& name_str);
797
798 error::Error GetUniformLocationHelper(
799 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
800 const std::string& name_str);
801
[email protected]3916c97e2010-02-25 03:20:50802 // Helper for glShaderSource.
803 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03804 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30805
[email protected]3a2e7c7b2010-08-06 01:12:28806 // Clears any uncleared render buffers attached to the given frame buffer.
[email protected]8e3e0662010-08-23 18:46:30807 void ClearUnclearedRenderbuffers(
808 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28809
[email protected]c007aa02010-09-02 22:22:40810 // Restore all GL state that affects clearing.
811 void RestoreClearState();
812
[email protected]3a2e7c7b2010-08-06 01:12:28813 // Remembers the state of some capabilities.
[email protected]297ca1c2011-06-20 23:08:46814 // Returns: true if glEnable/glDisable should actually be called.
815 bool SetCapabilityState(GLenum cap, bool enabled);
[email protected]3a2e7c7b2010-08-06 01:12:28816
[email protected]3a03a8f2011-03-19 00:51:27817 // Check that the current frame buffer is complete. Generates error if not.
818 bool CheckFramebufferComplete(const char* func_name);
819
[email protected]939e7362010-05-13 20:49:10820 // Checks if the current program exists and is valid. If not generates the
821 // appropriate GL error. Returns true if the current program is in a usable
822 // state.
823 bool CheckCurrentProgram(const char* function_name);
824
825 // Checks if the current program exists and is valid and that location is not
826 // -1. If the current program is not valid generates the appropriate GL
827 // error. Returns true if the current program is in a usable state and
828 // location is not -1.
829 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
830
831 // Gets the type of a uniform for a location in the current program. Sets GL
832 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:36833 // program is valid and the location exists. Adjusts count so it
834 // does not overflow the uniform.
835 bool PrepForSetUniformByLocation(
836 GLint location, const char* function_name, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:10837
[email protected]b273e432010-04-12 17:23:58838 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
839 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
840
[email protected]96449d2c2009-11-25 00:01:32841 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03842 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32843
844 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03845 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32846
[email protected]3916c97e2010-02-25 03:20:50847 // Wrapper for glActiveTexture
848 void DoActiveTexture(GLenum texture_unit);
849
[email protected]ae51d192010-04-27 00:48:03850 // Wrapper for glAttachShader
851 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
852
[email protected]96449d2c2009-11-25 00:01:32853 // Wrapper for glBindBuffer since we need to track the current targets.
854 void DoBindBuffer(GLenum target, GLuint buffer);
855
[email protected]86093972010-03-11 00:13:56856 // Wrapper for glBindFramebuffer since we need to track the current targets.
857 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
858
859 // Wrapper for glBindRenderbuffer since we need to track the current targets.
860 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
861
[email protected]a93bb842010-02-16 23:03:47862 // Wrapper for glBindTexture since we need to track the current targets.
863 void DoBindTexture(GLenum target, GLuint texture);
864
[email protected]8e3e0662010-08-23 18:46:30865 // Wrapper for glBlitFramebufferEXT.
866 void DoBlitFramebufferEXT(
867 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
868 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
869 GLbitfield mask, GLenum filter);
870
[email protected]36cef8ce2010-03-16 07:34:45871 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:11872 void DoBufferData(
873 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
874
[email protected]36cef8ce2010-03-16 07:34:45875 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:11876 void DoBufferSubData(
877 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
878
[email protected]36cef8ce2010-03-16 07:34:45879 // Wrapper for glCheckFramebufferStatus
880 GLenum DoCheckFramebufferStatus(GLenum target);
881
[email protected]3a03a8f2011-03-19 00:51:27882 // Wrapper for glClear
883 void DoClear(GLbitfield mask);
884
[email protected]3a2e7c7b2010-08-06 01:12:28885 // Wrappers for clear and mask settings functions.
886 void DoClearColor(
887 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
888 void DoClearDepthf(GLclampf depth);
889 void DoClearStencil(GLint s);
890 void DoColorMask(
891 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
892 void DoDepthMask(GLboolean depth);
893 void DoStencilMask(GLuint mask);
894 void DoStencilMaskSeparate(GLenum face, GLuint mask);
895
[email protected]45bf5152010-02-12 00:11:31896 // Wrapper for glCompileShader.
897 void DoCompileShader(GLuint shader);
898
[email protected]269200b12010-11-18 22:53:06899 // Helper for DeleteSharedIdsCHROMIUM commands.
900 void DoDeleteSharedIdsCHROMIUM(
901 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:10902
[email protected]ae51d192010-04-27 00:48:03903 // Wrapper for glDetachShader
904 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
905
[email protected]3a2e7c7b2010-08-06 01:12:28906 // Wrapper for glDisable
907 void DoDisable(GLenum cap);
908
[email protected]07f54fcc2009-12-22 02:46:30909 // Wrapper for glDisableVertexAttribArray.
910 void DoDisableVertexAttribArray(GLuint index);
911
[email protected]3a2e7c7b2010-08-06 01:12:28912 // Wrapper for glEnable
913 void DoEnable(GLenum cap);
914
[email protected]07f54fcc2009-12-22 02:46:30915 // Wrapper for glEnableVertexAttribArray.
916 void DoEnableVertexAttribArray(GLuint index);
917
[email protected]36cef8ce2010-03-16 07:34:45918 // Wrapper for glFramebufferRenderbufffer.
919 void DoFramebufferRenderbuffer(
920 GLenum target, GLenum attachment, GLenum renderbuffertarget,
921 GLuint renderbuffer);
922
923 // Wrapper for glFramebufferTexture2D.
924 void DoFramebufferTexture2D(
925 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
926 GLint level);
927
[email protected]a93bb842010-02-16 23:03:47928 // Wrapper for glGenerateMipmap
929 void DoGenerateMipmap(GLenum target);
930
[email protected]269200b12010-11-18 22:53:06931 // Helper for GenSharedIdsCHROMIUM commands.
932 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:10933 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
934
[email protected]b273e432010-04-12 17:23:58935 // Wrapper for DoGetBooleanv.
936 void DoGetBooleanv(GLenum pname, GLboolean* params);
937
938 // Wrapper for DoGetFloatv.
939 void DoGetFloatv(GLenum pname, GLfloat* params);
940
[email protected]36cef8ce2010-03-16 07:34:45941 // Wrapper for glGetFramebufferAttachmentParameteriv.
942 void DoGetFramebufferAttachmentParameteriv(
943 GLenum target, GLenum attachment, GLenum pname, GLint* params);
944
[email protected]a0c3e972010-04-21 00:49:13945 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:58946 void DoGetIntegerv(GLenum pname, GLint* params);
947
[email protected]29a9eb52010-04-13 09:04:23948 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:06949 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:23950 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
951
[email protected]a0c3e972010-04-21 00:49:13952 // Wrapper for glGetProgramiv.
953 void DoGetProgramiv(
954 GLuint program_id, GLenum pname, GLint* params);
955
[email protected]36cef8ce2010-03-16 07:34:45956 // Wrapper for glRenderbufferParameteriv.
957 void DoGetRenderbufferParameteriv(
958 GLenum target, GLenum pname, GLint* params);
959
[email protected]ddd968b82010-03-02 00:44:29960 // Wrapper for glGetShaderiv
961 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
962
[email protected]b1122982010-05-17 23:04:24963 // Wrappers for glGetVertexAttrib.
964 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
965 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
966
[email protected]1958e0e2010-04-22 05:17:15967 // Wrappers for glIsXXX functions.
968 bool DoIsBuffer(GLuint client_id);
969 bool DoIsFramebuffer(GLuint client_id);
970 bool DoIsProgram(GLuint client_id);
971 bool DoIsRenderbuffer(GLuint client_id);
972 bool DoIsShader(GLuint client_id);
973 bool DoIsTexture(GLuint client_id);
974
[email protected]07f54fcc2009-12-22 02:46:30975 // Wrapper for glLinkProgram
976 void DoLinkProgram(GLuint program);
977
[email protected]269200b12010-11-18 22:53:06978 // Helper for RegisterSharedIdsCHROMIUM.
979 void DoRegisterSharedIdsCHROMIUM(
980 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:10981
[email protected]36cef8ce2010-03-16 07:34:45982 // Wrapper for glRenderbufferStorage.
983 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:03984 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:45985
[email protected]8e3e0662010-08-23 18:46:30986 // Wrapper for glRenderbufferStorageMultisampleEXT.
987 void DoRenderbufferStorageMultisample(
988 GLenum target, GLsizei samples, GLenum internalformat,
989 GLsizei width, GLsizei height);
990
[email protected]b273e432010-04-12 17:23:58991 // Wrapper for glReleaseShaderCompiler.
992 void DoReleaseShaderCompiler() { }
993
[email protected]3916c97e2010-02-25 03:20:50994 // Wrappers for glTexParameter functions.
995 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
996 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
997 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
998 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
999
1000 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1001 // spec only these 2 functions can be used to set sampler uniforms.
1002 void DoUniform1i(GLint location, GLint v0);
[email protected]939e7362010-05-13 20:49:101003 void DoUniform1iv(GLint location, GLsizei count, const GLint* value);
[email protected]43c2f1f2011-03-25 18:35:361004 void DoUniform2iv(GLint location, GLsizei count, const GLint* value);
1005 void DoUniform3iv(GLint location, GLsizei count, const GLint* value);
1006 void DoUniform4iv(GLint location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101007
1008 // Wrappers for glUniformfv because some drivers don't correctly accept
1009 // bool uniforms.
1010 void DoUniform1fv(GLint location, GLsizei count, const GLfloat* value);
1011 void DoUniform2fv(GLint location, GLsizei count, const GLfloat* value);
1012 void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value);
1013 void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501014
[email protected]43c2f1f2011-03-25 18:35:361015 void DoUniformMatrix2fv(
1016 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1017 void DoUniformMatrix3fv(
1018 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1019 void DoUniformMatrix4fv(
1020 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1021
[email protected]b1122982010-05-17 23:04:241022 // Wrappers for glVertexAttrib??
1023 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1024 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1025 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1026 void DoVertexAttrib4f(
1027 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1028 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1029 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1030 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1031 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1032
[email protected]07f54fcc2009-12-22 02:46:301033 // Wrapper for glUseProgram
1034 void DoUseProgram(GLuint program);
1035
[email protected]ae51d192010-04-27 00:48:031036 // Wrapper for glValidateProgram.
1037 void DoValidateProgram(GLuint program_client_id);
1038
[email protected]297ca1c2011-06-20 23:08:461039 void DoCopyTextureToParentTextureCHROMIUM(
1040 GLuint client_texture_id, GLuint parent_client_texture_id);
[email protected]a3a93e7b2010-08-28 00:48:561041
[email protected]43ecf372010-11-16 19:19:391042 void DoResizeCHROMIUM(GLuint width, GLuint height);
1043
[email protected]fbe20372011-06-01 01:46:381044 void DoSetSurfaceCHROMIUM(GLint surface_id);
1045
[email protected]4e8a5b122010-05-08 22:00:101046 // Gets the number of values that will be returned by glGetXXX. Returns
1047 // false if pname is unknown.
1048 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1049
[email protected]96449d2c2009-11-25 00:01:321050 // Gets the GLError through our wrapper.
1051 GLenum GetGLError();
1052
[email protected]1002c2d2011-06-28 22:39:041053 // Gets the GLError and stores it in our wrapper. Effectively
1054 // this lets us peek at the error without losing it.
1055 GLenum PeekGLError();
1056
[email protected]96449d2c2009-11-25 00:01:321057 // Sets our wrapper for the GLError.
[email protected]8eee29c2010-04-29 03:38:291058 void SetGLError(GLenum error, const char* msg);
[email protected]96449d2c2009-11-25 00:01:321059
[email protected]07f54fcc2009-12-22 02:46:301060 // Copies the real GL errors to the wrapper. This is so we can
1061 // make sure there are no native GL errors before calling some GL function
1062 // so that on return we know any error generated was for that specific
1063 // command.
1064 void CopyRealGLErrorsToWrapper();
1065
[email protected]6217d392010-03-25 22:08:351066 // Clear all real GL errors. This is to prevent the client from seeing any
1067 // errors caused by GL calls that it was not responsible for issuing.
1068 void ClearRealGLErrors();
1069
[email protected]07f54fcc2009-12-22 02:46:301070 // Checks if the current program and vertex attributes are valid for drawing.
1071 bool IsDrawValid(GLuint max_vertex_accessed);
1072
[email protected]b1122982010-05-17 23:04:241073 // Returns true if attrib0 was simulated.
1074 bool SimulateAttrib0(GLuint max_vertex_accessed);
1075 void RestoreStateForSimulatedAttrib0();
1076
[email protected]ef526492010-06-02 23:12:251077 // Returns true if textures were set.
1078 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501079 void RestoreStateForNonRenderableTextures();
1080
[email protected]8fbedc02010-11-18 18:43:401081 // Returns true if GL_FIXED attribs were simulated.
1082 bool SimulateFixedAttribs(GLuint max_vertex_accessed, bool* simulated);
1083 void RestoreStateForSimulatedFixedAttribs();
1084
[email protected]07f54fcc2009-12-22 02:46:301085 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501086 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301087 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501088 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1089 bound_array_buffer_ : bound_element_array_buffer_;
1090 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:301091 }
1092
[email protected]a93bb842010-02-16 23:03:471093 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501094 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1095 TextureUnit& unit = texture_units_[active_texture_unit_];
1096 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471097 switch (target) {
1098 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501099 info = unit.bound_texture_2d;
1100 break;
[email protected]a93bb842010-02-16 23:03:471101 case GL_TEXTURE_CUBE_MAP:
1102 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1103 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1104 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1105 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1106 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1107 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501108 info = unit.bound_texture_cube_map;
1109 break;
[email protected]61eeb33f2011-07-26 15:30:311110 case GL_TEXTURE_EXTERNAL_OES:
1111 info = unit.bound_texture_external_oes;
1112 break;
[email protected]1aef98132010-02-23 18:00:071113 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
1114 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
1115 // because |texture_| is used by the FBO rendering mechanism for readback
1116 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:471117 default:
1118 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501119 return NULL;
[email protected]a93bb842010-02-16 23:03:471120 }
[email protected]3916c97e2010-02-25 03:20:501121 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:471122 }
1123
[email protected]61eeb33f2011-07-26 15:30:311124 GLenum GetBindTargetForSamplerType(GLenum type) {
1125 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1126 type == GL_SAMPLER_EXTERNAL_OES);
1127 return type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
1128 (type == GL_SAMPLER_EXTERNAL_OES ? GL_TEXTURE_EXTERNAL_OES :
1129 GL_TEXTURE_CUBE_MAP);
1130 }
1131
[email protected]8e3e0662010-08-23 18:46:301132 // Gets the framebuffer info for a particular target.
1133 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1134 GLenum target) {
1135 FramebufferManager::FramebufferInfo* info = NULL;
1136 switch (target) {
1137 case GL_FRAMEBUFFER:
1138 case GL_DRAW_FRAMEBUFFER:
1139 info = bound_draw_framebuffer_;
1140 break;
1141 case GL_READ_FRAMEBUFFER:
1142 info = bound_read_framebuffer_;
1143 break;
1144 default:
1145 NOTREACHED();
1146 break;
1147 }
1148 return (info && !info->IsDeleted()) ? info : NULL;
1149 }
1150
[email protected]f7b85372010-02-03 01:11:371151 // Validates the program and location for a glGetUniform call and returns
1152 // a SizeResult setup to receive the result. Returns true if glGetUniform
1153 // should be called.
1154 bool GetUniformSetup(
1155 GLuint program, GLint location,
1156 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:101157 error::Error* error, GLuint* service_id, void** result,
1158 GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371159
[email protected]38d139d2011-07-14 00:38:431160 // Returns true if the context was just lost due to e.g. GL_ARB_robustness.
1161 bool WasContextLost();
1162
[email protected]96449d2c2009-11-25 00:01:321163 // Generate a member function prototype for each command in an automated and
1164 // typesafe way.
1165 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141166 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191167 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321168 const gles2::name& args); \
1169
1170 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1171
1172 #undef GLES2_CMD_OP
1173
[email protected]fbe20372011-06-01 01:46:381174 // Maps surface IDs to GLSurface.
1175 gpu::SurfaceManager* surface_manager_;
1176
[email protected]2f2d7042010-04-14 21:45:581177 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381178 scoped_refptr<gfx::GLSurface> surface_;
1179 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021180
[email protected]a3ded6d2010-10-19 06:44:391181 // The ContextGroup for this decoder uses to track resources.
1182 ContextGroup::Ref group_;
1183
[email protected]6217d392010-03-25 22:08:351184 // A parent decoder can access this decoders saved offscreen frame buffer.
1185 // The parent pointer is reset if the parent is destroyed.
1186 base::WeakPtr<GLES2DecoderImpl> parent_;
1187
1188 // Width and height to which an offscreen frame buffer should be resized on
1189 // the next call to SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:021190 gfx::Size pending_offscreen_size_;
[email protected]6217d392010-03-25 22:08:351191
[email protected]34ff8b0c2010-10-01 20:06:021192 // Current width and height of the offscreen frame buffer.
1193 gfx::Size offscreen_size_;
1194
[email protected]96449d2c2009-11-25 00:01:321195 // Current GL error bits.
1196 uint32 error_bits_;
1197
[email protected]96449d2c2009-11-25 00:01:321198 // Util to help with GL.
1199 GLES2Util util_;
1200
1201 // pack alignment as last set by glPixelStorei
1202 GLint pack_alignment_;
1203
1204 // unpack alignment as last set by glPixelStorei
1205 GLint unpack_alignment_;
1206
1207 // The currently bound array buffer. If this is 0 it is illegal to call
1208 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501209 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321210
1211 // The currently bound element array buffer. If this is 0 it is illegal
1212 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501213 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301214
[email protected]f39f4b3f2010-05-12 17:04:081215 // Class that manages vertex attribs.
1216 VertexAttribManager vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301217
[email protected]b1122982010-05-17 23:04:241218 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1219 GLuint attrib_0_buffer_id_;
1220
1221 // The value currently in attrib_0.
1222 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1223
[email protected]fc753442011-02-04 19:49:491224 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1225 bool attrib_0_buffer_matches_value_;
1226
[email protected]b1122982010-05-17 23:04:241227 // The size of attrib 0.
1228 GLsizei attrib_0_size_;
1229
[email protected]8fbedc02010-11-18 18:43:401230 // The buffer used to simulate GL_FIXED attribs.
1231 GLuint fixed_attrib_buffer_id_;
1232
1233 // The size of fiixed attrib buffer.
1234 GLsizei fixed_attrib_buffer_size_;
1235
[email protected]3916c97e2010-02-25 03:20:501236 // Current active texture by 0 - n index.
1237 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1238 // be 2.
1239 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301240
[email protected]3916c97e2010-02-25 03:20:501241 // Which textures are bound to texture units through glActiveTexture.
1242 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471243
[email protected]3a2e7c7b2010-08-06 01:12:281244 // state saved for clearing so we can clear render buffers and then
1245 // restore to these values.
1246 GLclampf clear_red_;
1247 GLclampf clear_green_;
1248 GLclampf clear_blue_;
1249 GLclampf clear_alpha_;
1250 GLboolean mask_red_;
1251 GLboolean mask_green_;
1252 GLboolean mask_blue_;
1253 GLboolean mask_alpha_;
1254 GLint clear_stencil_;
1255 GLuint mask_stencil_front_;
1256 GLuint mask_stencil_back_;
1257 GLclampf clear_depth_;
1258 GLboolean mask_depth_;
1259 bool enable_scissor_test_;
[email protected]297ca1c2011-06-20 23:08:461260 bool enable_depth_test_;
1261 bool enable_stencil_test_;
1262 bool state_dirty_;
[email protected]3a2e7c7b2010-08-06 01:12:281263
[email protected]1d32bc82010-01-13 22:06:461264 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501265 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301266
[email protected]8e3e0662010-08-23 18:46:301267 // The currently bound framebuffers
1268 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1269 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561270
1271 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081272 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561273
[email protected]b9363b22010-06-09 22:06:151274 // The offscreen frame buffer that the client renders to. With EGL, the
1275 // depth and stencil buffers are separate. With regular GL there is a single
1276 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1277 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351278 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1279 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021280 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151281 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1282 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021283 GLenum offscreen_target_color_format_;
1284 GLenum offscreen_target_depth_format_;
1285 GLenum offscreen_target_stencil_format_;
1286 GLsizei offscreen_target_samples_;
[email protected]6217d392010-03-25 22:08:351287
[email protected]a3a93e7b2010-08-28 00:48:561288 GLuint copy_texture_to_parent_texture_fb_;
1289
[email protected]de26b3c2011-08-03 21:54:271290 // The copy that is saved when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021291 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351292 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]de26b3c2011-08-03 21:54:271293
1294 // The copy that is used as the destination for multi-sample resolves.
1295 scoped_ptr<FrameBuffer> offscreen_resolved_frame_buffer_;
1296 scoped_ptr<Texture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051297 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351298
[email protected]7ff86b92010-11-25 17:50:001299 scoped_ptr<Callback1<gfx::Size>::Type> resize_callback_;
[email protected]43f28f832010-02-03 02:28:481300 scoped_ptr<Callback0::Type> swap_buffers_callback_;
1301
[email protected]32fe9aa2011-01-21 23:47:131302 // The format of the back buffer_
1303 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461304 bool back_buffer_has_depth_;
1305 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131306
[email protected]473c01ccb2011-06-07 01:33:301307 bool teximage2d_faster_than_texsubimage2d_;
1308 bool bufferdata_faster_than_buffersubdata_;
1309
[email protected]8eee29c2010-04-29 03:38:291310 // The last error message set.
1311 std::string last_error_;
1312
[email protected]a3a93e7b2010-08-28 00:48:561313 // The current decoder error.
1314 error::Error current_decoder_error_;
1315
[email protected]b1d2dcb2010-05-17 19:24:181316 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451317 scoped_ptr<ShaderTranslator> vertex_translator_;
1318 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181319
[email protected]c410da802011-03-14 19:17:411320 DisallowedExtensions disallowed_extensions_;
1321
[email protected]915a59a12010-09-30 21:29:111322 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051323 const Validators* validators_;
[email protected]915a59a12010-09-30 21:29:111324 FeatureInfo* feature_info_;
[email protected]9438b012010-06-15 22:55:051325
[email protected]b493ee622011-04-13 23:52:001326 // This indicates all the following texSubImage2D calls that are part of the
1327 // failed texImage2D call should be ignored.
1328 bool tex_image_2d_failed_;
1329
[email protected]65225772011-05-12 21:10:241330 int frame_number_;
1331
[email protected]38d139d2011-07-14 00:38:431332 bool has_arb_robustness_;
1333 GLenum reset_status_;
1334
[email protected]96449d2c2009-11-25 00:01:321335 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1336};
1337
[email protected]6217d392010-03-25 22:08:351338ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1339 : decoder_(decoder) {
1340 decoder_->CopyRealGLErrorsToWrapper();
1341}
1342
1343ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1344 decoder_->ClearRealGLErrors();
1345}
1346
1347ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1348 GLuint id)
1349 : decoder_(decoder) {
1350 ScopedGLErrorSuppressor suppressor(decoder_);
1351
1352 // TODO(apatrick): Check if there are any other states that need to be reset
1353 // before binding a new texture.
1354 glActiveTexture(GL_TEXTURE0);
1355 glBindTexture(GL_TEXTURE_2D, id);
1356}
1357
1358ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1359 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301360 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351361}
1362
1363ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1364 GLuint id)
1365 : decoder_(decoder) {
1366 ScopedGLErrorSuppressor suppressor(decoder_);
1367 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1368}
1369
1370ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1371 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301372 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351373}
1374
1375ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1376 GLuint id)
1377 : decoder_(decoder) {
1378 ScopedGLErrorSuppressor suppressor(decoder_);
1379 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1380}
1381
1382ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1383 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301384 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351385}
1386
[email protected]34ff8b0c2010-10-01 20:06:021387ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271388 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521389 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021390 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1391 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]c0701082011-04-20 00:34:521392 (!decoder_->bound_read_framebuffer_.get() ||
1393 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021394 if (!resolve_and_bind_)
1395 return;
1396
1397 ScopedGLErrorSuppressor suppressor(decoder_);
1398 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1399 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271400 GLuint targetid;
1401 if (internal) {
1402 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1403 decoder_->offscreen_resolved_frame_buffer_.reset(
1404 new FrameBuffer(decoder_));
1405 decoder_->offscreen_resolved_frame_buffer_->Create();
1406 decoder_->offscreen_resolved_color_texture_.reset(new Texture(decoder_));
1407 decoder_->offscreen_resolved_color_texture_->Create();
1408
1409 DCHECK(decoder_->offscreen_saved_color_format_);
1410 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1411 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_);
1412
1413 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1414 decoder_->offscreen_resolved_color_texture_.get());
1415 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1416 GL_FRAMEBUFFER_COMPLETE) {
1417 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1418 << "because offscreen resolved FBO was incomplete.";
1419 return;
1420 }
1421 }
1422 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1423 } else {
1424 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1425 }
1426 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021427 const int width = decoder_->offscreen_size_.width();
1428 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181429 glDisable(GL_SCISSOR_TEST);
[email protected]34ff8b0c2010-10-01 20:06:021430 if (IsAngle()) {
1431 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1432 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1433 } else {
1434 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1435 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1436 }
[email protected]de26b3c2011-08-03 21:54:271437 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021438}
1439
1440ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1441 if (!resolve_and_bind_)
1442 return;
1443
1444 ScopedGLErrorSuppressor suppressor(decoder_);
1445 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181446 if (decoder_->enable_scissor_test_) {
1447 glEnable(GL_SCISSOR_TEST);
1448 }
[email protected]34ff8b0c2010-10-01 20:06:021449}
1450
[email protected]6217d392010-03-25 22:08:351451Texture::Texture(GLES2DecoderImpl* decoder)
1452 : decoder_(decoder),
[email protected]3a4d0c52011-06-29 23:11:581453 id_(0) {
[email protected]6217d392010-03-25 22:08:351454}
1455
1456Texture::~Texture() {
1457 // This does not destroy the render texture because that would require that
1458 // the associated GL context was current. Just check that it was explicitly
1459 // destroyed.
1460 DCHECK_EQ(id_, 0u);
1461}
1462
1463void Texture::Create() {
1464 ScopedGLErrorSuppressor suppressor(decoder_);
1465 Destroy();
1466 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581467 ScopedTexture2DBinder binder(decoder_, id_);
1468 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1469 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1470 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1471 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]6217d392010-03-25 22:08:351472}
1473
[email protected]34ff8b0c2010-10-01 20:06:021474bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351475 DCHECK_NE(id_, 0u);
1476 ScopedGLErrorSuppressor suppressor(decoder_);
1477 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]6217d392010-03-25 22:08:351478
1479 glTexImage2D(GL_TEXTURE_2D,
1480 0, // mip level
[email protected]34ff8b0c2010-10-01 20:06:021481 format,
[email protected]6217d392010-03-25 22:08:351482 size.width(),
1483 size.height(),
1484 0, // border
[email protected]34ff8b0c2010-10-01 20:06:021485 format,
[email protected]6217d392010-03-25 22:08:351486 GL_UNSIGNED_BYTE,
1487 NULL);
1488
[email protected]d37231fa2010-04-09 21:16:021489 size_ = size;
1490
[email protected]6217d392010-03-25 22:08:351491 return glGetError() == GL_NO_ERROR;
1492}
1493
[email protected]3a4d0c52011-06-29 23:11:581494void Texture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351495 DCHECK_NE(id_, 0u);
1496 ScopedGLErrorSuppressor suppressor(decoder_);
1497 ScopedTexture2DBinder binder(decoder_, id_);
1498 glCopyTexImage2D(GL_TEXTURE_2D,
1499 0, // level
[email protected]3a4d0c52011-06-29 23:11:581500 format,
[email protected]6217d392010-03-25 22:08:351501 0, 0,
1502 size.width(),
1503 size.height(),
1504 0); // border
1505}
1506
1507void Texture::Destroy() {
1508 if (id_ != 0) {
1509 ScopedGLErrorSuppressor suppressor(decoder_);
1510 glDeleteTextures(1, &id_);
1511 id_ = 0;
1512 }
1513}
1514
[email protected]97872062010-11-03 19:07:051515void Texture::Invalidate() {
1516 id_ = 0;
1517}
1518
[email protected]6217d392010-03-25 22:08:351519RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1520 : decoder_(decoder),
1521 id_(0) {
1522}
1523
1524RenderBuffer::~RenderBuffer() {
1525 // This does not destroy the render buffer because that would require that
1526 // the associated GL context was current. Just check that it was explicitly
1527 // destroyed.
1528 DCHECK_EQ(id_, 0u);
1529}
1530
1531void RenderBuffer::Create() {
1532 ScopedGLErrorSuppressor suppressor(decoder_);
1533 Destroy();
1534 glGenRenderbuffersEXT(1, &id_);
1535}
1536
[email protected]34ff8b0c2010-10-01 20:06:021537bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1538 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351539 ScopedGLErrorSuppressor suppressor(decoder_);
1540 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021541 if (samples <= 1) {
1542 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1543 format,
1544 size.width(),
1545 size.height());
1546 } else {
1547 if (IsAngle()) {
1548 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1549 samples,
1550 format,
1551 size.width(),
1552 size.height());
1553 } else {
1554 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1555 samples,
1556 format,
1557 size.width(),
1558 size.height());
1559 }
1560 }
[email protected]6217d392010-03-25 22:08:351561 return glGetError() == GL_NO_ERROR;
1562}
1563
1564void RenderBuffer::Destroy() {
1565 if (id_ != 0) {
1566 ScopedGLErrorSuppressor suppressor(decoder_);
1567 glDeleteRenderbuffersEXT(1, &id_);
1568 id_ = 0;
1569 }
1570}
1571
[email protected]97872062010-11-03 19:07:051572void RenderBuffer::Invalidate() {
1573 id_ = 0;
1574}
1575
[email protected]6217d392010-03-25 22:08:351576FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1577 : decoder_(decoder),
1578 id_(0) {
1579}
1580
1581FrameBuffer::~FrameBuffer() {
1582 // This does not destroy the frame buffer because that would require that
1583 // the associated GL context was current. Just check that it was explicitly
1584 // destroyed.
1585 DCHECK_EQ(id_, 0u);
1586}
1587
1588void FrameBuffer::Create() {
1589 ScopedGLErrorSuppressor suppressor(decoder_);
1590 Destroy();
1591 glGenFramebuffersEXT(1, &id_);
1592}
1593
1594void FrameBuffer::AttachRenderTexture(Texture* texture) {
1595 DCHECK_NE(id_, 0u);
1596 ScopedGLErrorSuppressor suppressor(decoder_);
1597 ScopedFrameBufferBinder binder(decoder_, id_);
1598 GLuint attach_id = texture ? texture->id() : 0;
1599 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1600 GL_COLOR_ATTACHMENT0,
1601 GL_TEXTURE_2D,
1602 attach_id,
1603 0);
1604}
1605
[email protected]b9363b22010-06-09 22:06:151606void FrameBuffer::AttachRenderBuffer(GLenum target,
1607 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351608 DCHECK_NE(id_, 0u);
1609 ScopedGLErrorSuppressor suppressor(decoder_);
1610 ScopedFrameBufferBinder binder(decoder_, id_);
1611 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1612 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151613 target,
[email protected]6217d392010-03-25 22:08:351614 GL_RENDERBUFFER,
1615 attach_id);
1616}
1617
1618void FrameBuffer::Clear(GLbitfield buffers) {
1619 ScopedGLErrorSuppressor suppressor(decoder_);
1620 ScopedFrameBufferBinder binder(decoder_, id_);
1621 glClear(buffers);
1622}
1623
1624void FrameBuffer::Destroy() {
1625 if (id_ != 0) {
1626 ScopedGLErrorSuppressor suppressor(decoder_);
1627 glDeleteFramebuffersEXT(1, &id_);
1628 id_ = 0;
1629 }
1630}
1631
[email protected]97872062010-11-03 19:07:051632void FrameBuffer::Invalidate() {
1633 id_ = 0;
1634}
1635
[email protected]6217d392010-03-25 22:08:351636GLenum FrameBuffer::CheckStatus() {
1637 DCHECK_NE(id_, 0u);
1638 ScopedGLErrorSuppressor suppressor(decoder_);
1639 ScopedFrameBufferBinder binder(decoder_, id_);
1640 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1641}
1642
[email protected]fbe20372011-06-01 01:46:381643GLES2Decoder* GLES2Decoder::Create(SurfaceManager* surface_manager,
1644 ContextGroup* group) {
1645 return new GLES2DecoderImpl(surface_manager, group);
[email protected]96449d2c2009-11-25 00:01:321646}
1647
[email protected]fbe20372011-06-01 01:46:381648GLES2DecoderImpl::GLES2DecoderImpl(SurfaceManager* surface_manager,
1649 ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391650 : GLES2Decoder(),
[email protected]fbe20372011-06-01 01:46:381651 surface_manager_(surface_manager),
[email protected]3b1ecc262011-08-03 22:49:571652 group_(group),
[email protected]96449d2c2009-11-25 00:01:321653 error_bits_(0),
[email protected]96449d2c2009-11-25 00:01:321654 pack_alignment_(4),
1655 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241656 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491657 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241658 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401659 fixed_attrib_buffer_id_(0),
1660 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501661 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281662 clear_red_(0),
1663 clear_green_(0),
1664 clear_blue_(0),
1665 clear_alpha_(0),
1666 mask_red_(true),
1667 mask_green_(true),
1668 mask_blue_(true),
1669 mask_alpha_(true),
1670 clear_stencil_(0),
1671 mask_stencil_front_(-1),
1672 mask_stencil_back_(-1),
1673 clear_depth_(1.0f),
1674 mask_depth_(true),
1675 enable_scissor_test_(false),
[email protected]297ca1c2011-06-20 23:08:461676 enable_depth_test_(false),
1677 enable_stencil_test_(false),
1678 state_dirty_(true),
[email protected]34ff8b0c2010-10-01 20:06:021679 offscreen_target_color_format_(0),
1680 offscreen_target_depth_format_(0),
1681 offscreen_target_stencil_format_(0),
1682 offscreen_target_samples_(0),
[email protected]5ea88812011-03-28 10:45:391683 copy_texture_to_parent_texture_fb_(0),
[email protected]97872062010-11-03 19:07:051684 offscreen_saved_color_format_(0),
[email protected]32fe9aa2011-01-21 23:47:131685 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:461686 back_buffer_has_depth_(false),
1687 back_buffer_has_stencil_(false),
[email protected]473c01ccb2011-06-07 01:33:301688 teximage2d_faster_than_texsubimage2d_(true),
1689 bufferdata_faster_than_buffersubdata_(true),
[email protected]a3a93e7b2010-08-28 00:48:561690 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051691 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111692 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001693 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241694 tex_image_2d_failed_(false),
[email protected]38d139d2011-07-14 00:38:431695 frame_number_(0),
1696 has_arb_robustness_(false),
1697 reset_status_(GL_NO_ERROR) {
[email protected]3b1ecc262011-08-03 22:49:571698 DCHECK(group);
1699
[email protected]b1122982010-05-17 23:04:241700 attrib_0_value_.v[0] = 0.0f;
1701 attrib_0_value_.v[1] = 0.0f;
1702 attrib_0_value_.v[2] = 0.0f;
1703 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151704
[email protected]c2f8c8402010-12-06 18:07:241705 // The shader translator is used for WebGL even when running on EGL
1706 // because additional restrictions are needed (like only enabling
1707 // GL_OES_standard_derivatives on demand). It is used for the unit
1708 // tests because
1709 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1710 // empty string to CompileShader and this is not a valid shader.
1711 // TODO(apatrick): fix this test.
1712 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
1713 !feature_info_->feature_flags().chromium_webglsl) ||
[email protected]b9363b22010-06-09 22:06:151714 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) {
1715 use_shader_translator_ = false;
1716 }
[email protected]473c01ccb2011-06-07 01:33:301717
1718 // TODO(gman): Consider setting these based on GPU and/or driver.
1719 if (IsAngle()) {
1720 teximage2d_faster_than_texsubimage2d_ = false;
1721 bufferdata_faster_than_buffersubdata_ = false;
1722 }
[email protected]96449d2c2009-11-25 00:01:321723}
1724
[email protected]c410da802011-03-14 19:17:411725bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:381726 const scoped_refptr<gfx::GLSurface>& surface,
1727 const scoped_refptr<gfx::GLContext>& context,
[email protected]c410da802011-03-14 19:17:411728 const gfx::Size& size,
1729 const DisallowedExtensions& disallowed_extensions,
1730 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:241731 const std::vector<int32>& attribs) {
[email protected]4bedba72010-04-20 22:08:541732 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301733 DCHECK(!context_.get());
1734
[email protected]fbe20372011-06-01 01:46:381735 // Take ownership of the GLSurface. TODO(apatrick): once the parent / child
1736 // context is retired, the decoder should not take an initial surface as
1737 // an argument to this function.
1738 // Maybe create a short lived offscreen GLSurface for the purpose of
1739 // initializing the decoder's GLContext.
1740 surface_ = surface;
[email protected]f62a5ab2011-05-23 20:34:151741
[email protected]66791e382010-07-14 20:48:301742 // Take ownership of the GLContext.
[email protected]fbe20372011-06-01 01:46:381743 context_ = context;
[email protected]d37231fa2010-04-09 21:16:021744
[email protected]246a70452010-03-05 21:53:501745 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:011746 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
1747 << "MakeCurrent failed.";
[email protected]246a70452010-03-05 21:53:501748 Destroy();
1749 return false;
[email protected]eb54a562010-01-20 21:55:181750 }
1751
[email protected]c410da802011-03-14 19:17:411752 if (!group_->Initialize(disallowed_extensions, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:221753 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:391754 << "failed to initialize.";
1755 Destroy();
[email protected]ae1741092010-11-17 19:16:031756 return false;
[email protected]a3ded6d2010-10-19 06:44:391757 }
1758
[email protected]246a70452010-03-05 21:53:501759 CHECK_GL_ERROR();
[email protected]c410da802011-03-14 19:17:411760 disallowed_extensions_ = disallowed_extensions;
[email protected]246a70452010-03-05 21:53:501761
[email protected]f39f4b3f2010-05-12 17:04:081762 vertex_attrib_manager_.Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:321763
[email protected]302ce6d2011-07-07 23:28:111764 util_.set_num_compressed_texture_formats(
1765 validators_->compressed_texture_format.GetValues().size());
1766
[email protected]1071e572011-02-09 20:00:121767 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1768 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
1769 // OpenGL ES 2.0 does not have this issue.
1770 glEnableVertexAttribArray(0);
1771 }
[email protected]b1122982010-05-17 23:04:241772 glGenBuffersARB(1, &attrib_0_buffer_id_);
1773 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
1774 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
1775 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:401776 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:081777
[email protected]246a70452010-03-05 21:53:501778 texture_units_.reset(
1779 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:151780 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:491781 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:311782 // We want the last bind to be 2D.
1783 TextureManager::TextureInfo* info;
1784 if (feature_info_->feature_flags().oes_egl_image_external) {
1785 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_EXTERNAL_OES);
1786 texture_units_[tt].bound_texture_external_oes = info;
1787 glBindTexture(GL_TEXTURE_EXTERNAL_OES, info->service_id());
1788 }
1789 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:491790 texture_units_[tt].bound_texture_cube_map = info;
1791 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
1792 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
1793 texture_units_[tt].bound_texture_2d = info;
1794 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:151795 }
[email protected]00f893d2010-08-24 18:55:491796 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:501797 CHECK_GL_ERROR();
1798
[email protected]297ca1c2011-06-20 23:08:461799 ContextCreationAttribParser attrib_parser;
1800 if (!attrib_parser.Parse(attribs))
1801 return false;
[email protected]41c56362011-06-14 16:47:431802
[email protected]297ca1c2011-06-20 23:08:461803 // These are NOT if the back buffer has these proprorties. They are
1804 // if we want the command buffer to enforce them regardless of what
1805 // the real backbuffer is assuming the real back buffer gives us more than
1806 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
1807 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
1808 // can't do anything about that.
1809
1810 GLint v = 0;
1811 glGetIntegerv(GL_ALPHA_BITS, &v);
1812 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
1813 // user requested RGB then RGB. If the user did not specify a preference than
1814 // use whatever we were given. Same for DEPTH and STENCIL.
1815 back_buffer_color_format_ =
1816 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
1817 glGetIntegerv(GL_DEPTH_BITS, &v);
1818 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
1819 glGetIntegerv(GL_STENCIL_BITS, &v);
1820 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
1821
1822 if (surface_->IsOffscreen()) {
[email protected]34ff8b0c2010-10-01 20:06:021823 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:541824 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:021825 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
1826 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:431827 // max_sample_count must be initialized to a sane value. If
1828 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
1829 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:021830 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
1831 offscreen_target_samples_ = std::min(attrib_parser.samples_,
1832 max_sample_count);
1833 } else {
1834 offscreen_target_samples_ = 1;
1835 }
1836
1837 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
1838 const bool rgb8_supported =
1839 context_->HasExtension("GL_OES_rgb8_rgba8");
1840 // The only available default render buffer formats in GLES2 have very
1841 // little precision. Don't enable multisampling unless 8-bit render
1842 // buffer formats are available--instead fall back to 8-bit textures.
1843 if (rgb8_supported && offscreen_target_samples_ > 1) {
1844 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1845 GL_RGBA8 : GL_RGB8;
1846 } else {
1847 offscreen_target_samples_ = 1;
1848 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1849 GL_RGBA : GL_RGB;
1850 }
1851
1852 // ANGLE only supports packed depth/stencil formats, so use it if it is
1853 // available.
1854 const bool depth24_stencil8_supported =
1855 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271856 VLOG(1) << "GL_OES_packed_depth_stencil "
1857 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:001858 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1859 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021860 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1861 offscreen_target_stencil_format_ = 0;
1862 } else {
1863 // It may be the case that this depth/stencil combination is not
1864 // supported, but this will be checked later by CheckFramebufferStatus.
1865 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1866 GL_DEPTH_COMPONENT16 : 0;
1867 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1868 GL_STENCIL_INDEX8 : 0;
1869 }
1870 } else {
1871 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1872 GL_RGBA : GL_RGB;
1873
1874 // If depth is requested at all, use the packed depth stencil format if
1875 // it's available, as some desktop GL drivers don't support any non-packed
1876 // formats for depth attachments.
1877 const bool depth24_stencil8_supported =
1878 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271879 VLOG(1) << "GL_EXT_packed_depth_stencil "
1880 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:021881
[email protected]71ee3642010-10-14 18:08:001882 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1883 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021884 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1885 offscreen_target_stencil_format_ = 0;
1886 } else {
1887 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1888 GL_DEPTH_COMPONENT : 0;
1889 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1890 GL_STENCIL_INDEX : 0;
1891 }
1892 }
1893
[email protected]97872062010-11-03 19:07:051894 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
1895 GL_RGBA : GL_RGB;
1896
[email protected]6217d392010-03-25 22:08:351897 // Create the target frame buffer. This is the one that the client renders
1898 // directly to.
1899 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
1900 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021901 // Due to GLES2 format limitations, either the color texture (for
1902 // non-multisampling) or the color render buffer (for multisampling) will be
1903 // attached to the offscreen frame buffer. The render buffer has more
1904 // limited formats available to it, but the texture can't do multisampling.
1905 if (IsOffscreenBufferMultisampled()) {
1906 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
1907 offscreen_target_color_render_buffer_->Create();
1908 } else {
1909 offscreen_target_color_texture_.reset(new Texture(this));
1910 offscreen_target_color_texture_->Create();
1911 }
1912 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151913 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021914 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151915 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:351916
1917 // Create the saved offscreen texture. The target frame buffer is copied
1918 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021919 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
1920 offscreen_saved_frame_buffer_->Create();
1921 //
[email protected]6217d392010-03-25 22:08:351922 offscreen_saved_color_texture_.reset(new Texture(this));
1923 offscreen_saved_color_texture_->Create();
1924
[email protected]6217d392010-03-25 22:08:351925 // Allocate the render buffers at their initial size and check the status
1926 // of the frame buffers is okay.
[email protected]d37231fa2010-04-09 21:16:021927 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:351928 if (!UpdateOffscreenFrameBufferSize()) {
[email protected]d0498742010-09-20 20:27:011929 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:351930 Destroy();
1931 return false;
1932 }
1933
1934 // Bind to the new default frame buffer (the offscreen target frame buffer).
1935 // This should now be associated with ID zero.
1936 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
[email protected]a3a93e7b2010-08-28 00:48:561937
1938 glGenFramebuffersEXT(1, &copy_texture_to_parent_texture_fb_);
[email protected]6217d392010-03-25 22:08:351939 }
1940
[email protected]76a0ee102010-04-07 21:03:041941 // OpenGL ES 2.0 implicitly enables the desktop GL capability
1942 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
1943 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:371944 // mailing list archives. It also implicitly enables the desktop GL
1945 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
1946 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:151947 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1948 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:371949 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:151950 }
[email protected]de17df392010-04-23 21:09:411951
[email protected]38d139d2011-07-14 00:38:431952 has_arb_robustness_ = context->HasExtension("GL_ARB_robustness");
1953
[email protected]c2f8c8402010-12-06 18:07:241954 if (!InitializeShaderTranslator()) {
1955 return false;
[email protected]de17df392010-04-23 21:09:411956 }
[email protected]76a0ee102010-04-07 21:03:041957
[email protected]246a70452010-03-05 21:53:501958 return true;
[email protected]96449d2c2009-11-25 00:01:321959}
1960
[email protected]302ce6d2011-07-07 23:28:111961void GLES2DecoderImpl::UpdateCapabilities() {
1962 util_.set_num_compressed_texture_formats(
1963 validators_->compressed_texture_format.GetValues().size());
1964 util_.set_num_shader_binary_formats(
1965 validators_->shader_binary_format.GetValues().size());
1966}
1967
[email protected]c2f8c8402010-12-06 18:07:241968bool GLES2DecoderImpl::InitializeShaderTranslator() {
1969 // Re-check the state of use_shader_translator_ each time this is called.
1970 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
1971 feature_info_->feature_flags().chromium_webglsl &&
1972 !use_shader_translator_) {
1973 use_shader_translator_ = true;
1974 }
1975 if (!use_shader_translator_) {
1976 return true;
1977 }
1978 ShBuiltInResources resources;
1979 ShInitBuiltInResources(&resources);
1980 resources.MaxVertexAttribs = group_->max_vertex_attribs();
1981 resources.MaxVertexUniformVectors =
1982 group_->max_vertex_uniform_vectors();
1983 resources.MaxVaryingVectors = group_->max_varying_vectors();
1984 resources.MaxVertexTextureImageUnits =
1985 group_->max_vertex_texture_image_units();
1986 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
1987 resources.MaxTextureImageUnits = group_->max_texture_image_units();
1988 resources.MaxFragmentUniformVectors =
1989 group_->max_fragment_uniform_vectors();
1990 resources.MaxDrawBuffers = 1;
1991 resources.OES_standard_derivatives =
1992 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
1993 vertex_translator_.reset(new ShaderTranslator);
1994 ShShaderSpec shader_spec = feature_info_->feature_flags().chromium_webglsl ?
1995 SH_WEBGL_SPEC : SH_GLES2_SPEC;
1996 bool is_glsl_es =
1997 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
1998 if (!vertex_translator_->Init(
1999 SH_VERTEX_SHADER, shader_spec, &resources, is_glsl_es)) {
2000 LOG(ERROR) << "Could not initialize vertex shader translator.";
2001 Destroy();
2002 return false;
2003 }
2004 fragment_translator_.reset(new ShaderTranslator);
2005 if (!fragment_translator_->Init(
2006 SH_FRAGMENT_SHADER, shader_spec, &resources, is_glsl_es)) {
2007 LOG(ERROR) << "Could not initialize fragment shader translator.";
2008 Destroy();
2009 return false;
2010 }
2011 return true;
2012}
2013
[email protected]ae51d192010-04-27 00:48:032014bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472015 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032016 if (GetBufferInfo(client_ids[ii])) {
2017 return false;
2018 }
2019 }
2020 scoped_array<GLuint> service_ids(new GLuint[n]);
2021 glGenBuffersARB(n, service_ids.get());
2022 for (GLsizei ii = 0; ii < n; ++ii) {
2023 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2024 }
2025 return true;
2026}
2027
2028bool GLES2DecoderImpl::GenFramebuffersHelper(
2029 GLsizei n, const GLuint* client_ids) {
2030 for (GLsizei ii = 0; ii < n; ++ii) {
2031 if (GetFramebufferInfo(client_ids[ii])) {
2032 return false;
2033 }
2034 }
2035 scoped_array<GLuint> service_ids(new GLuint[n]);
2036 glGenFramebuffersEXT(n, service_ids.get());
2037 for (GLsizei ii = 0; ii < n; ++ii) {
2038 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2039 }
2040 return true;
2041}
2042
2043bool GLES2DecoderImpl::GenRenderbuffersHelper(
2044 GLsizei n, const GLuint* client_ids) {
2045 for (GLsizei ii = 0; ii < n; ++ii) {
2046 if (GetRenderbufferInfo(client_ids[ii])) {
2047 return false;
2048 }
2049 }
2050 scoped_array<GLuint> service_ids(new GLuint[n]);
2051 glGenRenderbuffersEXT(n, service_ids.get());
2052 for (GLsizei ii = 0; ii < n; ++ii) {
2053 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2054 }
2055 return true;
2056}
2057
2058bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2059 for (GLsizei ii = 0; ii < n; ++ii) {
2060 if (GetTextureInfo(client_ids[ii])) {
2061 return false;
2062 }
2063 }
2064 scoped_array<GLuint> service_ids(new GLuint[n]);
2065 glGenTextures(n, service_ids.get());
2066 for (GLsizei ii = 0; ii < n; ++ii) {
2067 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2068 }
2069 return true;
2070}
2071
2072void GLES2DecoderImpl::DeleteBuffersHelper(
2073 GLsizei n, const GLuint* client_ids) {
2074 for (GLsizei ii = 0; ii < n; ++ii) {
2075 BufferManager::BufferInfo* info = GetBufferInfo(client_ids[ii]);
2076 if (info) {
2077 GLuint service_id = info->service_id();
2078 glDeleteBuffersARB(1, &service_id);
2079 RemoveBufferInfo(client_ids[ii]);
2080 }
[email protected]a93bb842010-02-16 23:03:472081 }
[email protected]07f54fcc2009-12-22 02:46:302082}
2083
[email protected]ae51d192010-04-27 00:48:032084void GLES2DecoderImpl::DeleteFramebuffersHelper(
2085 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582086 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032087 FramebufferManager::FramebufferInfo* info =
2088 GetFramebufferInfo(client_ids[ii]);
2089 if (info) {
[email protected]297ca1c2011-06-20 23:08:462090 if (info == bound_draw_framebuffer_) {
2091 bound_draw_framebuffer_ = NULL;
2092 state_dirty_ = true;
2093 }
[email protected]ae51d192010-04-27 00:48:032094 GLuint service_id = info->service_id();
2095 glDeleteFramebuffersEXT(1, &service_id);
2096 RemoveFramebufferInfo(client_ids[ii]);
2097 }
[email protected]a25fa872010-03-25 02:57:582098 }
[email protected]07f54fcc2009-12-22 02:46:302099}
2100
[email protected]ae51d192010-04-27 00:48:032101void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2102 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582103 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032104 RenderbufferManager::RenderbufferInfo* info =
2105 GetRenderbufferInfo(client_ids[ii]);
2106 if (info) {
[email protected]297ca1c2011-06-20 23:08:462107 state_dirty_ = true;
[email protected]ae51d192010-04-27 00:48:032108 GLuint service_id = info->service_id();
2109 glDeleteRenderbuffersEXT(1, &service_id);
2110 RemoveRenderbufferInfo(client_ids[ii]);
2111 }
[email protected]a25fa872010-03-25 02:57:582112 }
[email protected]07f54fcc2009-12-22 02:46:302113}
2114
[email protected]ae51d192010-04-27 00:48:032115void GLES2DecoderImpl::DeleteTexturesHelper(
2116 GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472117 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032118 TextureManager::TextureInfo* info = GetTextureInfo(client_ids[ii]);
2119 if (info) {
[email protected]297ca1c2011-06-20 23:08:462120 if (info->IsAttachedToFramebuffer()) {
2121 state_dirty_ = true;
2122 }
[email protected]5f4f2a732011-07-30 00:47:552123 GLuint service_id = info->service_id();
2124 glDeleteTextures(1, &service_id);
[email protected]ae51d192010-04-27 00:48:032125 RemoveTextureInfo(client_ids[ii]);
2126 }
[email protected]a93bb842010-02-16 23:03:472127 }
[email protected]07f54fcc2009-12-22 02:46:302128}
2129
[email protected]43f28f832010-02-03 02:28:482130// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322131
[email protected]eb54a562010-01-20 21:55:182132bool GLES2DecoderImpl::MakeCurrent() {
[email protected]38d139d2011-07-14 00:38:432133 bool result = context_.get() ? context_->MakeCurrent(surface_.get()) : false;
2134 if (result && WasContextLost()) {
2135 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2136 result = false;
2137 }
2138
2139 return result;
[email protected]eb54a562010-01-20 21:55:182140}
2141
[email protected]8e3e0662010-08-23 18:46:302142void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
2143 glBindRenderbufferEXT(
2144 GL_RENDERBUFFER,
2145 bound_renderbuffer_ ? bound_renderbuffer_->service_id() : 0);
2146}
2147
2148static void RebindCurrentFramebuffer(
2149 GLenum target,
2150 FramebufferManager::FramebufferInfo* info,
2151 FrameBuffer* offscreen_frame_buffer) {
2152 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462153
[email protected]8e3e0662010-08-23 18:46:302154 if (framebuffer_id == 0 && offscreen_frame_buffer) {
2155 framebuffer_id = offscreen_frame_buffer->id();
2156 }
[email protected]297ca1c2011-06-20 23:08:462157
[email protected]8e3e0662010-08-23 18:46:302158 glBindFramebufferEXT(target, framebuffer_id);
2159}
2160
2161void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]297ca1c2011-06-20 23:08:462162 state_dirty_ = true;
2163
[email protected]a3ded6d2010-10-19 06:44:392164 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302165 RebindCurrentFramebuffer(
2166 GL_FRAMEBUFFER,
2167 bound_draw_framebuffer_.get(),
2168 offscreen_target_frame_buffer_.get());
2169 } else {
2170 RebindCurrentFramebuffer(
2171 GL_READ_FRAMEBUFFER_EXT,
2172 bound_read_framebuffer_.get(),
2173 offscreen_target_frame_buffer_.get());
2174 RebindCurrentFramebuffer(
2175 GL_DRAW_FRAMEBUFFER_EXT,
2176 bound_draw_framebuffer_.get(),
2177 offscreen_target_frame_buffer_.get());
2178 }
2179}
2180
2181void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2182 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2183 GLuint last_id;
2184 if (info.bound_texture_2d) {
2185 last_id = info.bound_texture_2d->service_id();
2186 } else {
2187 last_id = 0;
2188 }
2189
2190 glBindTexture(GL_TEXTURE_2D, last_id);
2191 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2192}
2193
[email protected]3a03a8f2011-03-19 00:51:272194bool GLES2DecoderImpl::CheckFramebufferComplete(const char* func_name) {
2195 if (bound_draw_framebuffer_ && bound_draw_framebuffer_->IsNotComplete()) {
[email protected]be45d7c2011-04-15 18:03:352196 SetGLError(GL_INVALID_FRAMEBUFFER_OPERATION,
[email protected]3a03a8f2011-03-19 00:51:272197 (std::string(func_name) + " framebuffer incomplete").c_str());
2198 return false;
2199 }
2200 return true;
2201}
2202
[email protected]8e3e0662010-08-23 18:46:302203gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
2204 if (bound_read_framebuffer_ != 0) {
[email protected]9edc6b22010-12-23 02:00:262205 const FramebufferManager::FramebufferInfo::Attachment* attachment =
2206 bound_read_framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
2207 if (attachment) {
2208 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502209 }
[email protected]9edc6b22010-12-23 02:00:262210 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022211 } else if (offscreen_target_frame_buffer_.get()) {
2212 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352213 } else {
[email protected]f62a5ab2011-05-23 20:34:152214 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022215 }
[email protected]246a70452010-03-05 21:53:502216}
2217
[email protected]9edc6b22010-12-23 02:00:262218GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
2219 if (bound_read_framebuffer_ != 0) {
[email protected]297ca1c2011-06-20 23:08:462220 return bound_read_framebuffer_->GetColorAttachmentFormat();
2221 } else if (offscreen_target_frame_buffer_.get()) {
2222 return offscreen_target_color_format_;
2223 } else {
2224 return back_buffer_color_format_;
2225 }
2226}
2227
2228GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
2229 if (bound_draw_framebuffer_ != 0) {
2230 return bound_draw_framebuffer_->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262231 } else if (offscreen_target_frame_buffer_.get()) {
2232 return offscreen_target_color_format_;
2233 } else {
[email protected]32fe9aa2011-01-21 23:47:132234 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262235 }
2236}
2237
[email protected]6217d392010-03-25 22:08:352238bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
[email protected]34ff8b0c2010-10-01 20:06:022239 if (offscreen_size_ == pending_offscreen_size_)
[email protected]6217d392010-03-25 22:08:352240 return true;
2241
[email protected]34ff8b0c2010-10-01 20:06:022242 offscreen_size_ = pending_offscreen_size_;
[email protected]a470d612011-02-25 04:15:002243 int w = offscreen_size_.width();
2244 int h = offscreen_size_.height();
2245 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
2246 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2247 << "to allocate storage due to excessive dimensions.";
2248 return false;
2249 }
[email protected]34ff8b0c2010-10-01 20:06:022250
[email protected]6217d392010-03-25 22:08:352251 // Reallocate the offscreen target buffers.
[email protected]34ff8b0c2010-10-01 20:06:022252 DCHECK(offscreen_target_color_format_);
2253 if (IsOffscreenBufferMultisampled()) {
2254 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2255 pending_offscreen_size_, offscreen_target_color_format_,
2256 offscreen_target_samples_)) {
2257 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2258 << "to allocate storage for offscreen target color buffer.";
2259 return false;
2260 }
2261 } else {
2262 if (!offscreen_target_color_texture_->AllocateStorage(
2263 pending_offscreen_size_, offscreen_target_color_format_)) {
2264 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2265 << "to allocate storage for offscreen target color texture.";
2266 return false;
2267 }
2268 }
2269 if (offscreen_target_depth_format_ &&
2270 !offscreen_target_depth_render_buffer_->AllocateStorage(
2271 pending_offscreen_size_, offscreen_target_depth_format_,
2272 offscreen_target_samples_)) {
[email protected]d0498742010-09-20 20:27:012273 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
[email protected]34ff8b0c2010-10-01 20:06:022274 << "to allocate storage for offscreen target depth buffer.";
2275 return false;
2276 }
2277 if (offscreen_target_stencil_format_ &&
2278 !offscreen_target_stencil_render_buffer_->AllocateStorage(
2279 pending_offscreen_size_, offscreen_target_stencil_format_,
2280 offscreen_target_samples_)) {
2281 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2282 << "to allocate storage for offscreen target stencil buffer.";
[email protected]6217d392010-03-25 22:08:352283 return false;
2284 }
2285
[email protected]2f2d7042010-04-14 21:45:582286 // Attach the offscreen target buffers to the target frame buffer.
[email protected]34ff8b0c2010-10-01 20:06:022287 if (IsOffscreenBufferMultisampled()) {
[email protected]b9363b22010-06-09 22:06:152288 offscreen_target_frame_buffer_->AttachRenderBuffer(
[email protected]34ff8b0c2010-10-01 20:06:022289 GL_COLOR_ATTACHMENT0,
2290 offscreen_target_color_render_buffer_.get());
[email protected]b9363b22010-06-09 22:06:152291 } else {
[email protected]34ff8b0c2010-10-01 20:06:022292 offscreen_target_frame_buffer_->AttachRenderTexture(
2293 offscreen_target_color_texture_.get());
2294 }
2295 if (offscreen_target_depth_format_) {
2296 offscreen_target_frame_buffer_->AttachRenderBuffer(
2297 GL_DEPTH_ATTACHMENT,
2298 offscreen_target_depth_render_buffer_.get());
2299 }
2300 const bool packed_depth_stencil =
2301 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2302 if (packed_depth_stencil) {
[email protected]b9363b22010-06-09 22:06:152303 offscreen_target_frame_buffer_->AttachRenderBuffer(
2304 GL_STENCIL_ATTACHMENT,
2305 offscreen_target_depth_render_buffer_.get());
[email protected]34ff8b0c2010-10-01 20:06:022306 } else if (offscreen_target_stencil_format_) {
2307 offscreen_target_frame_buffer_->AttachRenderBuffer(
2308 GL_STENCIL_ATTACHMENT,
2309 offscreen_target_stencil_render_buffer_.get());
[email protected]b9363b22010-06-09 22:06:152310 }
[email protected]34ff8b0c2010-10-01 20:06:022311
[email protected]6217d392010-03-25 22:08:352312 if (offscreen_target_frame_buffer_->CheckStatus() !=
2313 GL_FRAMEBUFFER_COMPLETE) {
[email protected]d0498742010-09-20 20:27:012314 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2315 << "because offscreen FBO was incomplete.";
[email protected]6217d392010-03-25 22:08:352316 return false;
2317 }
2318
[email protected]c007aa02010-09-02 22:22:402319 // Clear the target frame buffer.
2320 {
2321 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
[email protected]297ca1c2011-06-20 23:08:462322 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2323 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
[email protected]c007aa02010-09-02 22:22:402324 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2325 glClearStencil(0);
[email protected]297ca1c2011-06-20 23:08:462326 glStencilMaskSeparate(GL_FRONT, -1);
2327 glStencilMaskSeparate(GL_BACK, -1);
[email protected]c007aa02010-09-02 22:22:402328 glClearDepth(0);
2329 glDepthMask(GL_TRUE);
2330 glDisable(GL_SCISSOR_TEST);
[email protected]2f2d7042010-04-14 21:45:582331 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
[email protected]c007aa02010-09-02 22:22:402332 RestoreClearState();
[email protected]2f2d7042010-04-14 21:45:582333 }
[email protected]2f2d7042010-04-14 21:45:582334
[email protected]9a5afa432011-07-22 18:16:392335 // Allocate the offscreen saved color texture.
2336 DCHECK(offscreen_saved_color_format_);
2337 offscreen_saved_color_texture_->AllocateStorage(
2338 pending_offscreen_size_, offscreen_saved_color_format_);
[email protected]d37231fa2010-04-09 21:16:022339
[email protected]9a5afa432011-07-22 18:16:392340 offscreen_saved_frame_buffer_->AttachRenderTexture(
2341 offscreen_saved_color_texture_.get());
2342 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2343 GL_FRAMEBUFFER_COMPLETE) {
2344 LOG(ERROR) << "GLES2DecoderImpl::UpdateOffscreenFrameBufferSize failed "
2345 << "because offscreen saved FBO was incomplete.";
2346 return false;
[email protected]34ff8b0c2010-10-01 20:06:022347 }
2348
[email protected]de26b3c2011-08-03 21:54:272349 // Destroy the offscreen resolved framebuffers.
2350 if (offscreen_resolved_frame_buffer_.get())
2351 offscreen_resolved_frame_buffer_->Destroy();
2352 if (offscreen_resolved_color_texture_.get())
2353 offscreen_resolved_color_texture_->Destroy();
2354 offscreen_resolved_color_texture_.reset();
2355 offscreen_resolved_frame_buffer_.reset();
2356
[email protected]9a5afa432011-07-22 18:16:392357 // Clear the offscreen color texture.
2358 {
2359 ScopedFrameBufferBinder binder(this, offscreen_saved_frame_buffer_->id());
2360 glClearColor(0, 0, 0, 0);
2361 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2362 glDisable(GL_SCISSOR_TEST);
2363 glClear(GL_COLOR_BUFFER_BIT);
2364 RestoreClearState();
2365 }
2366
2367 UpdateParentTextureInfo();
2368
2369 return true;
2370}
2371
2372void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]34ff8b0c2010-10-01 20:06:022373 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582374 // Update the info about the offscreen saved color texture in the parent.
2375 // The reference to the parent is a weak pointer and will become null if the
2376 // parent is later destroyed.
[email protected]6217d392010-03-25 22:08:352377 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]8d25d042010-06-16 19:48:142378 GLuint client_id;
[email protected]262d7aa2010-12-03 22:07:292379 TextureManager* parent_texture_manager = parent_->texture_manager();
2380 CHECK(parent_texture_manager->GetClientId(service_id, &client_id));
[email protected]8d25d042010-06-16 19:48:142381 TextureManager::TextureInfo* info = parent_->GetTextureInfo(client_id);
[email protected]6217d392010-03-25 22:08:352382 DCHECK(info);
2383
[email protected]262d7aa2010-12-03 22:07:292384 parent_texture_manager->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:112385 feature_info_,
[email protected]ef526492010-06-02 23:12:252386 info,
2387 GL_TEXTURE_2D,
2388 0, // level
2389 GL_RGBA,
2390 pending_offscreen_size_.width(),
2391 pending_offscreen_size_.height(),
2392 1, // depth
2393 0, // border
2394 GL_RGBA,
2395 GL_UNSIGNED_BYTE);
[email protected]262d7aa2010-12-03 22:07:292396 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042397 feature_info_,
2398 info,
2399 GL_TEXTURE_MAG_FILTER,
2400 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292401 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042402 feature_info_,
2403 info,
2404 GL_TEXTURE_MIN_FILTER,
2405 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292406 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042407 feature_info_,
2408 info,
2409 GL_TEXTURE_WRAP_S,
2410 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292411 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042412 feature_info_,
2413 info,
2414 GL_TEXTURE_WRAP_T,
2415 GL_CLAMP_TO_EDGE);
[email protected]0c8c9d22010-06-25 17:36:392416 }
[email protected]6217d392010-03-25 22:08:352417}
2418
[email protected]7ff86b92010-11-25 17:50:002419void GLES2DecoderImpl::SetResizeCallback(Callback1<gfx::Size>::Type* callback) {
2420 resize_callback_.reset(callback);
2421}
2422
[email protected]43f28f832010-02-03 02:28:482423void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
2424 swap_buffers_callback_.reset(callback);
2425}
2426
[email protected]1318e922010-09-17 22:03:162427bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2428 uint32* service_texture_id) {
2429 TextureManager::TextureInfo* texture =
2430 texture_manager()->GetTextureInfo(client_texture_id);
2431 if (texture) {
2432 *service_texture_id = texture->service_id();
2433 return true;
2434 }
2435 return false;
2436}
2437
[email protected]96449d2c2009-11-25 00:01:322438void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392439 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052440
2441 if (group_.get())
2442 group_->set_have_context(have_context);
2443
[email protected]3c644d82011-06-20 19:58:242444 SetParent(NULL, 0);
2445
[email protected]eadc96792010-10-27 19:39:392446 if (have_context) {
[email protected]ca488e12010-12-13 20:06:142447 if (current_program_) {
2448 program_manager()->UnuseProgram(shader_manager(), current_program_);
2449 current_program_ = NULL;
2450 }
2451
[email protected]b1122982010-05-17 23:04:242452 if (attrib_0_buffer_id_) {
2453 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2454 }
[email protected]8fbedc02010-11-18 18:43:402455 if (fixed_attrib_buffer_id_) {
2456 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2457 }
[email protected]b1122982010-05-17 23:04:242458
[email protected]3c644d82011-06-20 19:58:242459 if (copy_texture_to_parent_texture_fb_)
[email protected]a3a93e7b2010-08-28 00:48:562460 glDeleteFramebuffersEXT(1, &copy_texture_to_parent_texture_fb_);
[email protected]6217d392010-03-25 22:08:352461
[email protected]97872062010-11-03 19:07:052462 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542463 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052464 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542465 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052466 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022467 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052468 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152469 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052470 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152471 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052472 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022473 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052474 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542475 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:272476 if (offscreen_resolved_frame_buffer_.get())
2477 offscreen_resolved_frame_buffer_->Destroy();
2478 if (offscreen_resolved_color_texture_.get())
2479 offscreen_resolved_color_texture_->Destroy();
[email protected]66791e382010-07-14 20:48:302480
[email protected]eadc96792010-10-27 19:39:392481 // must release the ContextGroup before destroying the context as its
2482 // destructor uses GL.
2483 group_ = NULL;
[email protected]97872062010-11-03 19:07:052484 } else {
2485 if (offscreen_target_frame_buffer_.get())
2486 offscreen_target_frame_buffer_->Invalidate();
2487 if (offscreen_target_color_texture_.get())
2488 offscreen_target_color_texture_->Invalidate();
2489 if (offscreen_target_color_render_buffer_.get())
2490 offscreen_target_color_render_buffer_->Invalidate();
2491 if (offscreen_target_depth_render_buffer_.get())
2492 offscreen_target_depth_render_buffer_->Invalidate();
2493 if (offscreen_target_stencil_render_buffer_.get())
2494 offscreen_target_stencil_render_buffer_->Invalidate();
2495 if (offscreen_saved_frame_buffer_.get())
2496 offscreen_saved_frame_buffer_->Invalidate();
2497 if (offscreen_saved_color_texture_.get())
2498 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:272499 if (offscreen_resolved_frame_buffer_.get())
2500 offscreen_resolved_frame_buffer_->Invalidate();
2501 if (offscreen_resolved_color_texture_.get())
2502 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022503 }
[email protected]97872062010-11-03 19:07:052504
[email protected]fe871662011-06-16 20:43:052505 if (context_.get()) {
2506 context_->ReleaseCurrent(NULL);
[email protected]0fc35742011-04-13 17:57:542507 context_->Destroy();
[email protected]fe871662011-06-16 20:43:052508 }
[email protected]fbe20372011-06-01 01:46:382509 context_ = NULL;
[email protected]0fc35742011-04-13 17:57:542510
[email protected]97872062010-11-03 19:07:052511 offscreen_target_frame_buffer_.reset();
2512 offscreen_target_color_texture_.reset();
2513 offscreen_target_color_render_buffer_.reset();
2514 offscreen_target_depth_render_buffer_.reset();
2515 offscreen_target_stencil_render_buffer_.reset();
2516 offscreen_saved_frame_buffer_.reset();
2517 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:272518 offscreen_resolved_frame_buffer_.reset();
2519 offscreen_resolved_color_texture_.reset();
[email protected]96449d2c2009-11-25 00:01:322520}
2521
[email protected]3c644d82011-06-20 19:58:242522bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
2523 uint32 new_parent_texture_id) {
[email protected]9a5afa432011-07-22 18:16:392524 if (!offscreen_saved_color_texture_.get())
2525 return false;
2526
[email protected]3c644d82011-06-20 19:58:242527 // Remove the saved frame buffer mapping from the parent decoder. The
2528 // parent pointer is a weak pointer so it will be null if the parent has
2529 // already been destroyed.
2530 if (parent_) {
2531 // First check the texture has been mapped into the parent. This might not
2532 // be the case if initialization failed midway through.
2533 GLuint service_id = offscreen_saved_color_texture_->id();
2534 GLuint client_id = 0;
2535 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
2536 parent_->texture_manager()->RemoveTextureInfo(feature_info_, client_id);
2537 }
2538 }
2539
2540 GLES2DecoderImpl* new_parent_impl = static_cast<GLES2DecoderImpl*>(
2541 new_parent);
2542 if (new_parent_impl) {
2543 // Map the ID of the saved offscreen texture into the parent so that
2544 // it can reference it.
2545 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]98687862011-07-11 23:31:302546
2547 // Replace texture info when ID is already in use by parent.
2548 if (new_parent_impl->texture_manager()->GetTextureInfo(
2549 new_parent_texture_id))
2550 new_parent_impl->texture_manager()->RemoveTextureInfo(
2551 feature_info_, new_parent_texture_id);
2552
[email protected]3c644d82011-06-20 19:58:242553 TextureManager::TextureInfo* info =
[email protected]5f4f2a732011-07-30 00:47:552554 new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id);
2555 info->SetNotOwned();
[email protected]3c644d82011-06-20 19:58:242556 new_parent_impl->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
2557
2558 parent_ = new_parent_impl->AsWeakPtr();
[email protected]9a5afa432011-07-22 18:16:392559
2560 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:242561 } else {
2562 parent_.reset();
2563 }
2564
2565 return true;
2566}
2567
[email protected]6217d392010-03-25 22:08:352568void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2569 // We can't resize the render buffers immediately because there might be a
2570 // partial frame rendered into them and we don't want the tail end of that
2571 // rendered into the reallocated storage. Defer until the next SwapBuffers.
[email protected]d37231fa2010-04-09 21:16:022572 pending_offscreen_size_ = size;
[email protected]6217d392010-03-25 22:08:352573}
2574
[email protected]269200b12010-11-18 22:53:062575void GLES2DecoderImpl::DoCopyTextureToParentTextureCHROMIUM(
[email protected]c007aa02010-09-02 22:22:402576 GLuint client_texture_id,
2577 GLuint parent_client_texture_id) {
[email protected]a3a93e7b2010-08-28 00:48:562578 if (parent_) {
[email protected]c007aa02010-09-02 22:22:402579 TextureManager::TextureInfo* texture = texture_manager()->GetTextureInfo(
2580 client_texture_id);
2581 TextureManager::TextureInfo* parent_texture =
2582 parent_->texture_manager()->GetTextureInfo(parent_client_texture_id);
[email protected]a3a93e7b2010-08-28 00:48:562583 if (!texture || !parent_texture) {
2584 current_decoder_error_ = error::kInvalidArguments;
2585 return;
2586 }
2587 ScopedFrameBufferBinder fb_binder(this, copy_texture_to_parent_texture_fb_);
2588 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2589 GL_COLOR_ATTACHMENT0,
2590 GL_TEXTURE_2D,
2591 texture->service_id(),
2592 0);
2593 ScopedTexture2DBinder tex_binder(this, parent_texture->service_id());
2594 GLsizei width, height;
2595 parent_texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height);
2596 glCopyTexImage2D(GL_TEXTURE_2D,
2597 0, // level
2598 GL_RGBA,
[email protected]c007aa02010-09-02 22:22:402599 0, 0, // x, y
[email protected]a3a93e7b2010-08-28 00:48:562600 width,
2601 height,
2602 0); // border
2603 }
2604}
2605
[email protected]43ecf372010-11-16 19:19:392606void GLES2DecoderImpl::DoResizeCHROMIUM(GLuint width, GLuint height) {
[email protected]2e7bbf22011-07-22 18:41:292607#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(TOUCH_UI)
[email protected]7ff86b92010-11-25 17:50:002608 // Make sure that we are done drawing to the back buffer before resizing.
2609 glFinish();
2610#endif
2611 if (resize_callback_.get()) {
2612 gfx::Size size(width, height);
2613 resize_callback_->Run(size);
2614 }
[email protected]43ecf372010-11-16 19:19:392615}
2616
[email protected]fbe20372011-06-01 01:46:382617void GLES2DecoderImpl::DoSetSurfaceCHROMIUM(GLint surface_id) {
2618 gfx::GLSurface* surface = surface_manager_->LookupSurface(surface_id);
2619 if (!surface)
2620 return;
2621
2622 surface_ = surface;
2623}
2624
[email protected]96449d2c2009-11-25 00:01:322625const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
2626 if (command_id > kStartPoint && command_id < kNumCommands) {
2627 return gles2::GetCommandName(static_cast<CommandId>(command_id));
2628 }
2629 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
2630}
2631
2632// Decode command with its arguments, and call the corresponding GL function.
2633// Note: args is a pointer to the command buffer. As such, it could be changed
2634// by a (malicious) client at any time, so if validation has to happen, it
2635// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:142636error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:322637 unsigned int command,
2638 unsigned int arg_count,
2639 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:142640 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192641 if (debug()) {
2642 // TODO(gman): Change output to something useful for NaCl.
[email protected]8e1b98a2011-06-14 23:39:532643 DLOG(INFO) << "[" << this << "]" << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192644 }
[email protected]96449d2c2009-11-25 00:01:322645 unsigned int command_index = command - kStartPoint - 1;
2646 if (command_index < arraysize(g_command_info)) {
2647 const CommandInfo& info = g_command_info[command_index];
2648 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
2649 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
2650 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:192651 uint32 immediate_data_size =
2652 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:322653 switch (command) {
2654 #define GLES2_CMD_OP(name) \
2655 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:192656 result = Handle ## name( \
2657 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:322658 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:192659 break; \
[email protected]96449d2c2009-11-25 00:01:322660
2661 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:322662 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:382663 }
2664 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:302665 GLenum error;
2666 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:382667 // TODO(gman): Change output to something useful for NaCl.
[email protected]8eee29c2010-04-29 03:38:292668 SetGLError(error, NULL);
[email protected]8e1b98a2011-06-14 23:39:532669 DLOG(INFO) << "[" << this << "]"
2670 << "GL ERROR: " << error << " : " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192671 }
[email protected]96449d2c2009-11-25 00:01:322672 }
2673 } else {
[email protected]f7a64ee2010-02-01 22:24:142674 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:322675 }
[email protected]b9849abf2009-11-25 19:13:192676 } else {
2677 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:322678 }
[email protected]a3a93e7b2010-08-28 00:48:562679 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
2680 result = current_decoder_error_;
2681 current_decoder_error_ = error::kNoError;
2682 }
[email protected]b9849abf2009-11-25 19:13:192683 return result;
[email protected]96449d2c2009-11-25 00:01:322684}
2685
[email protected]ae51d192010-04-27 00:48:032686void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
2687 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:502688}
2689
[email protected]ae51d192010-04-27 00:48:032690bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
2691 if (GetProgramInfo(client_id)) {
2692 return false;
2693 }
[email protected]96449d2c2009-11-25 00:01:322694 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:032695 if (service_id != 0) {
2696 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:322697 }
[email protected]ae51d192010-04-27 00:48:032698 return true;
[email protected]96449d2c2009-11-25 00:01:322699}
2700
[email protected]ae51d192010-04-27 00:48:032701bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
2702 if (GetShaderInfo(client_id)) {
2703 return false;
[email protected]96449d2c2009-11-25 00:01:322704 }
[email protected]ae51d192010-04-27 00:48:032705 GLuint service_id = glCreateShader(type);
2706 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:382707 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:032708 }
2709 return true;
[email protected]96449d2c2009-11-25 00:01:322710}
2711
[email protected]3916c97e2010-02-25 03:20:502712void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:452713 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]660858b2011-07-13 23:16:142714 if (texture_index >= group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:292715 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:502716 return;
2717 }
[email protected]36cef8ce2010-03-16 07:34:452718 active_texture_unit_ = texture_index;
2719 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:502720}
2721
[email protected]051b1372010-04-12 02:42:082722void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:502723 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082724 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032725 if (client_id != 0) {
2726 info = GetBufferInfo(client_id);
2727 if (!info) {
2728 // It's a new id so make a buffer info for it.
2729 glGenBuffersARB(1, &service_id);
2730 CreateBufferInfo(client_id, service_id);
2731 info = GetBufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:572732 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:102733 group_->GetIdAllocator(id_namespaces::kBuffers);
2734 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032735 }
[email protected]051b1372010-04-12 02:42:082736 }
[email protected]ae51d192010-04-27 00:48:032737 if (info) {
[email protected]4e8a5b122010-05-08 22:00:102738 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:292739 SetGLError(GL_INVALID_OPERATION,
2740 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:472741 return;
2742 }
[email protected]ae51d192010-04-27 00:48:032743 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:472744 }
[email protected]96449d2c2009-11-25 00:01:322745 switch (target) {
2746 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502747 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322748 break;
2749 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502750 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322751 break;
2752 default:
[email protected]a93bb842010-02-16 23:03:472753 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:322754 break;
2755 }
[email protected]051b1372010-04-12 02:42:082756 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:322757}
2758
[email protected]297ca1c2011-06-20 23:08:462759bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
2760 return (GLES2Util::GetChannelsForFormat(
2761 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
2762}
2763
2764bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
2765 if (bound_draw_framebuffer_) {
2766 return bound_draw_framebuffer_->HasDepthAttachment();
2767 }
2768 if (offscreen_target_frame_buffer_.get()) {
2769 return offscreen_target_depth_format_ != 0;
2770 }
2771 return back_buffer_has_depth_;
2772}
2773
2774bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
2775 if (bound_draw_framebuffer_) {
2776 return bound_draw_framebuffer_->HasStencilAttachment();
2777 }
2778 if (offscreen_target_frame_buffer_.get()) {
2779 return offscreen_target_stencil_format_ != 0 ||
2780 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2781 }
2782 return back_buffer_has_stencil_;
2783}
2784
2785void GLES2DecoderImpl::ApplyDirtyState() {
2786 if (state_dirty_) {
2787 glColorMask(
2788 mask_red_, mask_green_, mask_blue_,
2789 mask_alpha_ && BoundFramebufferHasColorAttachmentWithAlpha());
2790 bool have_depth = BoundFramebufferHasDepthAttachment();
2791 glDepthMask(mask_depth_ && have_depth);
2792 EnableDisable(GL_DEPTH_TEST, enable_depth_test_ && have_depth);
2793 bool have_stencil = BoundFramebufferHasStencilAttachment();
2794 glStencilMaskSeparate(GL_FRONT, have_stencil ? mask_stencil_front_ : 0);
2795 glStencilMaskSeparate(GL_BACK, have_stencil ? mask_stencil_back_ : 0);
2796 EnableDisable(GL_STENCIL_TEST, enable_stencil_test_ && have_stencil);
2797 state_dirty_ = false;
2798 }
2799}
2800
[email protected]051b1372010-04-12 02:42:082801void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
2802 FramebufferManager::FramebufferInfo* info = NULL;
2803 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032804 if (client_id != 0) {
2805 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082806 if (!info) {
[email protected]ae51d192010-04-27 00:48:032807 // It's a new id so make a framebuffer info for it.
2808 glGenFramebuffersEXT(1, &service_id);
2809 CreateFramebufferInfo(client_id, service_id);
2810 info = GetFramebufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:572811 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:102812 group_->GetIdAllocator(id_namespaces::kFramebuffers);
2813 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032814 } else {
2815 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082816 }
[email protected]06c8b082011-01-05 18:00:362817 info->MarkAsValid();
[email protected]eff9a222010-12-21 21:48:562818 } else {
[email protected]2e7bbf22011-07-22 18:41:292819 service_id = surface_->GetBackingFrameBufferObject();
[email protected]051b1372010-04-12 02:42:082820 }
[email protected]8e3e0662010-08-23 18:46:302821
2822 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
2823 bound_draw_framebuffer_ = info;
2824 }
2825 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
2826 bound_read_framebuffer_ = info;
2827 }
[email protected]6217d392010-03-25 22:08:352828
[email protected]297ca1c2011-06-20 23:08:462829 state_dirty_ = true;
2830
[email protected]6217d392010-03-25 22:08:352831 // When rendering to an offscreen frame buffer, instead of unbinding from
2832 // the current frame buffer, bind to the offscreen target frame buffer.
[email protected]297ca1c2011-06-20 23:08:462833 if (info == NULL && offscreen_target_frame_buffer_.get()) {
[email protected]051b1372010-04-12 02:42:082834 service_id = offscreen_target_frame_buffer_->id();
[email protected]297ca1c2011-06-20 23:08:462835 }
[email protected]6217d392010-03-25 22:08:352836
[email protected]051b1372010-04-12 02:42:082837 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562838}
2839
[email protected]051b1372010-04-12 02:42:082840void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
2841 RenderbufferManager::RenderbufferInfo* info = NULL;
2842 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032843 if (client_id != 0) {
2844 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082845 if (!info) {
[email protected]ae51d192010-04-27 00:48:032846 // It's a new id so make a renderbuffer info for it.
2847 glGenRenderbuffersEXT(1, &service_id);
2848 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:102849 info = GetRenderbufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:572850 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:102851 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
2852 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032853 } else {
2854 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082855 }
[email protected]06c8b082011-01-05 18:00:362856 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:082857 }
2858 bound_renderbuffer_ = info;
2859 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562860}
2861
[email protected]051b1372010-04-12 02:42:082862void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032863 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082864 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032865 if (client_id != 0) {
2866 info = GetTextureInfo(client_id);
2867 if (!info) {
2868 // It's a new id so make a texture info for it.
2869 glGenTextures(1, &service_id);
2870 CreateTextureInfo(client_id, service_id);
2871 info = GetTextureInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:572872 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:102873 group_->GetIdAllocator(id_namespaces::kTextures);
2874 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032875 }
2876 } else {
2877 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:082878 }
[email protected]ae51d192010-04-27 00:48:032879
[email protected]1958e0e2010-04-22 05:17:152880 // Check the texture exists
2881 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:032882 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:292883 SetGLError(GL_INVALID_OPERATION,
2884 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:152885 return;
2886 }
2887 if (info->target() == 0) {
2888 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:472889 }
[email protected]ae51d192010-04-27 00:48:032890 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:502891 TextureUnit& unit = texture_units_[active_texture_unit_];
2892 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:472893 switch (target) {
2894 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:502895 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:472896 break;
2897 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:502898 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:472899 break;
[email protected]61eeb33f2011-07-26 15:30:312900 case GL_TEXTURE_EXTERNAL_OES:
2901 unit.bound_texture_external_oes = info;
2902 break;
[email protected]a93bb842010-02-16 23:03:472903 default:
2904 NOTREACHED(); // Validation should prevent us getting here.
2905 break;
2906 }
2907}
2908
[email protected]07f54fcc2009-12-22 02:46:302909void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082910 if (vertex_attrib_manager_.Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:122911 if (index != 0 ||
2912 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:242913 glDisableVertexAttribArray(index);
2914 }
[email protected]07f54fcc2009-12-22 02:46:302915 } else {
[email protected]8eee29c2010-04-29 03:38:292916 SetGLError(GL_INVALID_VALUE,
2917 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302918 }
2919}
2920
2921void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082922 if (vertex_attrib_manager_.Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:302923 glEnableVertexAttribArray(index);
2924 } else {
[email protected]8eee29c2010-04-29 03:38:292925 SetGLError(GL_INVALID_VALUE,
2926 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302927 }
2928}
2929
[email protected]a93bb842010-02-16 23:03:472930void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:502931 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]915a59a12010-09-30 21:29:112932 if (!info || !texture_manager()->MarkMipmapsGenerated(feature_info_, info)) {
[email protected]8eee29c2010-04-29 03:38:292933 SetGLError(GL_INVALID_OPERATION,
2934 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:472935 return;
2936 }
[email protected]59f3ca02011-03-26 22:24:192937 // Workaround for Mac driver bug. In the large scheme of things setting
2938 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
2939 // hit so there's probably no need to make this conditional.
2940 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
[email protected]a93bb842010-02-16 23:03:472941 glGenerateMipmapEXT(target);
[email protected]59f3ca02011-03-26 22:24:192942 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
[email protected]a93bb842010-02-16 23:03:472943}
2944
[email protected]b273e432010-04-12 17:23:582945bool GLES2DecoderImpl::GetHelper(
2946 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:582947 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:152948 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2949 switch (pname) {
[email protected]b273e432010-04-12 17:23:582950 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2951 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102952 if (params) {
[email protected]5094b0f2010-11-09 19:45:242953 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:102954 }
[email protected]b273e432010-04-12 17:23:582955 return true;
2956 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2957 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102958 if (params) {
[email protected]5094b0f2010-11-09 19:45:242959 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:102960 }
[email protected]b273e432010-04-12 17:23:582961 return true;
2962 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
2963 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102964 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482965 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102966 }
[email protected]b273e432010-04-12 17:23:582967 return true;
2968 case GL_MAX_VARYING_VECTORS:
2969 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102970 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482971 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:102972 }
[email protected]b273e432010-04-12 17:23:582973 return true;
2974 case GL_MAX_VERTEX_UNIFORM_VECTORS:
2975 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102976 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482977 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102978 }
[email protected]b273e432010-04-12 17:23:582979 return true;
[email protected]5094b0f2010-11-09 19:45:242980 case GL_MAX_VIEWPORT_DIMS:
2981 if (offscreen_target_frame_buffer_.get()) {
2982 *num_written = 2;
2983 if (params) {
2984 params[0] = renderbuffer_manager()->max_renderbuffer_size();
2985 params[1] = renderbuffer_manager()->max_renderbuffer_size();
2986 }
2987 return true;
2988 }
[email protected]b9363b22010-06-09 22:06:152989 }
2990 }
2991 switch (pname) {
[email protected]297ca1c2011-06-20 23:08:462992 case GL_COLOR_WRITEMASK:
2993 *num_written = 4;
2994 if (params) {
2995 params[0] = mask_red_;
2996 params[1] = mask_green_;
2997 params[2] = mask_blue_;
2998 params[3] = mask_alpha_;
2999 }
3000 return true;
3001 case GL_DEPTH_WRITEMASK:
3002 *num_written = 1;
3003 if (params) {
3004 params[0] = mask_depth_;
3005 }
3006 return true;
3007 case GL_STENCIL_BACK_WRITEMASK:
3008 *num_written = 1;
3009 if (params) {
3010 params[0] = mask_stencil_back_;
3011 }
3012 return true;
3013 case GL_STENCIL_WRITEMASK:
3014 *num_written = 1;
3015 if (params) {
3016 params[0] = mask_stencil_front_;
3017 }
3018 return true;
3019 case GL_DEPTH_TEST:
3020 *num_written = 1;
3021 if (params) {
3022 params[0] = enable_depth_test_;
3023 }
3024 return true;
3025 case GL_STENCIL_TEST:
3026 *num_written = 1;
3027 if (params) {
3028 params[0] = enable_stencil_test_;
3029 }
3030 return true;
3031 case GL_ALPHA_BITS:
3032 *num_written = 1;
3033 if (params) {
3034 GLint v = 0;
3035 glGetIntegerv(GL_ALPHA_BITS, &v);
3036 params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0;
3037 }
3038 return true;
3039 case GL_DEPTH_BITS:
3040 *num_written = 1;
3041 if (params) {
3042 GLint v = 0;
3043 glGetIntegerv(GL_DEPTH_BITS, &v);
3044 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
3045 }
3046 return true;
3047 case GL_STENCIL_BITS:
3048 *num_written = 1;
3049 if (params) {
3050 GLint v = 0;
3051 glGetIntegerv(GL_STENCIL_BITS, &v);
3052 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
3053 }
3054 return true;
[email protected]656dcaad2010-05-07 17:18:373055 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113056 *num_written = validators_->compressed_texture_format.GetValues().size();
3057 if (params) {
3058 for (GLint ii = 0; ii < *num_written; ++ii) {
3059 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
3060 }
3061 }
[email protected]656dcaad2010-05-07 17:18:373062 return true;
[email protected]b273e432010-04-12 17:23:583063 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
3064 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103065 if (params) {
[email protected]302ce6d2011-07-07 23:28:113066 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103067 }
[email protected]b273e432010-04-12 17:23:583068 return true;
3069 case GL_NUM_SHADER_BINARY_FORMATS:
3070 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103071 if (params) {
[email protected]302ce6d2011-07-07 23:28:113072 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103073 }
[email protected]b273e432010-04-12 17:23:583074 return true;
3075 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113076 *num_written = validators_->shader_binary_format.GetValues().size();
3077 if (params) {
3078 for (GLint ii = 0; ii < *num_written; ++ii) {
3079 params[ii] = validators_->shader_binary_format.GetValues()[ii];
3080 }
3081 }
3082 return true;
[email protected]b273e432010-04-12 17:23:583083 case GL_SHADER_COMPILER:
3084 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103085 if (params) {
3086 *params = GL_TRUE;
3087 }
[email protected]b273e432010-04-12 17:23:583088 return true;
[email protected]6b8cf1a2010-05-06 16:13:583089 case GL_ARRAY_BUFFER_BINDING:
3090 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103091 if (params) {
3092 if (bound_array_buffer_) {
3093 GLuint client_id = 0;
3094 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
3095 &client_id);
3096 *params = client_id;
3097 } else {
3098 *params = 0;
3099 }
[email protected]6b8cf1a2010-05-06 16:13:583100 }
3101 return true;
3102 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3103 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103104 if (params) {
3105 if (bound_element_array_buffer_) {
3106 GLuint client_id = 0;
3107 buffer_manager()->GetClientId(
3108 bound_element_array_buffer_->service_id(),
3109 &client_id);
3110 *params = client_id;
3111 } else {
3112 *params = 0;
3113 }
[email protected]6b8cf1a2010-05-06 16:13:583114 }
3115 return true;
3116 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:303117 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:583118 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103119 if (params) {
[email protected]8e3e0662010-08-23 18:46:303120 if (bound_draw_framebuffer_) {
[email protected]4e8a5b122010-05-08 22:00:103121 GLuint client_id = 0;
3122 framebuffer_manager()->GetClientId(
[email protected]8e3e0662010-08-23 18:46:303123 bound_draw_framebuffer_->service_id(), &client_id);
3124 *params = client_id;
3125 } else {
3126 *params = 0;
3127 }
3128 }
3129 return true;
3130 case GL_READ_FRAMEBUFFER_BINDING:
3131 *num_written = 1;
3132 if (params) {
3133 if (bound_read_framebuffer_) {
3134 GLuint client_id = 0;
3135 framebuffer_manager()->GetClientId(
3136 bound_read_framebuffer_->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103137 *params = client_id;
3138 } else {
3139 *params = 0;
3140 }
[email protected]6b8cf1a2010-05-06 16:13:583141 }
3142 return true;
3143 case GL_RENDERBUFFER_BINDING:
3144 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103145 if (params) {
3146 if (bound_renderbuffer_) {
3147 GLuint client_id = 0;
3148 renderbuffer_manager()->GetClientId(
3149 bound_renderbuffer_->service_id(), &client_id);
3150 *params = client_id;
3151 } else {
3152 *params = 0;
3153 }
[email protected]6b8cf1a2010-05-06 16:13:583154 }
3155 return true;
3156 case GL_CURRENT_PROGRAM:
3157 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103158 if (params) {
3159 if (current_program_) {
3160 GLuint client_id = 0;
3161 program_manager()->GetClientId(
3162 current_program_->service_id(), &client_id);
3163 *params = client_id;
3164 } else {
3165 *params = 0;
3166 }
[email protected]6b8cf1a2010-05-06 16:13:583167 }
3168 return true;
[email protected]4e8a5b122010-05-08 22:00:103169 case GL_TEXTURE_BINDING_2D:
3170 *num_written = 1;
3171 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583172 TextureUnit& unit = texture_units_[active_texture_unit_];
3173 if (unit.bound_texture_2d) {
3174 GLuint client_id = 0;
3175 texture_manager()->GetClientId(
3176 unit.bound_texture_2d->service_id(), &client_id);
3177 *params = client_id;
3178 } else {
3179 *params = 0;
3180 }
[email protected]6b8cf1a2010-05-06 16:13:583181 }
[email protected]4e8a5b122010-05-08 22:00:103182 return true;
3183 case GL_TEXTURE_BINDING_CUBE_MAP:
3184 *num_written = 1;
3185 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583186 TextureUnit& unit = texture_units_[active_texture_unit_];
3187 if (unit.bound_texture_cube_map) {
3188 GLuint client_id = 0;
3189 texture_manager()->GetClientId(
3190 unit.bound_texture_cube_map->service_id(), &client_id);
3191 *params = client_id;
3192 } else {
3193 *params = 0;
3194 }
[email protected]6b8cf1a2010-05-06 16:13:583195 }
[email protected]4e8a5b122010-05-08 22:00:103196 return true;
[email protected]61eeb33f2011-07-26 15:30:313197 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3198 *num_written = 1;
3199 if (params) {
3200 TextureUnit& unit = texture_units_[active_texture_unit_];
3201 if (unit.bound_texture_external_oes) {
3202 GLuint client_id = 0;
3203 texture_manager()->GetClientId(
3204 unit.bound_texture_external_oes->service_id(), &client_id);
3205 *params = client_id;
3206 } else {
3207 *params = 0;
3208 }
3209 }
3210 return true;
[email protected]b273e432010-04-12 17:23:583211 default:
[email protected]4e8a5b122010-05-08 22:00:103212 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533213 return false;
[email protected]b273e432010-04-12 17:23:583214 }
3215}
3216
[email protected]4e8a5b122010-05-08 22:00:103217bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3218 GLenum pname, GLsizei* num_values) {
3219 return GetHelper(pname, NULL, num_values);
3220}
3221
[email protected]b273e432010-04-12 17:23:583222void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3223 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103224 GLsizei num_written = 0;
3225 if (GetHelper(pname, NULL, &num_written)) {
3226 scoped_array<GLint> values(new GLint[num_written]);
3227 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583228 for (GLsizei ii = 0; ii < num_written; ++ii) {
3229 params[ii] = static_cast<GLboolean>(values[ii]);
3230 }
3231 } else {
3232 glGetBooleanv(pname, params);
3233 }
3234}
3235
3236void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3237 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103238 GLsizei num_written = 0;
3239 if (GetHelper(pname, NULL, &num_written)) {
3240 scoped_array<GLint> values(new GLint[num_written]);
3241 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583242 for (GLsizei ii = 0; ii < num_written; ++ii) {
3243 params[ii] = static_cast<GLfloat>(values[ii]);
3244 }
3245 } else {
3246 glGetFloatv(pname, params);
3247 }
3248}
3249
3250void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3251 DCHECK(params);
3252 GLsizei num_written;
3253 if (!GetHelper(pname, params, &num_written)) {
3254 glGetIntegerv(pname, params);
3255 }
3256}
3257
[email protected]a0c3e972010-04-21 00:49:133258void GLES2DecoderImpl::DoGetProgramiv(
3259 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583260 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3261 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133262 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133263 return;
3264 }
3265 info->GetProgramiv(pname, params);
3266}
3267
[email protected]558847a2010-03-24 07:02:543268error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3269 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
[email protected]6b8cf1a2010-05-06 16:13:583270 GLuint program = static_cast<GLuint>(c.program);
3271 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3272 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033273 if (!info) {
[email protected]558847a2010-03-24 07:02:543274 return error::kNoError;
3275 }
3276 GLuint index = static_cast<GLuint>(c.index);
3277 uint32 name_size = c.data_size;
3278 const char* name = GetSharedMemoryAs<const char*>(
3279 c.name_shm_id, c.name_shm_offset, name_size);
3280 if (name == NULL) {
3281 return error::kOutOfBounds;
3282 }
3283 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033284 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543285 return error::kNoError;
3286}
3287
3288error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3289 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583290 GLuint program = static_cast<GLuint>(c.program);
3291 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3292 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033293 if (!info) {
[email protected]558847a2010-03-24 07:02:543294 return error::kNoError;
3295 }
3296 GLuint index = static_cast<GLuint>(c.index);
3297 uint32 name_size = c.data_size;
3298 const char* name = GetImmediateDataAs<const char*>(
3299 c, name_size, immediate_data_size);
3300 if (name == NULL) {
3301 return error::kOutOfBounds;
3302 }
3303 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033304 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543305 return error::kNoError;
3306}
3307
3308error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3309 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583310 GLuint program = static_cast<GLuint>(c.program);
3311 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3312 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033313 if (!info) {
[email protected]558847a2010-03-24 07:02:543314 return error::kNoError;
3315 }
3316 GLuint index = static_cast<GLuint>(c.index);
3317 Bucket* bucket = GetBucket(c.name_bucket_id);
3318 if (!bucket || bucket->size() == 0) {
3319 return error::kInvalidArguments;
3320 }
3321 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183322 if (!bucket->GetAsString(&name_str)) {
3323 return error::kInvalidArguments;
3324 }
[email protected]ae51d192010-04-27 00:48:033325 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543326 return error::kNoError;
3327}
3328
[email protected]f7a64ee2010-02-01 22:24:143329error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463330 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033331 GLuint client_id = c.shader;
3332 if (client_id) {
3333 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3334 if (info) {
[email protected]ca488e12010-12-13 20:06:143335 if (!info->IsDeleted()) {
3336 glDeleteShader(info->service_id());
3337 shader_manager()->MarkAsDeleted(info);
3338 }
[email protected]ae51d192010-04-27 00:48:033339 } else {
[email protected]8eee29c2010-04-29 03:38:293340 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033341 }
[email protected]96449d2c2009-11-25 00:01:323342 }
[email protected]f7a64ee2010-02-01 22:24:143343 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323344}
3345
[email protected]f7a64ee2010-02-01 22:24:143346error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463347 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033348 GLuint client_id = c.program;
3349 if (client_id) {
3350 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3351 if (info) {
[email protected]ca488e12010-12-13 20:06:143352 if (!info->IsDeleted()) {
3353 glDeleteProgram(info->service_id());
3354 program_manager()->MarkAsDeleted(shader_manager(), info);
3355 }
[email protected]ae51d192010-04-27 00:48:033356 } else {
[email protected]8eee29c2010-04-29 03:38:293357 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033358 }
[email protected]96449d2c2009-11-25 00:01:323359 }
[email protected]f7a64ee2010-02-01 22:24:143360 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323361}
3362
[email protected]269200b12010-11-18 22:53:063363void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103364 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573365 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103366 for (GLsizei ii = 0; ii < n; ++ii) {
3367 id_allocator->FreeID(ids[ii]);
3368 }
3369}
3370
[email protected]269200b12010-11-18 22:53:063371error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
3372 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103373 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3374 GLsizei n = static_cast<GLsizei>(c.n);
3375 uint32 data_size;
3376 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3377 return error::kOutOfBounds;
3378 }
3379 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3380 c.ids_shm_id, c.ids_shm_offset, data_size);
3381 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063382 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103383 return error::kNoError;
3384 }
3385 if (ids == NULL) {
3386 return error::kOutOfBounds;
3387 }
[email protected]269200b12010-11-18 22:53:063388 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103389 return error::kNoError;
3390}
3391
[email protected]269200b12010-11-18 22:53:063392void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103393 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573394 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103395 if (id_offset == 0) {
3396 for (GLsizei ii = 0; ii < n; ++ii) {
3397 ids[ii] = id_allocator->AllocateID();
3398 }
3399 } else {
3400 for (GLsizei ii = 0; ii < n; ++ii) {
3401 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
3402 id_offset = ids[ii] + 1;
3403 }
3404 }
3405}
3406
[email protected]269200b12010-11-18 22:53:063407error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
3408 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103409 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3410 GLuint id_offset = static_cast<GLuint>(c.id_offset);
3411 GLsizei n = static_cast<GLsizei>(c.n);
3412 uint32 data_size;
3413 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3414 return error::kOutOfBounds;
3415 }
3416 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3417 c.ids_shm_id, c.ids_shm_offset, data_size);
3418 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063419 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103420 return error::kNoError;
3421 }
3422 if (ids == NULL) {
3423 return error::kOutOfBounds;
3424 }
[email protected]269200b12010-11-18 22:53:063425 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:103426 return error::kNoError;
3427}
3428
[email protected]269200b12010-11-18 22:53:063429void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103430 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573431 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103432 for (GLsizei ii = 0; ii < n; ++ii) {
3433 if (!id_allocator->MarkAsUsed(ids[ii])) {
3434 for (GLsizei jj = 0; jj < ii; ++jj) {
3435 id_allocator->FreeID(ids[jj]);
3436 }
3437 SetGLError(
3438 GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:063439 "RegisterSharedIdsCHROMIUM: attempt to register "
3440 "id that already exists");
[email protected]066849e32010-05-03 19:14:103441 return;
3442 }
3443 }
3444}
3445
[email protected]269200b12010-11-18 22:53:063446error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
3447 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103448 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3449 GLsizei n = static_cast<GLsizei>(c.n);
3450 uint32 data_size;
3451 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3452 return error::kOutOfBounds;
3453 }
3454 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3455 c.ids_shm_id, c.ids_shm_offset, data_size);
3456 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063457 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103458 return error::kNoError;
3459 }
3460 if (ids == NULL) {
3461 return error::kOutOfBounds;
3462 }
[email protected]269200b12010-11-18 22:53:063463 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103464 return error::kNoError;
3465}
3466
[email protected]3a03a8f2011-03-19 00:51:273467void GLES2DecoderImpl::DoClear(GLbitfield mask) {
3468 if (CheckFramebufferComplete("glClear")) {
[email protected]297ca1c2011-06-20 23:08:463469 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:273470 glClear(mask);
3471 }
3472}
3473
[email protected]36cef8ce2010-03-16 07:34:453474void GLES2DecoderImpl::DoFramebufferRenderbuffer(
3475 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:033476 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:303477 FramebufferManager::FramebufferInfo* framebuffer_info =
3478 GetFramebufferInfoForTarget(target);
3479 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293480 SetGLError(GL_INVALID_OPERATION,
3481 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453482 return;
3483 }
[email protected]ae51d192010-04-27 00:48:033484 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283485 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033486 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283487 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:033488 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293489 SetGLError(GL_INVALID_OPERATION,
3490 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:033491 return;
3492 }
3493 service_id = info->service_id();
3494 }
[email protected]9edc6b22010-12-23 02:00:263495 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033496 glFramebufferRenderbufferEXT(
3497 target, attachment, renderbuffertarget, service_id);
[email protected]1002c2d2011-06-28 22:39:043498 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263499 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:303500 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]9edc6b22010-12-23 02:00:263501 if (service_id == 0 ||
3502 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
3503 if (info) {
3504 ClearUnclearedRenderbuffers(target, framebuffer_info);
3505 }
[email protected]3a2e7c7b2010-08-06 01:12:283506 }
3507 }
[email protected]297ca1c2011-06-20 23:08:463508 if (framebuffer_info == bound_draw_framebuffer_) {
3509 state_dirty_ = true;
3510 }
[email protected]3a2e7c7b2010-08-06 01:12:283511}
3512
[email protected]297ca1c2011-06-20 23:08:463513bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
[email protected]3a2e7c7b2010-08-06 01:12:283514 switch (cap) {
3515 case GL_SCISSOR_TEST:
3516 enable_scissor_test_ = enabled;
[email protected]297ca1c2011-06-20 23:08:463517 return true;
3518 case GL_DEPTH_TEST: {
3519 if (enable_depth_test_ != enabled) {
3520 enable_depth_test_ = enabled;
3521 state_dirty_ = true;
3522 }
3523 return false;
3524 }
3525 case GL_STENCIL_TEST:
3526 if (enable_stencil_test_ != enabled) {
3527 enable_stencil_test_ = enabled;
3528 state_dirty_ = true;
3529 }
3530 return false;
[email protected]3a2e7c7b2010-08-06 01:12:283531 default:
[email protected]297ca1c2011-06-20 23:08:463532 return true;
[email protected]3a2e7c7b2010-08-06 01:12:283533 }
3534}
3535
3536void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:463537 if (SetCapabilityState(cap, false)) {
3538 glDisable(cap);
3539 }
[email protected]3a2e7c7b2010-08-06 01:12:283540}
3541
3542void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:463543 if (SetCapabilityState(cap, true)) {
3544 glEnable(cap);
3545 }
[email protected]3a2e7c7b2010-08-06 01:12:283546}
3547
3548void GLES2DecoderImpl::DoClearColor(
3549 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
3550 clear_red_ = red;
3551 clear_green_ = green;
3552 clear_blue_ = blue;
3553 clear_alpha_ = alpha;
3554 glClearColor(red, green, blue, alpha);
3555}
3556
3557void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
3558 clear_depth_ = depth;
3559 glClearDepth(depth);
3560}
3561
3562void GLES2DecoderImpl::DoClearStencil(GLint s) {
3563 clear_stencil_ = s;
3564 glClearStencil(s);
3565}
3566
3567void GLES2DecoderImpl::DoColorMask(
3568 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
3569 mask_red_ = red;
3570 mask_green_ = green;
3571 mask_blue_ = blue;
3572 mask_alpha_ = alpha;
[email protected]297ca1c2011-06-20 23:08:463573 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283574}
3575
3576void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
3577 mask_depth_ = depth;
[email protected]297ca1c2011-06-20 23:08:463578 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283579}
3580
3581void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
3582 mask_stencil_front_ = mask;
3583 mask_stencil_back_ = mask;
[email protected]297ca1c2011-06-20 23:08:463584 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283585}
3586
3587void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
[email protected]297ca1c2011-06-20 23:08:463588 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:283589 mask_stencil_front_ = mask;
[email protected]297ca1c2011-06-20 23:08:463590 }
3591 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:283592 mask_stencil_back_ = mask;
3593 }
[email protected]297ca1c2011-06-20 23:08:463594 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283595}
3596
3597// NOTE: There's an assumption here that Texture attachments
3598// are cleared because they are textures so we only need to clear
3599// the renderbuffers.
3600void GLES2DecoderImpl::ClearUnclearedRenderbuffers(
[email protected]8e3e0662010-08-23 18:46:303601 GLenum target, FramebufferManager::FramebufferInfo* info) {
3602 if (target == GL_READ_FRAMEBUFFER_EXT) {
3603 // TODO(gman): bind this to the DRAW point, clear then bind back to READ
3604 }
[email protected]3a2e7c7b2010-08-06 01:12:283605 GLbitfield clear_bits = 0;
3606 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:463607 glClearColor(
3608 0, 0, 0,
3609 (GLES2Util::GetChannelsForFormat(
3610 info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0 : 1);
[email protected]3a2e7c7b2010-08-06 01:12:283611 glColorMask(true, true, true, true);
3612 clear_bits |= GL_COLOR_BUFFER_BIT;
3613 }
3614
3615 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
3616 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3617 glClearStencil(0);
3618 glStencilMask(-1);
3619 clear_bits |= GL_STENCIL_BUFFER_BIT;
3620 }
3621
3622 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
3623 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3624 glClearDepth(1.0f);
3625 glDepthMask(true);
3626 clear_bits |= GL_DEPTH_BUFFER_BIT;
3627 }
3628
3629 glDisable(GL_SCISSOR_TEST);
3630 glClear(clear_bits);
3631
3632 info->MarkAttachedRenderbuffersAsCleared();
3633
[email protected]c007aa02010-09-02 22:22:403634 RestoreClearState();
3635
3636 if (target == GL_READ_FRAMEBUFFER_EXT) {
3637 // TODO(gman): rebind draw.
3638 }
3639}
3640
3641void GLES2DecoderImpl::RestoreClearState() {
[email protected]297ca1c2011-06-20 23:08:463642 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283643 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
[email protected]3a2e7c7b2010-08-06 01:12:283644 glClearStencil(clear_stencil_);
[email protected]3a2e7c7b2010-08-06 01:12:283645 glClearDepth(clear_depth_);
[email protected]3a2e7c7b2010-08-06 01:12:283646 if (enable_scissor_test_) {
3647 glEnable(GL_SCISSOR_TEST);
3648 }
[email protected]36cef8ce2010-03-16 07:34:453649}
3650
3651GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]8e3e0662010-08-23 18:46:303652 FramebufferManager::FramebufferInfo* info =
3653 GetFramebufferInfoForTarget(target);
3654 if (!info) {
[email protected]36cef8ce2010-03-16 07:34:453655 return GL_FRAMEBUFFER_COMPLETE;
3656 }
3657 return glCheckFramebufferStatusEXT(target);
3658}
3659
3660void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:033661 GLenum target, GLenum attachment, GLenum textarget,
3662 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:303663 FramebufferManager::FramebufferInfo* framebuffer_info =
3664 GetFramebufferInfoForTarget(target);
3665 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293666 SetGLError(GL_INVALID_OPERATION,
3667 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:453668 return;
3669 }
[email protected]ae51d192010-04-27 00:48:033670 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283671 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033672 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283673 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:033674 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293675 SetGLError(GL_INVALID_OPERATION,
3676 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:033677 return;
3678 }
3679 service_id = info->service_id();
3680 }
[email protected]9edc6b22010-12-23 02:00:263681 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033682 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]1002c2d2011-06-28 22:39:043683 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263684 if (error == GL_NO_ERROR) {
3685 framebuffer_info->AttachTexture(attachment, info, textarget, level);
3686 if (service_id != 0 &&
3687 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
3688 ClearUnclearedRenderbuffers(target, framebuffer_info);
3689 }
[email protected]3a2e7c7b2010-08-06 01:12:283690 }
[email protected]297ca1c2011-06-20 23:08:463691 if (framebuffer_info == bound_draw_framebuffer_) {
3692 state_dirty_ = true;
3693 }
[email protected]36cef8ce2010-03-16 07:34:453694}
3695
3696void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
3697 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:303698 FramebufferManager::FramebufferInfo* framebuffer_info =
3699 GetFramebufferInfoForTarget(target);
3700 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293701 SetGLError(GL_INVALID_OPERATION,
3702 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453703 return;
3704 }
3705 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:573706 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
3707 GLint type = 0;
3708 GLuint client_id = 0;
3709 glGetFramebufferAttachmentParameterivEXT(
3710 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
3711 switch (type) {
3712 case GL_RENDERBUFFER: {
3713 renderbuffer_manager()->GetClientId(*params, &client_id);
3714 break;
3715 }
3716 case GL_TEXTURE: {
3717 texture_manager()->GetClientId(*params, &client_id);
3718 break;
3719 }
3720 default:
3721 break;
3722 }
3723 *params = client_id;
3724 }
[email protected]36cef8ce2010-03-16 07:34:453725}
3726
3727void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
3728 GLenum target, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:083729 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293730 SetGLError(GL_INVALID_OPERATION,
3731 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453732 return;
3733 }
[email protected]3a03a8f2011-03-19 00:51:273734 switch (pname) {
3735 case GL_RENDERBUFFER_INTERNAL_FORMAT:
[email protected]b71f52c2010-06-18 22:20:203736 *params = bound_renderbuffer_->internal_format();
[email protected]3a03a8f2011-03-19 00:51:273737 break;
3738 case GL_RENDERBUFFER_WIDTH:
3739 *params = bound_renderbuffer_->width();
3740 break;
3741 case GL_RENDERBUFFER_HEIGHT:
3742 *params = bound_renderbuffer_->height();
3743 break;
3744 default:
3745 glGetRenderbufferParameterivEXT(target, pname, params);
3746 break;
[email protected]b71f52c2010-06-18 22:20:203747 }
[email protected]36cef8ce2010-03-16 07:34:453748}
3749
[email protected]8e3e0662010-08-23 18:46:303750void GLES2DecoderImpl::DoBlitFramebufferEXT(
3751 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
3752 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
3753 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:393754 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303755 SetGLError(GL_INVALID_OPERATION,
3756 "glBlitFramebufferEXT: function not available");
3757 }
[email protected]5094b0f2010-11-09 19:45:243758 if (IsAngle()) {
3759 glBlitFramebufferANGLE(
3760 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3761 } else {
3762 glBlitFramebufferEXT(
3763 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3764 }
[email protected]8e3e0662010-08-23 18:46:303765}
3766
3767void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
3768 GLenum target, GLsizei samples, GLenum internalformat,
3769 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:393770 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303771 SetGLError(GL_INVALID_OPERATION,
3772 "glRenderbufferStorageMultisampleEXT: function not available");
3773 return;
3774 }
[email protected]8e3e0662010-08-23 18:46:303775
[email protected]9edc6b22010-12-23 02:00:263776 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:303777 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:263778 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:303779 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:263780 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:303781 break;
3782 case GL_RGBA4:
3783 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:263784 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:303785 break;
3786 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:263787 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:303788 break;
3789 }
3790 }
3791
[email protected]9edc6b22010-12-23 02:00:263792 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:083793 if (IsAngle()) {
3794 glRenderbufferStorageMultisampleANGLE(
3795 target, samples, impl_format, width, height);
3796 } else {
3797 glRenderbufferStorageMultisampleEXT(
3798 target, samples, impl_format, width, height);
3799 }
[email protected]1002c2d2011-06-28 22:39:043800 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263801 if (error == GL_NO_ERROR) {
3802 bound_renderbuffer_->SetInfo(samples, internalformat, width, height);
3803 }
[email protected]8e3e0662010-08-23 18:46:303804}
3805
[email protected]36cef8ce2010-03-16 07:34:453806void GLES2DecoderImpl::DoRenderbufferStorage(
3807 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]051b1372010-04-12 02:42:083808 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293809 SetGLError(GL_INVALID_OPERATION,
3810 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453811 return;
3812 }
[email protected]876f6fee2010-08-02 23:10:323813
[email protected]9edc6b22010-12-23 02:00:263814 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:323815 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:263816 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:323817 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:263818 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:323819 break;
3820 case GL_RGBA4:
3821 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:263822 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:323823 break;
3824 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:263825 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:323826 break;
3827 }
[email protected]b71f52c2010-06-18 22:20:203828 }
[email protected]876f6fee2010-08-02 23:10:323829
[email protected]9edc6b22010-12-23 02:00:263830 CopyRealGLErrorsToWrapper();
3831 glRenderbufferStorageEXT(target, impl_format, width, height);
[email protected]1002c2d2011-06-28 22:39:043832 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263833 if (error == GL_NO_ERROR) {
3834 bound_renderbuffer_->SetInfo(0, internalformat, width, height);
3835 }
[email protected]36cef8ce2010-03-16 07:34:453836}
3837
[email protected]07f54fcc2009-12-22 02:46:303838void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]0c8fabf2011-06-14 19:35:223839 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]6b8cf1a2010-05-06 16:13:583840 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3841 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:473842 if (!info) {
[email protected]a93bb842010-02-16 23:03:473843 return;
3844 }
[email protected]05afda12011-01-20 00:17:343845
[email protected]d685a682011-04-29 16:19:573846 info->Link();
[email protected]07f54fcc2009-12-22 02:46:303847};
3848
[email protected]3916c97e2010-02-25 03:20:503849void GLES2DecoderImpl::DoTexParameterf(
3850 GLenum target, GLenum pname, GLfloat param) {
3851 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:303852 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293853 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243854 return;
[email protected]07f54fcc2009-12-22 02:46:303855 }
[email protected]cbb22e42011-05-12 23:36:243856
3857 if (!texture_manager()->SetParameter(
3858 feature_info_, info, pname, static_cast<GLint>(param))) {
3859 SetGLError(GL_INVALID_ENUM, "glTexParameterf: param GL_INVALID_ENUM");
3860 return;
3861 }
3862 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:303863}
3864
[email protected]3916c97e2010-02-25 03:20:503865void GLES2DecoderImpl::DoTexParameteri(
3866 GLenum target, GLenum pname, GLint param) {
3867 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3868 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293869 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243870 return;
[email protected]3916c97e2010-02-25 03:20:503871 }
[email protected]cbb22e42011-05-12 23:36:243872
3873 if (!texture_manager()->SetParameter(feature_info_, info, pname, param)) {
3874 SetGLError(GL_INVALID_ENUM, "glTexParameteri: param GL_INVALID_ENUM");
3875 return;
3876 }
3877 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:503878}
3879
3880void GLES2DecoderImpl::DoTexParameterfv(
3881 GLenum target, GLenum pname, const GLfloat* params) {
3882 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3883 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293884 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243885 return;
[email protected]3916c97e2010-02-25 03:20:503886 }
[email protected]cbb22e42011-05-12 23:36:243887
3888 if (!texture_manager()->SetParameter(
3889 feature_info_, info, pname, static_cast<GLint>(params[0]))) {
3890 SetGLError(GL_INVALID_ENUM, "glTexParameterfv: param GL_INVALID_ENUM");
3891 return;
3892 }
3893 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:503894}
3895
3896void GLES2DecoderImpl::DoTexParameteriv(
3897 GLenum target, GLenum pname, const GLint* params) {
3898 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3899 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293900 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243901 return;
[email protected]3916c97e2010-02-25 03:20:503902 }
[email protected]cbb22e42011-05-12 23:36:243903
3904 if (!texture_manager()->SetParameter(feature_info_, info, pname, *params)) {
3905 SetGLError(GL_INVALID_ENUM, "glTexParameteriv: param GL_INVALID_ENUM");
3906 return;
3907 }
3908 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:503909}
3910
[email protected]939e7362010-05-13 20:49:103911bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:143912 if (!current_program_) {
[email protected]939e7362010-05-13 20:49:103913 // The program does not exist.
3914 SetGLError(GL_INVALID_OPERATION,
3915 (std::string(function_name) + ": no program in use").c_str());
3916 return false;
3917 }
[email protected]ca488e12010-12-13 20:06:143918 if (!current_program_->InUse()) {
[email protected]939e7362010-05-13 20:49:103919 SetGLError(GL_INVALID_OPERATION,
3920 (std::string(function_name) + ": program not linked").c_str());
3921 return false;
3922 }
3923 return true;
3924}
3925
3926bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
3927 GLint location, const char* function_name) {
3928 if (!CheckCurrentProgram(function_name)) {
3929 return false;
3930 }
3931 return location != -1;
3932}
3933
[email protected]43c2f1f2011-03-25 18:35:363934bool GLES2DecoderImpl::PrepForSetUniformByLocation(
3935 GLint location, const char* function_name, GLenum* type, GLsizei* count) {
3936 DCHECK(type);
3937 DCHECK(count);
[email protected]939e7362010-05-13 20:49:103938 if (!CheckCurrentProgramForUniform(location, function_name)) {
3939 return false;
3940 }
[email protected]43c2f1f2011-03-25 18:35:363941 GLint array_index = -1;
3942 const ProgramManager::ProgramInfo::UniformInfo* info =
3943 current_program_->GetUniformInfoByLocation(location, &array_index);
3944 if (!info) {
[email protected]939e7362010-05-13 20:49:103945 SetGLError(GL_INVALID_OPERATION,
[email protected]43c2f1f2011-03-25 18:35:363946 (std::string(function_name) + ": unknown location").c_str());
[email protected]939e7362010-05-13 20:49:103947 return false;
3948 }
[email protected]43c2f1f2011-03-25 18:35:363949 if (*count > 1 && !info->is_array) {
3950 SetGLError(
3951 GL_INVALID_OPERATION,
3952 (std::string(function_name) + ": count > 1 for non-array").c_str());
3953 return false;
3954 }
3955 *count = std::min(info->size - array_index, *count);
3956 if (*count <= 0) {
3957 return false;
3958 }
3959 *type = info->type;
[email protected]939e7362010-05-13 20:49:103960 return true;
3961}
3962
[email protected]939e7362010-05-13 20:49:103963void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
3964 if (!CheckCurrentProgramForUniform(location, "glUniform1i")) {
[email protected]3916c97e2010-02-25 03:20:503965 return;
3966 }
3967 current_program_->SetSamplers(location, 1, &v0);
3968 glUniform1i(location, v0);
3969}
3970
3971void GLES2DecoderImpl::DoUniform1iv(
3972 GLint location, GLsizei count, const GLint *value) {
[email protected]939e7362010-05-13 20:49:103973 if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) {
[email protected]3916c97e2010-02-25 03:20:503974 return;
3975 }
[email protected]43c2f1f2011-03-25 18:35:363976 GLenum type = 0;
3977 if (!PrepForSetUniformByLocation(location, "glUniform1iv", &type, &count)) {
3978 return;
3979 }
[email protected]61eeb33f2011-07-26 15:30:313980 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
3981 type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]43c2f1f2011-03-25 18:35:363982 current_program_->SetSamplers(location, count, value);
3983 }
[email protected]3916c97e2010-02-25 03:20:503984 glUniform1iv(location, count, value);
3985}
3986
[email protected]939e7362010-05-13 20:49:103987void GLES2DecoderImpl::DoUniform1fv(
3988 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363989 GLenum type = 0;
3990 if (!PrepForSetUniformByLocation(location, "glUniform1fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103991 return;
3992 }
3993 if (type == GL_BOOL) {
3994 scoped_array<GLint> temp(new GLint[count]);
3995 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:533996 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:103997 }
3998 DoUniform1iv(location, count, temp.get());
3999 } else {
4000 glUniform1fv(location, count, value);
4001 }
4002}
4003
4004void GLES2DecoderImpl::DoUniform2fv(
4005 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364006 GLenum type = 0;
4007 if (!PrepForSetUniformByLocation(location, "glUniform2fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104008 return;
4009 }
4010 if (type == GL_BOOL_VEC2) {
4011 GLsizei num_values = count * 2;
4012 scoped_array<GLint> temp(new GLint[num_values]);
4013 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534014 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104015 }
4016 glUniform2iv(location, count, temp.get());
4017 } else {
4018 glUniform2fv(location, count, value);
4019 }
4020}
4021
4022void GLES2DecoderImpl::DoUniform3fv(
4023 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364024 GLenum type = 0;
4025 if (!PrepForSetUniformByLocation(location, "glUniform3fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104026 return;
4027 }
4028 if (type == GL_BOOL_VEC3) {
4029 GLsizei num_values = count * 3;
4030 scoped_array<GLint> temp(new GLint[num_values]);
4031 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534032 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104033 }
4034 glUniform3iv(location, count, temp.get());
4035 } else {
4036 glUniform3fv(location, count, value);
4037 }
4038}
4039
4040void GLES2DecoderImpl::DoUniform4fv(
4041 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364042 GLenum type = 0;
4043 if (!PrepForSetUniformByLocation(location, "glUniform4fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104044 return;
4045 }
4046 if (type == GL_BOOL_VEC4) {
4047 GLsizei num_values = count * 4;
4048 scoped_array<GLint> temp(new GLint[num_values]);
4049 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534050 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104051 }
4052 glUniform4iv(location, count, temp.get());
4053 } else {
4054 glUniform4fv(location, count, value);
4055 }
4056}
4057
[email protected]43c2f1f2011-03-25 18:35:364058void GLES2DecoderImpl::DoUniform2iv(
4059 GLint location, GLsizei count, const GLint* value) {
4060 GLenum type = 0;
4061 if (!PrepForSetUniformByLocation(location, "glUniform2iv", &type, &count)) {
4062 return;
4063 }
4064 glUniform2iv(location, count, value);
4065}
4066
4067void GLES2DecoderImpl::DoUniform3iv(
4068 GLint location, GLsizei count, const GLint* value) {
4069 GLenum type = 0;
4070 if (!PrepForSetUniformByLocation(location, "glUniform3iv", &type, &count)) {
4071 return;
4072 }
4073 glUniform3iv(location, count, value);
4074}
4075
4076void GLES2DecoderImpl::DoUniform4iv(
4077 GLint location, GLsizei count, const GLint* value) {
4078 GLenum type = 0;
4079 if (!PrepForSetUniformByLocation(location, "glUniform4iv", &type, &count)) {
4080 return;
4081 }
4082 glUniform4iv(location, count, value);
4083}
4084
4085void GLES2DecoderImpl::DoUniformMatrix2fv(
4086 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4087 GLenum type = 0;
4088 if (!PrepForSetUniformByLocation(
4089 location, "glUniformMatrix2fv", &type, &count)) {
4090 return;
4091 }
4092 glUniformMatrix2fv (location, count, transpose, value);
4093}
4094
4095void GLES2DecoderImpl::DoUniformMatrix3fv(
4096 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4097 GLenum type = 0;
4098 if (!PrepForSetUniformByLocation(
4099 location, "glUniformMatrix3fv", &type, &count)) {
4100 return;
4101 }
4102 glUniformMatrix3fv (location, count, transpose, value);
4103}
4104
4105void GLES2DecoderImpl::DoUniformMatrix4fv(
4106 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4107 GLenum type = 0;
4108 if (!PrepForSetUniformByLocation(
4109 location, "glUniformMatrix4fv", &type, &count)) {
4110 return;
4111 }
4112 glUniformMatrix4fv (location, count, transpose, value);
4113}
4114
[email protected]3916c97e2010-02-25 03:20:504115void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:034116 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:504117 ProgramManager::ProgramInfo* info = NULL;
4118 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:584119 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:504120 if (!info) {
[email protected]ae51d192010-04-27 00:48:034121 return;
4122 }
4123 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:504124 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:294125 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:504126 return;
4127 }
[email protected]ae51d192010-04-27 00:48:034128 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:504129 }
[email protected]ca488e12010-12-13 20:06:144130 if (current_program_) {
4131 program_manager()->UnuseProgram(shader_manager(), current_program_);
4132 }
[email protected]3916c97e2010-02-25 03:20:504133 current_program_ = info;
[email protected]ca488e12010-12-13 20:06:144134 if (current_program_) {
4135 program_manager()->UseProgram(current_program_);
4136 }
[email protected]ae51d192010-04-27 00:48:034137 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:504138}
4139
[email protected]96449d2c2009-11-25 00:01:324140GLenum GLES2DecoderImpl::GetGLError() {
4141 // Check the GL error first, then our wrapped error.
4142 GLenum error = glGetError();
4143 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:374144 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:324145 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:294146 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:324147 break;
4148 }
4149 }
4150 }
4151
4152 if (error != GL_NO_ERROR) {
4153 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:294154 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324155 }
4156 return error;
4157}
4158
[email protected]1002c2d2011-06-28 22:39:044159GLenum GLES2DecoderImpl::PeekGLError() {
4160 GLenum error = glGetError();
4161 if (error != GL_NO_ERROR) {
4162 SetGLError(error, "");
4163 }
4164 return error;
4165}
4166
[email protected]8eee29c2010-04-29 03:38:294167void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
4168 if (msg) {
4169 last_error_ = msg;
[email protected]d0498742010-09-20 20:27:014170 LOG(ERROR) << last_error_;
[email protected]8eee29c2010-04-29 03:38:294171 }
[email protected]ddd968b82010-03-02 00:44:294172 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324173}
4174
[email protected]07f54fcc2009-12-22 02:46:304175void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
4176 GLenum error;
4177 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294178 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:304179 }
4180}
4181
[email protected]6217d392010-03-25 22:08:354182void GLES2DecoderImpl::ClearRealGLErrors() {
4183 GLenum error;
4184 while ((error = glGetError()) != GL_NO_ERROR) {
4185 NOTREACHED() << "GL error " << error << " was unhandled.";
4186 }
4187}
4188
[email protected]ef526492010-06-02 23:12:254189bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:504190 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:254191 // Only check if there are some unrenderable textures.
4192 if (!texture_manager()->HaveUnrenderableTextures()) {
4193 return false;
4194 }
4195 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:504196 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4197 current_program_->sampler_indices();
4198 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4199 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4200 current_program_->GetUniformInfo(sampler_indices[ii]);
4201 DCHECK(uniform_info);
4202 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4203 GLuint texture_unit_index = uniform_info->texture_units[jj];
4204 if (texture_unit_index < group_->max_texture_units()) {
4205 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4206 TextureManager::TextureInfo* texture_info =
[email protected]61eeb33f2011-07-26 15:30:314207 texture_unit.GetInfoForSamplerType(uniform_info->type);
[email protected]915a59a12010-09-30 21:29:114208 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]ef526492010-06-02 23:12:254209 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:504210 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4211 glBindTexture(
[email protected]61eeb33f2011-07-26 15:30:314212 GetBindTargetForSamplerType(uniform_info->type),
[email protected]00f893d2010-08-24 18:55:494213 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:504214 }
4215 }
4216 // else: should this be an error?
4217 }
4218 }
[email protected]ef526492010-06-02 23:12:254219 return textures_set;
[email protected]3916c97e2010-02-25 03:20:504220}
4221
4222void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
4223 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:504224 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4225 current_program_->sampler_indices();
4226 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4227 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4228 current_program_->GetUniformInfo(sampler_indices[ii]);
4229 DCHECK(uniform_info);
4230 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4231 GLuint texture_unit_index = uniform_info->texture_units[jj];
4232 if (texture_unit_index < group_->max_texture_units()) {
4233 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4234 TextureManager::TextureInfo* texture_info =
4235 uniform_info->type == GL_SAMPLER_2D ?
4236 texture_unit.bound_texture_2d :
4237 texture_unit.bound_texture_cube_map;
[email protected]915a59a12010-09-30 21:29:114238 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]3916c97e2010-02-25 03:20:504239 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4240 // Get the texture info that was previously bound here.
4241 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
4242 texture_unit.bound_texture_2d :
4243 texture_unit.bound_texture_cube_map;
4244 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:034245 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:504246 }
4247 }
4248 }
4249 }
4250 // Set the active texture back to whatever the user had it as.
4251 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:304252}
4253
4254bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]689fa1c52010-06-09 18:35:034255 // NOTE: We specifically do not check current_program->IsValid() because
4256 // it could never be invalid since glUseProgram would have failed. While
4257 // glLinkProgram could later mark the program as invalid the previous
4258 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:144259 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:504260 // The program does not exist.
4261 // But GL says no ERROR.
4262 return false;
4263 }
[email protected]f39f4b3f2010-05-12 17:04:084264 // Validate all attribs currently enabled. If they are used by the current
4265 // program then check that they have enough elements to handle the draw call.
4266 // If they are not used by the current program check that they have a buffer
4267 // assigned.
4268 const VertexAttribManager::VertexAttribInfoList& infos =
4269 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4270 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:404271 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:084272 const VertexAttribManager::VertexAttribInfo* info = *it;
4273 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4274 current_program_->GetAttribInfoByLocation(info->index());
4275 if (attrib_info) {
4276 // This attrib is used in the current program.
4277 if (!info->CanAccess(max_vertex_accessed)) {
4278 SetGLError(GL_INVALID_OPERATION,
4279 "glDrawXXX: attempt to access out of range vertices");
4280 return false;
4281 }
4282 } else {
4283 // This attrib is not used in the current program.
4284 if (!info->buffer() || info->buffer()->IsDeleted()) {
4285 SetGLError(
4286 GL_INVALID_OPERATION,
4287 "glDrawXXX: attempt to render with no buffer attached to enabled "
4288 "attrib");
4289 return false;
4290 }
[email protected]1d32bc82010-01-13 22:06:464291 }
[email protected]07f54fcc2009-12-22 02:46:304292 }
[email protected]3916c97e2010-02-25 03:20:504293 return true;
[email protected]b1122982010-05-17 23:04:244294}
4295
4296bool GLES2DecoderImpl::SimulateAttrib0(GLuint max_vertex_accessed) {
[email protected]876f6fee2010-08-02 23:10:324297 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4298 return false;
4299
[email protected]b1122982010-05-17 23:04:244300 const VertexAttribManager::VertexAttribInfo* info =
4301 vertex_attrib_manager_.GetVertexAttribInfo(0);
4302 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:494303 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
4304 if (info->enabled() && attrib_0_used) {
[email protected]b1122982010-05-17 23:04:244305 return false;
4306 }
4307
4308 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
4309
4310 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
4311
4312 // Make a buffer with a single repeated vec4 value enough to
4313 // simulate the constant value that is supposed to be here.
4314 // This is required to emulate GLES2 on GL.
4315 GLsizei num_vertices = max_vertex_accessed + 1;
4316 GLsizei size_needed = num_vertices * sizeof(Vec4); // NOLINT
[email protected]fc753442011-02-04 19:49:494317 if (size_needed > attrib_0_size_) {
4318 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
4319 // TODO(gman): check for error here?
4320 attrib_0_buffer_matches_value_ = false;
4321 }
4322 if (attrib_0_used &&
4323 (!attrib_0_buffer_matches_value_ ||
4324 (info->value().v[0] != attrib_0_value_.v[0] ||
4325 info->value().v[1] != attrib_0_value_.v[1] ||
4326 info->value().v[2] != attrib_0_value_.v[2] ||
4327 info->value().v[3] != attrib_0_value_.v[3]))) {
4328 std::vector<Vec4> temp(num_vertices, info->value());
4329 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
4330 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:244331 attrib_0_value_ = info->value();
4332 attrib_0_size_ = size_needed;
4333 }
4334
4335 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4336
4337 return true;
[email protected]b1122982010-05-17 23:04:244338}
4339
4340void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
4341 const VertexAttribManager::VertexAttribInfo* info =
4342 vertex_attrib_manager_.GetVertexAttribInfo(0);
4343 const void* ptr = reinterpret_cast<const void*>(info->offset());
4344 BufferManager::BufferInfo* buffer_info = info->buffer();
4345 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
4346 glVertexAttribPointer(
4347 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
4348 ptr);
4349 glBindBuffer(GL_ARRAY_BUFFER,
4350 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4351}
[email protected]07f54fcc2009-12-22 02:46:304352
[email protected]8fbedc02010-11-18 18:43:404353bool GLES2DecoderImpl::SimulateFixedAttribs(
4354 GLuint max_vertex_accessed, bool* simulated) {
4355 DCHECK(simulated);
4356 *simulated = false;
4357 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4358 return true;
4359
4360 if (!vertex_attrib_manager_.HaveFixedAttribs()) {
4361 return true;
4362 }
4363
4364 // NOTE: we could be smart and try to check if a buffer is used
4365 // twice in 2 different attribs, find the overlapping parts and therefore
4366 // duplicate the minimum amount of data but this whole code path is not meant
4367 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
4368 // tests so we just add to the buffer attrib used.
4369
4370 // Compute the number of elements needed.
4371 int num_vertices = max_vertex_accessed + 1;
4372 int elements_needed = 0;
4373 const VertexAttribManager::VertexAttribInfoList& infos =
4374 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4375 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4376 infos.begin(); it != infos.end(); ++it) {
4377 const VertexAttribManager::VertexAttribInfo* info = *it;
4378 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4379 current_program_->GetAttribInfoByLocation(info->index());
4380 if (attrib_info &&
4381 info->CanAccess(max_vertex_accessed) &&
4382 info->type() == GL_FIXED) {
4383 int elements_used = 0;
4384 if (!SafeMultiply(
4385 static_cast<int>(num_vertices),
4386 info->size(), &elements_used) ||
4387 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
4388 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4389 return false;
4390 }
4391 }
4392 }
4393
4394 const int kSizeOfFloat = sizeof(float); // NOLINT
4395 int size_needed = 0;
4396 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed)) {
4397 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4398 return false;
4399 }
4400
4401
4402 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
4403 if (size_needed > fixed_attrib_buffer_size_) {
4404 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
4405 }
4406
4407 // Copy the elements and convert to float
4408 GLintptr offset = 0;
4409 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4410 infos.begin(); it != infos.end(); ++it) {
4411 const VertexAttribManager::VertexAttribInfo* info = *it;
4412 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4413 current_program_->GetAttribInfoByLocation(info->index());
4414 if (attrib_info &&
4415 info->CanAccess(max_vertex_accessed) &&
4416 info->type() == GL_FIXED) {
4417 int num_elements = info->size() * kSizeOfFloat;
4418 int size = num_elements * num_vertices;
4419 scoped_array<float> data(new float[size]);
4420 const int32* src = reinterpret_cast<const int32 *>(
4421 info->buffer()->GetRange(info->offset(), size));
4422 const int32* end = src + num_elements;
4423 float* dst = data.get();
4424 while (src != end) {
4425 *dst++ = static_cast<float>(*src++) / 65536.0f;
4426 }
4427 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
4428 glVertexAttribPointer(
4429 info->index(), info->size(), GL_FLOAT, false, 0,
4430 reinterpret_cast<GLvoid*>(offset));
4431 offset += size;
4432 }
4433 }
4434 *simulated = true;
4435 return true;
4436}
4437
4438void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
4439 // There's no need to call glVertexAttribPointer because we shadow all the
4440 // settings and passing GL_FIXED to it will not work.
4441 glBindBuffer(GL_ARRAY_BUFFER,
4442 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4443}
4444
[email protected]38d139d2011-07-14 00:38:434445error::Error GLES2DecoderImpl::HandleDrawArrays(
4446 uint32 immediate_data_size, const gles2::DrawArrays& c) {
4447 GLenum mode = static_cast<GLenum>(c.mode);
4448 GLint first = static_cast<GLint>(c.first);
4449 GLsizei count = static_cast<GLsizei>(c.count);
4450 if (!validators_->draw_mode.IsValid(mode)) {
4451 SetGLError(GL_INVALID_ENUM, "glDrawArrays: mode GL_INVALID_ENUM");
4452 return error::kNoError;
4453 }
4454 if (count < 0) {
4455 SetGLError(GL_INVALID_VALUE, "glDrawArrays: count < 0");
4456 return error::kNoError;
4457 }
4458 if (!CheckFramebufferComplete("glDrawArrays")) {
4459 return error::kNoError;
4460 }
4461 // We have to check this here because the prototype for glDrawArrays
4462 // is GLint not GLsizei.
4463 if (first < 0) {
4464 SetGLError(GL_INVALID_VALUE, "glDrawArrays: first < 0");
4465 return error::kNoError;
4466 }
4467
4468 if (count == 0) {
4469 return error::kNoError;
4470 }
4471
4472 GLuint max_vertex_accessed = first + count - 1;
4473 if (IsDrawValid(max_vertex_accessed)) {
4474 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
4475 bool simulated_fixed_attribs = false;
4476 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
4477 bool textures_set = SetBlackTextureForNonRenderableTextures();
4478 ApplyDirtyState();
4479 glDrawArrays(mode, first, count);
4480 if (textures_set) {
4481 RestoreStateForNonRenderableTextures();
4482 }
4483 if (simulated_fixed_attribs) {
4484 RestoreStateForSimulatedFixedAttribs();
4485 }
4486 }
4487 if (simulated_attrib_0) {
4488 RestoreStateForSimulatedAttrib0();
4489 }
4490 if (WasContextLost()) {
4491 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawArrays.";
4492 return error::kLostContext;
4493 }
4494 }
4495 return error::kNoError;
4496}
4497
[email protected]f7a64ee2010-02-01 22:24:144498error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:194499 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:504500 if (!bound_element_array_buffer_ ||
4501 bound_element_array_buffer_->IsDeleted()) {
[email protected]8eee29c2010-04-29 03:38:294502 SetGLError(GL_INVALID_OPERATION,
4503 "glDrawElements: No element array buffer bound");
4504 return error::kNoError;
4505 }
4506
4507 GLenum mode = c.mode;
4508 GLsizei count = c.count;
4509 GLenum type = c.type;
4510 int32 offset = c.index_offset;
4511 if (count < 0) {
4512 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
4513 return error::kNoError;
4514 }
4515 if (offset < 0) {
4516 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
4517 return error::kNoError;
4518 }
[email protected]9438b012010-06-15 22:55:054519 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:294520 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
4521 return error::kNoError;
4522 }
[email protected]9438b012010-06-15 22:55:054523 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294524 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
4525 return error::kNoError;
4526 }
4527
[email protected]3a03a8f2011-03-19 00:51:274528 if (!CheckFramebufferComplete("glDrawElements")) {
4529 return error::kNoError;
4530 }
4531
[email protected]6c788fb72010-08-26 02:16:314532 if (count == 0) {
4533 return error::kNoError;
4534 }
4535
[email protected]8eee29c2010-04-29 03:38:294536 GLuint max_vertex_accessed;
4537 if (!bound_element_array_buffer_->GetMaxValueForRange(
4538 offset, count, type, &max_vertex_accessed)) {
4539 SetGLError(GL_INVALID_OPERATION,
4540 "glDrawElements: range out of bounds for buffer");
4541 return error::kNoError;
4542 }
4543
4544 if (IsDrawValid(max_vertex_accessed)) {
[email protected]b1122982010-05-17 23:04:244545 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
[email protected]8fbedc02010-11-18 18:43:404546 bool simulated_fixed_attribs = false;
4547 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
4548 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:464549 ApplyDirtyState();
[email protected]8fbedc02010-11-18 18:43:404550 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
4551 glDrawElements(mode, count, type, indices);
4552 if (textures_set) {
4553 RestoreStateForNonRenderableTextures();
4554 }
4555 if (simulated_fixed_attribs) {
4556 RestoreStateForSimulatedFixedAttribs();
4557 }
[email protected]ba3176a2009-12-16 18:19:464558 }
[email protected]b1122982010-05-17 23:04:244559 if (simulated_attrib_0) {
4560 RestoreStateForSimulatedAttrib0();
4561 }
[email protected]38d139d2011-07-14 00:38:434562 if (WasContextLost()) {
4563 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawElements.";
4564 return error::kLostContext;
4565 }
[email protected]96449d2c2009-11-25 00:01:324566 }
[email protected]f7a64ee2010-02-01 22:24:144567 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324568}
4569
[email protected]269200b12010-11-18 22:53:064570GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:234571 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
4572 GLuint max_vertex_accessed = 0;
4573 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:294574 if (!info) {
[email protected]ae51d192010-04-27 00:48:034575 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:294576 SetGLError(GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:064577 "GetMaxValueInBufferCHROMIUM: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:234578 } else {
4579 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:034580 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:064581 SetGLError(
4582 GL_INVALID_OPERATION,
4583 "GetMaxValueInBufferCHROMIUM: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:234584 }
4585 }
4586 return max_vertex_accessed;
4587}
4588
[email protected]96449d2c2009-11-25 00:01:324589// Calls glShaderSource for the various versions of the ShaderSource command.
4590// Assumes that data / data_size points to a piece of memory that is in range
4591// of whatever context it came from (shared memory, immediate memory, bucket
4592// memory.)
[email protected]45bf5152010-02-12 00:11:314593error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034594 GLuint client_id, const char* data, uint32 data_size) {
[email protected]6b8cf1a2010-05-06 16:13:584595 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4596 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:314597 if (!info) {
[email protected]45bf5152010-02-12 00:11:314598 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324599 }
[email protected]45bf5152010-02-12 00:11:314600 // Note: We don't actually call glShaderSource here. We wait until
4601 // the call to glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:524602 info->Update(std::string(data, data + data_size).c_str());
[email protected]f7a64ee2010-02-01 22:24:144603 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324604}
4605
[email protected]f7a64ee2010-02-01 22:24:144606error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:194607 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:324608 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314609 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:324610 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:464611 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144612 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324613 }
[email protected]ae51d192010-04-27 00:48:034614 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:324615}
4616
[email protected]f7a64ee2010-02-01 22:24:144617error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:194618 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:324619 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314620 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:304621 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:464622 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144623 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324624 }
[email protected]ae51d192010-04-27 00:48:034625 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:314626}
4627
[email protected]558847a2010-03-24 07:02:544628error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
4629 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:544630 Bucket* bucket = GetBucket(c.data_bucket_id);
4631 if (!bucket || bucket->size() == 0) {
4632 return error::kInvalidArguments;
4633 }
4634 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034635 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:544636 bucket->size() - 1);
4637}
4638
[email protected]ae51d192010-04-27 00:48:034639void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]0c8fabf2011-06-14 19:35:224640 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]6b8cf1a2010-05-06 16:13:584641 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4642 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:314643 if (!info) {
[email protected]45bf5152010-02-12 00:11:314644 return;
4645 }
[email protected]de17df392010-04-23 21:09:414646 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
4647 // glShaderSource and then glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:524648 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:344649 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:184650 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:344651 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:454652 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:234653
[email protected]a550584e2010-09-17 18:01:454654 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:344655 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:184656 return;
4657 }
[email protected]a550584e2010-09-17 18:01:454658 shader_src = translator->translated_shader();
[email protected]de17df392010-04-23 21:09:414659 }
[email protected]de17df392010-04-23 21:09:414660
[email protected]ae51d192010-04-27 00:48:034661 glShaderSource(info->service_id(), 1, &shader_src, NULL);
4662 glCompileShader(info->service_id());
[email protected]e5186162010-06-14 18:54:414663 GLint status = GL_FALSE;
4664 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
4665 if (status) {
[email protected]f57bb282010-11-12 00:51:344666 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:414667 } else {
[email protected]d9977d42010-09-01 20:27:024668 // We cannot reach here if we are using the shader translator.
4669 // All invalid shaders must be rejected by the translator.
4670 // All translated shaders must compile.
4671 LOG_IF(ERROR, use_shader_translator_)
4672 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:334673 GLint max_len = 0;
4674 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
4675 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:414676 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:334677 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
4678 DCHECK(max_len == 0 || len < max_len);
4679 DCHECK(len ==0 || temp[len] == '\0');
[email protected]df6cf1ad2011-01-29 01:20:524680 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
[email protected]e5186162010-06-14 18:54:414681 }
[email protected]45bf5152010-02-12 00:11:314682};
4683
[email protected]ddd968b82010-03-02 00:44:294684void GLES2DecoderImpl::DoGetShaderiv(
4685 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:584686 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4687 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:294688 if (!info) {
[email protected]ddd968b82010-03-02 00:44:294689 return;
4690 }
[email protected]8f1ccdac2010-05-19 21:01:484691 switch (pname) {
4692 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:524693 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:484694 return;
4695 case GL_COMPILE_STATUS:
[email protected]e5186162010-06-14 18:54:414696 *params = info->IsValid();
4697 return;
[email protected]8f1ccdac2010-05-19 21:01:484698 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:524699 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:414700 return;
[email protected]8f1ccdac2010-05-19 21:01:484701 default:
4702 break;
[email protected]ddd968b82010-03-02 00:44:294703 }
[email protected]8f1ccdac2010-05-19 21:01:484704 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:294705}
4706
[email protected]ae51d192010-04-27 00:48:034707error::Error GLES2DecoderImpl::HandleGetShaderSource(
4708 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
4709 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:034710 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4711 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:584712 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4713 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:524714 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:294715 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:294716 return error::kNoError;
4717 }
[email protected]df6cf1ad2011-01-29 01:20:524718 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:034719 return error::kNoError;
4720}
4721
4722error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
4723 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
4724 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:584725 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4726 Bucket* bucket = CreateBucket(bucket_id);
4727 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4728 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:524729 if (!info || !info->log_info()) {
4730 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:034731 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:314732 }
[email protected]df6cf1ad2011-01-29 01:20:524733 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:034734 return error::kNoError;
4735}
4736
4737error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
4738 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
4739 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:584740 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4741 Bucket* bucket = CreateBucket(bucket_id);
4742 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4743 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:524744 if (!info || !info->log_info()) {
[email protected]6b8cf1a2010-05-06 16:13:584745 bucket->SetSize(0);
[email protected]ae51d192010-04-27 00:48:034746 return error::kNoError;
4747 }
[email protected]df6cf1ad2011-01-29 01:20:524748 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:034749 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324750}
4751
[email protected]1958e0e2010-04-22 05:17:154752bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364753 const BufferManager::BufferInfo* info = GetBufferInfo(client_id);
4754 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154755}
4756
4757bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364758 const FramebufferManager::FramebufferInfo* info =
4759 GetFramebufferInfo(client_id);
4760 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154761}
4762
4763bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364764 // IsProgram is true for programs as soon as they are created, until they are
4765 // deleted and no longer in use.
[email protected]ae51d192010-04-27 00:48:034766 return GetProgramInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154767}
4768
4769bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364770 const RenderbufferManager::RenderbufferInfo* info =
4771 GetRenderbufferInfo(client_id);
4772 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154773}
4774
4775bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364776 // IsShader is true for shaders as soon as they are created, until they
4777 // are deleted and not attached to any programs.
[email protected]ae51d192010-04-27 00:48:034778 return GetShaderInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154779}
4780
4781bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364782 const TextureManager::TextureInfo* info = GetTextureInfo(client_id);
4783 return info && info->IsValid();
[email protected]ae51d192010-04-27 00:48:034784}
4785
4786void GLES2DecoderImpl::DoAttachShader(
4787 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584788 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4789 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034790 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034791 return;
[email protected]1958e0e2010-04-22 05:17:154792 }
[email protected]6b8cf1a2010-05-06 16:13:584793 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4794 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034795 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034796 return;
4797 }
[email protected]ca488e12010-12-13 20:06:144798 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:314799 SetGLError(GL_INVALID_OPERATION,
4800 "glAttachShader: can not attach more than"
4801 " one shader of the same type.");
4802 return;
4803 }
[email protected]ae51d192010-04-27 00:48:034804 glAttachShader(program_info->service_id(), shader_info->service_id());
4805}
4806
4807void GLES2DecoderImpl::DoDetachShader(
4808 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584809 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4810 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034811 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034812 return;
4813 }
[email protected]6b8cf1a2010-05-06 16:13:584814 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4815 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034816 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034817 return;
4818 }
[email protected]9a0ccd42011-03-16 23:58:224819 if (!program_info->DetachShader(shader_manager(), shader_info)) {
4820 SetGLError(GL_INVALID_OPERATION,
4821 "glDetachShader: shader not attached to program");
4822 return;
4823 }
[email protected]ae51d192010-04-27 00:48:034824 glDetachShader(program_info->service_id(), shader_info->service_id());
4825}
4826
4827void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584828 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4829 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:034830 if (!info) {
[email protected]ae51d192010-04-27 00:48:034831 return;
4832 }
[email protected]d685a682011-04-29 16:19:574833 info->Validate();
[email protected]1958e0e2010-04-22 05:17:154834}
4835
[email protected]b1122982010-05-17 23:04:244836void GLES2DecoderImpl::DoGetVertexAttribfv(
4837 GLuint index, GLenum pname, GLfloat* params) {
4838 VertexAttribManager::VertexAttribInfo* info =
4839 vertex_attrib_manager_.GetVertexAttribInfo(index);
4840 if (!info) {
4841 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
4842 return;
4843 }
4844 switch (pname) {
4845 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4846 BufferManager::BufferInfo* buffer = info->buffer();
4847 if (buffer && !buffer->IsDeleted()) {
4848 GLuint client_id;
4849 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4850 *params = static_cast<GLfloat>(client_id);
4851 }
4852 break;
4853 }
4854 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4855 *params = static_cast<GLfloat>(info->enabled());
4856 break;
4857 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4858 *params = static_cast<GLfloat>(info->size());
4859 break;
4860 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4861 *params = static_cast<GLfloat>(info->gl_stride());
4862 break;
4863 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4864 *params = static_cast<GLfloat>(info->type());
4865 break;
4866 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4867 *params = static_cast<GLfloat>(info->normalized());
4868 break;
4869 case GL_CURRENT_VERTEX_ATTRIB:
4870 params[0] = info->value().v[0];
4871 params[1] = info->value().v[1];
4872 params[2] = info->value().v[2];
4873 params[3] = info->value().v[3];
4874 break;
4875 default:
4876 NOTREACHED();
4877 break;
4878 }
4879}
4880
4881void GLES2DecoderImpl::DoGetVertexAttribiv(
4882 GLuint index, GLenum pname, GLint* params) {
4883 VertexAttribManager::VertexAttribInfo* info =
4884 vertex_attrib_manager_.GetVertexAttribInfo(index);
4885 if (!info) {
4886 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
4887 return;
4888 }
4889 switch (pname) {
4890 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4891 BufferManager::BufferInfo* buffer = info->buffer();
4892 if (buffer && !buffer->IsDeleted()) {
4893 GLuint client_id;
4894 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4895 *params = client_id;
4896 }
4897 break;
4898 }
4899 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4900 *params = info->enabled();
4901 break;
4902 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4903 *params = info->size();
4904 break;
4905 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4906 *params = info->gl_stride();
4907 break;
4908 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4909 *params = info->type();
4910 break;
4911 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4912 *params = static_cast<GLint>(info->normalized());
4913 break;
4914 case GL_CURRENT_VERTEX_ATTRIB:
4915 params[0] = static_cast<GLint>(info->value().v[0]);
4916 params[1] = static_cast<GLint>(info->value().v[1]);
4917 params[2] = static_cast<GLint>(info->value().v[2]);
4918 params[3] = static_cast<GLint>(info->value().v[3]);
4919 break;
4920 default:
4921 NOTREACHED();
4922 break;
4923 }
4924}
4925
4926void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
4927 VertexAttribManager::VertexAttribInfo* info =
4928 vertex_attrib_manager_.GetVertexAttribInfo(index);
4929 if (!info) {
4930 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
4931 return;
4932 }
4933 VertexAttribManager::VertexAttribInfo::Vec4 value;
4934 value.v[0] = v0;
4935 value.v[1] = 0.0f;
4936 value.v[2] = 0.0f;
4937 value.v[3] = 1.0f;
4938 info->set_value(value);
4939 glVertexAttrib1f(index, v0);
4940}
4941
4942void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
4943 VertexAttribManager::VertexAttribInfo* info =
4944 vertex_attrib_manager_.GetVertexAttribInfo(index);
4945 if (!info) {
4946 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
4947 return;
4948 }
4949 VertexAttribManager::VertexAttribInfo::Vec4 value;
4950 value.v[0] = v0;
4951 value.v[1] = v1;
4952 value.v[2] = 0.0f;
4953 value.v[3] = 1.0f;
4954 info->set_value(value);
4955 glVertexAttrib2f(index, v0, v1);
4956}
4957
4958void GLES2DecoderImpl::DoVertexAttrib3f(
4959 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
4960 VertexAttribManager::VertexAttribInfo* info =
4961 vertex_attrib_manager_.GetVertexAttribInfo(index);
4962 if (!info) {
4963 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
4964 return;
4965 }
4966 VertexAttribManager::VertexAttribInfo::Vec4 value;
4967 value.v[0] = v0;
4968 value.v[1] = v1;
4969 value.v[2] = v2;
4970 value.v[3] = 1.0f;
4971 info->set_value(value);
4972 glVertexAttrib3f(index, v0, v1, v2);
4973}
4974
4975void GLES2DecoderImpl::DoVertexAttrib4f(
4976 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
4977 VertexAttribManager::VertexAttribInfo* info =
4978 vertex_attrib_manager_.GetVertexAttribInfo(index);
4979 if (!info) {
4980 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
4981 return;
4982 }
4983 VertexAttribManager::VertexAttribInfo::Vec4 value;
4984 value.v[0] = v0;
4985 value.v[1] = v1;
4986 value.v[2] = v2;
4987 value.v[3] = v3;
4988 info->set_value(value);
4989 glVertexAttrib4f(index, v0, v1, v2, v3);
4990}
4991
4992void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
4993 VertexAttribManager::VertexAttribInfo* info =
4994 vertex_attrib_manager_.GetVertexAttribInfo(index);
4995 if (!info) {
4996 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
4997 return;
4998 }
4999 VertexAttribManager::VertexAttribInfo::Vec4 value;
5000 value.v[0] = v[0];
5001 value.v[1] = 0.0f;
5002 value.v[2] = 0.0f;
5003 value.v[3] = 1.0f;
5004 info->set_value(value);
5005 glVertexAttrib1fv(index, v);
5006}
5007
5008void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
5009 VertexAttribManager::VertexAttribInfo* info =
5010 vertex_attrib_manager_.GetVertexAttribInfo(index);
5011 if (!info) {
5012 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
5013 return;
5014 }
5015 VertexAttribManager::VertexAttribInfo::Vec4 value;
5016 value.v[0] = v[0];
5017 value.v[1] = v[1];
5018 value.v[2] = 0.0f;
5019 value.v[3] = 1.0f;
5020 info->set_value(value);
5021 glVertexAttrib2fv(index, v);
5022}
5023
5024void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
5025 VertexAttribManager::VertexAttribInfo* info =
5026 vertex_attrib_manager_.GetVertexAttribInfo(index);
5027 if (!info) {
5028 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
5029 return;
5030 }
5031 VertexAttribManager::VertexAttribInfo::Vec4 value;
5032 value.v[0] = v[0];
5033 value.v[1] = v[1];
5034 value.v[2] = v[2];
5035 value.v[3] = 1.0f;
5036 info->set_value(value);
5037 glVertexAttrib3fv(index, v);
5038}
5039
5040void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
5041 VertexAttribManager::VertexAttribInfo* info =
5042 vertex_attrib_manager_.GetVertexAttribInfo(index);
5043 if (!info) {
5044 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
5045 return;
5046 }
5047 VertexAttribManager::VertexAttribInfo::Vec4 value;
5048 value.v[0] = v[0];
5049 value.v[1] = v[1];
5050 value.v[2] = v[2];
5051 value.v[3] = v[3];
5052 info->set_value(value);
5053 glVertexAttrib4fv(index, v);
5054}
5055
[email protected]f7a64ee2010-02-01 22:24:145056error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:195057 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:295058 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
5059 SetGLError(GL_INVALID_VALUE,
5060 "glVertexAttribPointer: no array buffer bound");
5061 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325062 }
[email protected]8eee29c2010-04-29 03:38:295063
5064 GLuint indx = c.indx;
5065 GLint size = c.size;
5066 GLenum type = c.type;
5067 GLboolean normalized = c.normalized;
5068 GLsizei stride = c.stride;
5069 GLsizei offset = c.offset;
5070 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:055071 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295072 SetGLError(GL_INVALID_ENUM,
5073 "glVertexAttribPointer: type GL_INVALID_ENUM");
5074 return error::kNoError;
5075 }
[email protected]9438b012010-06-15 22:55:055076 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:315077 SetGLError(GL_INVALID_VALUE,
[email protected]8eee29c2010-04-29 03:38:295078 "glVertexAttribPointer: size GL_INVALID_VALUE");
5079 return error::kNoError;
5080 }
5081 if (indx >= group_->max_vertex_attribs()) {
5082 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
5083 return error::kNoError;
5084 }
5085 if (stride < 0) {
5086 SetGLError(GL_INVALID_VALUE,
5087 "glVertexAttribPointer: stride < 0");
5088 return error::kNoError;
5089 }
5090 if (stride > 255) {
5091 SetGLError(GL_INVALID_VALUE,
5092 "glVertexAttribPointer: stride > 255");
5093 return error::kNoError;
5094 }
5095 if (offset < 0) {
5096 SetGLError(GL_INVALID_VALUE,
5097 "glVertexAttribPointer: offset < 0");
5098 return error::kNoError;
5099 }
5100 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:315101 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:295102 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:315103 SetGLError(GL_INVALID_OPERATION,
5104 "glVertexAttribPointer: offset not valid for type");
5105 return error::kNoError;
5106 }
5107 if (stride % component_size > 0) {
5108 SetGLError(GL_INVALID_OPERATION,
[email protected]8eee29c2010-04-29 03:38:295109 "glVertexAttribPointer: stride not valid for type");
5110 return error::kNoError;
5111 }
[email protected]8fbedc02010-11-18 18:43:405112 vertex_attrib_manager_.SetAttribInfo(
5113 indx,
[email protected]8eee29c2010-04-29 03:38:295114 bound_array_buffer_,
5115 size,
5116 type,
[email protected]b1122982010-05-17 23:04:245117 normalized,
5118 stride,
5119 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:295120 offset);
[email protected]8fbedc02010-11-18 18:43:405121 if (type != GL_FIXED) {
5122 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
5123 }
[email protected]f7a64ee2010-02-01 22:24:145124 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325125}
5126
[email protected]f7a64ee2010-02-01 22:24:145127error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:195128 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:315129 GLint x = c.x;
5130 GLint y = c.y;
5131 GLsizei width = c.width;
5132 GLsizei height = c.height;
5133 GLenum format = c.format;
5134 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:565135 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:295136 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:565137 return error::kNoError;
5138 }
[email protected]a51788e2010-02-24 21:54:255139 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:185140 uint32 pixels_size;
5141 if (!GLES2Util::ComputeImageDataSize(
5142 width, height, format, type, pack_alignment_, &pixels_size)) {
5143 return error::kOutOfBounds;
5144 }
[email protected]612d2f82009-12-08 20:49:315145 void* pixels = GetSharedMemoryAs<void*>(
5146 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:255147 Result* result = GetSharedMemoryAs<Result*>(
5148 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5149 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:145150 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465151 }
[email protected]a51788e2010-02-24 21:54:255152
[email protected]9438b012010-06-15 22:55:055153 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295154 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
5155 return error::kNoError;
5156 }
[email protected]9438b012010-06-15 22:55:055157 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295158 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125159 return error::kNoError;
5160 }
[email protected]57f223832010-03-19 01:57:565161 if (width == 0 || height == 0) {
5162 return error::kNoError;
5163 }
5164
5165 CopyRealGLErrorsToWrapper();
5166
[email protected]de26b3c2011-08-03 21:54:275167 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]34ff8b0c2010-10-01 20:06:025168
[email protected]57f223832010-03-19 01:57:565169 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:305170 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:565171
5172 GLint max_x;
5173 GLint max_y;
5174 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:295175 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:145176 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:315177 }
[email protected]57f223832010-03-19 01:57:565178
[email protected]d37231fa2010-04-09 21:16:025179 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:565180 // The user requested an out of range area. Get the results 1 line
5181 // at a time.
5182 uint32 temp_size;
5183 if (!GLES2Util::ComputeImageDataSize(
5184 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295185 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565186 return error::kNoError;
5187 }
5188 GLsizei unpadded_row_size = temp_size;
5189 if (!GLES2Util::ComputeImageDataSize(
5190 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295191 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565192 return error::kNoError;
5193 }
5194 GLsizei padded_row_size = temp_size - unpadded_row_size;
5195 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:295196 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565197 return error::kNoError;
5198 }
5199
5200 GLint dest_x_offset = std::max(-x, 0);
5201 uint32 dest_row_offset;
5202 if (!GLES2Util::ComputeImageDataSize(
5203 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:295204 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565205 return error::kNoError;
5206 }
5207
5208 // Copy each row into the larger dest rect.
5209 int8* dst = static_cast<int8*>(pixels);
5210 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:025211 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:565212 GLint read_width = read_end_x - read_x;
5213 for (GLint yy = 0; yy < height; ++yy) {
5214 GLint ry = y + yy;
5215
5216 // Clear the row.
5217 memset(dst, 0, unpadded_row_size);
5218
5219 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:025220 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:565221 glReadPixels(
5222 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
5223 }
5224 dst += padded_row_size;
5225 }
5226 } else {
5227 glReadPixels(x, y, width, height, format, type, pixels);
5228 }
[email protected]1002c2d2011-06-28 22:39:045229 GLenum error = PeekGLError();
[email protected]a51788e2010-02-24 21:54:255230 if (error == GL_NO_ERROR) {
5231 *result = true;
[email protected]4848b9f82011-03-10 18:37:565232
5233 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5234 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5235 if ((channels_exist & 0x0008) == 0) {
5236 // Set the alpha to 255 because some drivers are buggy in this regard.
5237 uint32 temp_size;
5238 if (!GLES2Util::ComputeImageDataSize(
5239 width, 1, format, type, pack_alignment_, &temp_size)) {
5240 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5241 return error::kNoError;
5242 }
5243 GLsizei unpadded_row_size = temp_size;
5244 if (!GLES2Util::ComputeImageDataSize(
5245 width, 2, format, type, pack_alignment_, &temp_size)) {
5246 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5247 return error::kNoError;
5248 }
5249 GLsizei padded_row_size = temp_size - unpadded_row_size;
5250 if (padded_row_size < 0 || unpadded_row_size < 0) {
5251 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5252 return error::kNoError;
5253 }
5254 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
5255 // of this implementation.
5256 if (type != GL_UNSIGNED_BYTE) {
5257 SetGLError(GL_INVALID_OPERATION, "unsupported readPixel format");
5258 return error::kNoError;
5259 }
5260 switch (format) {
5261 case GL_RGBA:
[email protected]297ca1c2011-06-20 23:08:465262 case GL_BGRA_EXT:
[email protected]4848b9f82011-03-10 18:37:565263 case GL_ALPHA: {
5264 int offset = (format == GL_ALPHA) ? 0 : 3;
5265 int step = (format == GL_ALPHA) ? 1 : 4;
5266 uint8* dst = static_cast<uint8*>(pixels) + offset;
5267 for (GLint yy = 0; yy < height; ++yy) {
5268 uint8* end = dst + unpadded_row_size;
5269 for (uint8* d = dst; d < end; d += step) {
5270 *d = 255;
5271 }
5272 dst += padded_row_size;
5273 }
5274 break;
5275 }
5276 default:
5277 break;
5278 }
5279 }
[email protected]a51788e2010-02-24 21:54:255280 }
[email protected]4848b9f82011-03-10 18:37:565281
[email protected]f7a64ee2010-02-01 22:24:145282 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325283}
5284
[email protected]f7a64ee2010-02-01 22:24:145285error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:195286 uint32 immediate_data_size, const gles2::PixelStorei& c) {
5287 GLenum pname = c.pname;
5288 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:055289 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:295290 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125291 return error::kNoError;
5292 }
[email protected]9438b012010-06-15 22:55:055293 if (!validators_->pixel_store_alignment.IsValid(param)) {
[email protected]8eee29c2010-04-29 03:38:295294 SetGLError(GL_INVALID_VALUE, "glPixelSTore: param GL_INVALID_VALUE");
[email protected]f7a64ee2010-02-01 22:24:145295 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195296 }
5297 glPixelStorei(pname, param);
5298 switch (pname) {
5299 case GL_PACK_ALIGNMENT:
5300 pack_alignment_ = param;
5301 break;
5302 case GL_UNPACK_ALIGNMENT:
5303 unpack_alignment_ = param;
5304 break;
5305 default:
5306 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:375307 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:195308 break;
5309 }
[email protected]f7a64ee2010-02-01 22:24:145310 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195311}
5312
[email protected]558847a2010-03-24 07:02:545313error::Error GLES2DecoderImpl::GetAttribLocationHelper(
5314 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5315 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:585316 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5317 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:035318 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145319 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195320 }
[email protected]ae51d192010-04-27 00:48:035321 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295322 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255323 return error::kNoError;
5324 }
[email protected]b9849abf2009-11-25 19:13:195325 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:545326 location_shm_id, location_shm_offset, sizeof(GLint));
5327 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:145328 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195329 }
[email protected]558847a2010-03-24 07:02:545330 // Require the client to init this incase the context is lost and we are no
5331 // longer executing commands.
5332 if (*location != -1) {
5333 return error::kGenericError;
5334 }
[email protected]0bfd9882010-02-05 23:02:255335 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:145336 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195337}
5338
[email protected]558847a2010-03-24 07:02:545339error::Error GLES2DecoderImpl::HandleGetAttribLocation(
5340 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
5341 uint32 name_size = c.data_size;
5342 const char* name = GetSharedMemoryAs<const char*>(
5343 c.name_shm_id, c.name_shm_offset, name_size);
5344 if (!name) {
5345 return error::kOutOfBounds;
5346 }
5347 String name_str(name, name_size);
5348 return GetAttribLocationHelper(
5349 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5350}
5351
[email protected]f7a64ee2010-02-01 22:24:145352error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:195353 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:545354 uint32 name_size = c.data_size;
5355 const char* name = GetImmediateDataAs<const char*>(
5356 c, name_size, immediate_data_size);
5357 if (!name) {
5358 return error::kOutOfBounds;
5359 }
5360 String name_str(name, name_size);
5361 return GetAttribLocationHelper(
5362 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5363}
5364
5365error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
5366 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
5367 Bucket* bucket = GetBucket(c.name_bucket_id);
5368 if (!bucket) {
5369 return error::kInvalidArguments;
5370 }
5371 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185372 if (!bucket->GetAsString(&name_str)) {
5373 return error::kInvalidArguments;
5374 }
[email protected]558847a2010-03-24 07:02:545375 return GetAttribLocationHelper(
5376 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5377}
5378
5379error::Error GLES2DecoderImpl::GetUniformLocationHelper(
5380 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5381 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:585382 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5383 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:035384 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145385 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195386 }
[email protected]ae51d192010-04-27 00:48:035387 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295388 SetGLError(GL_INVALID_OPERATION,
5389 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255390 return error::kNoError;
5391 }
[email protected]b9849abf2009-11-25 19:13:195392 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:545393 location_shm_id, location_shm_offset, sizeof(GLint));
5394 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:145395 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195396 }
[email protected]558847a2010-03-24 07:02:545397 // Require the client to init this incase the context is lost an we are no
5398 // longer executing commands.
5399 if (*location != -1) {
5400 return error::kGenericError;
5401 }
5402 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:145403 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195404}
5405
[email protected]f7a64ee2010-02-01 22:24:145406error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:195407 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:195408 uint32 name_size = c.data_size;
5409 const char* name = GetSharedMemoryAs<const char*>(
5410 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:545411 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:145412 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195413 }
5414 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:545415 return GetUniformLocationHelper(
5416 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195417}
5418
[email protected]f7a64ee2010-02-01 22:24:145419error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:195420 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:195421 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:305422 const char* name = GetImmediateDataAs<const char*>(
5423 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:545424 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:145425 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195426 }
5427 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:545428 return GetUniformLocationHelper(
5429 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5430}
5431
5432error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
5433 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
5434 Bucket* bucket = GetBucket(c.name_bucket_id);
5435 if (!bucket) {
5436 return error::kInvalidArguments;
5437 }
5438 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185439 if (!bucket->GetAsString(&name_str)) {
5440 return error::kInvalidArguments;
5441 }
[email protected]558847a2010-03-24 07:02:545442 return GetUniformLocationHelper(
5443 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195444}
5445
[email protected]ddd968b82010-03-02 00:44:295446error::Error GLES2DecoderImpl::HandleGetString(
5447 uint32 immediate_data_size, const gles2::GetString& c) {
5448 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:055449 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:295450 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:295451 return error::kNoError;
5452 }
[email protected]1958e0e2010-04-22 05:17:155453 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
5454 const char* str = NULL;
5455 switch (name) {
5456 case GL_VERSION:
5457 str = "OpenGL ES 2.0 Chromium";
5458 break;
5459 case GL_SHADING_LANGUAGE_VERSION:
5460 str = "OpenGL ES GLSL ES 1.0 Chromium";
5461 break;
5462 case GL_EXTENSIONS:
[email protected]915a59a12010-09-30 21:29:115463 str = feature_info_->extensions().c_str();
[email protected]1958e0e2010-04-22 05:17:155464 break;
5465 default:
5466 str = gl_str;
5467 break;
5468 }
[email protected]ddd968b82010-03-02 00:44:295469 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:155470 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:295471 return error::kNoError;
5472}
5473
[email protected]0c86dbf2010-03-05 08:14:115474void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:155475 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:055476 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295477 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
5478 return;
5479 }
[email protected]9438b012010-06-15 22:55:055480 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:295481 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:115482 return;
[email protected]3b6ec202010-03-05 05:16:235483 }
5484 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:295485 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:285486 return;
[email protected]3b6ec202010-03-05 05:16:235487 }
5488 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
5489 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295490 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285491 return;
[email protected]3b6ec202010-03-05 05:16:235492 }
5493 // Clear the buffer to 0 if no initial data was passed in.
5494 scoped_array<int8> zero;
5495 if (!data) {
5496 zero.reset(new int8[size]);
5497 memset(zero.get(), 0, size);
5498 data = zero.get();
5499 }
[email protected]473c01ccb2011-06-07 01:33:305500
5501 if (!bufferdata_faster_than_buffersubdata_ &&
5502 size == info->size() && usage == info->usage()) {
5503 glBufferSubData(target, 0, size, data);
5504 info->SetRange(0, size, data);
5505 return;
5506 }
5507
[email protected]3b6ec202010-03-05 05:16:235508 CopyRealGLErrorsToWrapper();
5509 glBufferData(target, size, data, usage);
[email protected]1002c2d2011-06-28 22:39:045510 GLenum error = PeekGLError();
5511 if (error == GL_NO_ERROR) {
[email protected]473c01ccb2011-06-07 01:33:305512 buffer_manager()->SetInfo(info, size, usage);
[email protected]0c86dbf2010-03-05 08:14:115513 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:235514 }
[email protected]0c86dbf2010-03-05 08:14:115515}
5516
5517error::Error GLES2DecoderImpl::HandleBufferData(
5518 uint32 immediate_data_size, const gles2::BufferData& c) {
5519 GLenum target = static_cast<GLenum>(c.target);
5520 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
5521 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5522 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5523 GLenum usage = static_cast<GLenum>(c.usage);
5524 const void* data = NULL;
5525 if (data_shm_id != 0 || data_shm_offset != 0) {
5526 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
5527 if (!data) {
5528 return error::kOutOfBounds;
5529 }
5530 }
5531 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:145532 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195533}
5534
[email protected]f7a64ee2010-02-01 22:24:145535error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:195536 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
5537 GLenum target = static_cast<GLenum>(c.target);
5538 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:305539 const void* data = GetImmediateDataAs<const void*>(
5540 c, size, immediate_data_size);
5541 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145542 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:305543 }
[email protected]b9849abf2009-11-25 19:13:195544 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:115545 DoBufferData(target, size, data, usage);
5546 return error::kNoError;
5547}
5548
5549void GLES2DecoderImpl::DoBufferSubData(
5550 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:505551 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475552 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295553 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285554 return;
[email protected]a93bb842010-02-16 23:03:475555 }
[email protected]0c86dbf2010-03-05 08:14:115556 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:295557 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]473c01ccb2011-06-07 01:33:305558 return;
[email protected]07f54fcc2009-12-22 02:46:305559 }
[email protected]473c01ccb2011-06-07 01:33:305560 if (bufferdata_faster_than_buffersubdata_ &&
5561 offset == 0 && size == info->size()) {
5562 glBufferData(target, size, data, info->usage());
5563 return;
5564 }
5565 glBufferSubData(target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:195566}
5567
[email protected]a93bb842010-02-16 23:03:475568error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
5569 GLenum target,
5570 GLint level,
5571 GLenum internal_format,
5572 GLsizei width,
5573 GLsizei height,
5574 GLint border,
5575 GLsizei image_size,
5576 const void* data) {
[email protected]a93bb842010-02-16 23:03:475577 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:055578 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295579 SetGLError(GL_INVALID_ENUM,
5580 "glCompressedTexImage2D: target GL_INVALID_ENUM");
5581 return error::kNoError;
5582 }
[email protected]9438b012010-06-15 22:55:055583 if (!validators_->compressed_texture_format.IsValid(
5584 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295585 SetGLError(GL_INVALID_ENUM,
5586 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:475587 return error::kNoError;
5588 }
[email protected]915a59a12010-09-30 21:29:115589 if (!texture_manager()->ValidForTarget(
5590 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475591 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295592 SetGLError(GL_INVALID_VALUE,
5593 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475594 return error::kNoError;
5595 }
[email protected]3916c97e2010-02-25 03:20:505596 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475597 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295598 SetGLError(GL_INVALID_VALUE,
5599 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:475600 return error::kNoError;
5601 }
5602 scoped_array<int8> zero;
5603 if (!data) {
5604 zero.reset(new int8[image_size]);
5605 memset(zero.get(), 0, image_size);
5606 data = zero.get();
5607 }
[email protected]cadde4a2010-07-31 17:10:435608 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:475609 glCompressedTexImage2D(
5610 target, level, internal_format, width, height, border, image_size, data);
[email protected]1002c2d2011-06-28 22:39:045611 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:435612 if (error == GL_NO_ERROR) {
5613 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:115614 feature_info_,
[email protected]cadde4a2010-07-31 17:10:435615 info, target, level, internal_format, width, height, 1, border, 0, 0);
5616 }
[email protected]a93bb842010-02-16 23:03:475617 return error::kNoError;
5618}
5619
[email protected]f7a64ee2010-02-01 22:24:145620error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195621 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
5622 GLenum target = static_cast<GLenum>(c.target);
5623 GLint level = static_cast<GLint>(c.level);
5624 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5625 GLsizei width = static_cast<GLsizei>(c.width);
5626 GLsizei height = static_cast<GLsizei>(c.height);
5627 GLint border = static_cast<GLint>(c.border);
5628 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
5629 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5630 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5631 const void* data = NULL;
5632 if (data_shm_id != 0 || data_shm_offset != 0) {
5633 data = GetSharedMemoryAs<const void*>(
5634 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:465635 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145636 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195637 }
5638 }
[email protected]a93bb842010-02-16 23:03:475639 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195640 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:195641}
5642
[email protected]f7a64ee2010-02-01 22:24:145643error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195644 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
5645 GLenum target = static_cast<GLenum>(c.target);
5646 GLint level = static_cast<GLint>(c.level);
5647 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5648 GLsizei width = static_cast<GLsizei>(c.width);
5649 GLsizei height = static_cast<GLsizei>(c.height);
5650 GLint border = static_cast<GLint>(c.border);
5651 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:305652 const void* data = GetImmediateDataAs<const void*>(
5653 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465654 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145655 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465656 }
[email protected]a93bb842010-02-16 23:03:475657 return DoCompressedTexImage2D(
5658 target, level, internal_format, width, height, border, image_size, data);
5659}
5660
[email protected]b6140d02010-05-17 14:47:165661error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
5662 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
5663 GLenum target = static_cast<GLenum>(c.target);
5664 GLint level = static_cast<GLint>(c.level);
5665 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5666 GLsizei width = static_cast<GLsizei>(c.width);
5667 GLsizei height = static_cast<GLsizei>(c.height);
5668 GLint border = static_cast<GLint>(c.border);
5669 Bucket* bucket = GetBucket(c.bucket_id);
5670 return DoCompressedTexImage2D(
5671 target, level, internal_format, width, height, border,
5672 bucket->size(), bucket->GetData(0, bucket->size()));
5673}
5674
5675error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
5676 uint32 immediate_data_size,
5677 const gles2::CompressedTexSubImage2DBucket& c) {
5678 GLenum target = static_cast<GLenum>(c.target);
5679 GLint level = static_cast<GLint>(c.level);
5680 GLint xoffset = static_cast<GLint>(c.xoffset);
5681 GLint yoffset = static_cast<GLint>(c.yoffset);
5682 GLsizei width = static_cast<GLsizei>(c.width);
5683 GLsizei height = static_cast<GLsizei>(c.height);
5684 GLenum format = static_cast<GLenum>(c.format);
5685 Bucket* bucket = GetBucket(c.bucket_id);
5686 uint32 data_size = bucket->size();
5687 GLsizei imageSize = data_size;
5688 const void* data = bucket->GetData(0, data_size);
[email protected]9438b012010-06-15 22:55:055689 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:165690 SetGLError(
5691 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
5692 return error::kNoError;
5693 }
[email protected]9438b012010-06-15 22:55:055694 if (!validators_->compressed_texture_format.IsValid(format)) {
5695 SetGLError(GL_INVALID_ENUM,
5696 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
5697 return error::kNoError;
5698 }
[email protected]b6140d02010-05-17 14:47:165699 if (width < 0) {
5700 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
5701 return error::kNoError;
5702 }
5703 if (height < 0) {
5704 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
5705 return error::kNoError;
5706 }
5707 if (imageSize < 0) {
5708 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
5709 return error::kNoError;
5710 }
[email protected]cadde4a2010-07-31 17:10:435711 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:165712 target, level, xoffset, yoffset, width, height, format, imageSize, data);
5713 return error::kNoError;
5714}
5715
[email protected]a93bb842010-02-16 23:03:475716error::Error GLES2DecoderImpl::DoTexImage2D(
5717 GLenum target,
5718 GLint level,
5719 GLenum internal_format,
5720 GLsizei width,
5721 GLsizei height,
5722 GLint border,
5723 GLenum format,
5724 GLenum type,
5725 const void* pixels,
5726 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:055727 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295728 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
5729 return error::kNoError;
5730 }
[email protected]9438b012010-06-15 22:55:055731 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295732 SetGLError(GL_INVALID_ENUM,
5733 "glTexImage2D: internal_format GL_INVALID_ENUM");
5734 return error::kNoError;
5735 }
[email protected]9438b012010-06-15 22:55:055736 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295737 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
5738 return error::kNoError;
5739 }
[email protected]9438b012010-06-15 22:55:055740 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295741 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:145742 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195743 }
[email protected]7b92c412010-07-20 17:48:255744 if (format != internal_format) {
5745 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
5746 return error::kNoError;
5747 }
[email protected]915a59a12010-09-30 21:29:115748 if (!texture_manager()->ValidForTarget(
5749 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475750 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295751 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475752 return error::kNoError;
5753 }
[email protected]3916c97e2010-02-25 03:20:505754 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475755 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295756 SetGLError(GL_INVALID_OPERATION,
5757 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:475758 return error::kNoError;
5759 }
[email protected]0226c112011-07-22 03:25:075760
5761 GLsizei tex_width = 0;
5762 GLsizei tex_height = 0;
5763 GLenum tex_type = 0;
5764 GLenum tex_format = 0;
5765 bool level_is_same =
5766 info->GetLevelSize(target, level, &tex_width, &tex_height) &&
5767 info->GetLevelType(target, level, &tex_type, &tex_format) &&
5768 width == tex_width && height == tex_height &&
5769 type == tex_type && format == tex_format;
5770
5771 if (level_is_same && !pixels) {
5772 return error::kNoError;
5773 }
5774
[email protected]a93bb842010-02-16 23:03:475775 scoped_array<int8> zero;
5776 if (!pixels) {
5777 zero.reset(new int8[pixels_size]);
5778 memset(zero.get(), 0, pixels_size);
5779 pixels = zero.get();
5780 }
[email protected]876f6fee2010-08-02 23:10:325781
[email protected]297ca1c2011-06-20 23:08:465782 if (info->IsAttachedToFramebuffer()) {
5783 state_dirty_ = true;
5784 }
5785
[email protected]0226c112011-07-22 03:25:075786 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same) {
5787 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
5788 tex_image_2d_failed_ = false;
5789 return error::kNoError;
[email protected]7488d962010-07-16 02:41:585790 }
[email protected]876f6fee2010-08-02 23:10:325791
[email protected]cadde4a2010-07-31 17:10:435792 CopyRealGLErrorsToWrapper();
[email protected]473c01ccb2011-06-07 01:33:305793 WrappedTexImage2D(
5794 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475795 pixels);
[email protected]1002c2d2011-06-28 22:39:045796 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:435797 if (error == GL_NO_ERROR) {
[email protected]915a59a12010-09-30 21:29:115798 texture_manager()->SetLevelInfo(feature_info_, info,
[email protected]cadde4a2010-07-31 17:10:435799 target, level, internal_format, width, height, 1, border, format, type);
[email protected]b493ee622011-04-13 23:52:005800 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:435801 }
[email protected]f7a64ee2010-02-01 22:24:145802 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195803}
5804
[email protected]f7a64ee2010-02-01 22:24:145805error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195806 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]366ae242011-05-10 02:23:585807 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:005808 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:195809 GLenum target = static_cast<GLenum>(c.target);
5810 GLint level = static_cast<GLint>(c.level);
5811 GLint internal_format = static_cast<GLint>(c.internalformat);
5812 GLsizei width = static_cast<GLsizei>(c.width);
5813 GLsizei height = static_cast<GLsizei>(c.height);
5814 GLint border = static_cast<GLint>(c.border);
5815 GLenum format = static_cast<GLenum>(c.format);
5816 GLenum type = static_cast<GLenum>(c.type);
5817 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
5818 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:185819 uint32 pixels_size;
5820 if (!GLES2Util::ComputeImageDataSize(
5821 width, height, format, type, unpack_alignment_, &pixels_size)) {
5822 return error::kOutOfBounds;
5823 }
[email protected]b9849abf2009-11-25 19:13:195824 const void* pixels = NULL;
5825 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
5826 pixels = GetSharedMemoryAs<const void*>(
5827 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:465828 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145829 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195830 }
5831 }
[email protected]a93bb842010-02-16 23:03:475832 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195833 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475834 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:195835}
5836
[email protected]f7a64ee2010-02-01 22:24:145837error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195838 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
5839 GLenum target = static_cast<GLenum>(c.target);
5840 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:465841 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:195842 GLsizei width = static_cast<GLsizei>(c.width);
5843 GLsizei height = static_cast<GLsizei>(c.height);
5844 GLint border = static_cast<GLint>(c.border);
5845 GLenum format = static_cast<GLenum>(c.format);
5846 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:185847 uint32 size;
5848 if (!GLES2Util::ComputeImageDataSize(
5849 width, height, format, type, unpack_alignment_, &size)) {
5850 return error::kOutOfBounds;
5851 }
[email protected]07f54fcc2009-12-22 02:46:305852 const void* pixels = GetImmediateDataAs<const void*>(
5853 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465854 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145855 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465856 }
[email protected]a93bb842010-02-16 23:03:475857 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:465858 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475859 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:145860 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325861}
5862
[email protected]cadde4a2010-07-31 17:10:435863void GLES2DecoderImpl::DoCompressedTexSubImage2D(
5864 GLenum target,
5865 GLint level,
5866 GLint xoffset,
5867 GLint yoffset,
5868 GLsizei width,
5869 GLsizei height,
5870 GLenum format,
5871 GLsizei image_size,
5872 const void * data) {
5873 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5874 if (!info) {
5875 SetGLError(GL_INVALID_OPERATION,
5876 "glCompressedTexSubImage2D: unknown texture for target");
5877 return;
5878 }
5879 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:525880 GLenum internal_format = 0;
5881 if (!info->GetLevelType(target, level, &type, &internal_format)) {
5882 SetGLError(
5883 GL_INVALID_OPERATION,
5884 "glCompressdTexSubImage2D: level does not exist.");
5885 return;
5886 }
5887 if (internal_format != format) {
5888 SetGLError(
5889 GL_INVALID_OPERATION,
5890 "glCompressdTexSubImage2D: format does not match internal format.");
5891 return;
5892 }
5893 if (!info->ValidForTexture(
5894 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:435895 SetGLError(GL_INVALID_VALUE,
5896 "glCompressdTexSubImage2D: bad dimensions.");
5897 return;
5898 }
5899 glCompressedTexSubImage2D(
5900 target, level, xoffset, yoffset, width, height, format, image_size, data);
5901}
5902
[email protected]6e288612010-12-21 20:45:035903static void Clip(
5904 GLint start, GLint range, GLint sourceRange,
5905 GLint* out_start, GLint* out_range) {
5906 DCHECK(out_start);
5907 DCHECK(out_range);
5908 if (start < 0) {
5909 range += start;
5910 start = 0;
5911 }
5912 GLint end = start + range;
5913 if (end > sourceRange) {
5914 range -= end - sourceRange;
5915 }
5916 *out_start = start;
5917 *out_range = range;
5918}
5919
5920
[email protected]cadde4a2010-07-31 17:10:435921void GLES2DecoderImpl::DoCopyTexImage2D(
5922 GLenum target,
5923 GLint level,
5924 GLenum internal_format,
5925 GLint x,
5926 GLint y,
5927 GLsizei width,
5928 GLsizei height,
5929 GLint border) {
5930 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5931 if (!info) {
5932 SetGLError(GL_INVALID_OPERATION,
5933 "glCopyTexImage2D: unknown texture for target");
5934 return;
5935 }
[email protected]915a59a12010-09-30 21:29:115936 if (!texture_manager()->ValidForTarget(
5937 feature_info_, target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:185938 border != 0) {
5939 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
5940 return;
5941 }
5942
[email protected]9edc6b22010-12-23 02:00:265943 // Check we have compatible formats.
5944 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5945 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5946 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
5947
5948 if ((channels_needed & channels_exist) != channels_needed) {
5949 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
5950 return;
5951 }
5952
[email protected]cadde4a2010-07-31 17:10:435953 CopyRealGLErrorsToWrapper();
[email protected]de26b3c2011-08-03 21:54:275954 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:035955 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:265956
[email protected]297ca1c2011-06-20 23:08:465957 if (info->IsAttachedToFramebuffer()) {
5958 state_dirty_ = true;
5959 }
5960
[email protected]9edc6b22010-12-23 02:00:265961 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:035962 GLint copyX = 0;
5963 GLint copyY = 0;
5964 GLint copyWidth = 0;
5965 GLint copyHeight = 0;
5966 Clip(x, width, size.width(), &copyX, &copyWidth);
5967 Clip(y, height, size.height(), &copyY, &copyHeight);
5968
5969 if (copyX != x ||
5970 copyY != y ||
5971 copyWidth != width ||
5972 copyHeight != height) {
5973 // some part was clipped so clear the texture.
5974 uint32 pixels_size = 0;
5975 if (!GLES2Util::ComputeImageDataSize(
5976 width, height, internal_format, GL_UNSIGNED_BYTE,
5977 unpack_alignment_, &pixels_size)) {
5978 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions too large");
5979 return;
5980 }
5981 scoped_array<char> zero(new char[pixels_size]);
5982 memset(zero.get(), 0, pixels_size);
5983 glTexImage2D(target, level, internal_format, width, height, 0,
5984 internal_format, GL_UNSIGNED_BYTE, zero.get());
5985 if (copyHeight > 0 && copyWidth > 0) {
5986 GLint dx = copyX - x;
5987 GLint dy = copyY - y;
5988 GLint destX = dx;
5989 GLint destY = dy;
5990 glCopyTexSubImage2D(target, level,
5991 destX, destY, copyX, copyY,
5992 copyWidth, copyHeight);
5993 }
5994 } else {
5995 glCopyTexImage2D(target, level, internal_format,
5996 copyX, copyY, copyWidth, copyHeight, border);
5997 }
[email protected]1002c2d2011-06-28 22:39:045998 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:435999 if (error == GL_NO_ERROR) {
6000 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:116001 feature_info_, info, target, level, internal_format, width, height, 1,
6002 border, internal_format, GL_UNSIGNED_BYTE);
[email protected]cadde4a2010-07-31 17:10:436003 }
6004}
6005
6006void GLES2DecoderImpl::DoCopyTexSubImage2D(
6007 GLenum target,
6008 GLint level,
6009 GLint xoffset,
6010 GLint yoffset,
6011 GLint x,
6012 GLint y,
6013 GLsizei width,
6014 GLsizei height) {
6015 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6016 if (!info) {
6017 SetGLError(GL_INVALID_OPERATION,
6018 "glCopyTexSubImage2D: unknown texture for target");
6019 return;
6020 }
6021 GLenum type = 0;
6022 GLenum format = 0;
6023 if (!info->GetLevelType(target, level, &type, &format) ||
6024 !info->ValidForTexture(
6025 target, level, xoffset, yoffset, width, height, format, type)) {
6026 SetGLError(GL_INVALID_VALUE,
6027 "glCopyTexSubImage2D: bad dimensions.");
6028 return;
6029 }
[email protected]9edc6b22010-12-23 02:00:266030
6031 // Check we have compatible formats.
6032 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6033 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6034 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
6035
6036 if ((channels_needed & channels_exist) != channels_needed) {
6037 SetGLError(
6038 GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
6039 return;
6040 }
6041
[email protected]de26b3c2011-08-03 21:54:276042 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:036043 gfx::Size size = GetBoundReadFrameBufferSize();
6044 GLint copyX = 0;
6045 GLint copyY = 0;
6046 GLint copyWidth = 0;
6047 GLint copyHeight = 0;
6048 Clip(x, width, size.width(), &copyX, &copyWidth);
6049 Clip(y, height, size.height(), &copyY, &copyHeight);
6050 if (copyX != x ||
6051 copyY != y ||
6052 copyWidth != width ||
6053 copyHeight != height) {
6054 // some part was clipped so clear the texture.
6055 uint32 pixels_size = 0;
6056 if (!GLES2Util::ComputeImageDataSize(
6057 width, height, format, type, unpack_alignment_, &pixels_size)) {
6058 SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large");
6059 return;
6060 }
6061 scoped_array<char> zero(new char[pixels_size]);
6062 memset(zero.get(), 0, pixels_size);
6063 glTexSubImage2D(
6064 target, level, xoffset, yoffset, width, height,
6065 format, type, zero.get());
6066 }
6067 if (copyHeight > 0 && copyWidth > 0) {
6068 GLint dx = copyX - x;
6069 GLint dy = copyY - y;
6070 GLint destX = xoffset + dx;
6071 GLint destY = yoffset + dy;
6072 glCopyTexSubImage2D(target, level,
6073 destX, destY, copyX, copyY,
6074 copyWidth, copyHeight);
6075 }
[email protected]cadde4a2010-07-31 17:10:436076}
6077
6078void GLES2DecoderImpl::DoTexSubImage2D(
6079 GLenum target,
6080 GLint level,
6081 GLint xoffset,
6082 GLint yoffset,
6083 GLsizei width,
6084 GLsizei height,
6085 GLenum format,
6086 GLenum type,
6087 const void * data) {
6088 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6089 if (!info) {
6090 SetGLError(GL_INVALID_OPERATION,
6091 "glTexSubImage2D: unknown texture for target");
6092 return;
6093 }
[email protected]df6cf1ad2011-01-29 01:20:526094 GLenum current_type = 0;
6095 GLenum internal_format = 0;
6096 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
6097 SetGLError(
6098 GL_INVALID_OPERATION,
6099 "glTexSubImage2D: level does not exist.");
6100 return;
6101 }
6102 if (format != internal_format) {
6103 SetGLError(GL_INVALID_OPERATION,
6104 "glTexSubImage2D: format does not match internal format.");
6105 return;
6106 }
6107 if (type != current_type) {
6108 SetGLError(GL_INVALID_OPERATION,
6109 "glTexSubImage2D: type does not match type of texture.");
6110 return;
6111 }
6112
[email protected]cadde4a2010-07-31 17:10:436113 if (!info->ValidForTexture(
6114 target, level, xoffset, yoffset, width, height, format, type)) {
6115 SetGLError(GL_INVALID_VALUE,
6116 "glTexSubImage2D: bad dimensions.");
6117 return;
6118 }
[email protected]473c01ccb2011-06-07 01:33:306119
6120 // See if we can call glTexImage2D instead since it appears to be faster.
6121 if (teximage2d_faster_than_texsubimage2d_ && xoffset == 0 && yoffset == 0) {
6122 GLsizei tex_width = 0;
6123 GLsizei tex_height = 0;
6124 bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height);
6125 DCHECK(ok);
6126 if (width == tex_width && height == tex_height) {
6127 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
6128 // same as internal_foramt. If that changes we'll need to look them up.
6129 WrappedTexImage2D(
6130 target, level, format, width, height, 0, format, type, data);
6131 return;
6132 }
6133 }
[email protected]cadde4a2010-07-31 17:10:436134 glTexSubImage2D(
6135 target, level, xoffset, yoffset, width, height, format, type, data);
6136}
6137
[email protected]b493ee622011-04-13 23:52:006138error::Error GLES2DecoderImpl::HandleTexSubImage2D(
6139 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]366ae242011-05-10 02:23:586140 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:006141 GLboolean internal = static_cast<GLboolean>(c.internal);
6142 if (internal == GL_TRUE && tex_image_2d_failed_)
6143 return error::kNoError;
6144
6145 GLenum target = static_cast<GLenum>(c.target);
6146 GLint level = static_cast<GLint>(c.level);
6147 GLint xoffset = static_cast<GLint>(c.xoffset);
6148 GLint yoffset = static_cast<GLint>(c.yoffset);
6149 GLsizei width = static_cast<GLsizei>(c.width);
6150 GLsizei height = static_cast<GLsizei>(c.height);
6151 GLenum format = static_cast<GLenum>(c.format);
6152 GLenum type = static_cast<GLenum>(c.type);
6153 uint32 data_size;
6154 if (!GLES2Util::ComputeImageDataSize(
6155 width, height, format, type, unpack_alignment_, &data_size)) {
6156 return error::kOutOfBounds;
6157 }
6158 const void* pixels = GetSharedMemoryAs<const void*>(
6159 c.pixels_shm_id, c.pixels_shm_offset, data_size);
6160 if (!validators_->texture_target.IsValid(target)) {
6161 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
6162 return error::kNoError;
6163 }
6164 if (width < 0) {
6165 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
6166 return error::kNoError;
6167 }
6168 if (height < 0) {
6169 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
6170 return error::kNoError;
6171 }
6172 if (!validators_->texture_format.IsValid(format)) {
6173 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
6174 return error::kNoError;
6175 }
6176 if (!validators_->pixel_type.IsValid(type)) {
6177 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
6178 return error::kNoError;
6179 }
6180 if (pixels == NULL) {
6181 return error::kOutOfBounds;
6182 }
6183 DoTexSubImage2D(
6184 target, level, xoffset, yoffset, width, height, format, type, pixels);
6185 return error::kNoError;
6186}
6187
6188error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
6189 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
6190 GLboolean internal = static_cast<GLboolean>(c.internal);
6191 if (internal == GL_TRUE && tex_image_2d_failed_)
6192 return error::kNoError;
6193
6194 GLenum target = static_cast<GLenum>(c.target);
6195 GLint level = static_cast<GLint>(c.level);
6196 GLint xoffset = static_cast<GLint>(c.xoffset);
6197 GLint yoffset = static_cast<GLint>(c.yoffset);
6198 GLsizei width = static_cast<GLsizei>(c.width);
6199 GLsizei height = static_cast<GLsizei>(c.height);
6200 GLenum format = static_cast<GLenum>(c.format);
6201 GLenum type = static_cast<GLenum>(c.type);
6202 uint32 data_size;
6203 if (!GLES2Util::ComputeImageDataSize(
6204 width, height, format, type, unpack_alignment_, &data_size)) {
6205 return error::kOutOfBounds;
6206 }
6207 const void* pixels = GetImmediateDataAs<const void*>(
6208 c, data_size, immediate_data_size);
6209 if (!validators_->texture_target.IsValid(target)) {
6210 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
6211 return error::kNoError;
6212 }
6213 if (width < 0) {
6214 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
6215 return error::kNoError;
6216 }
6217 if (height < 0) {
6218 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
6219 return error::kNoError;
6220 }
6221 if (!validators_->texture_format.IsValid(format)) {
6222 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
6223 return error::kNoError;
6224 }
6225 if (!validators_->pixel_type.IsValid(type)) {
6226 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
6227 return error::kNoError;
6228 }
6229 if (pixels == NULL) {
6230 return error::kOutOfBounds;
6231 }
6232 DoTexSubImage2D(
6233 target, level, xoffset, yoffset, width, height, format, type, pixels);
6234 return error::kNoError;
6235}
6236
[email protected]f7a64ee2010-02-01 22:24:146237error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:196238 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:366239 GLuint index = static_cast<GLuint>(c.index);
6240 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:256241 typedef gles2::GetVertexAttribPointerv::Result Result;
6242 Result* result = GetSharedMemoryAs<Result*>(
6243 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:366244 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:146245 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:366246 }
[email protected]07d0cc82010-02-17 04:51:406247 // Check that the client initialized the result.
6248 if (result->size != 0) {
6249 return error::kInvalidArguments;
6250 }
[email protected]9438b012010-06-15 22:55:056251 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:296252 SetGLError(GL_INVALID_ENUM,
6253 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:146254 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:366255 }
[email protected]3916c97e2010-02-25 03:20:506256 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:296257 SetGLError(GL_INVALID_VALUE,
6258 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:146259 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:366260 }
[email protected]0bfd9882010-02-05 23:02:256261 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:086262 *result->GetData() =
6263 vertex_attrib_manager_.GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:146264 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326265}
6266
[email protected]f7b85372010-02-03 01:11:376267bool GLES2DecoderImpl::GetUniformSetup(
6268 GLuint program, GLint location,
6269 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:106270 error::Error* error, GLuint* service_id, void** result_pointer,
6271 GLenum* result_type) {
6272 DCHECK(error);
6273 DCHECK(service_id);
6274 DCHECK(result_pointer);
6275 DCHECK(result_type);
[email protected]f7b85372010-02-03 01:11:376276 *error = error::kNoError;
6277 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:256278 SizedResult<GLint>* result;
6279 result = GetSharedMemoryAs<SizedResult<GLint>*>(
6280 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
6281 if (!result) {
[email protected]f7b85372010-02-03 01:11:376282 *error = error::kOutOfBounds;
6283 return false;
6284 }
[email protected]0bfd9882010-02-05 23:02:256285 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:376286 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:256287 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:586288 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6289 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:376290 if (!info) {
[email protected]ae51d192010-04-27 00:48:036291 return false;
6292 }
6293 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:376294 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:296295 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:376296 return false;
6297 }
[email protected]ae51d192010-04-27 00:48:036298 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:366299 GLint array_index = -1;
6300 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
6301 info->GetUniformInfoByLocation(location, &array_index);
6302 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:376303 // No such location.
[email protected]8eee29c2010-04-29 03:38:296304 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:376305 return false;
6306 }
[email protected]43c2f1f2011-03-25 18:35:366307 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:506308 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:376309 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:296310 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:376311 return false;
6312 }
[email protected]0bfd9882010-02-05 23:02:256313 result = GetSharedMemoryAs<SizedResult<GLint>*>(
6314 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
6315 if (!result) {
[email protected]f7b85372010-02-03 01:11:376316 *error = error::kOutOfBounds;
6317 return false;
6318 }
[email protected]0bfd9882010-02-05 23:02:256319 result->size = size;
[email protected]939e7362010-05-13 20:49:106320 *result_type = type;
[email protected]f7b85372010-02-03 01:11:376321 return true;
6322}
6323
[email protected]f7a64ee2010-02-01 22:24:146324error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:196325 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:376326 GLuint program = c.program;
6327 GLint location = c.location;
6328 GLuint service_id;
[email protected]939e7362010-05-13 20:49:106329 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:376330 Error error;
[email protected]0bfd9882010-02-05 23:02:256331 void* result;
[email protected]f7b85372010-02-03 01:11:376332 if (GetUniformSetup(
6333 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:106334 &error, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:256335 glGetUniformiv(
6336 service_id, location,
6337 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:376338 }
6339 return error;
[email protected]96449d2c2009-11-25 00:01:326340}
6341
[email protected]f7a64ee2010-02-01 22:24:146342error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:196343 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:376344 GLuint program = c.program;
6345 GLint location = c.location;
6346 GLuint service_id;
6347 Error error;
[email protected]0bfd9882010-02-05 23:02:256348 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:106349 Result* result;
6350 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:376351 if (GetUniformSetup(
6352 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:106353 &error, &service_id, reinterpret_cast<void**>(&result), &result_type)) {
6354 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
6355 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
6356 GLsizei num_values = result->GetNumResults();
6357 scoped_array<GLint> temp(new GLint[num_values]);
6358 glGetUniformiv(service_id, location, temp.get());
6359 GLfloat* dst = result->GetData();
6360 for (GLsizei ii = 0; ii < num_values; ++ii) {
6361 dst[ii] = (temp[ii] != 0);
6362 }
6363 } else {
6364 glGetUniformfv(service_id, location, result->GetData());
6365 }
[email protected]f7b85372010-02-03 01:11:376366 }
6367 return error;
[email protected]96449d2c2009-11-25 00:01:326368}
6369
[email protected]f7a64ee2010-02-01 22:24:146370error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:196371 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:256372 GLenum shader_type = static_cast<GLenum>(c.shadertype);
6373 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
6374 typedef gles2::GetShaderPrecisionFormat::Result Result;
6375 Result* result = GetSharedMemoryAs<Result*>(
6376 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6377 if (!result) {
6378 return error::kOutOfBounds;
6379 }
[email protected]07d0cc82010-02-17 04:51:406380 // Check that the client initialized the result.
6381 if (result->success != 0) {
6382 return error::kInvalidArguments;
6383 }
[email protected]9438b012010-06-15 22:55:056384 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:296385 SetGLError(GL_INVALID_ENUM,
6386 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
6387 return error::kNoError;
6388 }
[email protected]9438b012010-06-15 22:55:056389 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:296390 SetGLError(GL_INVALID_ENUM,
6391 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
6392 return error::kNoError;
6393 }
6394
6395 result->success = 1; // true
6396 switch (precision_type) {
6397 case GL_LOW_INT:
6398 case GL_MEDIUM_INT:
6399 case GL_HIGH_INT:
6400 result->min_range = -31;
6401 result->max_range = 31;
6402 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:106403 break;
[email protected]8eee29c2010-04-29 03:38:296404 case GL_LOW_FLOAT:
6405 case GL_MEDIUM_FLOAT:
6406 case GL_HIGH_FLOAT:
6407 result->min_range = -62;
6408 result->max_range = 62;
6409 result->precision = -16;
6410 break;
6411 default:
6412 NOTREACHED();
6413 break;
[email protected]0bfd9882010-02-05 23:02:256414 }
[email protected]f7a64ee2010-02-01 22:24:146415 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326416}
6417
[email protected]f7a64ee2010-02-01 22:24:146418error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:196419 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:256420 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:586421 GLuint program = static_cast<GLuint>(c.program);
6422 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6423 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:036424 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256425 return error::kNoError;
6426 }
6427 typedef gles2::GetAttachedShaders::Result Result;
6428 uint32 max_count = Result::ComputeMaxResults(result_size);
6429 Result* result = GetSharedMemoryAs<Result*>(
6430 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
6431 if (!result) {
6432 return error::kOutOfBounds;
6433 }
[email protected]07d0cc82010-02-17 04:51:406434 // Check that the client initialized the result.
6435 if (result->size != 0) {
6436 return error::kInvalidArguments;
6437 }
[email protected]0bfd9882010-02-05 23:02:256438 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:036439 glGetAttachedShaders(
6440 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:256441 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:036442 if (!shader_manager()->GetClientId(result->GetData()[ii],
6443 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:256444 NOTREACHED();
6445 return error::kGenericError;
6446 }
6447 }
6448 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:146449 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326450}
6451
[email protected]f7a64ee2010-02-01 22:24:146452error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:196453 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:256454 GLuint program = c.program;
6455 GLuint index = c.index;
6456 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:256457 typedef gles2::GetActiveUniform::Result Result;
6458 Result* result = GetSharedMemoryAs<Result*>(
6459 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6460 if (!result) {
6461 return error::kOutOfBounds;
6462 }
[email protected]07d0cc82010-02-17 04:51:406463 // Check that the client initialized the result.
6464 if (result->success != 0) {
6465 return error::kInvalidArguments;
6466 }
[email protected]6b8cf1a2010-05-06 16:13:586467 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6468 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:036469 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256470 return error::kNoError;
6471 }
6472 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
6473 info->GetUniformInfo(index);
6474 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:296475 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:256476 return error::kNoError;
6477 }
6478 result->success = 1; // true.
6479 result->size = uniform_info->size;
6480 result->type = uniform_info->type;
6481 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:296482 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:146483 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326484}
6485
[email protected]f7a64ee2010-02-01 22:24:146486error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:196487 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:256488 GLuint program = c.program;
6489 GLuint index = c.index;
6490 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:256491 typedef gles2::GetActiveAttrib::Result Result;
6492 Result* result = GetSharedMemoryAs<Result*>(
6493 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6494 if (!result) {
6495 return error::kOutOfBounds;
6496 }
[email protected]07d0cc82010-02-17 04:51:406497 // Check that the client initialized the result.
6498 if (result->success != 0) {
6499 return error::kInvalidArguments;
6500 }
[email protected]6b8cf1a2010-05-06 16:13:586501 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6502 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:036503 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256504 return error::kNoError;
6505 }
6506 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
6507 info->GetAttribInfo(index);
6508 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:296509 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:256510 return error::kNoError;
6511 }
6512 result->success = 1; // true.
6513 result->size = attrib_info->size;
6514 result->type = attrib_info->type;
6515 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:296516 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:146517 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326518}
6519
[email protected]b273e432010-04-12 17:23:586520error::Error GLES2DecoderImpl::HandleShaderBinary(
6521 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
6522#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:296523 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:586524 return error::kNoError;
6525#else
6526 GLsizei n = static_cast<GLsizei>(c.n);
6527 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:296528 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:586529 return error::kNoError;
6530 }
6531 GLsizei length = static_cast<GLsizei>(c.length);
6532 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:296533 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:586534 return error::kNoError;
6535 }
6536 uint32 data_size;
6537 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
6538 return error::kOutOfBounds;
6539 }
6540 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
6541 c.shaders_shm_id, c.shaders_shm_offset, data_size);
6542 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
6543 const void* binary = GetSharedMemoryAs<const void*>(
6544 c.binary_shm_id, c.binary_shm_offset, length);
6545 if (shaders == NULL || binary == NULL) {
6546 return error::kOutOfBounds;
6547 }
6548 scoped_array<GLuint> service_ids(new GLuint[n]);
6549 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:036550 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
6551 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296552 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:586553 return error::kNoError;
6554 }
[email protected]ae51d192010-04-27 00:48:036555 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:586556 }
6557 // TODO(gman): call glShaderBinary
6558 return error::kNoError;
6559#endif
6560}
6561
[email protected]6217d392010-03-25 22:08:356562error::Error GLES2DecoderImpl::HandleSwapBuffers(
6563 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:496564 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
6565 int this_frame_number = frame_number_++;
6566 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
6567 "offscreen", is_offscreen,
6568 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:356569 // If offscreen then don't actually SwapBuffers to the display. Just copy
6570 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:496571 if (is_offscreen) {
[email protected]6217d392010-03-25 22:08:356572 ScopedGLErrorSuppressor suppressor(this);
6573
6574 // First check to see if a deferred offscreen render buffer resize is
6575 // pending.
[email protected]d0498742010-09-20 20:27:016576 if (!UpdateOffscreenFrameBufferSize()) {
6577 LOG(ERROR) << "Context lost because reallocation of offscreen FBO "
6578 << "failed.";
[email protected]6217d392010-03-25 22:08:356579 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:016580 }
[email protected]6217d392010-03-25 22:08:356581
[email protected]34ff8b0c2010-10-01 20:06:026582 if (IsOffscreenBufferMultisampled()) {
6583 // For multisampled buffers, bind the resolved frame buffer so that
6584 // callbacks can call ReadPixels or CopyTexImage2D.
[email protected]de26b3c2011-08-03 21:54:276585 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]34ff8b0c2010-10-01 20:06:026586 if (swap_buffers_callback_.get()) {
6587 swap_buffers_callback_->Run();
6588 }
[email protected]89d6ed02011-04-20 00:23:236589 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:486590 } else {
[email protected]0c8c9d22010-06-25 17:36:396591 ScopedFrameBufferBinder binder(this,
6592 offscreen_target_frame_buffer_->id());
[email protected]c007aa02010-09-02 22:22:406593
[email protected]9a5afa432011-07-22 18:16:396594 if (surface_->IsOffscreen()) {
[email protected]b86b14982010-10-11 18:45:486595 // Copy the target frame buffer to the saved offscreen texture.
6596 offscreen_saved_color_texture_->Copy(
[email protected]3a4d0c52011-06-29 23:11:586597 offscreen_saved_color_texture_->size(),
6598 offscreen_saved_color_format_);
[email protected]b86b14982010-10-11 18:45:486599
[email protected]a3ded6d2010-10-19 06:44:396600 // Ensure the side effects of the copy are visible to the parent
6601 // context. There is no need to do this for ANGLE because it uses a
6602 // single D3D device for all contexts.
[email protected]b86b14982010-10-11 18:45:486603 if (!IsAngle())
6604 glFlush();
6605 }
6606
6607 // Run the callback with |binder| in scope, so that the callback can call
6608 // ReadPixels or CopyTexImage2D.
6609 if (swap_buffers_callback_.get()) {
6610 swap_buffers_callback_->Run();
6611 }
[email protected]89d6ed02011-04-20 00:23:236612 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:396613 }
[email protected]6217d392010-03-25 22:08:356614 } else {
[email protected]64ace852011-05-19 21:49:496615 TRACE_EVENT1("gpu", "GLContext::SwapBuffers", "frame", this_frame_number);
[email protected]f62a5ab2011-05-23 20:34:156616 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:016617 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:026618 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:016619 }
[email protected]6217d392010-03-25 22:08:356620 }
6621
6622 if (swap_buffers_callback_.get()) {
6623 swap_buffers_callback_->Run();
6624 }
6625
[email protected]89d6ed02011-04-20 00:23:236626 return error::kNoError;
[email protected]6217d392010-03-25 22:08:356627}
6628
[email protected]269200b12010-11-18 22:53:066629error::Error GLES2DecoderImpl::HandleCommandBufferEnableCHROMIUM(
6630 uint32 immediate_data_size, const gles2::CommandBufferEnableCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:186631 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]269200b12010-11-18 22:53:066632 typedef gles2::CommandBufferEnableCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:186633 Result* result = GetSharedMemoryAs<Result*>(
6634 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6635 if (!result) {
6636 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:106637 }
[email protected]b1d2dcb2010-05-17 19:24:186638 // Check that the client initialized the result.
6639 if (*result != 0) {
6640 return error::kInvalidArguments;
6641 }
6642 std::string feature_str;
6643 if (!bucket->GetAsString(&feature_str)) {
6644 return error::kInvalidArguments;
6645 }
6646
6647 // TODO(gman): make this some kind of table to function pointer thingy.
6648 if (feature_str.compare(PEPPER3D_ALLOW_BUFFERS_ON_MULTIPLE_TARGETS) == 0) {
6649 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]8fbedc02010-11-18 18:43:406650 } else if (feature_str.compare(PEPPER3D_SUPPORT_FIXED_ATTRIBS) == 0) {
6651 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
6652 // TODO(gman): decide how to remove the need for this const_cast.
6653 // I could make validators_ non const but that seems bad as this is the only
6654 // place it is needed. I could make some special friend class of validators
6655 // just to allow this to set them. That seems silly. I could refactor this
6656 // code to use the extension mechanism or the initialization attributes to
6657 // turn this feature on. Given that the only real point of this is to make
6658 // the conformance tests pass and given that there is lots of real work that
6659 // needs to be done it seems like refactoring for one to one of those
6660 // methods is a very low priority.
6661 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]b1d2dcb2010-05-17 19:24:186662 } else if (feature_str.compare(PEPPER3D_SKIP_GLSL_TRANSLATION) == 0) {
6663 use_shader_translator_ = false;
6664 } else {
6665 return error::kNoError;
6666 }
6667
6668 *result = 1; // true.
6669 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:106670}
6671
[email protected]c2f8c8402010-12-06 18:07:246672error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
6673 uint32 immediate_data_size,
6674 const gles2::GetRequestableExtensionsCHROMIUM& c) {
6675 Bucket* bucket = CreateBucket(c.bucket_id);
6676 scoped_ptr<FeatureInfo> info(new FeatureInfo());
[email protected]c410da802011-03-14 19:17:416677 info->Initialize(disallowed_extensions_, NULL);
[email protected]c2f8c8402010-12-06 18:07:246678 bucket->SetFromString(info->extensions().c_str());
6679 return error::kNoError;
6680}
6681
6682error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
6683 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
6684 Bucket* bucket = GetBucket(c.bucket_id);
6685 std::string feature_str;
6686 if (!bucket->GetAsString(&feature_str)) {
6687 return error::kInvalidArguments;
6688 }
6689
6690 bool std_derivatives_enabled =
6691 feature_info_->feature_flags().oes_standard_derivatives;
6692 bool webglsl_enabled =
6693 feature_info_->feature_flags().chromium_webglsl;
6694
6695 feature_info_->AddFeatures(feature_str.c_str());
6696
6697 // If we just enabled a feature which affects the shader translator,
6698 // we may need to re-initialize it.
6699 if (std_derivatives_enabled !=
6700 feature_info_->feature_flags().oes_standard_derivatives ||
6701 webglsl_enabled !=
6702 feature_info_->feature_flags().chromium_webglsl) {
6703 InitializeShaderTranslator();
6704 }
6705
[email protected]302ce6d2011-07-07 23:28:116706 UpdateCapabilities();
6707
[email protected]c2f8c8402010-12-06 18:07:246708 return error::kNoError;
6709}
6710
[email protected]372e0412011-06-28 16:08:566711error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
6712 uint32 immediate_data_size, const gles2::GetMultipleIntegervCHROMIUM& c) {
6713 GLuint count = c.count;
6714 uint32 pnames_size;
6715 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
6716 return error::kOutOfBounds;
6717 }
6718 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
6719 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
6720 if (pnames == NULL) {
6721 return error::kOutOfBounds;
6722 }
6723
6724 // We have to copy them since we use them twice so the client
6725 // can't change them between the time we validate them and the time we use
6726 // them.
6727 scoped_array<GLenum> enums(new GLenum[count]);
6728 memcpy(enums.get(), pnames, pnames_size);
6729
6730 // Count up the space needed for the result.
6731 uint32 num_results = 0;
6732 for (GLuint ii = 0; ii < count; ++ii) {
6733 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
6734 if (num == 0) {
6735 SetGLError(GL_INVALID_ENUM,
6736 "glGetMulitpleCHROMIUM: pname GL_INVALID_ENUM");
6737 return error::kNoError;
6738 }
6739 // Num will never be more than 4.
6740 DCHECK_LE(num, 4u);
6741 if (!SafeAdd(num_results, num, &num_results)) {
6742 return error::kOutOfBounds;
6743 }
6744 }
6745
6746 uint32 result_size = 0;
6747 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
6748 return error::kOutOfBounds;
6749 }
6750
6751 if (result_size != static_cast<uint32>(c.size)) {
6752 SetGLError(GL_INVALID_VALUE,
6753 "glGetMulitpleCHROMIUM: bad size GL_INVALID_VALUE");
6754 return error::kNoError;
6755 }
6756
6757 GLint* results = GetSharedMemoryAs<GLint*>(
6758 c.results_shm_id, c.results_shm_offset, result_size);
6759 if (results == NULL) {
6760 return error::kOutOfBounds;
6761 }
6762
6763 // Check the results have been cleared in case the context was lost.
6764 for (uint32 ii = 0; ii < num_results; ++ii) {
6765 if (results[ii]) {
6766 return error::kInvalidArguments;
6767 }
6768 }
6769
6770 // Get each result.
6771 GLint* start = results;
6772 for (GLuint ii = 0; ii < count; ++ii) {
6773 GLsizei num_written = 0;
6774 if (!GetHelper(enums[ii], results, &num_written)) {
6775 glGetIntegerv(enums[ii], results);
6776 }
6777 results += num_written;
6778 }
6779
6780 // Just to verify. Should this be a DCHECK?
6781 if (static_cast<uint32>(results - start) != num_results) {
6782 return error::kOutOfBounds;
6783 }
6784
6785 return error::kNoError;
6786}
6787
[email protected]2318d342011-07-11 22:27:426788error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
6789 uint32 immediate_data_size, const gles2::GetProgramInfoCHROMIUM& c) {
6790 GLuint program = static_cast<GLuint>(c.program);
6791 uint32 bucket_id = c.bucket_id;
6792 Bucket* bucket = CreateBucket(bucket_id);
6793 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
6794 ProgramManager::ProgramInfo* info = NULL;
6795 if (program) {
6796 info = GetProgramInfoNotShader(program, "glGetProgramInfoCHROMIUM");
6797 if (!info) {
6798 return error::kNoError;
6799 }
6800 if (!info->IsValid()) {
6801 // Program was not linked successfully. (ie, glLinkProgram)
6802 SetGLError(GL_INVALID_OPERATION,
6803 "glGetProgramInfoCHROMIUM: program not linked");
6804 return error::kNoError;
6805 }
6806 }
6807 info->GetProgramInfo(bucket);
6808 return error::kNoError;
6809}
6810
[email protected]38d139d2011-07-14 00:38:436811error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
6812 switch (reset_status_) {
6813 case GL_NO_ERROR:
6814 // TODO(kbr): improve the precision of the error code in this case.
6815 // Consider delegating to context for error code if MakeCurrent fails.
6816 return error::kUnknown;
6817 case GL_GUILTY_CONTEXT_RESET_ARB:
6818 return error::kGuilty;
6819 case GL_INNOCENT_CONTEXT_RESET_ARB:
6820 return error::kInnocent;
6821 case GL_UNKNOWN_CONTEXT_RESET_ARB:
6822 return error::kUnknown;
6823 }
6824
6825 NOTREACHED();
6826 return error::kUnknown;
6827}
6828
6829bool GLES2DecoderImpl::WasContextLost() {
6830 if (context_->WasAllocatedUsingARBRobustness() && has_arb_robustness_) {
6831 GLenum status = glGetGraphicsResetStatusARB();
6832 if (status != GL_NO_ERROR) {
6833 // The graphics card was reset. Signal a lost context to the application.
6834 reset_status_ = status;
6835 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
6836 << " context lost via ARB_robustness. Reset status = 0x"
6837 << std::hex << status << std::dec;
6838 return true;
6839 }
6840 }
6841 return false;
6842}
6843
[email protected]96449d2c2009-11-25 00:01:326844// Include the auto-generated part of this file. We split this because it means
6845// we can easily edit the non-auto generated parts right here in this file
6846// instead of having to edit some template or the code generator.
6847#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
6848
6849} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:256850} // namespace gpu