blob: c35791312da115a6abff86310cac6b6f987e64e7 [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]75c023c2011-08-22 23:54:5118#if defined(OS_MACOSX)
19#include "base/mac/mac_util.h"
20#endif
[email protected]3b63f8f42011-03-28 01:54:1521#include "base/memory/scoped_ptr.h"
22#include "base/memory/weak_ptr.h"
[email protected]d37231fa2010-04-09 21:16:0223#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3224#define GLES2_GPU_SERVICE 1
25#include "gpu/command_buffer/common/gles2_cmd_format.h"
26#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1027#include "gpu/command_buffer/common/id_allocator.h"
[email protected]366ae242011-05-10 02:23:5828#include "gpu/command_buffer/common/trace_event.h"
[email protected]3916c97e2010-02-25 03:20:5029#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3230#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5031#include "gpu/command_buffer/service/context_group.h"
[email protected]915a59a12010-09-30 21:29:1132#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5833#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3234#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4635#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]a93bb842010-02-16 23:03:4736#include "gpu/command_buffer/service/program_manager.h"
[email protected]a25fa872010-03-25 02:57:5837#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4738#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4539#include "gpu/command_buffer/service/shader_translator.h"
[email protected]fbe20372011-06-01 01:46:3840#include "gpu/command_buffer/service/surface_manager.h"
[email protected]a93bb842010-02-16 23:03:4741#include "gpu/command_buffer/service/texture_manager.h"
[email protected]d8ea9772011-07-11 18:11:4342#include "gpu/command_buffer/service/vertex_attrib_manager.h"
[email protected]5ae0b282011-03-28 19:24:4943#include "ui/gfx/gl/gl_context.h"
44#include "ui/gfx/gl/gl_implementation.h"
[email protected]f62a5ab2011-05-23 20:34:1545#include "ui/gfx/gl/gl_surface.h"
[email protected]de17df392010-04-23 21:09:4146
[email protected]6217d392010-03-25 22:08:3547#if !defined(GL_DEPTH24_STENCIL8)
48#define GL_DEPTH24_STENCIL8 0x88F0
49#endif
50
[email protected]a7a27ace2009-12-12 00:11:2551namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3252namespace gles2 {
53
[email protected]6217d392010-03-25 22:08:3554class GLES2DecoderImpl;
55
[email protected]07f54fcc2009-12-22 02:46:3056// Check that certain assumptions the code makes are true. There are places in
57// the code where shared memory is passed direclty to GL. Example, glUniformiv,
58// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
59// a few others) are 32bits. If they are not 32bits the code will have to change
60// to call those GL functions with service side memory and then copy the results
61// to shared memory, converting the sizes.
62COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
63 GLint_not_same_size_as_uint32);
64COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
65 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3766COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
67 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3068
[email protected]43f28f832010-02-03 02:28:4869// TODO(kbr): the use of this anonymous namespace core dumps the
70// linker on Mac OS X 10.6 when the symbol ordering file is used
71// namespace {
[email protected]96449d2c2009-11-25 00:01:3272
73// Returns the address of the first byte after a struct.
74template <typename T>
75const void* AddressAfterStruct(const T& pod) {
76 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
77}
78
[email protected]07f54fcc2009-12-22 02:46:3079// Returns the address of the frst byte after the struct or NULL if size >
80// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3281template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3082RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
83 uint32 size,
84 uint32 immediate_data_size) {
85 return (size <= immediate_data_size) ?
86 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
87 NULL;
[email protected]96449d2c2009-11-25 00:01:3288}
89
[email protected]07f54fcc2009-12-22 02:46:3090// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:1891bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:3292 GLuint count,
93 size_t size,
[email protected]a76b0052010-03-05 00:33:1894 unsigned int elements_per_unit,
95 uint32* dst) {
96 uint32 value;
97 if (!SafeMultiplyUint32(count, size, &value)) {
98 return false;
99 }
100 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
101 return false;
102 }
103 *dst = value;
104 return true;
[email protected]96449d2c2009-11-25 00:01:32105}
106
107// A struct to hold info about each command.
108struct CommandInfo {
109 int arg_flags; // How to handle the arguments for this command
110 int arg_count; // How many arguments are expected for this command.
111};
112
113// A table of CommandInfo for all the commands.
114const CommandInfo g_command_info[] = {
115 #define GLES2_CMD_OP(name) { \
116 name::kArgFlags, \
117 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
118
119 GLES2_COMMAND_LIST(GLES2_CMD_OP)
120
121 #undef GLES2_CMD_OP
122};
123
[email protected]34ff8b0c2010-10-01 20:06:02124static bool IsAngle() {
125#if defined(OS_WIN)
126 return gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
127#else
128 return false;
129#endif
130}
131
[email protected]297ca1c2011-06-20 23:08:46132static void WrappedTexImage2D(
[email protected]473c01ccb2011-06-07 01:33:30133 GLenum target,
134 GLint level,
135 GLenum internal_format,
136 GLsizei width,
137 GLsizei height,
138 GLint border,
139 GLenum format,
140 GLenum type,
141 const void* pixels) {
142 GLenum gl_internal_format = internal_format;
143 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
144 if (format == GL_BGRA_EXT && internal_format == GL_BGRA_EXT) {
145 gl_internal_format = GL_RGBA;
146 } else if (type == GL_FLOAT) {
147 if (format == GL_RGBA) {
148 gl_internal_format = GL_RGBA32F_ARB;
149 } else if (format == GL_RGB) {
150 gl_internal_format = GL_RGB32F_ARB;
151 }
152 } else if (type == GL_HALF_FLOAT_OES) {
153 if (format == GL_RGBA) {
154 gl_internal_format = GL_RGBA16F_ARB;
155 } else if (format == GL_RGB) {
156 gl_internal_format = GL_RGB16F_ARB;
157 }
158 }
159 }
160 glTexImage2D(
161 target, level, gl_internal_format, width, height, border, format, type,
162 pixels);
163}
164
[email protected]297ca1c2011-06-20 23:08:46165// Wrapper for glEnable/glDisable that doesn't suck.
166static void EnableDisable(GLenum pname, bool enable) {
167 if (enable) {
168 glEnable(pname);
169 } else {
170 glDisable(pname);
171 }
172}
173
[email protected]6217d392010-03-25 22:08:35174// This class prevents any GL errors that occur when it is in scope from
175// being reported to the client.
176class ScopedGLErrorSuppressor {
177 public:
178 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
179 ~ScopedGLErrorSuppressor();
180 private:
181 GLES2DecoderImpl* decoder_;
182 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
183};
184
185// Temporarily changes a decoder's bound 2D texture and restore it when this
186// object goes out of scope. Also temporarily switches to using active texture
187// unit zero in case the client has changed that to something invalid.
188class ScopedTexture2DBinder {
189 public:
190 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
191 ~ScopedTexture2DBinder();
192
193 private:
194 GLES2DecoderImpl* decoder_;
195 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
196};
197
198// Temporarily changes a decoder's bound render buffer and restore it when this
199// object goes out of scope.
200class ScopedRenderBufferBinder {
201 public:
202 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
203 ~ScopedRenderBufferBinder();
204
205 private:
206 GLES2DecoderImpl* decoder_;
207 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
208};
209
210// Temporarily changes a decoder's bound frame buffer and restore it when this
211// object goes out of scope.
212class ScopedFrameBufferBinder {
213 public:
214 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
215 ~ScopedFrameBufferBinder();
216
217 private:
218 GLES2DecoderImpl* decoder_;
219 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
220};
221
[email protected]34ff8b0c2010-10-01 20:06:02222// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52223// the multisampled offscreen render buffer if that buffer is multisampled, and,
[email protected]de26b3c2011-08-03 21:54:27224// if it is bound or enforce_internal_framebuffer is true. If internal is
225// true, the resolved framebuffer is not visible to the parent.
[email protected]34ff8b0c2010-10-01 20:06:02226class ScopedResolvedFrameBufferBinder {
227 public:
[email protected]e7e38032011-07-26 17:25:25228 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
[email protected]de26b3c2011-08-03 21:54:27229 bool enforce_internal_framebuffer,
230 bool internal);
[email protected]34ff8b0c2010-10-01 20:06:02231 ~ScopedResolvedFrameBufferBinder();
232
233 private:
234 GLES2DecoderImpl* decoder_;
235 bool resolve_and_bind_;
236 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
237};
238
[email protected]6217d392010-03-25 22:08:35239// Encapsulates an OpenGL texture.
240class Texture {
241 public:
242 explicit Texture(GLES2DecoderImpl* decoder);
243 ~Texture();
244
245 // Create a new render texture.
246 void Create();
247
248 // Set the initial size and format of a render texture or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02249 bool AllocateStorage(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35250
251 // Copy the contents of the currently bound frame buffer.
[email protected]3a4d0c52011-06-29 23:11:58252 void Copy(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35253
254 // Destroy the render texture. This must be explicitly called before
255 // destroying this object.
256 void Destroy();
257
[email protected]97872062010-11-03 19:07:05258 // Invalidate the texture. This can be used when a context is lost and it is
259 // not possible to make it current in order to free the resource.
260 void Invalidate();
261
[email protected]6217d392010-03-25 22:08:35262 GLuint id() const {
263 return id_;
264 }
265
[email protected]d37231fa2010-04-09 21:16:02266 gfx::Size size() const {
267 return size_;
268 }
269
[email protected]6217d392010-03-25 22:08:35270 private:
271 GLES2DecoderImpl* decoder_;
272 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02273 gfx::Size size_;
[email protected]6217d392010-03-25 22:08:35274 DISALLOW_COPY_AND_ASSIGN(Texture);
275};
276
277// Encapsulates an OpenGL render buffer of any format.
278class RenderBuffer {
279 public:
280 explicit RenderBuffer(GLES2DecoderImpl* decoder);
281 ~RenderBuffer();
282
283 // Create a new render buffer.
284 void Create();
285
286 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02287 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35288
289 // Destroy the render buffer. This must be explicitly called before destroying
290 // this object.
291 void Destroy();
292
[email protected]97872062010-11-03 19:07:05293 // Invalidate the render buffer. This can be used when a context is lost and
294 // it is not possible to make it current in order to free the resource.
295 void Invalidate();
296
[email protected]6217d392010-03-25 22:08:35297 GLuint id() const {
298 return id_;
299 }
300
301 private:
302 GLES2DecoderImpl* decoder_;
303 GLuint id_;
304 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
305};
306
307// Encapsulates an OpenGL frame buffer.
308class FrameBuffer {
309 public:
310 explicit FrameBuffer(GLES2DecoderImpl* decoder);
311 ~FrameBuffer();
312
313 // Create a new frame buffer.
314 void Create();
315
316 // Attach a color render buffer to a frame buffer.
317 void AttachRenderTexture(Texture* texture);
318
[email protected]b9363b22010-06-09 22:06:15319 // Attach a render buffer to a frame buffer. Note that this unbinds any
320 // currently bound frame buffer.
321 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35322
323 // Clear the given attached buffers.
324 void Clear(GLbitfield buffers);
325
326 // Destroy the frame buffer. This must be explicitly called before destroying
327 // this object.
328 void Destroy();
329
[email protected]97872062010-11-03 19:07:05330 // Invalidate the frame buffer. This can be used when a context is lost and it
331 // is not possible to make it current in order to free the resource.
332 void Invalidate();
333
[email protected]6217d392010-03-25 22:08:35334 // See glCheckFramebufferStatusEXT.
335 GLenum CheckStatus();
336
337 GLuint id() const {
338 return id_;
339 }
340
341 private:
342 GLES2DecoderImpl* decoder_;
343 GLuint id_;
344 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
345};
[email protected]34ff8b0c2010-10-01 20:06:02346
347class ContextCreationAttribParser {
348 public:
349 ContextCreationAttribParser();
350 bool Parse(const std::vector<int32>& attribs);
351
352 // -1 if invalid or unspecified.
353 int32 alpha_size_;
354 int32 blue_size_;
355 int32 green_size_;
356 int32 red_size_;
357 int32 depth_size_;
358 int32 stencil_size_;
359 int32 samples_;
360 int32 sample_buffers_;
361};
362
363ContextCreationAttribParser::ContextCreationAttribParser()
364 : alpha_size_(-1),
365 blue_size_(-1),
366 green_size_(-1),
367 red_size_(-1),
368 depth_size_(-1),
369 stencil_size_(-1),
370 samples_(-1),
371 sample_buffers_(-1) {
372}
373
374bool ContextCreationAttribParser::Parse(const std::vector<int32>& attribs) {
375 // From <EGL/egl.h>.
376 const int32 EGL_ALPHA_SIZE = 0x3021;
377 const int32 EGL_BLUE_SIZE = 0x3022;
378 const int32 EGL_GREEN_SIZE = 0x3023;
379 const int32 EGL_RED_SIZE = 0x3024;
380 const int32 EGL_DEPTH_SIZE = 0x3025;
381 const int32 EGL_STENCIL_SIZE = 0x3026;
382 const int32 EGL_SAMPLES = 0x3031;
383 const int32 EGL_SAMPLE_BUFFERS = 0x3032;
384 const int32 EGL_NONE = 0x3038;
385
386 for (size_t i = 0; i < attribs.size(); i += 2) {
387 const int32 attrib = attribs[i];
388 if (i + 1 >= attribs.size()) {
389 if (attrib == EGL_NONE)
390 return true;
391
392 DLOG(ERROR) << "Missing value after context creation attribute: "
393 << attrib;
394 return false;
395 }
396
397 const int32 value = attribs[i+1];
398 switch (attrib) {
399 case EGL_ALPHA_SIZE:
400 alpha_size_ = value;
401 break;
402 case EGL_BLUE_SIZE:
403 blue_size_ = value;
404 break;
405 case EGL_GREEN_SIZE:
406 green_size_ = value;
407 break;
408 case EGL_RED_SIZE:
409 red_size_ = value;
410 break;
411 case EGL_DEPTH_SIZE:
412 depth_size_ = value;
413 break;
414 case EGL_STENCIL_SIZE:
415 stencil_size_ = value;
416 break;
417 case EGL_SAMPLES:
418 samples_ = value;
419 break;
420 case EGL_SAMPLE_BUFFERS:
421 sample_buffers_ = value;
422 break;
423 case EGL_NONE:
424 // Terminate list, even if more attributes.
425 return true;
426 default:
427 DLOG(ERROR) << "Invalid context creation attribute: " << attrib;
428 return false;
429 }
430 }
431
432 return true;
433}
434
[email protected]43f28f832010-02-03 02:28:48435// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32436
[email protected]ddb1e5a2010-12-13 20:10:45437bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
438 uint32* service_texture_id) {
439 return false;
440}
441
[email protected]a3ded6d2010-10-19 06:44:39442GLES2Decoder::GLES2Decoder()
443 : debug_(false) {
[email protected]96449d2c2009-11-25 00:01:32444}
445
[email protected]3916c97e2010-02-25 03:20:50446GLES2Decoder::~GLES2Decoder() {
447}
448
[email protected]f39f4b3f2010-05-12 17:04:08449// This class implements GLES2Decoder so we don't have to expose all the GLES2
450// cmd stuff to outside this class.
451class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
452 public GLES2Decoder {
453 public:
[email protected]e7e38032011-07-26 17:25:25454 GLES2DecoderImpl(SurfaceManager* surface_manager, ContextGroup* group);
[email protected]f39f4b3f2010-05-12 17:04:08455
[email protected]96449d2c2009-11-25 00:01:32456 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14457 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50458 unsigned int arg_count,
459 const void* args);
[email protected]96449d2c2009-11-25 00:01:32460
461 // Overridden from AsyncAPIInterface.
462 virtual const char* GetCommandName(unsigned int command_id) const;
463
464 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38465 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
466 const scoped_refptr<gfx::GLContext>& context,
[email protected]6217d392010-03-25 22:08:35467 const gfx::Size& size,
[email protected]c410da802011-03-14 19:17:41468 const DisallowedExtensions& disallowed_extensions,
[email protected]a3ded6d2010-10-19 06:44:39469 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:24470 const std::vector<int32>& attribs);
[email protected]96449d2c2009-11-25 00:01:32471 virtual void Destroy();
[email protected]3c644d82011-06-20 19:58:24472 virtual bool SetParent(GLES2Decoder* parent_decoder,
473 uint32 parent_texture_id);
[email protected]799b4b22011-08-22 17:09:59474 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]9a5afa432011-07-22 18:16:39475 void UpdateParentTextureInfo();
[email protected]eb54a562010-01-20 21:55:18476 virtual bool MakeCurrent();
[email protected]56ac89b2010-03-17 21:16:55477 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30478 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]f62a5ab2011-05-23 20:34:15479 virtual gfx::GLSurface* GetGLSurface() { return surface_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39480 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]43f28f832010-02-03 02:28:48481
[email protected]7ff86b92010-11-25 17:50:00482 virtual void SetResizeCallback(Callback1<gfx::Size>::Type* callback);
[email protected]43f28f832010-02-03 02:28:48483 virtual void SetSwapBuffersCallback(Callback0::Type* callback);
[email protected]1318e922010-09-17 22:03:16484 virtual bool GetServiceTextureId(uint32 client_texture_id,
485 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48486
[email protected]8e3e0662010-08-23 18:46:30487 // Restores the current state to the user's settings.
488 void RestoreCurrentFramebufferBindings();
489 void RestoreCurrentRenderbufferBindings();
490 void RestoreCurrentTexture2DBindings();
491
[email protected]297ca1c2011-06-20 23:08:46492 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
493 void ApplyDirtyState();
494
495 // These check the state of the currently bound framebuffer or the
496 // backbuffer if no framebuffer is bound.
497 bool BoundFramebufferHasColorAttachmentWithAlpha();
498 bool BoundFramebufferHasDepthAttachment();
499 bool BoundFramebufferHasStencilAttachment();
500
[email protected]38d139d2011-07-14 00:38:43501 virtual error::ContextLostReason GetContextLostReason();
502
[email protected]96449d2c2009-11-25 00:01:32503 private:
[email protected]6217d392010-03-25 22:08:35504 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02505 friend class ScopedResolvedFrameBufferBinder;
[email protected]6217d392010-03-25 22:08:35506 friend class RenderBuffer;
507 friend class FrameBuffer;
508
[email protected]3916c97e2010-02-25 03:20:50509 // State associated with each texture unit.
510 struct TextureUnit {
511 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
512
513 // The last target that was bound to this texture unit.
514 GLenum bind_target;
515
516 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
517 TextureManager::TextureInfo::Ref bound_texture_2d;
518
519 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
520 // glBindTexture
521 TextureManager::TextureInfo::Ref bound_texture_cube_map;
[email protected]61eeb33f2011-07-26 15:30:31522
523 // texture currently bound to this unit's GL_TEXTURE_EXTERNAL_OES with
524 // glBindTexture
525 TextureManager::TextureInfo::Ref bound_texture_external_oes;
526
527 TextureManager::TextureInfo::Ref GetInfoForSamplerType(GLenum type) {
528 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
529 type == GL_SAMPLER_EXTERNAL_OES);
530 return type == GL_SAMPLER_2D ? bound_texture_2d :
531 (type == GL_SAMPLER_EXTERNAL_OES ? bound_texture_external_oes :
532 bound_texture_cube_map);
533 }
[email protected]3916c97e2010-02-25 03:20:50534 };
535
[email protected]c2f8c8402010-12-06 18:07:24536 // Initialize or re-initialize the shader translator.
537 bool InitializeShaderTranslator();
538
[email protected]302ce6d2011-07-07 23:28:11539 void UpdateCapabilities();
540
[email protected]ae51d192010-04-27 00:48:03541 // Helpers for the glGen and glDelete functions.
542 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
543 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
544 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
545 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
546 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
547 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
548 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
549 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47550
[email protected]3916c97e2010-02-25 03:20:50551 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50552 BufferManager* buffer_manager() {
553 return group_->buffer_manager();
554 }
555
[email protected]a25fa872010-03-25 02:57:58556 RenderbufferManager* renderbuffer_manager() {
557 return group_->renderbuffer_manager();
558 }
559
560 FramebufferManager* framebuffer_manager() {
561 return group_->framebuffer_manager();
562 }
563
[email protected]3916c97e2010-02-25 03:20:50564 ProgramManager* program_manager() {
565 return group_->program_manager();
566 }
567
568 ShaderManager* shader_manager() {
569 return group_->shader_manager();
570 }
571
572 TextureManager* texture_manager() {
573 return group_->texture_manager();
574 }
575
[email protected]34ff8b0c2010-10-01 20:06:02576 bool IsOffscreenBufferMultisampled() const {
577 return offscreen_target_samples_ > 1;
578 }
579
[email protected]a93bb842010-02-16 23:03:47580 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03581 TextureManager::TextureInfo* CreateTextureInfo(
582 GLuint client_id, GLuint service_id) {
[email protected]915a59a12010-09-30 21:29:11583 return texture_manager()->CreateTextureInfo(
584 feature_info_, client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47585 }
586
587 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03588 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50589 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03590 texture_manager()->GetTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50591 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:47592 }
593
594 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03595 void RemoveTextureInfo(GLuint client_id) {
[email protected]915a59a12010-09-30 21:29:11596 texture_manager()->RemoveTextureInfo(feature_info_, client_id);
[email protected]3916c97e2010-02-25 03:20:50597 }
[email protected]a93bb842010-02-16 23:03:47598
[email protected]d37231fa2010-04-09 21:16:02599 // Get the size (in pixels) of the currently bound frame buffer (either FBO
600 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30601 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02602
[email protected]9edc6b22010-12-23 02:00:26603 // Get the format of the currently bound frame buffer (either FBO or regular
604 // back buffer)
605 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46606 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26607
[email protected]a93bb842010-02-16 23:03:47608 // Wrapper for CompressedTexImage2D commands.
609 error::Error DoCompressedTexImage2D(
610 GLenum target,
611 GLint level,
612 GLenum internal_format,
613 GLsizei width,
614 GLsizei height,
615 GLint border,
616 GLsizei image_size,
617 const void* data);
618
[email protected]cadde4a2010-07-31 17:10:43619 // Wrapper for CompressedTexSubImage2D.
620 void DoCompressedTexSubImage2D(
621 GLenum target,
622 GLint level,
623 GLint xoffset,
624 GLint yoffset,
625 GLsizei width,
626 GLsizei height,
627 GLenum format,
628 GLsizei imageSize,
629 const void * data);
630
631 // Wrapper for CopyTexImage2D.
632 void DoCopyTexImage2D(
633 GLenum target,
634 GLint level,
635 GLenum internal_format,
636 GLint x,
637 GLint y,
638 GLsizei width,
639 GLsizei height,
640 GLint border);
641
642 // Wrapper for CopyTexSubImage2D.
643 void DoCopyTexSubImage2D(
644 GLenum target,
645 GLint level,
646 GLint xoffset,
647 GLint yoffset,
648 GLint x,
649 GLint y,
650 GLsizei width,
651 GLsizei height);
652
[email protected]a93bb842010-02-16 23:03:47653 // Wrapper for TexImage2D commands.
654 error::Error DoTexImage2D(
655 GLenum target,
656 GLint level,
657 GLenum internal_format,
658 GLsizei width,
659 GLsizei height,
660 GLint border,
661 GLenum format,
662 GLenum type,
663 const void* pixels,
664 uint32 pixels_size);
665
[email protected]cadde4a2010-07-31 17:10:43666 // Wrapper for TexSubImage2D.
667 void DoTexSubImage2D(
668 GLenum target,
669 GLint level,
670 GLint xoffset,
671 GLint yoffset,
672 GLsizei width,
673 GLsizei height,
674 GLenum format,
675 GLenum type,
676 const void * data);
677
[email protected]a93bb842010-02-16 23:03:47678 // Creates a ProgramInfo for the given program.
[email protected]d685a682011-04-29 16:19:57679 ProgramManager::ProgramInfo* CreateProgramInfo(
680 GLuint client_id, GLuint service_id) {
681 return program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47682 }
683
[email protected]07f54fcc2009-12-22 02:46:30684 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03685 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14686 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46687 }
[email protected]07f54fcc2009-12-22 02:46:30688
[email protected]6b8cf1a2010-05-06 16:13:58689 // Gets the program info for the given program. If it's not a program
690 // generates a GL error. Returns NULL if not program.
691 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
692 GLuint client_id, const char* function_name) {
693 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
694 if (!info) {
695 if (GetShaderInfo(client_id)) {
696 SetGLError(GL_INVALID_OPERATION,
697 (std::string(function_name) +
698 ": shader passed for program").c_str());
699 } else {
700 SetGLError(GL_INVALID_VALUE,
701 (std::string(function_name) + ": unknown program").c_str());
702 }
703 }
704 return info;
705 }
706
707
[email protected]45bf5152010-02-12 00:11:31708 // Creates a ShaderInfo for the given shader.
[email protected]d685a682011-04-29 16:19:57709 ShaderManager::ShaderInfo* CreateShaderInfo(
710 GLuint client_id,
711 GLuint service_id,
712 GLenum shader_type) {
713 return shader_manager()->CreateShaderInfo(
714 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31715 }
716
717 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03718 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14719 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31720 }
721
[email protected]6b8cf1a2010-05-06 16:13:58722 // Gets the shader info for the given shader. If it's not a shader generates a
723 // GL error. Returns NULL if not shader.
724 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
725 GLuint client_id, const char* function_name) {
726 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
727 if (!info) {
728 if (GetProgramInfo(client_id)) {
729 SetGLError(
730 GL_INVALID_OPERATION,
731 (std::string(function_name) +
732 ": program passed for shader").c_str());
733 } else {
734 SetGLError(GL_INVALID_VALUE,
735 (std::string(function_name) + ": unknown shader").c_str());
736 }
737 }
738 return info;
739 }
740
[email protected]a93bb842010-02-16 23:03:47741 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03742 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
743 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47744 }
745
[email protected]07f54fcc2009-12-22 02:46:30746 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03747 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
748 BufferManager::BufferInfo* info =
749 buffer_manager()->GetBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50750 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]1d32bc82010-01-13 22:06:46751 }
[email protected]07f54fcc2009-12-22 02:46:30752
[email protected]a93bb842010-02-16 23:03:47753 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
754 // on glDeleteBuffers so we can make sure the user does not try to render
755 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03756 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47757
[email protected]a25fa872010-03-25 02:57:58758 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03759 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
760 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58761 }
762
763 // Gets the framebuffer info for the given framebuffer.
764 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03765 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58766 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03767 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58768 return (info && !info->IsDeleted()) ? info : NULL;
769 }
770
771 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03772 void RemoveFramebufferInfo(GLuint client_id) {
773 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58774 }
775
776 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03777 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
778 return renderbuffer_manager()->CreateRenderbufferInfo(
779 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58780 }
781
782 // Gets the renderbuffer info for the given renderbuffer.
783 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03784 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58785 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03786 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58787 return (info && !info->IsDeleted()) ? info : NULL;
788 }
789
790 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03791 void RemoveRenderbufferInfo(GLuint client_id) {
792 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58793 }
794
[email protected]558847a2010-03-24 07:02:54795 error::Error GetAttribLocationHelper(
796 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
797 const std::string& name_str);
798
799 error::Error GetUniformLocationHelper(
800 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
801 const std::string& name_str);
802
[email protected]3916c97e2010-02-25 03:20:50803 // Helper for glShaderSource.
804 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03805 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30806
[email protected]3a2e7c7b2010-08-06 01:12:28807 // Clears any uncleared render buffers attached to the given frame buffer.
[email protected]8e3e0662010-08-23 18:46:30808 void ClearUnclearedRenderbuffers(
809 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28810
[email protected]c007aa02010-09-02 22:22:40811 // Restore all GL state that affects clearing.
812 void RestoreClearState();
813
[email protected]3a2e7c7b2010-08-06 01:12:28814 // Remembers the state of some capabilities.
[email protected]297ca1c2011-06-20 23:08:46815 // Returns: true if glEnable/glDisable should actually be called.
816 bool SetCapabilityState(GLenum cap, bool enabled);
[email protected]3a2e7c7b2010-08-06 01:12:28817
[email protected]3a03a8f2011-03-19 00:51:27818 // Check that the current frame buffer is complete. Generates error if not.
819 bool CheckFramebufferComplete(const char* func_name);
820
[email protected]939e7362010-05-13 20:49:10821 // Checks if the current program exists and is valid. If not generates the
822 // appropriate GL error. Returns true if the current program is in a usable
823 // state.
824 bool CheckCurrentProgram(const char* function_name);
825
826 // Checks if the current program exists and is valid and that location is not
827 // -1. If the current program is not valid generates the appropriate GL
828 // error. Returns true if the current program is in a usable state and
829 // location is not -1.
830 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
831
832 // Gets the type of a uniform for a location in the current program. Sets GL
833 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:36834 // program is valid and the location exists. Adjusts count so it
835 // does not overflow the uniform.
836 bool PrepForSetUniformByLocation(
837 GLint location, const char* function_name, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:10838
[email protected]b273e432010-04-12 17:23:58839 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
840 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
841
[email protected]96449d2c2009-11-25 00:01:32842 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03843 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32844
845 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03846 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32847
[email protected]3916c97e2010-02-25 03:20:50848 // Wrapper for glActiveTexture
849 void DoActiveTexture(GLenum texture_unit);
850
[email protected]ae51d192010-04-27 00:48:03851 // Wrapper for glAttachShader
852 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
853
[email protected]96449d2c2009-11-25 00:01:32854 // Wrapper for glBindBuffer since we need to track the current targets.
855 void DoBindBuffer(GLenum target, GLuint buffer);
856
[email protected]86093972010-03-11 00:13:56857 // Wrapper for glBindFramebuffer since we need to track the current targets.
858 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
859
860 // Wrapper for glBindRenderbuffer since we need to track the current targets.
861 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
862
[email protected]a93bb842010-02-16 23:03:47863 // Wrapper for glBindTexture since we need to track the current targets.
864 void DoBindTexture(GLenum target, GLuint texture);
865
[email protected]8e3e0662010-08-23 18:46:30866 // Wrapper for glBlitFramebufferEXT.
867 void DoBlitFramebufferEXT(
868 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
869 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
870 GLbitfield mask, GLenum filter);
871
[email protected]36cef8ce2010-03-16 07:34:45872 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:11873 void DoBufferData(
874 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
875
[email protected]36cef8ce2010-03-16 07:34:45876 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:11877 void DoBufferSubData(
878 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
879
[email protected]36cef8ce2010-03-16 07:34:45880 // Wrapper for glCheckFramebufferStatus
881 GLenum DoCheckFramebufferStatus(GLenum target);
882
[email protected]3a03a8f2011-03-19 00:51:27883 // Wrapper for glClear
884 void DoClear(GLbitfield mask);
885
[email protected]3a2e7c7b2010-08-06 01:12:28886 // Wrappers for clear and mask settings functions.
887 void DoClearColor(
888 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
889 void DoClearDepthf(GLclampf depth);
890 void DoClearStencil(GLint s);
891 void DoColorMask(
892 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
893 void DoDepthMask(GLboolean depth);
894 void DoStencilMask(GLuint mask);
895 void DoStencilMaskSeparate(GLenum face, GLuint mask);
896
[email protected]45bf5152010-02-12 00:11:31897 // Wrapper for glCompileShader.
898 void DoCompileShader(GLuint shader);
899
[email protected]269200b12010-11-18 22:53:06900 // Helper for DeleteSharedIdsCHROMIUM commands.
901 void DoDeleteSharedIdsCHROMIUM(
902 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:10903
[email protected]ae51d192010-04-27 00:48:03904 // Wrapper for glDetachShader
905 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
906
[email protected]3a2e7c7b2010-08-06 01:12:28907 // Wrapper for glDisable
908 void DoDisable(GLenum cap);
909
[email protected]07f54fcc2009-12-22 02:46:30910 // Wrapper for glDisableVertexAttribArray.
911 void DoDisableVertexAttribArray(GLuint index);
912
[email protected]3a2e7c7b2010-08-06 01:12:28913 // Wrapper for glEnable
914 void DoEnable(GLenum cap);
915
[email protected]07f54fcc2009-12-22 02:46:30916 // Wrapper for glEnableVertexAttribArray.
917 void DoEnableVertexAttribArray(GLuint index);
918
[email protected]36cef8ce2010-03-16 07:34:45919 // Wrapper for glFramebufferRenderbufffer.
920 void DoFramebufferRenderbuffer(
921 GLenum target, GLenum attachment, GLenum renderbuffertarget,
922 GLuint renderbuffer);
923
924 // Wrapper for glFramebufferTexture2D.
925 void DoFramebufferTexture2D(
926 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
927 GLint level);
928
[email protected]a93bb842010-02-16 23:03:47929 // Wrapper for glGenerateMipmap
930 void DoGenerateMipmap(GLenum target);
931
[email protected]269200b12010-11-18 22:53:06932 // Helper for GenSharedIdsCHROMIUM commands.
933 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:10934 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
935
[email protected]b273e432010-04-12 17:23:58936 // Wrapper for DoGetBooleanv.
937 void DoGetBooleanv(GLenum pname, GLboolean* params);
938
939 // Wrapper for DoGetFloatv.
940 void DoGetFloatv(GLenum pname, GLfloat* params);
941
[email protected]36cef8ce2010-03-16 07:34:45942 // Wrapper for glGetFramebufferAttachmentParameteriv.
943 void DoGetFramebufferAttachmentParameteriv(
944 GLenum target, GLenum attachment, GLenum pname, GLint* params);
945
[email protected]a0c3e972010-04-21 00:49:13946 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:58947 void DoGetIntegerv(GLenum pname, GLint* params);
948
[email protected]29a9eb52010-04-13 09:04:23949 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:06950 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:23951 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
952
[email protected]a0c3e972010-04-21 00:49:13953 // Wrapper for glGetProgramiv.
954 void DoGetProgramiv(
955 GLuint program_id, GLenum pname, GLint* params);
956
[email protected]36cef8ce2010-03-16 07:34:45957 // Wrapper for glRenderbufferParameteriv.
958 void DoGetRenderbufferParameteriv(
959 GLenum target, GLenum pname, GLint* params);
960
[email protected]ddd968b82010-03-02 00:44:29961 // Wrapper for glGetShaderiv
962 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
963
[email protected]b1122982010-05-17 23:04:24964 // Wrappers for glGetVertexAttrib.
965 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
966 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
967
[email protected]1958e0e2010-04-22 05:17:15968 // Wrappers for glIsXXX functions.
969 bool DoIsBuffer(GLuint client_id);
970 bool DoIsFramebuffer(GLuint client_id);
971 bool DoIsProgram(GLuint client_id);
972 bool DoIsRenderbuffer(GLuint client_id);
973 bool DoIsShader(GLuint client_id);
974 bool DoIsTexture(GLuint client_id);
975
[email protected]07f54fcc2009-12-22 02:46:30976 // Wrapper for glLinkProgram
977 void DoLinkProgram(GLuint program);
978
[email protected]269200b12010-11-18 22:53:06979 // Helper for RegisterSharedIdsCHROMIUM.
980 void DoRegisterSharedIdsCHROMIUM(
981 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:10982
[email protected]36cef8ce2010-03-16 07:34:45983 // Wrapper for glRenderbufferStorage.
984 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:03985 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:45986
[email protected]8e3e0662010-08-23 18:46:30987 // Wrapper for glRenderbufferStorageMultisampleEXT.
988 void DoRenderbufferStorageMultisample(
989 GLenum target, GLsizei samples, GLenum internalformat,
990 GLsizei width, GLsizei height);
991
[email protected]b273e432010-04-12 17:23:58992 // Wrapper for glReleaseShaderCompiler.
993 void DoReleaseShaderCompiler() { }
994
[email protected]3916c97e2010-02-25 03:20:50995 // Wrappers for glTexParameter functions.
996 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
997 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
998 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
999 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1000
1001 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1002 // spec only these 2 functions can be used to set sampler uniforms.
1003 void DoUniform1i(GLint location, GLint v0);
[email protected]939e7362010-05-13 20:49:101004 void DoUniform1iv(GLint location, GLsizei count, const GLint* value);
[email protected]43c2f1f2011-03-25 18:35:361005 void DoUniform2iv(GLint location, GLsizei count, const GLint* value);
1006 void DoUniform3iv(GLint location, GLsizei count, const GLint* value);
1007 void DoUniform4iv(GLint location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101008
1009 // Wrappers for glUniformfv because some drivers don't correctly accept
1010 // bool uniforms.
1011 void DoUniform1fv(GLint location, GLsizei count, const GLfloat* value);
1012 void DoUniform2fv(GLint location, GLsizei count, const GLfloat* value);
1013 void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value);
1014 void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501015
[email protected]43c2f1f2011-03-25 18:35:361016 void DoUniformMatrix2fv(
1017 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1018 void DoUniformMatrix3fv(
1019 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1020 void DoUniformMatrix4fv(
1021 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
1022
[email protected]b1122982010-05-17 23:04:241023 // Wrappers for glVertexAttrib??
1024 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1025 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1026 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1027 void DoVertexAttrib4f(
1028 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1029 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1030 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1031 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1032 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1033
[email protected]07f54fcc2009-12-22 02:46:301034 // Wrapper for glUseProgram
1035 void DoUseProgram(GLuint program);
1036
[email protected]ae51d192010-04-27 00:48:031037 // Wrapper for glValidateProgram.
1038 void DoValidateProgram(GLuint program_client_id);
1039
[email protected]fbe20372011-06-01 01:46:381040 void DoSetSurfaceCHROMIUM(GLint surface_id);
1041
[email protected]4e8a5b122010-05-08 22:00:101042 // Gets the number of values that will be returned by glGetXXX. Returns
1043 // false if pname is unknown.
1044 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1045
[email protected]96449d2c2009-11-25 00:01:321046 // Gets the GLError through our wrapper.
1047 GLenum GetGLError();
1048
[email protected]1002c2d2011-06-28 22:39:041049 // Gets the GLError and stores it in our wrapper. Effectively
1050 // this lets us peek at the error without losing it.
1051 GLenum PeekGLError();
1052
[email protected]96449d2c2009-11-25 00:01:321053 // Sets our wrapper for the GLError.
[email protected]8eee29c2010-04-29 03:38:291054 void SetGLError(GLenum error, const char* msg);
[email protected]96449d2c2009-11-25 00:01:321055
[email protected]07f54fcc2009-12-22 02:46:301056 // Copies the real GL errors to the wrapper. This is so we can
1057 // make sure there are no native GL errors before calling some GL function
1058 // so that on return we know any error generated was for that specific
1059 // command.
1060 void CopyRealGLErrorsToWrapper();
1061
[email protected]6217d392010-03-25 22:08:351062 // Clear all real GL errors. This is to prevent the client from seeing any
1063 // errors caused by GL calls that it was not responsible for issuing.
1064 void ClearRealGLErrors();
1065
[email protected]07f54fcc2009-12-22 02:46:301066 // Checks if the current program and vertex attributes are valid for drawing.
1067 bool IsDrawValid(GLuint max_vertex_accessed);
1068
[email protected]b1122982010-05-17 23:04:241069 // Returns true if attrib0 was simulated.
1070 bool SimulateAttrib0(GLuint max_vertex_accessed);
1071 void RestoreStateForSimulatedAttrib0();
1072
[email protected]ef526492010-06-02 23:12:251073 // Returns true if textures were set.
1074 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501075 void RestoreStateForNonRenderableTextures();
1076
[email protected]8fbedc02010-11-18 18:43:401077 // Returns true if GL_FIXED attribs were simulated.
1078 bool SimulateFixedAttribs(GLuint max_vertex_accessed, bool* simulated);
1079 void RestoreStateForSimulatedFixedAttribs();
1080
[email protected]07f54fcc2009-12-22 02:46:301081 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501082 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301083 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501084 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1085 bound_array_buffer_ : bound_element_array_buffer_;
1086 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]07f54fcc2009-12-22 02:46:301087 }
1088
[email protected]a93bb842010-02-16 23:03:471089 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501090 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1091 TextureUnit& unit = texture_units_[active_texture_unit_];
1092 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471093 switch (target) {
1094 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501095 info = unit.bound_texture_2d;
1096 break;
[email protected]a93bb842010-02-16 23:03:471097 case GL_TEXTURE_CUBE_MAP:
1098 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1099 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1100 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1101 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1102 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1103 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501104 info = unit.bound_texture_cube_map;
1105 break;
[email protected]61eeb33f2011-07-26 15:30:311106 case GL_TEXTURE_EXTERNAL_OES:
1107 info = unit.bound_texture_external_oes;
1108 break;
[email protected]1aef98132010-02-23 18:00:071109 // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to
1110 // track |texture_| with the currently bound TEXTURE_RECTANGLE texture,
1111 // because |texture_| is used by the FBO rendering mechanism for readback
1112 // to the bits that get sent to the browser.
[email protected]a93bb842010-02-16 23:03:471113 default:
1114 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501115 return NULL;
[email protected]a93bb842010-02-16 23:03:471116 }
[email protected]3916c97e2010-02-25 03:20:501117 return (info && !info->IsDeleted()) ? info : NULL;
[email protected]a93bb842010-02-16 23:03:471118 }
1119
[email protected]61eeb33f2011-07-26 15:30:311120 GLenum GetBindTargetForSamplerType(GLenum type) {
1121 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1122 type == GL_SAMPLER_EXTERNAL_OES);
1123 return type == GL_SAMPLER_2D ? GL_TEXTURE_2D :
1124 (type == GL_SAMPLER_EXTERNAL_OES ? GL_TEXTURE_EXTERNAL_OES :
1125 GL_TEXTURE_CUBE_MAP);
1126 }
1127
[email protected]8e3e0662010-08-23 18:46:301128 // Gets the framebuffer info for a particular target.
1129 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1130 GLenum target) {
1131 FramebufferManager::FramebufferInfo* info = NULL;
1132 switch (target) {
1133 case GL_FRAMEBUFFER:
1134 case GL_DRAW_FRAMEBUFFER:
1135 info = bound_draw_framebuffer_;
1136 break;
1137 case GL_READ_FRAMEBUFFER:
1138 info = bound_read_framebuffer_;
1139 break;
1140 default:
1141 NOTREACHED();
1142 break;
1143 }
1144 return (info && !info->IsDeleted()) ? info : NULL;
1145 }
1146
[email protected]f7b85372010-02-03 01:11:371147 // Validates the program and location for a glGetUniform call and returns
1148 // a SizeResult setup to receive the result. Returns true if glGetUniform
1149 // should be called.
1150 bool GetUniformSetup(
1151 GLuint program, GLint location,
1152 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:101153 error::Error* error, GLuint* service_id, void** result,
1154 GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371155
[email protected]38d139d2011-07-14 00:38:431156 // Returns true if the context was just lost due to e.g. GL_ARB_robustness.
1157 bool WasContextLost();
1158
[email protected]96449d2c2009-11-25 00:01:321159 // Generate a member function prototype for each command in an automated and
1160 // typesafe way.
1161 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141162 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191163 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321164 const gles2::name& args); \
1165
1166 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1167
1168 #undef GLES2_CMD_OP
1169
[email protected]fbe20372011-06-01 01:46:381170 // Maps surface IDs to GLSurface.
1171 gpu::SurfaceManager* surface_manager_;
1172
[email protected]2f2d7042010-04-14 21:45:581173 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381174 scoped_refptr<gfx::GLSurface> surface_;
1175 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021176
[email protected]a3ded6d2010-10-19 06:44:391177 // The ContextGroup for this decoder uses to track resources.
1178 ContextGroup::Ref group_;
1179
[email protected]6217d392010-03-25 22:08:351180 // A parent decoder can access this decoders saved offscreen frame buffer.
1181 // The parent pointer is reset if the parent is destroyed.
1182 base::WeakPtr<GLES2DecoderImpl> parent_;
1183
[email protected]34ff8b0c2010-10-01 20:06:021184 // Current width and height of the offscreen frame buffer.
1185 gfx::Size offscreen_size_;
1186
[email protected]96449d2c2009-11-25 00:01:321187 // Current GL error bits.
1188 uint32 error_bits_;
1189
[email protected]96449d2c2009-11-25 00:01:321190 // Util to help with GL.
1191 GLES2Util util_;
1192
1193 // pack alignment as last set by glPixelStorei
1194 GLint pack_alignment_;
1195
1196 // unpack alignment as last set by glPixelStorei
1197 GLint unpack_alignment_;
1198
1199 // The currently bound array buffer. If this is 0 it is illegal to call
1200 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501201 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321202
1203 // The currently bound element array buffer. If this is 0 it is illegal
1204 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501205 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301206
[email protected]f39f4b3f2010-05-12 17:04:081207 // Class that manages vertex attribs.
1208 VertexAttribManager vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301209
[email protected]b1122982010-05-17 23:04:241210 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1211 GLuint attrib_0_buffer_id_;
1212
1213 // The value currently in attrib_0.
1214 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1215
[email protected]fc753442011-02-04 19:49:491216 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1217 bool attrib_0_buffer_matches_value_;
1218
[email protected]b1122982010-05-17 23:04:241219 // The size of attrib 0.
1220 GLsizei attrib_0_size_;
1221
[email protected]8fbedc02010-11-18 18:43:401222 // The buffer used to simulate GL_FIXED attribs.
1223 GLuint fixed_attrib_buffer_id_;
1224
1225 // The size of fiixed attrib buffer.
1226 GLsizei fixed_attrib_buffer_size_;
1227
[email protected]3916c97e2010-02-25 03:20:501228 // Current active texture by 0 - n index.
1229 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1230 // be 2.
1231 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301232
[email protected]3916c97e2010-02-25 03:20:501233 // Which textures are bound to texture units through glActiveTexture.
1234 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471235
[email protected]3a2e7c7b2010-08-06 01:12:281236 // state saved for clearing so we can clear render buffers and then
1237 // restore to these values.
1238 GLclampf clear_red_;
1239 GLclampf clear_green_;
1240 GLclampf clear_blue_;
1241 GLclampf clear_alpha_;
1242 GLboolean mask_red_;
1243 GLboolean mask_green_;
1244 GLboolean mask_blue_;
1245 GLboolean mask_alpha_;
1246 GLint clear_stencil_;
1247 GLuint mask_stencil_front_;
1248 GLuint mask_stencil_back_;
1249 GLclampf clear_depth_;
1250 GLboolean mask_depth_;
1251 bool enable_scissor_test_;
[email protected]297ca1c2011-06-20 23:08:461252 bool enable_depth_test_;
1253 bool enable_stencil_test_;
1254 bool state_dirty_;
[email protected]3a2e7c7b2010-08-06 01:12:281255
[email protected]1d32bc82010-01-13 22:06:461256 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501257 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301258
[email protected]8e3e0662010-08-23 18:46:301259 // The currently bound framebuffers
1260 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1261 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561262
1263 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081264 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561265
[email protected]b9363b22010-06-09 22:06:151266 // The offscreen frame buffer that the client renders to. With EGL, the
1267 // depth and stencil buffers are separate. With regular GL there is a single
1268 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1269 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351270 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1271 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021272 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151273 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1274 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021275 GLenum offscreen_target_color_format_;
1276 GLenum offscreen_target_depth_format_;
1277 GLenum offscreen_target_stencil_format_;
1278 GLsizei offscreen_target_samples_;
[email protected]6217d392010-03-25 22:08:351279
[email protected]de26b3c2011-08-03 21:54:271280 // The copy that is saved when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021281 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351282 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]de26b3c2011-08-03 21:54:271283
1284 // The copy that is used as the destination for multi-sample resolves.
1285 scoped_ptr<FrameBuffer> offscreen_resolved_frame_buffer_;
1286 scoped_ptr<Texture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051287 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351288
[email protected]7ff86b92010-11-25 17:50:001289 scoped_ptr<Callback1<gfx::Size>::Type> resize_callback_;
[email protected]43f28f832010-02-03 02:28:481290 scoped_ptr<Callback0::Type> swap_buffers_callback_;
1291
[email protected]32fe9aa2011-01-21 23:47:131292 // The format of the back buffer_
1293 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461294 bool back_buffer_has_depth_;
1295 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131296
[email protected]473c01ccb2011-06-07 01:33:301297 bool teximage2d_faster_than_texsubimage2d_;
1298 bool bufferdata_faster_than_buffersubdata_;
1299
[email protected]8eee29c2010-04-29 03:38:291300 // The last error message set.
1301 std::string last_error_;
1302
[email protected]a3a93e7b2010-08-28 00:48:561303 // The current decoder error.
1304 error::Error current_decoder_error_;
1305
[email protected]b1d2dcb2010-05-17 19:24:181306 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451307 scoped_ptr<ShaderTranslator> vertex_translator_;
1308 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181309
[email protected]c410da802011-03-14 19:17:411310 DisallowedExtensions disallowed_extensions_;
1311
[email protected]915a59a12010-09-30 21:29:111312 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051313 const Validators* validators_;
[email protected]915a59a12010-09-30 21:29:111314 FeatureInfo* feature_info_;
[email protected]9438b012010-06-15 22:55:051315
[email protected]b493ee622011-04-13 23:52:001316 // This indicates all the following texSubImage2D calls that are part of the
1317 // failed texImage2D call should be ignored.
1318 bool tex_image_2d_failed_;
1319
[email protected]65225772011-05-12 21:10:241320 int frame_number_;
1321
[email protected]38d139d2011-07-14 00:38:431322 bool has_arb_robustness_;
1323 GLenum reset_status_;
1324
[email protected]75c023c2011-08-22 23:54:511325 bool needs_mac_nvidia_driver_workaround_;
1326
[email protected]96449d2c2009-11-25 00:01:321327 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1328};
1329
[email protected]6217d392010-03-25 22:08:351330ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1331 : decoder_(decoder) {
1332 decoder_->CopyRealGLErrorsToWrapper();
1333}
1334
1335ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1336 decoder_->ClearRealGLErrors();
1337}
1338
1339ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1340 GLuint id)
1341 : decoder_(decoder) {
1342 ScopedGLErrorSuppressor suppressor(decoder_);
1343
1344 // TODO(apatrick): Check if there are any other states that need to be reset
1345 // before binding a new texture.
1346 glActiveTexture(GL_TEXTURE0);
1347 glBindTexture(GL_TEXTURE_2D, id);
1348}
1349
1350ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1351 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301352 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351353}
1354
1355ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1356 GLuint id)
1357 : decoder_(decoder) {
1358 ScopedGLErrorSuppressor suppressor(decoder_);
1359 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1360}
1361
1362ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1363 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301364 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351365}
1366
1367ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1368 GLuint id)
1369 : decoder_(decoder) {
1370 ScopedGLErrorSuppressor suppressor(decoder_);
1371 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1372}
1373
1374ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1375 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301376 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351377}
1378
[email protected]34ff8b0c2010-10-01 20:06:021379ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271380 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521381 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021382 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1383 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]c0701082011-04-20 00:34:521384 (!decoder_->bound_read_framebuffer_.get() ||
1385 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021386 if (!resolve_and_bind_)
1387 return;
1388
1389 ScopedGLErrorSuppressor suppressor(decoder_);
1390 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1391 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271392 GLuint targetid;
1393 if (internal) {
1394 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1395 decoder_->offscreen_resolved_frame_buffer_.reset(
1396 new FrameBuffer(decoder_));
1397 decoder_->offscreen_resolved_frame_buffer_->Create();
1398 decoder_->offscreen_resolved_color_texture_.reset(new Texture(decoder_));
1399 decoder_->offscreen_resolved_color_texture_->Create();
1400
1401 DCHECK(decoder_->offscreen_saved_color_format_);
1402 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1403 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_);
1404
1405 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1406 decoder_->offscreen_resolved_color_texture_.get());
1407 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1408 GL_FRAMEBUFFER_COMPLETE) {
1409 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1410 << "because offscreen resolved FBO was incomplete.";
1411 return;
1412 }
1413 }
1414 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1415 } else {
1416 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1417 }
1418 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021419 const int width = decoder_->offscreen_size_.width();
1420 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181421 glDisable(GL_SCISSOR_TEST);
[email protected]34ff8b0c2010-10-01 20:06:021422 if (IsAngle()) {
1423 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1424 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1425 } else {
1426 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1427 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1428 }
[email protected]de26b3c2011-08-03 21:54:271429 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021430}
1431
1432ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1433 if (!resolve_and_bind_)
1434 return;
1435
1436 ScopedGLErrorSuppressor suppressor(decoder_);
1437 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181438 if (decoder_->enable_scissor_test_) {
1439 glEnable(GL_SCISSOR_TEST);
1440 }
[email protected]34ff8b0c2010-10-01 20:06:021441}
1442
[email protected]6217d392010-03-25 22:08:351443Texture::Texture(GLES2DecoderImpl* decoder)
1444 : decoder_(decoder),
[email protected]3a4d0c52011-06-29 23:11:581445 id_(0) {
[email protected]6217d392010-03-25 22:08:351446}
1447
1448Texture::~Texture() {
1449 // This does not destroy the render texture because that would require that
1450 // the associated GL context was current. Just check that it was explicitly
1451 // destroyed.
1452 DCHECK_EQ(id_, 0u);
1453}
1454
1455void Texture::Create() {
1456 ScopedGLErrorSuppressor suppressor(decoder_);
1457 Destroy();
1458 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581459 ScopedTexture2DBinder binder(decoder_, id_);
1460 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1461 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1462 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1463 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]6217d392010-03-25 22:08:351464}
1465
[email protected]34ff8b0c2010-10-01 20:06:021466bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351467 DCHECK_NE(id_, 0u);
1468 ScopedGLErrorSuppressor suppressor(decoder_);
1469 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]6217d392010-03-25 22:08:351470
1471 glTexImage2D(GL_TEXTURE_2D,
1472 0, // mip level
[email protected]34ff8b0c2010-10-01 20:06:021473 format,
[email protected]6217d392010-03-25 22:08:351474 size.width(),
1475 size.height(),
1476 0, // border
[email protected]34ff8b0c2010-10-01 20:06:021477 format,
[email protected]6217d392010-03-25 22:08:351478 GL_UNSIGNED_BYTE,
1479 NULL);
1480
[email protected]d37231fa2010-04-09 21:16:021481 size_ = size;
1482
[email protected]6217d392010-03-25 22:08:351483 return glGetError() == GL_NO_ERROR;
1484}
1485
[email protected]3a4d0c52011-06-29 23:11:581486void Texture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351487 DCHECK_NE(id_, 0u);
1488 ScopedGLErrorSuppressor suppressor(decoder_);
1489 ScopedTexture2DBinder binder(decoder_, id_);
1490 glCopyTexImage2D(GL_TEXTURE_2D,
1491 0, // level
[email protected]3a4d0c52011-06-29 23:11:581492 format,
[email protected]6217d392010-03-25 22:08:351493 0, 0,
1494 size.width(),
1495 size.height(),
1496 0); // border
1497}
1498
1499void Texture::Destroy() {
1500 if (id_ != 0) {
1501 ScopedGLErrorSuppressor suppressor(decoder_);
1502 glDeleteTextures(1, &id_);
1503 id_ = 0;
1504 }
1505}
1506
[email protected]97872062010-11-03 19:07:051507void Texture::Invalidate() {
1508 id_ = 0;
1509}
1510
[email protected]6217d392010-03-25 22:08:351511RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1512 : decoder_(decoder),
1513 id_(0) {
1514}
1515
1516RenderBuffer::~RenderBuffer() {
1517 // This does not destroy the render buffer because that would require that
1518 // the associated GL context was current. Just check that it was explicitly
1519 // destroyed.
1520 DCHECK_EQ(id_, 0u);
1521}
1522
1523void RenderBuffer::Create() {
1524 ScopedGLErrorSuppressor suppressor(decoder_);
1525 Destroy();
1526 glGenRenderbuffersEXT(1, &id_);
1527}
1528
[email protected]34ff8b0c2010-10-01 20:06:021529bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1530 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351531 ScopedGLErrorSuppressor suppressor(decoder_);
1532 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021533 if (samples <= 1) {
1534 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1535 format,
1536 size.width(),
1537 size.height());
1538 } else {
1539 if (IsAngle()) {
1540 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1541 samples,
1542 format,
1543 size.width(),
1544 size.height());
1545 } else {
1546 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1547 samples,
1548 format,
1549 size.width(),
1550 size.height());
1551 }
1552 }
[email protected]6217d392010-03-25 22:08:351553 return glGetError() == GL_NO_ERROR;
1554}
1555
1556void RenderBuffer::Destroy() {
1557 if (id_ != 0) {
1558 ScopedGLErrorSuppressor suppressor(decoder_);
1559 glDeleteRenderbuffersEXT(1, &id_);
1560 id_ = 0;
1561 }
1562}
1563
[email protected]97872062010-11-03 19:07:051564void RenderBuffer::Invalidate() {
1565 id_ = 0;
1566}
1567
[email protected]6217d392010-03-25 22:08:351568FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1569 : decoder_(decoder),
1570 id_(0) {
1571}
1572
1573FrameBuffer::~FrameBuffer() {
1574 // This does not destroy the frame buffer because that would require that
1575 // the associated GL context was current. Just check that it was explicitly
1576 // destroyed.
1577 DCHECK_EQ(id_, 0u);
1578}
1579
1580void FrameBuffer::Create() {
1581 ScopedGLErrorSuppressor suppressor(decoder_);
1582 Destroy();
1583 glGenFramebuffersEXT(1, &id_);
1584}
1585
1586void FrameBuffer::AttachRenderTexture(Texture* texture) {
1587 DCHECK_NE(id_, 0u);
1588 ScopedGLErrorSuppressor suppressor(decoder_);
1589 ScopedFrameBufferBinder binder(decoder_, id_);
1590 GLuint attach_id = texture ? texture->id() : 0;
1591 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1592 GL_COLOR_ATTACHMENT0,
1593 GL_TEXTURE_2D,
1594 attach_id,
1595 0);
1596}
1597
[email protected]b9363b22010-06-09 22:06:151598void FrameBuffer::AttachRenderBuffer(GLenum target,
1599 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351600 DCHECK_NE(id_, 0u);
1601 ScopedGLErrorSuppressor suppressor(decoder_);
1602 ScopedFrameBufferBinder binder(decoder_, id_);
1603 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1604 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151605 target,
[email protected]6217d392010-03-25 22:08:351606 GL_RENDERBUFFER,
1607 attach_id);
1608}
1609
1610void FrameBuffer::Clear(GLbitfield buffers) {
1611 ScopedGLErrorSuppressor suppressor(decoder_);
1612 ScopedFrameBufferBinder binder(decoder_, id_);
1613 glClear(buffers);
1614}
1615
1616void FrameBuffer::Destroy() {
1617 if (id_ != 0) {
1618 ScopedGLErrorSuppressor suppressor(decoder_);
1619 glDeleteFramebuffersEXT(1, &id_);
1620 id_ = 0;
1621 }
1622}
1623
[email protected]97872062010-11-03 19:07:051624void FrameBuffer::Invalidate() {
1625 id_ = 0;
1626}
1627
[email protected]6217d392010-03-25 22:08:351628GLenum FrameBuffer::CheckStatus() {
1629 DCHECK_NE(id_, 0u);
1630 ScopedGLErrorSuppressor suppressor(decoder_);
1631 ScopedFrameBufferBinder binder(decoder_, id_);
1632 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1633}
1634
[email protected]fbe20372011-06-01 01:46:381635GLES2Decoder* GLES2Decoder::Create(SurfaceManager* surface_manager,
1636 ContextGroup* group) {
1637 return new GLES2DecoderImpl(surface_manager, group);
[email protected]96449d2c2009-11-25 00:01:321638}
1639
[email protected]fbe20372011-06-01 01:46:381640GLES2DecoderImpl::GLES2DecoderImpl(SurfaceManager* surface_manager,
1641 ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391642 : GLES2Decoder(),
[email protected]fbe20372011-06-01 01:46:381643 surface_manager_(surface_manager),
[email protected]3b1ecc262011-08-03 22:49:571644 group_(group),
[email protected]96449d2c2009-11-25 00:01:321645 error_bits_(0),
[email protected]96449d2c2009-11-25 00:01:321646 pack_alignment_(4),
1647 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241648 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491649 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241650 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401651 fixed_attrib_buffer_id_(0),
1652 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501653 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281654 clear_red_(0),
1655 clear_green_(0),
1656 clear_blue_(0),
1657 clear_alpha_(0),
1658 mask_red_(true),
1659 mask_green_(true),
1660 mask_blue_(true),
1661 mask_alpha_(true),
1662 clear_stencil_(0),
1663 mask_stencil_front_(-1),
1664 mask_stencil_back_(-1),
1665 clear_depth_(1.0f),
1666 mask_depth_(true),
1667 enable_scissor_test_(false),
[email protected]297ca1c2011-06-20 23:08:461668 enable_depth_test_(false),
1669 enable_stencil_test_(false),
1670 state_dirty_(true),
[email protected]34ff8b0c2010-10-01 20:06:021671 offscreen_target_color_format_(0),
1672 offscreen_target_depth_format_(0),
1673 offscreen_target_stencil_format_(0),
1674 offscreen_target_samples_(0),
[email protected]97872062010-11-03 19:07:051675 offscreen_saved_color_format_(0),
[email protected]32fe9aa2011-01-21 23:47:131676 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:461677 back_buffer_has_depth_(false),
1678 back_buffer_has_stencil_(false),
[email protected]473c01ccb2011-06-07 01:33:301679 teximage2d_faster_than_texsubimage2d_(true),
1680 bufferdata_faster_than_buffersubdata_(true),
[email protected]a3a93e7b2010-08-28 00:48:561681 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051682 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111683 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001684 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241685 tex_image_2d_failed_(false),
[email protected]38d139d2011-07-14 00:38:431686 frame_number_(0),
1687 has_arb_robustness_(false),
[email protected]75c023c2011-08-22 23:54:511688 reset_status_(GL_NO_ERROR),
1689 needs_mac_nvidia_driver_workaround_(false) {
[email protected]3b1ecc262011-08-03 22:49:571690 DCHECK(group);
1691
[email protected]b1122982010-05-17 23:04:241692 attrib_0_value_.v[0] = 0.0f;
1693 attrib_0_value_.v[1] = 0.0f;
1694 attrib_0_value_.v[2] = 0.0f;
1695 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151696
[email protected]c2f8c8402010-12-06 18:07:241697 // The shader translator is used for WebGL even when running on EGL
1698 // because additional restrictions are needed (like only enabling
1699 // GL_OES_standard_derivatives on demand). It is used for the unit
1700 // tests because
1701 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1702 // empty string to CompileShader and this is not a valid shader.
1703 // TODO(apatrick): fix this test.
1704 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
1705 !feature_info_->feature_flags().chromium_webglsl) ||
[email protected]b9363b22010-06-09 22:06:151706 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) {
1707 use_shader_translator_ = false;
1708 }
[email protected]473c01ccb2011-06-07 01:33:301709
1710 // TODO(gman): Consider setting these based on GPU and/or driver.
1711 if (IsAngle()) {
1712 teximage2d_faster_than_texsubimage2d_ = false;
1713 bufferdata_faster_than_buffersubdata_ = false;
1714 }
[email protected]96449d2c2009-11-25 00:01:321715}
1716
[email protected]c410da802011-03-14 19:17:411717bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:381718 const scoped_refptr<gfx::GLSurface>& surface,
1719 const scoped_refptr<gfx::GLContext>& context,
[email protected]c410da802011-03-14 19:17:411720 const gfx::Size& size,
1721 const DisallowedExtensions& disallowed_extensions,
1722 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:241723 const std::vector<int32>& attribs) {
[email protected]4bedba72010-04-20 22:08:541724 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301725 DCHECK(!context_.get());
1726
[email protected]fbe20372011-06-01 01:46:381727 // Take ownership of the GLSurface. TODO(apatrick): once the parent / child
1728 // context is retired, the decoder should not take an initial surface as
1729 // an argument to this function.
1730 // Maybe create a short lived offscreen GLSurface for the purpose of
1731 // initializing the decoder's GLContext.
1732 surface_ = surface;
[email protected]f62a5ab2011-05-23 20:34:151733
[email protected]66791e382010-07-14 20:48:301734 // Take ownership of the GLContext.
[email protected]fbe20372011-06-01 01:46:381735 context_ = context;
[email protected]d37231fa2010-04-09 21:16:021736
[email protected]246a70452010-03-05 21:53:501737 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:011738 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
1739 << "MakeCurrent failed.";
[email protected]246a70452010-03-05 21:53:501740 Destroy();
1741 return false;
[email protected]eb54a562010-01-20 21:55:181742 }
1743
[email protected]c410da802011-03-14 19:17:411744 if (!group_->Initialize(disallowed_extensions, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:221745 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:391746 << "failed to initialize.";
1747 Destroy();
[email protected]ae1741092010-11-17 19:16:031748 return false;
[email protected]a3ded6d2010-10-19 06:44:391749 }
1750
[email protected]246a70452010-03-05 21:53:501751 CHECK_GL_ERROR();
[email protected]c410da802011-03-14 19:17:411752 disallowed_extensions_ = disallowed_extensions;
[email protected]246a70452010-03-05 21:53:501753
[email protected]f39f4b3f2010-05-12 17:04:081754 vertex_attrib_manager_.Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:321755
[email protected]302ce6d2011-07-07 23:28:111756 util_.set_num_compressed_texture_formats(
1757 validators_->compressed_texture_format.GetValues().size());
1758
[email protected]1071e572011-02-09 20:00:121759 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1760 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
1761 // OpenGL ES 2.0 does not have this issue.
1762 glEnableVertexAttribArray(0);
1763 }
[email protected]b1122982010-05-17 23:04:241764 glGenBuffersARB(1, &attrib_0_buffer_id_);
1765 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
1766 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
1767 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:401768 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:081769
[email protected]246a70452010-03-05 21:53:501770 texture_units_.reset(
1771 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:151772 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:491773 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:311774 // We want the last bind to be 2D.
1775 TextureManager::TextureInfo* info;
1776 if (feature_info_->feature_flags().oes_egl_image_external) {
1777 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_EXTERNAL_OES);
1778 texture_units_[tt].bound_texture_external_oes = info;
1779 glBindTexture(GL_TEXTURE_EXTERNAL_OES, info->service_id());
1780 }
1781 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:491782 texture_units_[tt].bound_texture_cube_map = info;
1783 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
1784 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
1785 texture_units_[tt].bound_texture_2d = info;
1786 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:151787 }
[email protected]00f893d2010-08-24 18:55:491788 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:501789 CHECK_GL_ERROR();
1790
[email protected]297ca1c2011-06-20 23:08:461791 ContextCreationAttribParser attrib_parser;
1792 if (!attrib_parser.Parse(attribs))
1793 return false;
[email protected]41c56362011-06-14 16:47:431794
[email protected]297ca1c2011-06-20 23:08:461795 // These are NOT if the back buffer has these proprorties. They are
1796 // if we want the command buffer to enforce them regardless of what
1797 // the real backbuffer is assuming the real back buffer gives us more than
1798 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
1799 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
1800 // can't do anything about that.
1801
1802 GLint v = 0;
1803 glGetIntegerv(GL_ALPHA_BITS, &v);
1804 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
1805 // user requested RGB then RGB. If the user did not specify a preference than
1806 // use whatever we were given. Same for DEPTH and STENCIL.
1807 back_buffer_color_format_ =
1808 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
1809 glGetIntegerv(GL_DEPTH_BITS, &v);
1810 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
1811 glGetIntegerv(GL_STENCIL_BITS, &v);
1812 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
1813
1814 if (surface_->IsOffscreen()) {
[email protected]34ff8b0c2010-10-01 20:06:021815 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:541816 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:021817 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
1818 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:431819 // max_sample_count must be initialized to a sane value. If
1820 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
1821 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:021822 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
1823 offscreen_target_samples_ = std::min(attrib_parser.samples_,
1824 max_sample_count);
1825 } else {
1826 offscreen_target_samples_ = 1;
1827 }
1828
1829 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
1830 const bool rgb8_supported =
1831 context_->HasExtension("GL_OES_rgb8_rgba8");
1832 // The only available default render buffer formats in GLES2 have very
1833 // little precision. Don't enable multisampling unless 8-bit render
1834 // buffer formats are available--instead fall back to 8-bit textures.
1835 if (rgb8_supported && offscreen_target_samples_ > 1) {
1836 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1837 GL_RGBA8 : GL_RGB8;
1838 } else {
1839 offscreen_target_samples_ = 1;
1840 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1841 GL_RGBA : GL_RGB;
1842 }
1843
1844 // ANGLE only supports packed depth/stencil formats, so use it if it is
1845 // available.
1846 const bool depth24_stencil8_supported =
1847 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271848 VLOG(1) << "GL_OES_packed_depth_stencil "
1849 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:001850 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1851 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021852 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1853 offscreen_target_stencil_format_ = 0;
1854 } else {
1855 // It may be the case that this depth/stencil combination is not
1856 // supported, but this will be checked later by CheckFramebufferStatus.
1857 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1858 GL_DEPTH_COMPONENT16 : 0;
1859 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1860 GL_STENCIL_INDEX8 : 0;
1861 }
1862 } else {
1863 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
1864 GL_RGBA : GL_RGB;
1865
1866 // If depth is requested at all, use the packed depth stencil format if
1867 // it's available, as some desktop GL drivers don't support any non-packed
1868 // formats for depth attachments.
1869 const bool depth24_stencil8_supported =
1870 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:271871 VLOG(1) << "GL_EXT_packed_depth_stencil "
1872 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:021873
[email protected]71ee3642010-10-14 18:08:001874 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
1875 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:021876 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
1877 offscreen_target_stencil_format_ = 0;
1878 } else {
1879 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
1880 GL_DEPTH_COMPONENT : 0;
1881 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
1882 GL_STENCIL_INDEX : 0;
1883 }
1884 }
1885
[email protected]97872062010-11-03 19:07:051886 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
1887 GL_RGBA : GL_RGB;
1888
[email protected]6217d392010-03-25 22:08:351889 // Create the target frame buffer. This is the one that the client renders
1890 // directly to.
1891 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
1892 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021893 // Due to GLES2 format limitations, either the color texture (for
1894 // non-multisampling) or the color render buffer (for multisampling) will be
1895 // attached to the offscreen frame buffer. The render buffer has more
1896 // limited formats available to it, but the texture can't do multisampling.
1897 if (IsOffscreenBufferMultisampled()) {
1898 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
1899 offscreen_target_color_render_buffer_->Create();
1900 } else {
1901 offscreen_target_color_texture_.reset(new Texture(this));
1902 offscreen_target_color_texture_->Create();
1903 }
1904 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151905 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:021906 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:151907 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:351908
1909 // Create the saved offscreen texture. The target frame buffer is copied
1910 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021911 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
1912 offscreen_saved_frame_buffer_->Create();
1913 //
[email protected]6217d392010-03-25 22:08:351914 offscreen_saved_color_texture_.reset(new Texture(this));
1915 offscreen_saved_color_texture_->Create();
1916
[email protected]6217d392010-03-25 22:08:351917 // Allocate the render buffers at their initial size and check the status
1918 // of the frame buffers is okay.
[email protected]799b4b22011-08-22 17:09:591919 if (!ResizeOffscreenFrameBuffer(size)) {
[email protected]d0498742010-09-20 20:27:011920 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:351921 Destroy();
1922 return false;
1923 }
1924
1925 // Bind to the new default frame buffer (the offscreen target frame buffer).
1926 // This should now be associated with ID zero.
1927 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
1928 }
1929
[email protected]76a0ee102010-04-07 21:03:041930 // OpenGL ES 2.0 implicitly enables the desktop GL capability
1931 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
1932 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:371933 // mailing list archives. It also implicitly enables the desktop GL
1934 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
1935 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:151936 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1937 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:371938 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:151939 }
[email protected]de17df392010-04-23 21:09:411940
[email protected]38d139d2011-07-14 00:38:431941 has_arb_robustness_ = context->HasExtension("GL_ARB_robustness");
1942
[email protected]75c023c2011-08-22 23:54:511943#if defined(OS_MACOSX)
1944 const char* vendor_str = reinterpret_cast<const char*>(
1945 glGetString(GL_VENDOR));
1946 needs_mac_nvidia_driver_workaround_ =
1947 vendor_str && strstr(vendor_str, "NVIDIA") &&
1948 base::mac::IsOSSnowLeopardOrEarlier();
1949#endif
1950
[email protected]c2f8c8402010-12-06 18:07:241951 if (!InitializeShaderTranslator()) {
1952 return false;
[email protected]de17df392010-04-23 21:09:411953 }
[email protected]76a0ee102010-04-07 21:03:041954
[email protected]246a70452010-03-05 21:53:501955 return true;
[email protected]96449d2c2009-11-25 00:01:321956}
1957
[email protected]302ce6d2011-07-07 23:28:111958void GLES2DecoderImpl::UpdateCapabilities() {
1959 util_.set_num_compressed_texture_formats(
1960 validators_->compressed_texture_format.GetValues().size());
1961 util_.set_num_shader_binary_formats(
1962 validators_->shader_binary_format.GetValues().size());
1963}
1964
[email protected]c2f8c8402010-12-06 18:07:241965bool GLES2DecoderImpl::InitializeShaderTranslator() {
1966 // Re-check the state of use_shader_translator_ each time this is called.
1967 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
1968 feature_info_->feature_flags().chromium_webglsl &&
1969 !use_shader_translator_) {
1970 use_shader_translator_ = true;
1971 }
1972 if (!use_shader_translator_) {
1973 return true;
1974 }
1975 ShBuiltInResources resources;
1976 ShInitBuiltInResources(&resources);
1977 resources.MaxVertexAttribs = group_->max_vertex_attribs();
1978 resources.MaxVertexUniformVectors =
1979 group_->max_vertex_uniform_vectors();
1980 resources.MaxVaryingVectors = group_->max_varying_vectors();
1981 resources.MaxVertexTextureImageUnits =
1982 group_->max_vertex_texture_image_units();
1983 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
1984 resources.MaxTextureImageUnits = group_->max_texture_image_units();
1985 resources.MaxFragmentUniformVectors =
1986 group_->max_fragment_uniform_vectors();
1987 resources.MaxDrawBuffers = 1;
1988 resources.OES_standard_derivatives =
1989 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
1990 vertex_translator_.reset(new ShaderTranslator);
1991 ShShaderSpec shader_spec = feature_info_->feature_flags().chromium_webglsl ?
1992 SH_WEBGL_SPEC : SH_GLES2_SPEC;
1993 bool is_glsl_es =
1994 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
1995 if (!vertex_translator_->Init(
1996 SH_VERTEX_SHADER, shader_spec, &resources, is_glsl_es)) {
1997 LOG(ERROR) << "Could not initialize vertex shader translator.";
1998 Destroy();
1999 return false;
2000 }
2001 fragment_translator_.reset(new ShaderTranslator);
2002 if (!fragment_translator_->Init(
2003 SH_FRAGMENT_SHADER, shader_spec, &resources, is_glsl_es)) {
2004 LOG(ERROR) << "Could not initialize fragment shader translator.";
2005 Destroy();
2006 return false;
2007 }
2008 return true;
2009}
2010
[email protected]ae51d192010-04-27 00:48:032011bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472012 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032013 if (GetBufferInfo(client_ids[ii])) {
2014 return false;
2015 }
2016 }
2017 scoped_array<GLuint> service_ids(new GLuint[n]);
2018 glGenBuffersARB(n, service_ids.get());
2019 for (GLsizei ii = 0; ii < n; ++ii) {
2020 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2021 }
2022 return true;
2023}
2024
2025bool GLES2DecoderImpl::GenFramebuffersHelper(
2026 GLsizei n, const GLuint* client_ids) {
2027 for (GLsizei ii = 0; ii < n; ++ii) {
2028 if (GetFramebufferInfo(client_ids[ii])) {
2029 return false;
2030 }
2031 }
2032 scoped_array<GLuint> service_ids(new GLuint[n]);
2033 glGenFramebuffersEXT(n, service_ids.get());
2034 for (GLsizei ii = 0; ii < n; ++ii) {
2035 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2036 }
2037 return true;
2038}
2039
2040bool GLES2DecoderImpl::GenRenderbuffersHelper(
2041 GLsizei n, const GLuint* client_ids) {
2042 for (GLsizei ii = 0; ii < n; ++ii) {
2043 if (GetRenderbufferInfo(client_ids[ii])) {
2044 return false;
2045 }
2046 }
2047 scoped_array<GLuint> service_ids(new GLuint[n]);
2048 glGenRenderbuffersEXT(n, service_ids.get());
2049 for (GLsizei ii = 0; ii < n; ++ii) {
2050 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2051 }
2052 return true;
2053}
2054
2055bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2056 for (GLsizei ii = 0; ii < n; ++ii) {
2057 if (GetTextureInfo(client_ids[ii])) {
2058 return false;
2059 }
2060 }
2061 scoped_array<GLuint> service_ids(new GLuint[n]);
2062 glGenTextures(n, service_ids.get());
2063 for (GLsizei ii = 0; ii < n; ++ii) {
2064 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2065 }
2066 return true;
2067}
2068
2069void GLES2DecoderImpl::DeleteBuffersHelper(
2070 GLsizei n, const GLuint* client_ids) {
2071 for (GLsizei ii = 0; ii < n; ++ii) {
2072 BufferManager::BufferInfo* info = GetBufferInfo(client_ids[ii]);
2073 if (info) {
2074 GLuint service_id = info->service_id();
2075 glDeleteBuffersARB(1, &service_id);
2076 RemoveBufferInfo(client_ids[ii]);
2077 }
[email protected]a93bb842010-02-16 23:03:472078 }
[email protected]07f54fcc2009-12-22 02:46:302079}
2080
[email protected]ae51d192010-04-27 00:48:032081void GLES2DecoderImpl::DeleteFramebuffersHelper(
2082 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582083 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032084 FramebufferManager::FramebufferInfo* info =
2085 GetFramebufferInfo(client_ids[ii]);
2086 if (info) {
[email protected]297ca1c2011-06-20 23:08:462087 if (info == bound_draw_framebuffer_) {
2088 bound_draw_framebuffer_ = NULL;
2089 state_dirty_ = true;
2090 }
[email protected]ae51d192010-04-27 00:48:032091 GLuint service_id = info->service_id();
2092 glDeleteFramebuffersEXT(1, &service_id);
2093 RemoveFramebufferInfo(client_ids[ii]);
2094 }
[email protected]a25fa872010-03-25 02:57:582095 }
[email protected]07f54fcc2009-12-22 02:46:302096}
2097
[email protected]ae51d192010-04-27 00:48:032098void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2099 GLsizei n, const GLuint* client_ids) {
[email protected]a25fa872010-03-25 02:57:582100 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032101 RenderbufferManager::RenderbufferInfo* info =
2102 GetRenderbufferInfo(client_ids[ii]);
2103 if (info) {
[email protected]297ca1c2011-06-20 23:08:462104 state_dirty_ = true;
[email protected]ae51d192010-04-27 00:48:032105 GLuint service_id = info->service_id();
2106 glDeleteRenderbuffersEXT(1, &service_id);
2107 RemoveRenderbufferInfo(client_ids[ii]);
2108 }
[email protected]a25fa872010-03-25 02:57:582109 }
[email protected]07f54fcc2009-12-22 02:46:302110}
2111
[email protected]ae51d192010-04-27 00:48:032112void GLES2DecoderImpl::DeleteTexturesHelper(
2113 GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472114 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032115 TextureManager::TextureInfo* info = GetTextureInfo(client_ids[ii]);
2116 if (info) {
[email protected]297ca1c2011-06-20 23:08:462117 if (info->IsAttachedToFramebuffer()) {
2118 state_dirty_ = true;
2119 }
[email protected]5f4f2a732011-07-30 00:47:552120 GLuint service_id = info->service_id();
2121 glDeleteTextures(1, &service_id);
[email protected]ae51d192010-04-27 00:48:032122 RemoveTextureInfo(client_ids[ii]);
2123 }
[email protected]a93bb842010-02-16 23:03:472124 }
[email protected]07f54fcc2009-12-22 02:46:302125}
2126
[email protected]43f28f832010-02-03 02:28:482127// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322128
[email protected]eb54a562010-01-20 21:55:182129bool GLES2DecoderImpl::MakeCurrent() {
[email protected]38d139d2011-07-14 00:38:432130 bool result = context_.get() ? context_->MakeCurrent(surface_.get()) : false;
2131 if (result && WasContextLost()) {
2132 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2133 result = false;
2134 }
2135
2136 return result;
[email protected]eb54a562010-01-20 21:55:182137}
2138
[email protected]8e3e0662010-08-23 18:46:302139void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
2140 glBindRenderbufferEXT(
2141 GL_RENDERBUFFER,
2142 bound_renderbuffer_ ? bound_renderbuffer_->service_id() : 0);
2143}
2144
2145static void RebindCurrentFramebuffer(
2146 GLenum target,
2147 FramebufferManager::FramebufferInfo* info,
2148 FrameBuffer* offscreen_frame_buffer) {
2149 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462150
[email protected]8e3e0662010-08-23 18:46:302151 if (framebuffer_id == 0 && offscreen_frame_buffer) {
2152 framebuffer_id = offscreen_frame_buffer->id();
2153 }
[email protected]297ca1c2011-06-20 23:08:462154
[email protected]8e3e0662010-08-23 18:46:302155 glBindFramebufferEXT(target, framebuffer_id);
2156}
2157
2158void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]297ca1c2011-06-20 23:08:462159 state_dirty_ = true;
2160
[email protected]a3ded6d2010-10-19 06:44:392161 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302162 RebindCurrentFramebuffer(
2163 GL_FRAMEBUFFER,
2164 bound_draw_framebuffer_.get(),
2165 offscreen_target_frame_buffer_.get());
2166 } else {
2167 RebindCurrentFramebuffer(
2168 GL_READ_FRAMEBUFFER_EXT,
2169 bound_read_framebuffer_.get(),
2170 offscreen_target_frame_buffer_.get());
2171 RebindCurrentFramebuffer(
2172 GL_DRAW_FRAMEBUFFER_EXT,
2173 bound_draw_framebuffer_.get(),
2174 offscreen_target_frame_buffer_.get());
2175 }
2176}
2177
2178void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2179 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2180 GLuint last_id;
2181 if (info.bound_texture_2d) {
2182 last_id = info.bound_texture_2d->service_id();
2183 } else {
2184 last_id = 0;
2185 }
2186
2187 glBindTexture(GL_TEXTURE_2D, last_id);
2188 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2189}
2190
[email protected]3a03a8f2011-03-19 00:51:272191bool GLES2DecoderImpl::CheckFramebufferComplete(const char* func_name) {
2192 if (bound_draw_framebuffer_ && bound_draw_framebuffer_->IsNotComplete()) {
[email protected]be45d7c2011-04-15 18:03:352193 SetGLError(GL_INVALID_FRAMEBUFFER_OPERATION,
[email protected]3a03a8f2011-03-19 00:51:272194 (std::string(func_name) + " framebuffer incomplete").c_str());
2195 return false;
2196 }
2197 return true;
2198}
2199
[email protected]8e3e0662010-08-23 18:46:302200gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
2201 if (bound_read_framebuffer_ != 0) {
[email protected]9edc6b22010-12-23 02:00:262202 const FramebufferManager::FramebufferInfo::Attachment* attachment =
2203 bound_read_framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
2204 if (attachment) {
2205 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502206 }
[email protected]9edc6b22010-12-23 02:00:262207 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022208 } else if (offscreen_target_frame_buffer_.get()) {
2209 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352210 } else {
[email protected]f62a5ab2011-05-23 20:34:152211 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022212 }
[email protected]246a70452010-03-05 21:53:502213}
2214
[email protected]9edc6b22010-12-23 02:00:262215GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
2216 if (bound_read_framebuffer_ != 0) {
[email protected]297ca1c2011-06-20 23:08:462217 return bound_read_framebuffer_->GetColorAttachmentFormat();
2218 } else if (offscreen_target_frame_buffer_.get()) {
2219 return offscreen_target_color_format_;
2220 } else {
2221 return back_buffer_color_format_;
2222 }
2223}
2224
2225GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
2226 if (bound_draw_framebuffer_ != 0) {
2227 return bound_draw_framebuffer_->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262228 } else if (offscreen_target_frame_buffer_.get()) {
2229 return offscreen_target_color_format_;
2230 } else {
[email protected]32fe9aa2011-01-21 23:47:132231 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262232 }
2233}
2234
[email protected]9a5afa432011-07-22 18:16:392235void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]34ff8b0c2010-10-01 20:06:022236 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582237 // Update the info about the offscreen saved color texture in the parent.
2238 // The reference to the parent is a weak pointer and will become null if the
2239 // parent is later destroyed.
[email protected]6217d392010-03-25 22:08:352240 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]8d25d042010-06-16 19:48:142241 GLuint client_id;
[email protected]262d7aa2010-12-03 22:07:292242 TextureManager* parent_texture_manager = parent_->texture_manager();
2243 CHECK(parent_texture_manager->GetClientId(service_id, &client_id));
[email protected]8d25d042010-06-16 19:48:142244 TextureManager::TextureInfo* info = parent_->GetTextureInfo(client_id);
[email protected]6217d392010-03-25 22:08:352245 DCHECK(info);
2246
[email protected]262d7aa2010-12-03 22:07:292247 parent_texture_manager->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:112248 feature_info_,
[email protected]ef526492010-06-02 23:12:252249 info,
2250 GL_TEXTURE_2D,
2251 0, // level
2252 GL_RGBA,
[email protected]799b4b22011-08-22 17:09:592253 offscreen_size_.width(),
2254 offscreen_size_.height(),
[email protected]ef526492010-06-02 23:12:252255 1, // depth
2256 0, // border
2257 GL_RGBA,
2258 GL_UNSIGNED_BYTE);
[email protected]262d7aa2010-12-03 22:07:292259 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042260 feature_info_,
2261 info,
2262 GL_TEXTURE_MAG_FILTER,
2263 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292264 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042265 feature_info_,
2266 info,
2267 GL_TEXTURE_MIN_FILTER,
2268 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292269 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042270 feature_info_,
2271 info,
2272 GL_TEXTURE_WRAP_S,
2273 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292274 parent_texture_manager->SetParameter(
[email protected]8c515f82010-11-09 03:40:042275 feature_info_,
2276 info,
2277 GL_TEXTURE_WRAP_T,
2278 GL_CLAMP_TO_EDGE);
[email protected]0c8c9d22010-06-25 17:36:392279 }
[email protected]6217d392010-03-25 22:08:352280}
2281
[email protected]799b4b22011-08-22 17:09:592282void GLES2DecoderImpl::SetResizeCallback(
2283 Callback1<gfx::Size>::Type* callback) {
[email protected]7ff86b92010-11-25 17:50:002284 resize_callback_.reset(callback);
2285}
2286
[email protected]43f28f832010-02-03 02:28:482287void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
2288 swap_buffers_callback_.reset(callback);
2289}
2290
[email protected]1318e922010-09-17 22:03:162291bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2292 uint32* service_texture_id) {
2293 TextureManager::TextureInfo* texture =
2294 texture_manager()->GetTextureInfo(client_texture_id);
2295 if (texture) {
2296 *service_texture_id = texture->service_id();
2297 return true;
2298 }
2299 return false;
2300}
2301
[email protected]96449d2c2009-11-25 00:01:322302void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392303 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052304
2305 if (group_.get())
2306 group_->set_have_context(have_context);
2307
[email protected]3c644d82011-06-20 19:58:242308 SetParent(NULL, 0);
2309
[email protected]eadc96792010-10-27 19:39:392310 if (have_context) {
[email protected]ca488e12010-12-13 20:06:142311 if (current_program_) {
2312 program_manager()->UnuseProgram(shader_manager(), current_program_);
2313 current_program_ = NULL;
2314 }
2315
[email protected]b1122982010-05-17 23:04:242316 if (attrib_0_buffer_id_) {
2317 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2318 }
[email protected]8fbedc02010-11-18 18:43:402319 if (fixed_attrib_buffer_id_) {
2320 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2321 }
[email protected]b1122982010-05-17 23:04:242322
[email protected]97872062010-11-03 19:07:052323 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542324 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052325 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542326 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052327 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022328 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052329 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152330 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052331 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152332 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052333 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022334 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052335 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542336 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:272337 if (offscreen_resolved_frame_buffer_.get())
2338 offscreen_resolved_frame_buffer_->Destroy();
2339 if (offscreen_resolved_color_texture_.get())
2340 offscreen_resolved_color_texture_->Destroy();
[email protected]66791e382010-07-14 20:48:302341
[email protected]eadc96792010-10-27 19:39:392342 // must release the ContextGroup before destroying the context as its
2343 // destructor uses GL.
2344 group_ = NULL;
[email protected]97872062010-11-03 19:07:052345 } else {
2346 if (offscreen_target_frame_buffer_.get())
2347 offscreen_target_frame_buffer_->Invalidate();
2348 if (offscreen_target_color_texture_.get())
2349 offscreen_target_color_texture_->Invalidate();
2350 if (offscreen_target_color_render_buffer_.get())
2351 offscreen_target_color_render_buffer_->Invalidate();
2352 if (offscreen_target_depth_render_buffer_.get())
2353 offscreen_target_depth_render_buffer_->Invalidate();
2354 if (offscreen_target_stencil_render_buffer_.get())
2355 offscreen_target_stencil_render_buffer_->Invalidate();
2356 if (offscreen_saved_frame_buffer_.get())
2357 offscreen_saved_frame_buffer_->Invalidate();
2358 if (offscreen_saved_color_texture_.get())
2359 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:272360 if (offscreen_resolved_frame_buffer_.get())
2361 offscreen_resolved_frame_buffer_->Invalidate();
2362 if (offscreen_resolved_color_texture_.get())
2363 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022364 }
[email protected]97872062010-11-03 19:07:052365
[email protected]fe871662011-06-16 20:43:052366 if (context_.get()) {
2367 context_->ReleaseCurrent(NULL);
[email protected]0fc35742011-04-13 17:57:542368 context_->Destroy();
[email protected]fe871662011-06-16 20:43:052369 }
[email protected]fbe20372011-06-01 01:46:382370 context_ = NULL;
[email protected]0fc35742011-04-13 17:57:542371
[email protected]97872062010-11-03 19:07:052372 offscreen_target_frame_buffer_.reset();
2373 offscreen_target_color_texture_.reset();
2374 offscreen_target_color_render_buffer_.reset();
2375 offscreen_target_depth_render_buffer_.reset();
2376 offscreen_target_stencil_render_buffer_.reset();
2377 offscreen_saved_frame_buffer_.reset();
2378 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:272379 offscreen_resolved_frame_buffer_.reset();
2380 offscreen_resolved_color_texture_.reset();
[email protected]96449d2c2009-11-25 00:01:322381}
2382
[email protected]3c644d82011-06-20 19:58:242383bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
2384 uint32 new_parent_texture_id) {
[email protected]9a5afa432011-07-22 18:16:392385 if (!offscreen_saved_color_texture_.get())
2386 return false;
2387
[email protected]3c644d82011-06-20 19:58:242388 // Remove the saved frame buffer mapping from the parent decoder. The
2389 // parent pointer is a weak pointer so it will be null if the parent has
2390 // already been destroyed.
2391 if (parent_) {
2392 // First check the texture has been mapped into the parent. This might not
2393 // be the case if initialization failed midway through.
2394 GLuint service_id = offscreen_saved_color_texture_->id();
2395 GLuint client_id = 0;
2396 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
2397 parent_->texture_manager()->RemoveTextureInfo(feature_info_, client_id);
2398 }
2399 }
2400
2401 GLES2DecoderImpl* new_parent_impl = static_cast<GLES2DecoderImpl*>(
2402 new_parent);
2403 if (new_parent_impl) {
2404 // Map the ID of the saved offscreen texture into the parent so that
2405 // it can reference it.
2406 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]98687862011-07-11 23:31:302407
2408 // Replace texture info when ID is already in use by parent.
2409 if (new_parent_impl->texture_manager()->GetTextureInfo(
2410 new_parent_texture_id))
2411 new_parent_impl->texture_manager()->RemoveTextureInfo(
2412 feature_info_, new_parent_texture_id);
2413
[email protected]3c644d82011-06-20 19:58:242414 TextureManager::TextureInfo* info =
[email protected]5f4f2a732011-07-30 00:47:552415 new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id);
2416 info->SetNotOwned();
[email protected]3c644d82011-06-20 19:58:242417 new_parent_impl->texture_manager()->SetInfoTarget(info, GL_TEXTURE_2D);
2418
2419 parent_ = new_parent_impl->AsWeakPtr();
[email protected]9a5afa432011-07-22 18:16:392420
2421 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:242422 } else {
2423 parent_.reset();
2424 }
2425
2426 return true;
2427}
2428
[email protected]799b4b22011-08-22 17:09:592429bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2430 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
2431 if (!is_offscreen) {
2432 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
2433 << " with an onscreen framebuffer.";
2434 return false;
2435 }
2436
2437 if (offscreen_size_ == size)
2438 return true;
2439
2440 offscreen_size_ = size;
2441 int w = offscreen_size_.width();
2442 int h = offscreen_size_.height();
2443 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
2444 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2445 << "to allocate storage due to excessive dimensions.";
2446 return false;
2447 }
2448
2449 // Reallocate the offscreen target buffers.
2450 DCHECK(offscreen_target_color_format_);
2451 if (IsOffscreenBufferMultisampled()) {
2452 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2453 offscreen_size_, offscreen_target_color_format_,
2454 offscreen_target_samples_)) {
2455 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2456 << "to allocate storage for offscreen target color buffer.";
2457 return false;
2458 }
2459 } else {
2460 if (!offscreen_target_color_texture_->AllocateStorage(
2461 offscreen_size_, offscreen_target_color_format_)) {
2462 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2463 << "to allocate storage for offscreen target color texture.";
2464 return false;
2465 }
2466 }
2467 if (offscreen_target_depth_format_ &&
2468 !offscreen_target_depth_render_buffer_->AllocateStorage(
2469 offscreen_size_, offscreen_target_depth_format_,
2470 offscreen_target_samples_)) {
2471 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2472 << "to allocate storage for offscreen target depth buffer.";
2473 return false;
2474 }
2475 if (offscreen_target_stencil_format_ &&
2476 !offscreen_target_stencil_render_buffer_->AllocateStorage(
2477 offscreen_size_, offscreen_target_stencil_format_,
2478 offscreen_target_samples_)) {
2479 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2480 << "to allocate storage for offscreen target stencil buffer.";
2481 return false;
2482 }
2483
2484 // Attach the offscreen target buffers to the target frame buffer.
2485 if (IsOffscreenBufferMultisampled()) {
2486 offscreen_target_frame_buffer_->AttachRenderBuffer(
2487 GL_COLOR_ATTACHMENT0,
2488 offscreen_target_color_render_buffer_.get());
2489 } else {
2490 offscreen_target_frame_buffer_->AttachRenderTexture(
2491 offscreen_target_color_texture_.get());
2492 }
2493 if (offscreen_target_depth_format_) {
2494 offscreen_target_frame_buffer_->AttachRenderBuffer(
2495 GL_DEPTH_ATTACHMENT,
2496 offscreen_target_depth_render_buffer_.get());
2497 }
2498 const bool packed_depth_stencil =
2499 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2500 if (packed_depth_stencil) {
2501 offscreen_target_frame_buffer_->AttachRenderBuffer(
2502 GL_STENCIL_ATTACHMENT,
2503 offscreen_target_depth_render_buffer_.get());
2504 } else if (offscreen_target_stencil_format_) {
2505 offscreen_target_frame_buffer_->AttachRenderBuffer(
2506 GL_STENCIL_ATTACHMENT,
2507 offscreen_target_stencil_render_buffer_.get());
2508 }
2509
2510 if (offscreen_target_frame_buffer_->CheckStatus() !=
2511 GL_FRAMEBUFFER_COMPLETE) {
2512 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2513 << "because offscreen FBO was incomplete.";
2514 return false;
2515 }
2516
2517 // Clear the target frame buffer.
2518 {
2519 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
2520 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2521 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
2522 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2523 glClearStencil(0);
2524 glStencilMaskSeparate(GL_FRONT, -1);
2525 glStencilMaskSeparate(GL_BACK, -1);
2526 glClearDepth(0);
2527 glDepthMask(GL_TRUE);
2528 glDisable(GL_SCISSOR_TEST);
2529 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2530 RestoreClearState();
2531 }
2532
[email protected]75c023c2011-08-22 23:54:512533 // Workaround for driver bug on OS X 10.6.x and earlier; crbug.com/89557
2534 if (needs_mac_nvidia_driver_workaround_)
2535 offscreen_saved_frame_buffer_->Create();
2536
[email protected]799b4b22011-08-22 17:09:592537 // Allocate the offscreen saved color texture.
2538 DCHECK(offscreen_saved_color_format_);
2539 offscreen_saved_color_texture_->AllocateStorage(
2540 offscreen_size_, offscreen_saved_color_format_);
2541
2542 offscreen_saved_frame_buffer_->AttachRenderTexture(
2543 offscreen_saved_color_texture_.get());
2544 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2545 GL_FRAMEBUFFER_COMPLETE) {
2546 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2547 << "because offscreen saved FBO was incomplete.";
2548 return false;
2549 }
2550
2551 // Destroy the offscreen resolved framebuffers.
2552 if (offscreen_resolved_frame_buffer_.get())
2553 offscreen_resolved_frame_buffer_->Destroy();
2554 if (offscreen_resolved_color_texture_.get())
2555 offscreen_resolved_color_texture_->Destroy();
2556 offscreen_resolved_color_texture_.reset();
2557 offscreen_resolved_frame_buffer_.reset();
2558
2559 // Clear the offscreen color texture.
2560 {
2561 ScopedFrameBufferBinder binder(this, offscreen_saved_frame_buffer_->id());
2562 glClearColor(0, 0, 0, 0);
2563 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2564 glDisable(GL_SCISSOR_TEST);
2565 glClear(GL_COLOR_BUFFER_BIT);
2566 RestoreClearState();
2567 }
2568
2569 UpdateParentTextureInfo();
2570
2571 return true;
[email protected]6217d392010-03-25 22:08:352572}
2573
[email protected]799b4b22011-08-22 17:09:592574error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
2575 uint32 immediate_data_size, const gles2::ResizeCHROMIUM& c) {
2576 GLuint width = static_cast<GLuint>(c.width);
2577 GLuint height = static_cast<GLuint>(c.height);
2578 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
[email protected]2e7bbf22011-07-22 18:41:292579#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(TOUCH_UI)
[email protected]7ff86b92010-11-25 17:50:002580 // Make sure that we are done drawing to the back buffer before resizing.
2581 glFinish();
2582#endif
[email protected]799b4b22011-08-22 17:09:592583 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
2584 if (is_offscreen) {
2585 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height)))
2586 return error::kLostContext;
[email protected]7ff86b92010-11-25 17:50:002587 }
[email protected]799b4b22011-08-22 17:09:592588
2589 if (resize_callback_.get())
2590 resize_callback_->Run(gfx::Size(width, height));
2591
2592 return error::kNoError;
[email protected]43ecf372010-11-16 19:19:392593}
2594
[email protected]fbe20372011-06-01 01:46:382595void GLES2DecoderImpl::DoSetSurfaceCHROMIUM(GLint surface_id) {
2596 gfx::GLSurface* surface = surface_manager_->LookupSurface(surface_id);
2597 if (!surface)
2598 return;
2599
2600 surface_ = surface;
2601}
2602
[email protected]96449d2c2009-11-25 00:01:322603const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
2604 if (command_id > kStartPoint && command_id < kNumCommands) {
2605 return gles2::GetCommandName(static_cast<CommandId>(command_id));
2606 }
2607 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
2608}
2609
2610// Decode command with its arguments, and call the corresponding GL function.
2611// Note: args is a pointer to the command buffer. As such, it could be changed
2612// by a (malicious) client at any time, so if validation has to happen, it
2613// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:142614error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:322615 unsigned int command,
2616 unsigned int arg_count,
2617 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:142618 error::Error result = error::kNoError;
[email protected]b9849abf2009-11-25 19:13:192619 if (debug()) {
2620 // TODO(gman): Change output to something useful for NaCl.
[email protected]8e1b98a2011-06-14 23:39:532621 DLOG(INFO) << "[" << this << "]" << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192622 }
[email protected]96449d2c2009-11-25 00:01:322623 unsigned int command_index = command - kStartPoint - 1;
2624 if (command_index < arraysize(g_command_info)) {
2625 const CommandInfo& info = g_command_info[command_index];
2626 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
2627 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
2628 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:192629 uint32 immediate_data_size =
2630 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:322631 switch (command) {
2632 #define GLES2_CMD_OP(name) \
2633 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:192634 result = Handle ## name( \
2635 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:322636 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:192637 break; \
[email protected]96449d2c2009-11-25 00:01:322638
2639 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:322640 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:382641 }
2642 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:302643 GLenum error;
2644 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]bf0985e2009-12-17 03:04:382645 // TODO(gman): Change output to something useful for NaCl.
[email protected]8eee29c2010-04-29 03:38:292646 SetGLError(error, NULL);
[email protected]8e1b98a2011-06-14 23:39:532647 DLOG(INFO) << "[" << this << "]"
2648 << "GL ERROR: " << error << " : " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:192649 }
[email protected]96449d2c2009-11-25 00:01:322650 }
2651 } else {
[email protected]f7a64ee2010-02-01 22:24:142652 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:322653 }
[email protected]b9849abf2009-11-25 19:13:192654 } else {
2655 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:322656 }
[email protected]a3a93e7b2010-08-28 00:48:562657 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
2658 result = current_decoder_error_;
2659 current_decoder_error_ = error::kNoError;
2660 }
[email protected]b9849abf2009-11-25 19:13:192661 return result;
[email protected]96449d2c2009-11-25 00:01:322662}
2663
[email protected]ae51d192010-04-27 00:48:032664void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
2665 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:502666}
2667
[email protected]ae51d192010-04-27 00:48:032668bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
2669 if (GetProgramInfo(client_id)) {
2670 return false;
2671 }
[email protected]96449d2c2009-11-25 00:01:322672 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:032673 if (service_id != 0) {
2674 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:322675 }
[email protected]ae51d192010-04-27 00:48:032676 return true;
[email protected]96449d2c2009-11-25 00:01:322677}
2678
[email protected]ae51d192010-04-27 00:48:032679bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
2680 if (GetShaderInfo(client_id)) {
2681 return false;
[email protected]96449d2c2009-11-25 00:01:322682 }
[email protected]ae51d192010-04-27 00:48:032683 GLuint service_id = glCreateShader(type);
2684 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:382685 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:032686 }
2687 return true;
[email protected]96449d2c2009-11-25 00:01:322688}
2689
[email protected]3916c97e2010-02-25 03:20:502690void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:452691 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]660858b2011-07-13 23:16:142692 if (texture_index >= group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:292693 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:502694 return;
2695 }
[email protected]36cef8ce2010-03-16 07:34:452696 active_texture_unit_ = texture_index;
2697 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:502698}
2699
[email protected]051b1372010-04-12 02:42:082700void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:502701 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082702 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032703 if (client_id != 0) {
2704 info = GetBufferInfo(client_id);
2705 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:352706 if (!group_->bind_generates_resource()) {
2707 SetGLError(GL_INVALID_VALUE,
2708 "glBindBuffer: id not generated by glGenBuffers");
2709 return;
2710 }
2711
[email protected]ae51d192010-04-27 00:48:032712 // It's a new id so make a buffer info for it.
2713 glGenBuffersARB(1, &service_id);
2714 CreateBufferInfo(client_id, service_id);
2715 info = GetBufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:572716 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:102717 group_->GetIdAllocator(id_namespaces::kBuffers);
2718 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032719 }
[email protected]051b1372010-04-12 02:42:082720 }
[email protected]ae51d192010-04-27 00:48:032721 if (info) {
[email protected]4e8a5b122010-05-08 22:00:102722 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:292723 SetGLError(GL_INVALID_OPERATION,
2724 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:472725 return;
2726 }
[email protected]ae51d192010-04-27 00:48:032727 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:472728 }
[email protected]96449d2c2009-11-25 00:01:322729 switch (target) {
2730 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502731 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322732 break;
2733 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:502734 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:322735 break;
2736 default:
[email protected]a93bb842010-02-16 23:03:472737 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:322738 break;
2739 }
[email protected]051b1372010-04-12 02:42:082740 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:322741}
2742
[email protected]297ca1c2011-06-20 23:08:462743bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
2744 return (GLES2Util::GetChannelsForFormat(
2745 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
2746}
2747
2748bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
2749 if (bound_draw_framebuffer_) {
2750 return bound_draw_framebuffer_->HasDepthAttachment();
2751 }
2752 if (offscreen_target_frame_buffer_.get()) {
2753 return offscreen_target_depth_format_ != 0;
2754 }
2755 return back_buffer_has_depth_;
2756}
2757
2758bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
2759 if (bound_draw_framebuffer_) {
2760 return bound_draw_framebuffer_->HasStencilAttachment();
2761 }
2762 if (offscreen_target_frame_buffer_.get()) {
2763 return offscreen_target_stencil_format_ != 0 ||
2764 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2765 }
2766 return back_buffer_has_stencil_;
2767}
2768
2769void GLES2DecoderImpl::ApplyDirtyState() {
2770 if (state_dirty_) {
2771 glColorMask(
2772 mask_red_, mask_green_, mask_blue_,
2773 mask_alpha_ && BoundFramebufferHasColorAttachmentWithAlpha());
2774 bool have_depth = BoundFramebufferHasDepthAttachment();
2775 glDepthMask(mask_depth_ && have_depth);
2776 EnableDisable(GL_DEPTH_TEST, enable_depth_test_ && have_depth);
2777 bool have_stencil = BoundFramebufferHasStencilAttachment();
2778 glStencilMaskSeparate(GL_FRONT, have_stencil ? mask_stencil_front_ : 0);
2779 glStencilMaskSeparate(GL_BACK, have_stencil ? mask_stencil_back_ : 0);
2780 EnableDisable(GL_STENCIL_TEST, enable_stencil_test_ && have_stencil);
2781 state_dirty_ = false;
2782 }
2783}
2784
[email protected]051b1372010-04-12 02:42:082785void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
2786 FramebufferManager::FramebufferInfo* info = NULL;
2787 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032788 if (client_id != 0) {
2789 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082790 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:352791 if (!group_->bind_generates_resource()) {
2792 SetGLError(GL_INVALID_VALUE,
2793 "glBindFramebuffer: id not generated by glGenFramebuffers");
2794 return;
2795 }
2796
[email protected]ae51d192010-04-27 00:48:032797 // It's a new id so make a framebuffer info for it.
2798 glGenFramebuffersEXT(1, &service_id);
2799 CreateFramebufferInfo(client_id, service_id);
2800 info = GetFramebufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:572801 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:102802 group_->GetIdAllocator(id_namespaces::kFramebuffers);
2803 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032804 } else {
2805 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082806 }
[email protected]06c8b082011-01-05 18:00:362807 info->MarkAsValid();
[email protected]eff9a222010-12-21 21:48:562808 } else {
[email protected]2e7bbf22011-07-22 18:41:292809 service_id = surface_->GetBackingFrameBufferObject();
[email protected]051b1372010-04-12 02:42:082810 }
[email protected]8e3e0662010-08-23 18:46:302811
2812 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
2813 bound_draw_framebuffer_ = info;
2814 }
2815 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
2816 bound_read_framebuffer_ = info;
2817 }
[email protected]6217d392010-03-25 22:08:352818
[email protected]297ca1c2011-06-20 23:08:462819 state_dirty_ = true;
2820
[email protected]6217d392010-03-25 22:08:352821 // When rendering to an offscreen frame buffer, instead of unbinding from
2822 // the current frame buffer, bind to the offscreen target frame buffer.
[email protected]297ca1c2011-06-20 23:08:462823 if (info == NULL && offscreen_target_frame_buffer_.get()) {
[email protected]051b1372010-04-12 02:42:082824 service_id = offscreen_target_frame_buffer_->id();
[email protected]297ca1c2011-06-20 23:08:462825 }
[email protected]6217d392010-03-25 22:08:352826
[email protected]051b1372010-04-12 02:42:082827 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562828}
2829
[email protected]051b1372010-04-12 02:42:082830void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
2831 RenderbufferManager::RenderbufferInfo* info = NULL;
2832 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032833 if (client_id != 0) {
2834 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:082835 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:352836 if (!group_->bind_generates_resource()) {
2837 SetGLError(
2838 GL_INVALID_VALUE,
2839 "glBindRenderbuffer: id not generated by glGenRenderbuffers");
2840 return;
2841 }
2842
[email protected]ae51d192010-04-27 00:48:032843 // It's a new id so make a renderbuffer info for it.
2844 glGenRenderbuffersEXT(1, &service_id);
2845 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:102846 info = GetRenderbufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:572847 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:102848 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
2849 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032850 } else {
2851 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:082852 }
[email protected]06c8b082011-01-05 18:00:362853 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:082854 }
2855 bound_renderbuffer_ = info;
2856 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:562857}
2858
[email protected]051b1372010-04-12 02:42:082859void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:032860 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:082861 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:032862 if (client_id != 0) {
2863 info = GetTextureInfo(client_id);
2864 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:352865 if (!group_->bind_generates_resource()) {
2866 SetGLError(GL_INVALID_VALUE,
2867 "glBindTexture: id not generated by glGenTextures");
2868 return;
2869 }
2870
[email protected]ae51d192010-04-27 00:48:032871 // It's a new id so make a texture info for it.
2872 glGenTextures(1, &service_id);
2873 CreateTextureInfo(client_id, service_id);
2874 info = GetTextureInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:572875 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:102876 group_->GetIdAllocator(id_namespaces::kTextures);
2877 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:032878 }
2879 } else {
2880 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:082881 }
[email protected]ae51d192010-04-27 00:48:032882
[email protected]1958e0e2010-04-22 05:17:152883 // Check the texture exists
2884 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:032885 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:292886 SetGLError(GL_INVALID_OPERATION,
2887 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:152888 return;
2889 }
2890 if (info->target() == 0) {
2891 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:472892 }
[email protected]ae51d192010-04-27 00:48:032893 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:502894 TextureUnit& unit = texture_units_[active_texture_unit_];
2895 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:472896 switch (target) {
2897 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:502898 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:472899 break;
2900 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:502901 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:472902 break;
[email protected]61eeb33f2011-07-26 15:30:312903 case GL_TEXTURE_EXTERNAL_OES:
2904 unit.bound_texture_external_oes = info;
2905 break;
[email protected]a93bb842010-02-16 23:03:472906 default:
2907 NOTREACHED(); // Validation should prevent us getting here.
2908 break;
2909 }
2910}
2911
[email protected]07f54fcc2009-12-22 02:46:302912void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082913 if (vertex_attrib_manager_.Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:122914 if (index != 0 ||
2915 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:242916 glDisableVertexAttribArray(index);
2917 }
[email protected]07f54fcc2009-12-22 02:46:302918 } else {
[email protected]8eee29c2010-04-29 03:38:292919 SetGLError(GL_INVALID_VALUE,
2920 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302921 }
2922}
2923
2924void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]f39f4b3f2010-05-12 17:04:082925 if (vertex_attrib_manager_.Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:302926 glEnableVertexAttribArray(index);
2927 } else {
[email protected]8eee29c2010-04-29 03:38:292928 SetGLError(GL_INVALID_VALUE,
2929 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:302930 }
2931}
2932
[email protected]a93bb842010-02-16 23:03:472933void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:502934 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]915a59a12010-09-30 21:29:112935 if (!info || !texture_manager()->MarkMipmapsGenerated(feature_info_, info)) {
[email protected]8eee29c2010-04-29 03:38:292936 SetGLError(GL_INVALID_OPERATION,
2937 "glGenerateMipmaps: Can not generate mips for npot textures");
[email protected]a93bb842010-02-16 23:03:472938 return;
2939 }
[email protected]59f3ca02011-03-26 22:24:192940 // Workaround for Mac driver bug. In the large scheme of things setting
2941 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
2942 // hit so there's probably no need to make this conditional.
2943 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
[email protected]a93bb842010-02-16 23:03:472944 glGenerateMipmapEXT(target);
[email protected]59f3ca02011-03-26 22:24:192945 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
[email protected]a93bb842010-02-16 23:03:472946}
2947
[email protected]b273e432010-04-12 17:23:582948bool GLES2DecoderImpl::GetHelper(
2949 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:582950 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:152951 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2952 switch (pname) {
[email protected]b273e432010-04-12 17:23:582953 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2954 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102955 if (params) {
[email protected]5094b0f2010-11-09 19:45:242956 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:102957 }
[email protected]b273e432010-04-12 17:23:582958 return true;
2959 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2960 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102961 if (params) {
[email protected]5094b0f2010-11-09 19:45:242962 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:102963 }
[email protected]b273e432010-04-12 17:23:582964 return true;
2965 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
2966 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102967 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482968 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102969 }
[email protected]b273e432010-04-12 17:23:582970 return true;
2971 case GL_MAX_VARYING_VECTORS:
2972 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102973 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482974 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:102975 }
[email protected]b273e432010-04-12 17:23:582976 return true;
2977 case GL_MAX_VERTEX_UNIFORM_VECTORS:
2978 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:102979 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:482980 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:102981 }
[email protected]b273e432010-04-12 17:23:582982 return true;
[email protected]5094b0f2010-11-09 19:45:242983 case GL_MAX_VIEWPORT_DIMS:
2984 if (offscreen_target_frame_buffer_.get()) {
2985 *num_written = 2;
2986 if (params) {
2987 params[0] = renderbuffer_manager()->max_renderbuffer_size();
2988 params[1] = renderbuffer_manager()->max_renderbuffer_size();
2989 }
2990 return true;
2991 }
[email protected]b9363b22010-06-09 22:06:152992 }
2993 }
2994 switch (pname) {
[email protected]297ca1c2011-06-20 23:08:462995 case GL_COLOR_WRITEMASK:
2996 *num_written = 4;
2997 if (params) {
2998 params[0] = mask_red_;
2999 params[1] = mask_green_;
3000 params[2] = mask_blue_;
3001 params[3] = mask_alpha_;
3002 }
3003 return true;
3004 case GL_DEPTH_WRITEMASK:
3005 *num_written = 1;
3006 if (params) {
3007 params[0] = mask_depth_;
3008 }
3009 return true;
3010 case GL_STENCIL_BACK_WRITEMASK:
3011 *num_written = 1;
3012 if (params) {
3013 params[0] = mask_stencil_back_;
3014 }
3015 return true;
3016 case GL_STENCIL_WRITEMASK:
3017 *num_written = 1;
3018 if (params) {
3019 params[0] = mask_stencil_front_;
3020 }
3021 return true;
3022 case GL_DEPTH_TEST:
3023 *num_written = 1;
3024 if (params) {
3025 params[0] = enable_depth_test_;
3026 }
3027 return true;
3028 case GL_STENCIL_TEST:
3029 *num_written = 1;
3030 if (params) {
3031 params[0] = enable_stencil_test_;
3032 }
3033 return true;
3034 case GL_ALPHA_BITS:
3035 *num_written = 1;
3036 if (params) {
3037 GLint v = 0;
3038 glGetIntegerv(GL_ALPHA_BITS, &v);
3039 params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0;
3040 }
3041 return true;
3042 case GL_DEPTH_BITS:
3043 *num_written = 1;
3044 if (params) {
3045 GLint v = 0;
3046 glGetIntegerv(GL_DEPTH_BITS, &v);
3047 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
3048 }
3049 return true;
3050 case GL_STENCIL_BITS:
3051 *num_written = 1;
3052 if (params) {
3053 GLint v = 0;
3054 glGetIntegerv(GL_STENCIL_BITS, &v);
3055 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
3056 }
3057 return true;
[email protected]656dcaad2010-05-07 17:18:373058 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113059 *num_written = validators_->compressed_texture_format.GetValues().size();
3060 if (params) {
3061 for (GLint ii = 0; ii < *num_written; ++ii) {
3062 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
3063 }
3064 }
[email protected]656dcaad2010-05-07 17:18:373065 return true;
[email protected]b273e432010-04-12 17:23:583066 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
3067 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103068 if (params) {
[email protected]302ce6d2011-07-07 23:28:113069 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103070 }
[email protected]b273e432010-04-12 17:23:583071 return true;
3072 case GL_NUM_SHADER_BINARY_FORMATS:
3073 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103074 if (params) {
[email protected]302ce6d2011-07-07 23:28:113075 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103076 }
[email protected]b273e432010-04-12 17:23:583077 return true;
3078 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113079 *num_written = validators_->shader_binary_format.GetValues().size();
3080 if (params) {
3081 for (GLint ii = 0; ii < *num_written; ++ii) {
3082 params[ii] = validators_->shader_binary_format.GetValues()[ii];
3083 }
3084 }
3085 return true;
[email protected]b273e432010-04-12 17:23:583086 case GL_SHADER_COMPILER:
3087 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103088 if (params) {
3089 *params = GL_TRUE;
3090 }
[email protected]b273e432010-04-12 17:23:583091 return true;
[email protected]6b8cf1a2010-05-06 16:13:583092 case GL_ARRAY_BUFFER_BINDING:
3093 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103094 if (params) {
3095 if (bound_array_buffer_) {
3096 GLuint client_id = 0;
3097 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
3098 &client_id);
3099 *params = client_id;
3100 } else {
3101 *params = 0;
3102 }
[email protected]6b8cf1a2010-05-06 16:13:583103 }
3104 return true;
3105 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3106 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103107 if (params) {
3108 if (bound_element_array_buffer_) {
3109 GLuint client_id = 0;
3110 buffer_manager()->GetClientId(
3111 bound_element_array_buffer_->service_id(),
3112 &client_id);
3113 *params = client_id;
3114 } else {
3115 *params = 0;
3116 }
[email protected]6b8cf1a2010-05-06 16:13:583117 }
3118 return true;
3119 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:303120 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:583121 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103122 if (params) {
[email protected]8e3e0662010-08-23 18:46:303123 if (bound_draw_framebuffer_) {
[email protected]4e8a5b122010-05-08 22:00:103124 GLuint client_id = 0;
3125 framebuffer_manager()->GetClientId(
[email protected]8e3e0662010-08-23 18:46:303126 bound_draw_framebuffer_->service_id(), &client_id);
3127 *params = client_id;
3128 } else {
3129 *params = 0;
3130 }
3131 }
3132 return true;
3133 case GL_READ_FRAMEBUFFER_BINDING:
3134 *num_written = 1;
3135 if (params) {
3136 if (bound_read_framebuffer_) {
3137 GLuint client_id = 0;
3138 framebuffer_manager()->GetClientId(
3139 bound_read_framebuffer_->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103140 *params = client_id;
3141 } else {
3142 *params = 0;
3143 }
[email protected]6b8cf1a2010-05-06 16:13:583144 }
3145 return true;
3146 case GL_RENDERBUFFER_BINDING:
3147 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103148 if (params) {
3149 if (bound_renderbuffer_) {
3150 GLuint client_id = 0;
3151 renderbuffer_manager()->GetClientId(
3152 bound_renderbuffer_->service_id(), &client_id);
3153 *params = client_id;
3154 } else {
3155 *params = 0;
3156 }
[email protected]6b8cf1a2010-05-06 16:13:583157 }
3158 return true;
3159 case GL_CURRENT_PROGRAM:
3160 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103161 if (params) {
3162 if (current_program_) {
3163 GLuint client_id = 0;
3164 program_manager()->GetClientId(
3165 current_program_->service_id(), &client_id);
3166 *params = client_id;
3167 } else {
3168 *params = 0;
3169 }
[email protected]6b8cf1a2010-05-06 16:13:583170 }
3171 return true;
[email protected]4e8a5b122010-05-08 22:00:103172 case GL_TEXTURE_BINDING_2D:
3173 *num_written = 1;
3174 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583175 TextureUnit& unit = texture_units_[active_texture_unit_];
3176 if (unit.bound_texture_2d) {
3177 GLuint client_id = 0;
3178 texture_manager()->GetClientId(
3179 unit.bound_texture_2d->service_id(), &client_id);
3180 *params = client_id;
3181 } else {
3182 *params = 0;
3183 }
[email protected]6b8cf1a2010-05-06 16:13:583184 }
[email protected]4e8a5b122010-05-08 22:00:103185 return true;
3186 case GL_TEXTURE_BINDING_CUBE_MAP:
3187 *num_written = 1;
3188 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583189 TextureUnit& unit = texture_units_[active_texture_unit_];
3190 if (unit.bound_texture_cube_map) {
3191 GLuint client_id = 0;
3192 texture_manager()->GetClientId(
3193 unit.bound_texture_cube_map->service_id(), &client_id);
3194 *params = client_id;
3195 } else {
3196 *params = 0;
3197 }
[email protected]6b8cf1a2010-05-06 16:13:583198 }
[email protected]4e8a5b122010-05-08 22:00:103199 return true;
[email protected]61eeb33f2011-07-26 15:30:313200 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3201 *num_written = 1;
3202 if (params) {
3203 TextureUnit& unit = texture_units_[active_texture_unit_];
3204 if (unit.bound_texture_external_oes) {
3205 GLuint client_id = 0;
3206 texture_manager()->GetClientId(
3207 unit.bound_texture_external_oes->service_id(), &client_id);
3208 *params = client_id;
3209 } else {
3210 *params = 0;
3211 }
3212 }
3213 return true;
[email protected]b273e432010-04-12 17:23:583214 default:
[email protected]4e8a5b122010-05-08 22:00:103215 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533216 return false;
[email protected]b273e432010-04-12 17:23:583217 }
3218}
3219
[email protected]4e8a5b122010-05-08 22:00:103220bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3221 GLenum pname, GLsizei* num_values) {
3222 return GetHelper(pname, NULL, num_values);
3223}
3224
[email protected]b273e432010-04-12 17:23:583225void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3226 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103227 GLsizei num_written = 0;
3228 if (GetHelper(pname, NULL, &num_written)) {
3229 scoped_array<GLint> values(new GLint[num_written]);
3230 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583231 for (GLsizei ii = 0; ii < num_written; ++ii) {
3232 params[ii] = static_cast<GLboolean>(values[ii]);
3233 }
3234 } else {
3235 glGetBooleanv(pname, params);
3236 }
3237}
3238
3239void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3240 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103241 GLsizei num_written = 0;
3242 if (GetHelper(pname, NULL, &num_written)) {
3243 scoped_array<GLint> values(new GLint[num_written]);
3244 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583245 for (GLsizei ii = 0; ii < num_written; ++ii) {
3246 params[ii] = static_cast<GLfloat>(values[ii]);
3247 }
3248 } else {
3249 glGetFloatv(pname, params);
3250 }
3251}
3252
3253void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3254 DCHECK(params);
3255 GLsizei num_written;
3256 if (!GetHelper(pname, params, &num_written)) {
3257 glGetIntegerv(pname, params);
3258 }
3259}
3260
[email protected]a0c3e972010-04-21 00:49:133261void GLES2DecoderImpl::DoGetProgramiv(
3262 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583263 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3264 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133265 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133266 return;
3267 }
3268 info->GetProgramiv(pname, params);
3269}
3270
[email protected]558847a2010-03-24 07:02:543271error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3272 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
[email protected]6b8cf1a2010-05-06 16:13:583273 GLuint program = static_cast<GLuint>(c.program);
3274 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3275 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033276 if (!info) {
[email protected]558847a2010-03-24 07:02:543277 return error::kNoError;
3278 }
3279 GLuint index = static_cast<GLuint>(c.index);
3280 uint32 name_size = c.data_size;
3281 const char* name = GetSharedMemoryAs<const char*>(
3282 c.name_shm_id, c.name_shm_offset, name_size);
3283 if (name == NULL) {
3284 return error::kOutOfBounds;
3285 }
3286 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033287 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543288 return error::kNoError;
3289}
3290
3291error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3292 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583293 GLuint program = static_cast<GLuint>(c.program);
3294 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3295 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033296 if (!info) {
[email protected]558847a2010-03-24 07:02:543297 return error::kNoError;
3298 }
3299 GLuint index = static_cast<GLuint>(c.index);
3300 uint32 name_size = c.data_size;
3301 const char* name = GetImmediateDataAs<const char*>(
3302 c, name_size, immediate_data_size);
3303 if (name == NULL) {
3304 return error::kOutOfBounds;
3305 }
3306 String name_str(name, name_size);
[email protected]ae51d192010-04-27 00:48:033307 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543308 return error::kNoError;
3309}
3310
3311error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3312 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583313 GLuint program = static_cast<GLuint>(c.program);
3314 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3315 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033316 if (!info) {
[email protected]558847a2010-03-24 07:02:543317 return error::kNoError;
3318 }
3319 GLuint index = static_cast<GLuint>(c.index);
3320 Bucket* bucket = GetBucket(c.name_bucket_id);
3321 if (!bucket || bucket->size() == 0) {
3322 return error::kInvalidArguments;
3323 }
3324 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183325 if (!bucket->GetAsString(&name_str)) {
3326 return error::kInvalidArguments;
3327 }
[email protected]ae51d192010-04-27 00:48:033328 glBindAttribLocation(info->service_id(), index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543329 return error::kNoError;
3330}
3331
[email protected]f7a64ee2010-02-01 22:24:143332error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463333 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033334 GLuint client_id = c.shader;
3335 if (client_id) {
3336 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3337 if (info) {
[email protected]ca488e12010-12-13 20:06:143338 if (!info->IsDeleted()) {
3339 glDeleteShader(info->service_id());
3340 shader_manager()->MarkAsDeleted(info);
3341 }
[email protected]ae51d192010-04-27 00:48:033342 } else {
[email protected]8eee29c2010-04-29 03:38:293343 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033344 }
[email protected]96449d2c2009-11-25 00:01:323345 }
[email protected]f7a64ee2010-02-01 22:24:143346 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323347}
3348
[email protected]f7a64ee2010-02-01 22:24:143349error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463350 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033351 GLuint client_id = c.program;
3352 if (client_id) {
3353 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3354 if (info) {
[email protected]ca488e12010-12-13 20:06:143355 if (!info->IsDeleted()) {
3356 glDeleteProgram(info->service_id());
3357 program_manager()->MarkAsDeleted(shader_manager(), info);
3358 }
[email protected]ae51d192010-04-27 00:48:033359 } else {
[email protected]8eee29c2010-04-29 03:38:293360 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033361 }
[email protected]96449d2c2009-11-25 00:01:323362 }
[email protected]f7a64ee2010-02-01 22:24:143363 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323364}
3365
[email protected]269200b12010-11-18 22:53:063366void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103367 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573368 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103369 for (GLsizei ii = 0; ii < n; ++ii) {
3370 id_allocator->FreeID(ids[ii]);
3371 }
3372}
3373
[email protected]269200b12010-11-18 22:53:063374error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
3375 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103376 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3377 GLsizei n = static_cast<GLsizei>(c.n);
3378 uint32 data_size;
3379 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3380 return error::kOutOfBounds;
3381 }
3382 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3383 c.ids_shm_id, c.ids_shm_offset, data_size);
3384 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063385 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103386 return error::kNoError;
3387 }
3388 if (ids == NULL) {
3389 return error::kOutOfBounds;
3390 }
[email protected]269200b12010-11-18 22:53:063391 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103392 return error::kNoError;
3393}
3394
[email protected]269200b12010-11-18 22:53:063395void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103396 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573397 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103398 if (id_offset == 0) {
3399 for (GLsizei ii = 0; ii < n; ++ii) {
3400 ids[ii] = id_allocator->AllocateID();
3401 }
3402 } else {
3403 for (GLsizei ii = 0; ii < n; ++ii) {
3404 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
3405 id_offset = ids[ii] + 1;
3406 }
3407 }
3408}
3409
[email protected]269200b12010-11-18 22:53:063410error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
3411 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103412 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3413 GLuint id_offset = static_cast<GLuint>(c.id_offset);
3414 GLsizei n = static_cast<GLsizei>(c.n);
3415 uint32 data_size;
3416 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3417 return error::kOutOfBounds;
3418 }
3419 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3420 c.ids_shm_id, c.ids_shm_offset, data_size);
3421 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063422 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103423 return error::kNoError;
3424 }
3425 if (ids == NULL) {
3426 return error::kOutOfBounds;
3427 }
[email protected]269200b12010-11-18 22:53:063428 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:103429 return error::kNoError;
3430}
3431
[email protected]269200b12010-11-18 22:53:063432void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103433 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573434 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103435 for (GLsizei ii = 0; ii < n; ++ii) {
3436 if (!id_allocator->MarkAsUsed(ids[ii])) {
3437 for (GLsizei jj = 0; jj < ii; ++jj) {
3438 id_allocator->FreeID(ids[jj]);
3439 }
3440 SetGLError(
3441 GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:063442 "RegisterSharedIdsCHROMIUM: attempt to register "
3443 "id that already exists");
[email protected]066849e32010-05-03 19:14:103444 return;
3445 }
3446 }
3447}
3448
[email protected]269200b12010-11-18 22:53:063449error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
3450 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103451 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3452 GLsizei n = static_cast<GLsizei>(c.n);
3453 uint32 data_size;
3454 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3455 return error::kOutOfBounds;
3456 }
3457 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3458 c.ids_shm_id, c.ids_shm_offset, data_size);
3459 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063460 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103461 return error::kNoError;
3462 }
3463 if (ids == NULL) {
3464 return error::kOutOfBounds;
3465 }
[email protected]269200b12010-11-18 22:53:063466 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103467 return error::kNoError;
3468}
3469
[email protected]3a03a8f2011-03-19 00:51:273470void GLES2DecoderImpl::DoClear(GLbitfield mask) {
3471 if (CheckFramebufferComplete("glClear")) {
[email protected]297ca1c2011-06-20 23:08:463472 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:273473 glClear(mask);
3474 }
3475}
3476
[email protected]36cef8ce2010-03-16 07:34:453477void GLES2DecoderImpl::DoFramebufferRenderbuffer(
3478 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:033479 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:303480 FramebufferManager::FramebufferInfo* framebuffer_info =
3481 GetFramebufferInfoForTarget(target);
3482 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293483 SetGLError(GL_INVALID_OPERATION,
3484 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453485 return;
3486 }
[email protected]ae51d192010-04-27 00:48:033487 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283488 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033489 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283490 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:033491 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293492 SetGLError(GL_INVALID_OPERATION,
3493 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:033494 return;
3495 }
3496 service_id = info->service_id();
3497 }
[email protected]9edc6b22010-12-23 02:00:263498 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033499 glFramebufferRenderbufferEXT(
3500 target, attachment, renderbuffertarget, service_id);
[email protected]1002c2d2011-06-28 22:39:043501 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263502 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:303503 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]9edc6b22010-12-23 02:00:263504 if (service_id == 0 ||
3505 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
3506 if (info) {
3507 ClearUnclearedRenderbuffers(target, framebuffer_info);
3508 }
[email protected]3a2e7c7b2010-08-06 01:12:283509 }
3510 }
[email protected]297ca1c2011-06-20 23:08:463511 if (framebuffer_info == bound_draw_framebuffer_) {
3512 state_dirty_ = true;
3513 }
[email protected]3a2e7c7b2010-08-06 01:12:283514}
3515
[email protected]297ca1c2011-06-20 23:08:463516bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
[email protected]3a2e7c7b2010-08-06 01:12:283517 switch (cap) {
3518 case GL_SCISSOR_TEST:
3519 enable_scissor_test_ = enabled;
[email protected]297ca1c2011-06-20 23:08:463520 return true;
3521 case GL_DEPTH_TEST: {
3522 if (enable_depth_test_ != enabled) {
3523 enable_depth_test_ = enabled;
3524 state_dirty_ = true;
3525 }
3526 return false;
3527 }
3528 case GL_STENCIL_TEST:
3529 if (enable_stencil_test_ != enabled) {
3530 enable_stencil_test_ = enabled;
3531 state_dirty_ = true;
3532 }
3533 return false;
[email protected]3a2e7c7b2010-08-06 01:12:283534 default:
[email protected]297ca1c2011-06-20 23:08:463535 return true;
[email protected]3a2e7c7b2010-08-06 01:12:283536 }
3537}
3538
3539void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:463540 if (SetCapabilityState(cap, false)) {
3541 glDisable(cap);
3542 }
[email protected]3a2e7c7b2010-08-06 01:12:283543}
3544
3545void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:463546 if (SetCapabilityState(cap, true)) {
3547 glEnable(cap);
3548 }
[email protected]3a2e7c7b2010-08-06 01:12:283549}
3550
3551void GLES2DecoderImpl::DoClearColor(
3552 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
3553 clear_red_ = red;
3554 clear_green_ = green;
3555 clear_blue_ = blue;
3556 clear_alpha_ = alpha;
3557 glClearColor(red, green, blue, alpha);
3558}
3559
3560void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
3561 clear_depth_ = depth;
3562 glClearDepth(depth);
3563}
3564
3565void GLES2DecoderImpl::DoClearStencil(GLint s) {
3566 clear_stencil_ = s;
3567 glClearStencil(s);
3568}
3569
3570void GLES2DecoderImpl::DoColorMask(
3571 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
3572 mask_red_ = red;
3573 mask_green_ = green;
3574 mask_blue_ = blue;
3575 mask_alpha_ = alpha;
[email protected]297ca1c2011-06-20 23:08:463576 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283577}
3578
3579void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
3580 mask_depth_ = depth;
[email protected]297ca1c2011-06-20 23:08:463581 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283582}
3583
3584void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
3585 mask_stencil_front_ = mask;
3586 mask_stencil_back_ = mask;
[email protected]297ca1c2011-06-20 23:08:463587 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283588}
3589
3590void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
[email protected]297ca1c2011-06-20 23:08:463591 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:283592 mask_stencil_front_ = mask;
[email protected]297ca1c2011-06-20 23:08:463593 }
3594 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:283595 mask_stencil_back_ = mask;
3596 }
[email protected]297ca1c2011-06-20 23:08:463597 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283598}
3599
3600// NOTE: There's an assumption here that Texture attachments
3601// are cleared because they are textures so we only need to clear
3602// the renderbuffers.
3603void GLES2DecoderImpl::ClearUnclearedRenderbuffers(
[email protected]8e3e0662010-08-23 18:46:303604 GLenum target, FramebufferManager::FramebufferInfo* info) {
3605 if (target == GL_READ_FRAMEBUFFER_EXT) {
3606 // TODO(gman): bind this to the DRAW point, clear then bind back to READ
3607 }
[email protected]3a2e7c7b2010-08-06 01:12:283608 GLbitfield clear_bits = 0;
3609 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:463610 glClearColor(
3611 0, 0, 0,
3612 (GLES2Util::GetChannelsForFormat(
3613 info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0 : 1);
[email protected]3a2e7c7b2010-08-06 01:12:283614 glColorMask(true, true, true, true);
3615 clear_bits |= GL_COLOR_BUFFER_BIT;
3616 }
3617
3618 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
3619 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3620 glClearStencil(0);
3621 glStencilMask(-1);
3622 clear_bits |= GL_STENCIL_BUFFER_BIT;
3623 }
3624
3625 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
3626 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
3627 glClearDepth(1.0f);
3628 glDepthMask(true);
3629 clear_bits |= GL_DEPTH_BUFFER_BIT;
3630 }
3631
3632 glDisable(GL_SCISSOR_TEST);
3633 glClear(clear_bits);
3634
3635 info->MarkAttachedRenderbuffersAsCleared();
3636
[email protected]c007aa02010-09-02 22:22:403637 RestoreClearState();
3638
3639 if (target == GL_READ_FRAMEBUFFER_EXT) {
3640 // TODO(gman): rebind draw.
3641 }
3642}
3643
3644void GLES2DecoderImpl::RestoreClearState() {
[email protected]297ca1c2011-06-20 23:08:463645 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:283646 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
[email protected]3a2e7c7b2010-08-06 01:12:283647 glClearStencil(clear_stencil_);
[email protected]3a2e7c7b2010-08-06 01:12:283648 glClearDepth(clear_depth_);
[email protected]3a2e7c7b2010-08-06 01:12:283649 if (enable_scissor_test_) {
3650 glEnable(GL_SCISSOR_TEST);
3651 }
[email protected]36cef8ce2010-03-16 07:34:453652}
3653
3654GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]8e3e0662010-08-23 18:46:303655 FramebufferManager::FramebufferInfo* info =
3656 GetFramebufferInfoForTarget(target);
3657 if (!info) {
[email protected]36cef8ce2010-03-16 07:34:453658 return GL_FRAMEBUFFER_COMPLETE;
3659 }
3660 return glCheckFramebufferStatusEXT(target);
3661}
3662
3663void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:033664 GLenum target, GLenum attachment, GLenum textarget,
3665 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:303666 FramebufferManager::FramebufferInfo* framebuffer_info =
3667 GetFramebufferInfoForTarget(target);
3668 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293669 SetGLError(GL_INVALID_OPERATION,
3670 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:453671 return;
3672 }
[email protected]ae51d192010-04-27 00:48:033673 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283674 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033675 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283676 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:033677 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293678 SetGLError(GL_INVALID_OPERATION,
3679 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:033680 return;
3681 }
3682 service_id = info->service_id();
3683 }
[email protected]9edc6b22010-12-23 02:00:263684 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:033685 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]1002c2d2011-06-28 22:39:043686 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263687 if (error == GL_NO_ERROR) {
3688 framebuffer_info->AttachTexture(attachment, info, textarget, level);
3689 if (service_id != 0 &&
3690 glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
3691 ClearUnclearedRenderbuffers(target, framebuffer_info);
3692 }
[email protected]3a2e7c7b2010-08-06 01:12:283693 }
[email protected]297ca1c2011-06-20 23:08:463694 if (framebuffer_info == bound_draw_framebuffer_) {
3695 state_dirty_ = true;
3696 }
[email protected]36cef8ce2010-03-16 07:34:453697}
3698
3699void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
3700 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:303701 FramebufferManager::FramebufferInfo* framebuffer_info =
3702 GetFramebufferInfoForTarget(target);
3703 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293704 SetGLError(GL_INVALID_OPERATION,
3705 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453706 return;
3707 }
3708 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:573709 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
3710 GLint type = 0;
3711 GLuint client_id = 0;
3712 glGetFramebufferAttachmentParameterivEXT(
3713 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
3714 switch (type) {
3715 case GL_RENDERBUFFER: {
3716 renderbuffer_manager()->GetClientId(*params, &client_id);
3717 break;
3718 }
3719 case GL_TEXTURE: {
3720 texture_manager()->GetClientId(*params, &client_id);
3721 break;
3722 }
3723 default:
3724 break;
3725 }
3726 *params = client_id;
3727 }
[email protected]36cef8ce2010-03-16 07:34:453728}
3729
3730void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
3731 GLenum target, GLenum pname, GLint* params) {
[email protected]051b1372010-04-12 02:42:083732 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293733 SetGLError(GL_INVALID_OPERATION,
3734 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453735 return;
3736 }
[email protected]3a03a8f2011-03-19 00:51:273737 switch (pname) {
3738 case GL_RENDERBUFFER_INTERNAL_FORMAT:
[email protected]b71f52c2010-06-18 22:20:203739 *params = bound_renderbuffer_->internal_format();
[email protected]3a03a8f2011-03-19 00:51:273740 break;
3741 case GL_RENDERBUFFER_WIDTH:
3742 *params = bound_renderbuffer_->width();
3743 break;
3744 case GL_RENDERBUFFER_HEIGHT:
3745 *params = bound_renderbuffer_->height();
3746 break;
3747 default:
3748 glGetRenderbufferParameterivEXT(target, pname, params);
3749 break;
[email protected]b71f52c2010-06-18 22:20:203750 }
[email protected]36cef8ce2010-03-16 07:34:453751}
3752
[email protected]8e3e0662010-08-23 18:46:303753void GLES2DecoderImpl::DoBlitFramebufferEXT(
3754 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
3755 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
3756 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:393757 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303758 SetGLError(GL_INVALID_OPERATION,
3759 "glBlitFramebufferEXT: function not available");
3760 }
[email protected]5094b0f2010-11-09 19:45:243761 if (IsAngle()) {
3762 glBlitFramebufferANGLE(
3763 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3764 } else {
3765 glBlitFramebufferEXT(
3766 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
3767 }
[email protected]8e3e0662010-08-23 18:46:303768}
3769
3770void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
3771 GLenum target, GLsizei samples, GLenum internalformat,
3772 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:393773 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:303774 SetGLError(GL_INVALID_OPERATION,
3775 "glRenderbufferStorageMultisampleEXT: function not available");
3776 return;
3777 }
[email protected]8e3e0662010-08-23 18:46:303778
[email protected]9edc6b22010-12-23 02:00:263779 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:303780 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:263781 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:303782 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:263783 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:303784 break;
3785 case GL_RGBA4:
3786 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:263787 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:303788 break;
3789 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:263790 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:303791 break;
3792 }
3793 }
3794
[email protected]9edc6b22010-12-23 02:00:263795 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:083796 if (IsAngle()) {
3797 glRenderbufferStorageMultisampleANGLE(
3798 target, samples, impl_format, width, height);
3799 } else {
3800 glRenderbufferStorageMultisampleEXT(
3801 target, samples, impl_format, width, height);
3802 }
[email protected]1002c2d2011-06-28 22:39:043803 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263804 if (error == GL_NO_ERROR) {
3805 bound_renderbuffer_->SetInfo(samples, internalformat, width, height);
3806 }
[email protected]8e3e0662010-08-23 18:46:303807}
3808
[email protected]36cef8ce2010-03-16 07:34:453809void GLES2DecoderImpl::DoRenderbufferStorage(
3810 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]051b1372010-04-12 02:42:083811 if (!bound_renderbuffer_) {
[email protected]8eee29c2010-04-29 03:38:293812 SetGLError(GL_INVALID_OPERATION,
3813 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453814 return;
3815 }
[email protected]876f6fee2010-08-02 23:10:323816
[email protected]9edc6b22010-12-23 02:00:263817 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:323818 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:263819 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:323820 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:263821 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:323822 break;
3823 case GL_RGBA4:
3824 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:263825 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:323826 break;
3827 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:263828 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:323829 break;
3830 }
[email protected]b71f52c2010-06-18 22:20:203831 }
[email protected]876f6fee2010-08-02 23:10:323832
[email protected]9edc6b22010-12-23 02:00:263833 CopyRealGLErrorsToWrapper();
3834 glRenderbufferStorageEXT(target, impl_format, width, height);
[email protected]1002c2d2011-06-28 22:39:043835 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:263836 if (error == GL_NO_ERROR) {
3837 bound_renderbuffer_->SetInfo(0, internalformat, width, height);
3838 }
[email protected]36cef8ce2010-03-16 07:34:453839}
3840
[email protected]07f54fcc2009-12-22 02:46:303841void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]0c8fabf2011-06-14 19:35:223842 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]6b8cf1a2010-05-06 16:13:583843 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3844 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:473845 if (!info) {
[email protected]a93bb842010-02-16 23:03:473846 return;
3847 }
[email protected]05afda12011-01-20 00:17:343848
[email protected]d685a682011-04-29 16:19:573849 info->Link();
[email protected]07f54fcc2009-12-22 02:46:303850};
3851
[email protected]3916c97e2010-02-25 03:20:503852void GLES2DecoderImpl::DoTexParameterf(
3853 GLenum target, GLenum pname, GLfloat param) {
3854 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:303855 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293856 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243857 return;
[email protected]07f54fcc2009-12-22 02:46:303858 }
[email protected]cbb22e42011-05-12 23:36:243859
3860 if (!texture_manager()->SetParameter(
3861 feature_info_, info, pname, static_cast<GLint>(param))) {
3862 SetGLError(GL_INVALID_ENUM, "glTexParameterf: param GL_INVALID_ENUM");
3863 return;
3864 }
3865 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:303866}
3867
[email protected]3916c97e2010-02-25 03:20:503868void GLES2DecoderImpl::DoTexParameteri(
3869 GLenum target, GLenum pname, GLint param) {
3870 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3871 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293872 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243873 return;
[email protected]3916c97e2010-02-25 03:20:503874 }
[email protected]cbb22e42011-05-12 23:36:243875
3876 if (!texture_manager()->SetParameter(feature_info_, info, pname, param)) {
3877 SetGLError(GL_INVALID_ENUM, "glTexParameteri: param GL_INVALID_ENUM");
3878 return;
3879 }
3880 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:503881}
3882
3883void GLES2DecoderImpl::DoTexParameterfv(
3884 GLenum target, GLenum pname, const GLfloat* params) {
3885 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3886 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293887 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243888 return;
[email protected]3916c97e2010-02-25 03:20:503889 }
[email protected]cbb22e42011-05-12 23:36:243890
3891 if (!texture_manager()->SetParameter(
3892 feature_info_, info, pname, static_cast<GLint>(params[0]))) {
3893 SetGLError(GL_INVALID_ENUM, "glTexParameterfv: param GL_INVALID_ENUM");
3894 return;
3895 }
3896 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:503897}
3898
3899void GLES2DecoderImpl::DoTexParameteriv(
3900 GLenum target, GLenum pname, const GLint* params) {
3901 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
3902 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293903 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:243904 return;
[email protected]3916c97e2010-02-25 03:20:503905 }
[email protected]cbb22e42011-05-12 23:36:243906
3907 if (!texture_manager()->SetParameter(feature_info_, info, pname, *params)) {
3908 SetGLError(GL_INVALID_ENUM, "glTexParameteriv: param GL_INVALID_ENUM");
3909 return;
3910 }
3911 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:503912}
3913
[email protected]939e7362010-05-13 20:49:103914bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:143915 if (!current_program_) {
[email protected]939e7362010-05-13 20:49:103916 // The program does not exist.
3917 SetGLError(GL_INVALID_OPERATION,
3918 (std::string(function_name) + ": no program in use").c_str());
3919 return false;
3920 }
[email protected]ca488e12010-12-13 20:06:143921 if (!current_program_->InUse()) {
[email protected]939e7362010-05-13 20:49:103922 SetGLError(GL_INVALID_OPERATION,
3923 (std::string(function_name) + ": program not linked").c_str());
3924 return false;
3925 }
3926 return true;
3927}
3928
3929bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
3930 GLint location, const char* function_name) {
3931 if (!CheckCurrentProgram(function_name)) {
3932 return false;
3933 }
3934 return location != -1;
3935}
3936
[email protected]43c2f1f2011-03-25 18:35:363937bool GLES2DecoderImpl::PrepForSetUniformByLocation(
3938 GLint location, const char* function_name, GLenum* type, GLsizei* count) {
3939 DCHECK(type);
3940 DCHECK(count);
[email protected]939e7362010-05-13 20:49:103941 if (!CheckCurrentProgramForUniform(location, function_name)) {
3942 return false;
3943 }
[email protected]43c2f1f2011-03-25 18:35:363944 GLint array_index = -1;
3945 const ProgramManager::ProgramInfo::UniformInfo* info =
3946 current_program_->GetUniformInfoByLocation(location, &array_index);
3947 if (!info) {
[email protected]939e7362010-05-13 20:49:103948 SetGLError(GL_INVALID_OPERATION,
[email protected]43c2f1f2011-03-25 18:35:363949 (std::string(function_name) + ": unknown location").c_str());
[email protected]939e7362010-05-13 20:49:103950 return false;
3951 }
[email protected]43c2f1f2011-03-25 18:35:363952 if (*count > 1 && !info->is_array) {
3953 SetGLError(
3954 GL_INVALID_OPERATION,
3955 (std::string(function_name) + ": count > 1 for non-array").c_str());
3956 return false;
3957 }
3958 *count = std::min(info->size - array_index, *count);
3959 if (*count <= 0) {
3960 return false;
3961 }
3962 *type = info->type;
[email protected]939e7362010-05-13 20:49:103963 return true;
3964}
3965
[email protected]939e7362010-05-13 20:49:103966void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
3967 if (!CheckCurrentProgramForUniform(location, "glUniform1i")) {
[email protected]3916c97e2010-02-25 03:20:503968 return;
3969 }
3970 current_program_->SetSamplers(location, 1, &v0);
3971 glUniform1i(location, v0);
3972}
3973
3974void GLES2DecoderImpl::DoUniform1iv(
3975 GLint location, GLsizei count, const GLint *value) {
[email protected]939e7362010-05-13 20:49:103976 if (!CheckCurrentProgramForUniform(location, "glUniform1iv")) {
[email protected]3916c97e2010-02-25 03:20:503977 return;
3978 }
[email protected]43c2f1f2011-03-25 18:35:363979 GLenum type = 0;
3980 if (!PrepForSetUniformByLocation(location, "glUniform1iv", &type, &count)) {
3981 return;
3982 }
[email protected]61eeb33f2011-07-26 15:30:313983 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
3984 type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]43c2f1f2011-03-25 18:35:363985 current_program_->SetSamplers(location, count, value);
3986 }
[email protected]3916c97e2010-02-25 03:20:503987 glUniform1iv(location, count, value);
3988}
3989
[email protected]939e7362010-05-13 20:49:103990void GLES2DecoderImpl::DoUniform1fv(
3991 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:363992 GLenum type = 0;
3993 if (!PrepForSetUniformByLocation(location, "glUniform1fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:103994 return;
3995 }
3996 if (type == GL_BOOL) {
3997 scoped_array<GLint> temp(new GLint[count]);
3998 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:533999 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104000 }
4001 DoUniform1iv(location, count, temp.get());
4002 } else {
4003 glUniform1fv(location, count, value);
4004 }
4005}
4006
4007void GLES2DecoderImpl::DoUniform2fv(
4008 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364009 GLenum type = 0;
4010 if (!PrepForSetUniformByLocation(location, "glUniform2fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104011 return;
4012 }
4013 if (type == GL_BOOL_VEC2) {
4014 GLsizei num_values = count * 2;
4015 scoped_array<GLint> temp(new GLint[num_values]);
4016 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534017 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104018 }
4019 glUniform2iv(location, count, temp.get());
4020 } else {
4021 glUniform2fv(location, count, value);
4022 }
4023}
4024
4025void GLES2DecoderImpl::DoUniform3fv(
4026 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364027 GLenum type = 0;
4028 if (!PrepForSetUniformByLocation(location, "glUniform3fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104029 return;
4030 }
4031 if (type == GL_BOOL_VEC3) {
4032 GLsizei num_values = count * 3;
4033 scoped_array<GLint> temp(new GLint[num_values]);
4034 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534035 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104036 }
4037 glUniform3iv(location, count, temp.get());
4038 } else {
4039 glUniform3fv(location, count, value);
4040 }
4041}
4042
4043void GLES2DecoderImpl::DoUniform4fv(
4044 GLint location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364045 GLenum type = 0;
4046 if (!PrepForSetUniformByLocation(location, "glUniform4fv", &type, &count)) {
[email protected]939e7362010-05-13 20:49:104047 return;
4048 }
4049 if (type == GL_BOOL_VEC4) {
4050 GLsizei num_values = count * 4;
4051 scoped_array<GLint> temp(new GLint[num_values]);
4052 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534053 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104054 }
4055 glUniform4iv(location, count, temp.get());
4056 } else {
4057 glUniform4fv(location, count, value);
4058 }
4059}
4060
[email protected]43c2f1f2011-03-25 18:35:364061void GLES2DecoderImpl::DoUniform2iv(
4062 GLint location, GLsizei count, const GLint* value) {
4063 GLenum type = 0;
4064 if (!PrepForSetUniformByLocation(location, "glUniform2iv", &type, &count)) {
4065 return;
4066 }
4067 glUniform2iv(location, count, value);
4068}
4069
4070void GLES2DecoderImpl::DoUniform3iv(
4071 GLint location, GLsizei count, const GLint* value) {
4072 GLenum type = 0;
4073 if (!PrepForSetUniformByLocation(location, "glUniform3iv", &type, &count)) {
4074 return;
4075 }
4076 glUniform3iv(location, count, value);
4077}
4078
4079void GLES2DecoderImpl::DoUniform4iv(
4080 GLint location, GLsizei count, const GLint* value) {
4081 GLenum type = 0;
4082 if (!PrepForSetUniformByLocation(location, "glUniform4iv", &type, &count)) {
4083 return;
4084 }
4085 glUniform4iv(location, count, value);
4086}
4087
4088void GLES2DecoderImpl::DoUniformMatrix2fv(
4089 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4090 GLenum type = 0;
4091 if (!PrepForSetUniformByLocation(
4092 location, "glUniformMatrix2fv", &type, &count)) {
4093 return;
4094 }
4095 glUniformMatrix2fv (location, count, transpose, value);
4096}
4097
4098void GLES2DecoderImpl::DoUniformMatrix3fv(
4099 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4100 GLenum type = 0;
4101 if (!PrepForSetUniformByLocation(
4102 location, "glUniformMatrix3fv", &type, &count)) {
4103 return;
4104 }
4105 glUniformMatrix3fv (location, count, transpose, value);
4106}
4107
4108void GLES2DecoderImpl::DoUniformMatrix4fv(
4109 GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
4110 GLenum type = 0;
4111 if (!PrepForSetUniformByLocation(
4112 location, "glUniformMatrix4fv", &type, &count)) {
4113 return;
4114 }
4115 glUniformMatrix4fv (location, count, transpose, value);
4116}
4117
[email protected]3916c97e2010-02-25 03:20:504118void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:034119 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:504120 ProgramManager::ProgramInfo* info = NULL;
4121 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:584122 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:504123 if (!info) {
[email protected]ae51d192010-04-27 00:48:034124 return;
4125 }
4126 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:504127 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:294128 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:504129 return;
4130 }
[email protected]ae51d192010-04-27 00:48:034131 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:504132 }
[email protected]ca488e12010-12-13 20:06:144133 if (current_program_) {
4134 program_manager()->UnuseProgram(shader_manager(), current_program_);
4135 }
[email protected]3916c97e2010-02-25 03:20:504136 current_program_ = info;
[email protected]ca488e12010-12-13 20:06:144137 if (current_program_) {
4138 program_manager()->UseProgram(current_program_);
4139 }
[email protected]ae51d192010-04-27 00:48:034140 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:504141}
4142
[email protected]96449d2c2009-11-25 00:01:324143GLenum GLES2DecoderImpl::GetGLError() {
4144 // Check the GL error first, then our wrapped error.
4145 GLenum error = glGetError();
4146 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:374147 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:324148 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:294149 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:324150 break;
4151 }
4152 }
4153 }
4154
4155 if (error != GL_NO_ERROR) {
4156 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:294157 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324158 }
4159 return error;
4160}
4161
[email protected]1002c2d2011-06-28 22:39:044162GLenum GLES2DecoderImpl::PeekGLError() {
4163 GLenum error = glGetError();
4164 if (error != GL_NO_ERROR) {
4165 SetGLError(error, "");
4166 }
4167 return error;
4168}
4169
[email protected]8eee29c2010-04-29 03:38:294170void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
4171 if (msg) {
4172 last_error_ = msg;
[email protected]d0498742010-09-20 20:27:014173 LOG(ERROR) << last_error_;
[email protected]8eee29c2010-04-29 03:38:294174 }
[email protected]ddd968b82010-03-02 00:44:294175 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324176}
4177
[email protected]07f54fcc2009-12-22 02:46:304178void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
4179 GLenum error;
4180 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294181 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:304182 }
4183}
4184
[email protected]6217d392010-03-25 22:08:354185void GLES2DecoderImpl::ClearRealGLErrors() {
4186 GLenum error;
4187 while ((error = glGetError()) != GL_NO_ERROR) {
4188 NOTREACHED() << "GL error " << error << " was unhandled.";
4189 }
4190}
4191
[email protected]ef526492010-06-02 23:12:254192bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:504193 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:254194 // Only check if there are some unrenderable textures.
4195 if (!texture_manager()->HaveUnrenderableTextures()) {
4196 return false;
4197 }
4198 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:504199 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4200 current_program_->sampler_indices();
4201 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4202 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4203 current_program_->GetUniformInfo(sampler_indices[ii]);
4204 DCHECK(uniform_info);
4205 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4206 GLuint texture_unit_index = uniform_info->texture_units[jj];
4207 if (texture_unit_index < group_->max_texture_units()) {
4208 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4209 TextureManager::TextureInfo* texture_info =
[email protected]61eeb33f2011-07-26 15:30:314210 texture_unit.GetInfoForSamplerType(uniform_info->type);
[email protected]915a59a12010-09-30 21:29:114211 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]ef526492010-06-02 23:12:254212 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:504213 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4214 glBindTexture(
[email protected]61eeb33f2011-07-26 15:30:314215 GetBindTargetForSamplerType(uniform_info->type),
[email protected]00f893d2010-08-24 18:55:494216 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:504217 }
4218 }
4219 // else: should this be an error?
4220 }
4221 }
[email protected]ef526492010-06-02 23:12:254222 return textures_set;
[email protected]3916c97e2010-02-25 03:20:504223}
4224
4225void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
4226 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:504227 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4228 current_program_->sampler_indices();
4229 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4230 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4231 current_program_->GetUniformInfo(sampler_indices[ii]);
4232 DCHECK(uniform_info);
4233 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4234 GLuint texture_unit_index = uniform_info->texture_units[jj];
4235 if (texture_unit_index < group_->max_texture_units()) {
4236 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4237 TextureManager::TextureInfo* texture_info =
4238 uniform_info->type == GL_SAMPLER_2D ?
4239 texture_unit.bound_texture_2d :
4240 texture_unit.bound_texture_cube_map;
[email protected]915a59a12010-09-30 21:29:114241 if (!texture_info || !texture_info->CanRender(feature_info_)) {
[email protected]3916c97e2010-02-25 03:20:504242 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4243 // Get the texture info that was previously bound here.
4244 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
4245 texture_unit.bound_texture_2d :
4246 texture_unit.bound_texture_cube_map;
4247 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:034248 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:504249 }
4250 }
4251 }
4252 }
4253 // Set the active texture back to whatever the user had it as.
4254 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:304255}
4256
4257bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
[email protected]689fa1c52010-06-09 18:35:034258 // NOTE: We specifically do not check current_program->IsValid() because
4259 // it could never be invalid since glUseProgram would have failed. While
4260 // glLinkProgram could later mark the program as invalid the previous
4261 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:144262 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:504263 // The program does not exist.
4264 // But GL says no ERROR.
4265 return false;
4266 }
[email protected]f39f4b3f2010-05-12 17:04:084267 // Validate all attribs currently enabled. If they are used by the current
4268 // program then check that they have enough elements to handle the draw call.
4269 // If they are not used by the current program check that they have a buffer
4270 // assigned.
4271 const VertexAttribManager::VertexAttribInfoList& infos =
4272 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4273 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:404274 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:084275 const VertexAttribManager::VertexAttribInfo* info = *it;
4276 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4277 current_program_->GetAttribInfoByLocation(info->index());
4278 if (attrib_info) {
4279 // This attrib is used in the current program.
4280 if (!info->CanAccess(max_vertex_accessed)) {
4281 SetGLError(GL_INVALID_OPERATION,
4282 "glDrawXXX: attempt to access out of range vertices");
4283 return false;
4284 }
4285 } else {
4286 // This attrib is not used in the current program.
4287 if (!info->buffer() || info->buffer()->IsDeleted()) {
4288 SetGLError(
4289 GL_INVALID_OPERATION,
4290 "glDrawXXX: attempt to render with no buffer attached to enabled "
4291 "attrib");
4292 return false;
4293 }
[email protected]1d32bc82010-01-13 22:06:464294 }
[email protected]07f54fcc2009-12-22 02:46:304295 }
[email protected]3916c97e2010-02-25 03:20:504296 return true;
[email protected]b1122982010-05-17 23:04:244297}
4298
4299bool GLES2DecoderImpl::SimulateAttrib0(GLuint max_vertex_accessed) {
[email protected]876f6fee2010-08-02 23:10:324300 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4301 return false;
4302
[email protected]b1122982010-05-17 23:04:244303 const VertexAttribManager::VertexAttribInfo* info =
4304 vertex_attrib_manager_.GetVertexAttribInfo(0);
4305 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:494306 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
4307 if (info->enabled() && attrib_0_used) {
[email protected]b1122982010-05-17 23:04:244308 return false;
4309 }
4310
4311 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
4312
4313 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
4314
4315 // Make a buffer with a single repeated vec4 value enough to
4316 // simulate the constant value that is supposed to be here.
4317 // This is required to emulate GLES2 on GL.
4318 GLsizei num_vertices = max_vertex_accessed + 1;
4319 GLsizei size_needed = num_vertices * sizeof(Vec4); // NOLINT
[email protected]fc753442011-02-04 19:49:494320 if (size_needed > attrib_0_size_) {
4321 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
4322 // TODO(gman): check for error here?
4323 attrib_0_buffer_matches_value_ = false;
4324 }
4325 if (attrib_0_used &&
4326 (!attrib_0_buffer_matches_value_ ||
4327 (info->value().v[0] != attrib_0_value_.v[0] ||
4328 info->value().v[1] != attrib_0_value_.v[1] ||
4329 info->value().v[2] != attrib_0_value_.v[2] ||
4330 info->value().v[3] != attrib_0_value_.v[3]))) {
4331 std::vector<Vec4> temp(num_vertices, info->value());
4332 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
4333 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:244334 attrib_0_value_ = info->value();
4335 attrib_0_size_ = size_needed;
4336 }
4337
4338 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4339
4340 return true;
[email protected]b1122982010-05-17 23:04:244341}
4342
4343void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
4344 const VertexAttribManager::VertexAttribInfo* info =
4345 vertex_attrib_manager_.GetVertexAttribInfo(0);
4346 const void* ptr = reinterpret_cast<const void*>(info->offset());
4347 BufferManager::BufferInfo* buffer_info = info->buffer();
4348 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
4349 glVertexAttribPointer(
4350 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
4351 ptr);
4352 glBindBuffer(GL_ARRAY_BUFFER,
4353 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4354}
[email protected]07f54fcc2009-12-22 02:46:304355
[email protected]8fbedc02010-11-18 18:43:404356bool GLES2DecoderImpl::SimulateFixedAttribs(
4357 GLuint max_vertex_accessed, bool* simulated) {
4358 DCHECK(simulated);
4359 *simulated = false;
4360 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
4361 return true;
4362
4363 if (!vertex_attrib_manager_.HaveFixedAttribs()) {
4364 return true;
4365 }
4366
4367 // NOTE: we could be smart and try to check if a buffer is used
4368 // twice in 2 different attribs, find the overlapping parts and therefore
4369 // duplicate the minimum amount of data but this whole code path is not meant
4370 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
4371 // tests so we just add to the buffer attrib used.
4372
4373 // Compute the number of elements needed.
4374 int num_vertices = max_vertex_accessed + 1;
4375 int elements_needed = 0;
4376 const VertexAttribManager::VertexAttribInfoList& infos =
4377 vertex_attrib_manager_.GetEnabledVertexAttribInfos();
4378 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4379 infos.begin(); it != infos.end(); ++it) {
4380 const VertexAttribManager::VertexAttribInfo* info = *it;
4381 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4382 current_program_->GetAttribInfoByLocation(info->index());
4383 if (attrib_info &&
4384 info->CanAccess(max_vertex_accessed) &&
4385 info->type() == GL_FIXED) {
4386 int elements_used = 0;
4387 if (!SafeMultiply(
4388 static_cast<int>(num_vertices),
4389 info->size(), &elements_used) ||
4390 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
4391 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4392 return false;
4393 }
4394 }
4395 }
4396
4397 const int kSizeOfFloat = sizeof(float); // NOLINT
4398 int size_needed = 0;
4399 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed)) {
4400 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
4401 return false;
4402 }
4403
4404
4405 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
4406 if (size_needed > fixed_attrib_buffer_size_) {
4407 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
4408 }
4409
4410 // Copy the elements and convert to float
4411 GLintptr offset = 0;
4412 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
4413 infos.begin(); it != infos.end(); ++it) {
4414 const VertexAttribManager::VertexAttribInfo* info = *it;
4415 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4416 current_program_->GetAttribInfoByLocation(info->index());
4417 if (attrib_info &&
4418 info->CanAccess(max_vertex_accessed) &&
4419 info->type() == GL_FIXED) {
4420 int num_elements = info->size() * kSizeOfFloat;
4421 int size = num_elements * num_vertices;
4422 scoped_array<float> data(new float[size]);
4423 const int32* src = reinterpret_cast<const int32 *>(
4424 info->buffer()->GetRange(info->offset(), size));
4425 const int32* end = src + num_elements;
4426 float* dst = data.get();
4427 while (src != end) {
4428 *dst++ = static_cast<float>(*src++) / 65536.0f;
4429 }
4430 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
4431 glVertexAttribPointer(
4432 info->index(), info->size(), GL_FLOAT, false, 0,
4433 reinterpret_cast<GLvoid*>(offset));
4434 offset += size;
4435 }
4436 }
4437 *simulated = true;
4438 return true;
4439}
4440
4441void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
4442 // There's no need to call glVertexAttribPointer because we shadow all the
4443 // settings and passing GL_FIXED to it will not work.
4444 glBindBuffer(GL_ARRAY_BUFFER,
4445 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
4446}
4447
[email protected]38d139d2011-07-14 00:38:434448error::Error GLES2DecoderImpl::HandleDrawArrays(
4449 uint32 immediate_data_size, const gles2::DrawArrays& c) {
4450 GLenum mode = static_cast<GLenum>(c.mode);
4451 GLint first = static_cast<GLint>(c.first);
4452 GLsizei count = static_cast<GLsizei>(c.count);
4453 if (!validators_->draw_mode.IsValid(mode)) {
4454 SetGLError(GL_INVALID_ENUM, "glDrawArrays: mode GL_INVALID_ENUM");
4455 return error::kNoError;
4456 }
4457 if (count < 0) {
4458 SetGLError(GL_INVALID_VALUE, "glDrawArrays: count < 0");
4459 return error::kNoError;
4460 }
4461 if (!CheckFramebufferComplete("glDrawArrays")) {
4462 return error::kNoError;
4463 }
4464 // We have to check this here because the prototype for glDrawArrays
4465 // is GLint not GLsizei.
4466 if (first < 0) {
4467 SetGLError(GL_INVALID_VALUE, "glDrawArrays: first < 0");
4468 return error::kNoError;
4469 }
4470
4471 if (count == 0) {
4472 return error::kNoError;
4473 }
4474
4475 GLuint max_vertex_accessed = first + count - 1;
4476 if (IsDrawValid(max_vertex_accessed)) {
4477 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
4478 bool simulated_fixed_attribs = false;
4479 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
4480 bool textures_set = SetBlackTextureForNonRenderableTextures();
4481 ApplyDirtyState();
4482 glDrawArrays(mode, first, count);
4483 if (textures_set) {
4484 RestoreStateForNonRenderableTextures();
4485 }
4486 if (simulated_fixed_attribs) {
4487 RestoreStateForSimulatedFixedAttribs();
4488 }
4489 }
4490 if (simulated_attrib_0) {
4491 RestoreStateForSimulatedAttrib0();
4492 }
4493 if (WasContextLost()) {
4494 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawArrays.";
4495 return error::kLostContext;
4496 }
4497 }
4498 return error::kNoError;
4499}
4500
[email protected]f7a64ee2010-02-01 22:24:144501error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]b9849abf2009-11-25 19:13:194502 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]3916c97e2010-02-25 03:20:504503 if (!bound_element_array_buffer_ ||
4504 bound_element_array_buffer_->IsDeleted()) {
[email protected]8eee29c2010-04-29 03:38:294505 SetGLError(GL_INVALID_OPERATION,
4506 "glDrawElements: No element array buffer bound");
4507 return error::kNoError;
4508 }
4509
4510 GLenum mode = c.mode;
4511 GLsizei count = c.count;
4512 GLenum type = c.type;
4513 int32 offset = c.index_offset;
4514 if (count < 0) {
4515 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
4516 return error::kNoError;
4517 }
4518 if (offset < 0) {
4519 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
4520 return error::kNoError;
4521 }
[email protected]9438b012010-06-15 22:55:054522 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:294523 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
4524 return error::kNoError;
4525 }
[email protected]9438b012010-06-15 22:55:054526 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:294527 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
4528 return error::kNoError;
4529 }
4530
[email protected]3a03a8f2011-03-19 00:51:274531 if (!CheckFramebufferComplete("glDrawElements")) {
4532 return error::kNoError;
4533 }
4534
[email protected]6c788fb72010-08-26 02:16:314535 if (count == 0) {
4536 return error::kNoError;
4537 }
4538
[email protected]8eee29c2010-04-29 03:38:294539 GLuint max_vertex_accessed;
4540 if (!bound_element_array_buffer_->GetMaxValueForRange(
4541 offset, count, type, &max_vertex_accessed)) {
4542 SetGLError(GL_INVALID_OPERATION,
4543 "glDrawElements: range out of bounds for buffer");
4544 return error::kNoError;
4545 }
4546
4547 if (IsDrawValid(max_vertex_accessed)) {
[email protected]b1122982010-05-17 23:04:244548 bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
[email protected]8fbedc02010-11-18 18:43:404549 bool simulated_fixed_attribs = false;
4550 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
4551 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:464552 ApplyDirtyState();
[email protected]8fbedc02010-11-18 18:43:404553 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
4554 glDrawElements(mode, count, type, indices);
4555 if (textures_set) {
4556 RestoreStateForNonRenderableTextures();
4557 }
4558 if (simulated_fixed_attribs) {
4559 RestoreStateForSimulatedFixedAttribs();
4560 }
[email protected]ba3176a2009-12-16 18:19:464561 }
[email protected]b1122982010-05-17 23:04:244562 if (simulated_attrib_0) {
4563 RestoreStateForSimulatedAttrib0();
4564 }
[email protected]38d139d2011-07-14 00:38:434565 if (WasContextLost()) {
4566 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawElements.";
4567 return error::kLostContext;
4568 }
[email protected]96449d2c2009-11-25 00:01:324569 }
[email protected]f7a64ee2010-02-01 22:24:144570 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324571}
4572
[email protected]269200b12010-11-18 22:53:064573GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:234574 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
4575 GLuint max_vertex_accessed = 0;
4576 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:294577 if (!info) {
[email protected]ae51d192010-04-27 00:48:034578 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:294579 SetGLError(GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:064580 "GetMaxValueInBufferCHROMIUM: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:234581 } else {
4582 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:034583 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:064584 SetGLError(
4585 GL_INVALID_OPERATION,
4586 "GetMaxValueInBufferCHROMIUM: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:234587 }
4588 }
4589 return max_vertex_accessed;
4590}
4591
[email protected]96449d2c2009-11-25 00:01:324592// Calls glShaderSource for the various versions of the ShaderSource command.
4593// Assumes that data / data_size points to a piece of memory that is in range
4594// of whatever context it came from (shared memory, immediate memory, bucket
4595// memory.)
[email protected]45bf5152010-02-12 00:11:314596error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034597 GLuint client_id, const char* data, uint32 data_size) {
[email protected]6b8cf1a2010-05-06 16:13:584598 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4599 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:314600 if (!info) {
[email protected]45bf5152010-02-12 00:11:314601 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324602 }
[email protected]45bf5152010-02-12 00:11:314603 // Note: We don't actually call glShaderSource here. We wait until
4604 // the call to glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:524605 info->Update(std::string(data, data + data_size).c_str());
[email protected]f7a64ee2010-02-01 22:24:144606 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324607}
4608
[email protected]f7a64ee2010-02-01 22:24:144609error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:194610 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:324611 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314612 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:324613 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:464614 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144615 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324616 }
[email protected]ae51d192010-04-27 00:48:034617 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:324618}
4619
[email protected]f7a64ee2010-02-01 22:24:144620error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:194621 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:324622 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:314623 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:304624 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:464625 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:144626 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:324627 }
[email protected]ae51d192010-04-27 00:48:034628 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:314629}
4630
[email protected]558847a2010-03-24 07:02:544631error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
4632 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:544633 Bucket* bucket = GetBucket(c.data_bucket_id);
4634 if (!bucket || bucket->size() == 0) {
4635 return error::kInvalidArguments;
4636 }
4637 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:034638 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:544639 bucket->size() - 1);
4640}
4641
[email protected]ae51d192010-04-27 00:48:034642void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]0c8fabf2011-06-14 19:35:224643 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]6b8cf1a2010-05-06 16:13:584644 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4645 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:314646 if (!info) {
[email protected]45bf5152010-02-12 00:11:314647 return;
4648 }
[email protected]de17df392010-04-23 21:09:414649 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
4650 // glShaderSource and then glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:524651 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:344652 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:184653 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:344654 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:454655 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:234656
[email protected]a550584e2010-09-17 18:01:454657 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:344658 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:184659 return;
4660 }
[email protected]a550584e2010-09-17 18:01:454661 shader_src = translator->translated_shader();
[email protected]de17df392010-04-23 21:09:414662 }
[email protected]de17df392010-04-23 21:09:414663
[email protected]ae51d192010-04-27 00:48:034664 glShaderSource(info->service_id(), 1, &shader_src, NULL);
4665 glCompileShader(info->service_id());
[email protected]e5186162010-06-14 18:54:414666 GLint status = GL_FALSE;
4667 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
4668 if (status) {
[email protected]f57bb282010-11-12 00:51:344669 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:414670 } else {
[email protected]d9977d42010-09-01 20:27:024671 // We cannot reach here if we are using the shader translator.
4672 // All invalid shaders must be rejected by the translator.
4673 // All translated shaders must compile.
4674 LOG_IF(ERROR, use_shader_translator_)
4675 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:334676 GLint max_len = 0;
4677 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
4678 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:414679 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:334680 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
4681 DCHECK(max_len == 0 || len < max_len);
4682 DCHECK(len ==0 || temp[len] == '\0');
[email protected]df6cf1ad2011-01-29 01:20:524683 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
[email protected]e5186162010-06-14 18:54:414684 }
[email protected]45bf5152010-02-12 00:11:314685};
4686
[email protected]ddd968b82010-03-02 00:44:294687void GLES2DecoderImpl::DoGetShaderiv(
4688 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:584689 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4690 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:294691 if (!info) {
[email protected]ddd968b82010-03-02 00:44:294692 return;
4693 }
[email protected]8f1ccdac2010-05-19 21:01:484694 switch (pname) {
4695 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:524696 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:484697 return;
4698 case GL_COMPILE_STATUS:
[email protected]e5186162010-06-14 18:54:414699 *params = info->IsValid();
4700 return;
[email protected]8f1ccdac2010-05-19 21:01:484701 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:524702 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:414703 return;
[email protected]8f1ccdac2010-05-19 21:01:484704 default:
4705 break;
[email protected]ddd968b82010-03-02 00:44:294706 }
[email protected]8f1ccdac2010-05-19 21:01:484707 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:294708}
4709
[email protected]ae51d192010-04-27 00:48:034710error::Error GLES2DecoderImpl::HandleGetShaderSource(
4711 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
4712 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:034713 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4714 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:584715 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4716 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:524717 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:294718 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:294719 return error::kNoError;
4720 }
[email protected]df6cf1ad2011-01-29 01:20:524721 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:034722 return error::kNoError;
4723}
4724
4725error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
4726 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
4727 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:584728 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4729 Bucket* bucket = CreateBucket(bucket_id);
4730 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4731 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:524732 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:464733 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:034734 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:314735 }
[email protected]df6cf1ad2011-01-29 01:20:524736 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:034737 return error::kNoError;
4738}
4739
4740error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
4741 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
4742 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:584743 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
4744 Bucket* bucket = CreateBucket(bucket_id);
4745 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
4746 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:524747 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:464748 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:034749 return error::kNoError;
4750 }
[email protected]df6cf1ad2011-01-29 01:20:524751 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:034752 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324753}
4754
[email protected]1958e0e2010-04-22 05:17:154755bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364756 const BufferManager::BufferInfo* info = GetBufferInfo(client_id);
4757 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154758}
4759
4760bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364761 const FramebufferManager::FramebufferInfo* info =
4762 GetFramebufferInfo(client_id);
4763 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154764}
4765
4766bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364767 // IsProgram is true for programs as soon as they are created, until they are
4768 // deleted and no longer in use.
[email protected]ae51d192010-04-27 00:48:034769 return GetProgramInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154770}
4771
4772bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364773 const RenderbufferManager::RenderbufferInfo* info =
4774 GetRenderbufferInfo(client_id);
4775 return info && info->IsValid();
[email protected]1958e0e2010-04-22 05:17:154776}
4777
4778bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364779 // IsShader is true for shaders as soon as they are created, until they
4780 // are deleted and not attached to any programs.
[email protected]ae51d192010-04-27 00:48:034781 return GetShaderInfo(client_id) != NULL;
[email protected]1958e0e2010-04-22 05:17:154782}
4783
4784bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:364785 const TextureManager::TextureInfo* info = GetTextureInfo(client_id);
4786 return info && info->IsValid();
[email protected]ae51d192010-04-27 00:48:034787}
4788
4789void GLES2DecoderImpl::DoAttachShader(
4790 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584791 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4792 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034793 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034794 return;
[email protected]1958e0e2010-04-22 05:17:154795 }
[email protected]6b8cf1a2010-05-06 16:13:584796 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4797 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:034798 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034799 return;
4800 }
[email protected]ca488e12010-12-13 20:06:144801 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:314802 SetGLError(GL_INVALID_OPERATION,
4803 "glAttachShader: can not attach more than"
4804 " one shader of the same type.");
4805 return;
4806 }
[email protected]ae51d192010-04-27 00:48:034807 glAttachShader(program_info->service_id(), shader_info->service_id());
4808}
4809
4810void GLES2DecoderImpl::DoDetachShader(
4811 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584812 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
4813 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034814 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:034815 return;
4816 }
[email protected]6b8cf1a2010-05-06 16:13:584817 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
4818 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:034819 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:034820 return;
4821 }
[email protected]9a0ccd42011-03-16 23:58:224822 if (!program_info->DetachShader(shader_manager(), shader_info)) {
4823 SetGLError(GL_INVALID_OPERATION,
4824 "glDetachShader: shader not attached to program");
4825 return;
4826 }
[email protected]ae51d192010-04-27 00:48:034827 glDetachShader(program_info->service_id(), shader_info->service_id());
4828}
4829
4830void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:584831 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4832 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:034833 if (!info) {
[email protected]ae51d192010-04-27 00:48:034834 return;
4835 }
[email protected]d685a682011-04-29 16:19:574836 info->Validate();
[email protected]1958e0e2010-04-22 05:17:154837}
4838
[email protected]b1122982010-05-17 23:04:244839void GLES2DecoderImpl::DoGetVertexAttribfv(
4840 GLuint index, GLenum pname, GLfloat* params) {
4841 VertexAttribManager::VertexAttribInfo* info =
4842 vertex_attrib_manager_.GetVertexAttribInfo(index);
4843 if (!info) {
4844 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
4845 return;
4846 }
4847 switch (pname) {
4848 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4849 BufferManager::BufferInfo* buffer = info->buffer();
4850 if (buffer && !buffer->IsDeleted()) {
4851 GLuint client_id;
4852 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4853 *params = static_cast<GLfloat>(client_id);
4854 }
4855 break;
4856 }
4857 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4858 *params = static_cast<GLfloat>(info->enabled());
4859 break;
4860 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4861 *params = static_cast<GLfloat>(info->size());
4862 break;
4863 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4864 *params = static_cast<GLfloat>(info->gl_stride());
4865 break;
4866 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4867 *params = static_cast<GLfloat>(info->type());
4868 break;
4869 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4870 *params = static_cast<GLfloat>(info->normalized());
4871 break;
4872 case GL_CURRENT_VERTEX_ATTRIB:
4873 params[0] = info->value().v[0];
4874 params[1] = info->value().v[1];
4875 params[2] = info->value().v[2];
4876 params[3] = info->value().v[3];
4877 break;
4878 default:
4879 NOTREACHED();
4880 break;
4881 }
4882}
4883
4884void GLES2DecoderImpl::DoGetVertexAttribiv(
4885 GLuint index, GLenum pname, GLint* params) {
4886 VertexAttribManager::VertexAttribInfo* info =
4887 vertex_attrib_manager_.GetVertexAttribInfo(index);
4888 if (!info) {
4889 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
4890 return;
4891 }
4892 switch (pname) {
4893 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
4894 BufferManager::BufferInfo* buffer = info->buffer();
4895 if (buffer && !buffer->IsDeleted()) {
4896 GLuint client_id;
4897 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
4898 *params = client_id;
4899 }
4900 break;
4901 }
4902 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4903 *params = info->enabled();
4904 break;
4905 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4906 *params = info->size();
4907 break;
4908 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4909 *params = info->gl_stride();
4910 break;
4911 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4912 *params = info->type();
4913 break;
4914 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4915 *params = static_cast<GLint>(info->normalized());
4916 break;
4917 case GL_CURRENT_VERTEX_ATTRIB:
4918 params[0] = static_cast<GLint>(info->value().v[0]);
4919 params[1] = static_cast<GLint>(info->value().v[1]);
4920 params[2] = static_cast<GLint>(info->value().v[2]);
4921 params[3] = static_cast<GLint>(info->value().v[3]);
4922 break;
4923 default:
4924 NOTREACHED();
4925 break;
4926 }
4927}
4928
4929void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
4930 VertexAttribManager::VertexAttribInfo* info =
4931 vertex_attrib_manager_.GetVertexAttribInfo(index);
4932 if (!info) {
4933 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
4934 return;
4935 }
4936 VertexAttribManager::VertexAttribInfo::Vec4 value;
4937 value.v[0] = v0;
4938 value.v[1] = 0.0f;
4939 value.v[2] = 0.0f;
4940 value.v[3] = 1.0f;
4941 info->set_value(value);
4942 glVertexAttrib1f(index, v0);
4943}
4944
4945void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
4946 VertexAttribManager::VertexAttribInfo* info =
4947 vertex_attrib_manager_.GetVertexAttribInfo(index);
4948 if (!info) {
4949 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
4950 return;
4951 }
4952 VertexAttribManager::VertexAttribInfo::Vec4 value;
4953 value.v[0] = v0;
4954 value.v[1] = v1;
4955 value.v[2] = 0.0f;
4956 value.v[3] = 1.0f;
4957 info->set_value(value);
4958 glVertexAttrib2f(index, v0, v1);
4959}
4960
4961void GLES2DecoderImpl::DoVertexAttrib3f(
4962 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
4963 VertexAttribManager::VertexAttribInfo* info =
4964 vertex_attrib_manager_.GetVertexAttribInfo(index);
4965 if (!info) {
4966 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
4967 return;
4968 }
4969 VertexAttribManager::VertexAttribInfo::Vec4 value;
4970 value.v[0] = v0;
4971 value.v[1] = v1;
4972 value.v[2] = v2;
4973 value.v[3] = 1.0f;
4974 info->set_value(value);
4975 glVertexAttrib3f(index, v0, v1, v2);
4976}
4977
4978void GLES2DecoderImpl::DoVertexAttrib4f(
4979 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
4980 VertexAttribManager::VertexAttribInfo* info =
4981 vertex_attrib_manager_.GetVertexAttribInfo(index);
4982 if (!info) {
4983 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
4984 return;
4985 }
4986 VertexAttribManager::VertexAttribInfo::Vec4 value;
4987 value.v[0] = v0;
4988 value.v[1] = v1;
4989 value.v[2] = v2;
4990 value.v[3] = v3;
4991 info->set_value(value);
4992 glVertexAttrib4f(index, v0, v1, v2, v3);
4993}
4994
4995void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
4996 VertexAttribManager::VertexAttribInfo* info =
4997 vertex_attrib_manager_.GetVertexAttribInfo(index);
4998 if (!info) {
4999 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
5000 return;
5001 }
5002 VertexAttribManager::VertexAttribInfo::Vec4 value;
5003 value.v[0] = v[0];
5004 value.v[1] = 0.0f;
5005 value.v[2] = 0.0f;
5006 value.v[3] = 1.0f;
5007 info->set_value(value);
5008 glVertexAttrib1fv(index, v);
5009}
5010
5011void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
5012 VertexAttribManager::VertexAttribInfo* info =
5013 vertex_attrib_manager_.GetVertexAttribInfo(index);
5014 if (!info) {
5015 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
5016 return;
5017 }
5018 VertexAttribManager::VertexAttribInfo::Vec4 value;
5019 value.v[0] = v[0];
5020 value.v[1] = v[1];
5021 value.v[2] = 0.0f;
5022 value.v[3] = 1.0f;
5023 info->set_value(value);
5024 glVertexAttrib2fv(index, v);
5025}
5026
5027void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
5028 VertexAttribManager::VertexAttribInfo* info =
5029 vertex_attrib_manager_.GetVertexAttribInfo(index);
5030 if (!info) {
5031 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
5032 return;
5033 }
5034 VertexAttribManager::VertexAttribInfo::Vec4 value;
5035 value.v[0] = v[0];
5036 value.v[1] = v[1];
5037 value.v[2] = v[2];
5038 value.v[3] = 1.0f;
5039 info->set_value(value);
5040 glVertexAttrib3fv(index, v);
5041}
5042
5043void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
5044 VertexAttribManager::VertexAttribInfo* info =
5045 vertex_attrib_manager_.GetVertexAttribInfo(index);
5046 if (!info) {
5047 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
5048 return;
5049 }
5050 VertexAttribManager::VertexAttribInfo::Vec4 value;
5051 value.v[0] = v[0];
5052 value.v[1] = v[1];
5053 value.v[2] = v[2];
5054 value.v[3] = v[3];
5055 info->set_value(value);
5056 glVertexAttrib4fv(index, v);
5057}
5058
[email protected]f7a64ee2010-02-01 22:24:145059error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:195060 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:295061 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
5062 SetGLError(GL_INVALID_VALUE,
5063 "glVertexAttribPointer: no array buffer bound");
5064 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325065 }
[email protected]8eee29c2010-04-29 03:38:295066
5067 GLuint indx = c.indx;
5068 GLint size = c.size;
5069 GLenum type = c.type;
5070 GLboolean normalized = c.normalized;
5071 GLsizei stride = c.stride;
5072 GLsizei offset = c.offset;
5073 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:055074 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295075 SetGLError(GL_INVALID_ENUM,
5076 "glVertexAttribPointer: type GL_INVALID_ENUM");
5077 return error::kNoError;
5078 }
[email protected]9438b012010-06-15 22:55:055079 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:315080 SetGLError(GL_INVALID_VALUE,
[email protected]8eee29c2010-04-29 03:38:295081 "glVertexAttribPointer: size GL_INVALID_VALUE");
5082 return error::kNoError;
5083 }
5084 if (indx >= group_->max_vertex_attribs()) {
5085 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
5086 return error::kNoError;
5087 }
5088 if (stride < 0) {
5089 SetGLError(GL_INVALID_VALUE,
5090 "glVertexAttribPointer: stride < 0");
5091 return error::kNoError;
5092 }
5093 if (stride > 255) {
5094 SetGLError(GL_INVALID_VALUE,
5095 "glVertexAttribPointer: stride > 255");
5096 return error::kNoError;
5097 }
5098 if (offset < 0) {
5099 SetGLError(GL_INVALID_VALUE,
5100 "glVertexAttribPointer: offset < 0");
5101 return error::kNoError;
5102 }
5103 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:315104 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:295105 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:315106 SetGLError(GL_INVALID_OPERATION,
5107 "glVertexAttribPointer: offset not valid for type");
5108 return error::kNoError;
5109 }
5110 if (stride % component_size > 0) {
5111 SetGLError(GL_INVALID_OPERATION,
[email protected]8eee29c2010-04-29 03:38:295112 "glVertexAttribPointer: stride not valid for type");
5113 return error::kNoError;
5114 }
[email protected]8fbedc02010-11-18 18:43:405115 vertex_attrib_manager_.SetAttribInfo(
5116 indx,
[email protected]8eee29c2010-04-29 03:38:295117 bound_array_buffer_,
5118 size,
5119 type,
[email protected]b1122982010-05-17 23:04:245120 normalized,
5121 stride,
5122 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:295123 offset);
[email protected]8fbedc02010-11-18 18:43:405124 if (type != GL_FIXED) {
5125 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
5126 }
[email protected]f7a64ee2010-02-01 22:24:145127 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325128}
5129
[email protected]f7a64ee2010-02-01 22:24:145130error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:195131 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:315132 GLint x = c.x;
5133 GLint y = c.y;
5134 GLsizei width = c.width;
5135 GLsizei height = c.height;
5136 GLenum format = c.format;
5137 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:565138 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:295139 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:565140 return error::kNoError;
5141 }
[email protected]a51788e2010-02-24 21:54:255142 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:185143 uint32 pixels_size;
5144 if (!GLES2Util::ComputeImageDataSize(
5145 width, height, format, type, pack_alignment_, &pixels_size)) {
5146 return error::kOutOfBounds;
5147 }
[email protected]612d2f82009-12-08 20:49:315148 void* pixels = GetSharedMemoryAs<void*>(
5149 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:255150 Result* result = GetSharedMemoryAs<Result*>(
5151 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5152 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:145153 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465154 }
[email protected]a51788e2010-02-24 21:54:255155
[email protected]9438b012010-06-15 22:55:055156 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295157 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
5158 return error::kNoError;
5159 }
[email protected]9438b012010-06-15 22:55:055160 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295161 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125162 return error::kNoError;
5163 }
[email protected]57f223832010-03-19 01:57:565164 if (width == 0 || height == 0) {
5165 return error::kNoError;
5166 }
5167
5168 CopyRealGLErrorsToWrapper();
5169
[email protected]de26b3c2011-08-03 21:54:275170 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]34ff8b0c2010-10-01 20:06:025171
[email protected]57f223832010-03-19 01:57:565172 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:305173 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:565174
5175 GLint max_x;
5176 GLint max_y;
5177 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:295178 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:145179 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:315180 }
[email protected]57f223832010-03-19 01:57:565181
[email protected]d37231fa2010-04-09 21:16:025182 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:565183 // The user requested an out of range area. Get the results 1 line
5184 // at a time.
5185 uint32 temp_size;
5186 if (!GLES2Util::ComputeImageDataSize(
5187 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295188 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565189 return error::kNoError;
5190 }
5191 GLsizei unpadded_row_size = temp_size;
5192 if (!GLES2Util::ComputeImageDataSize(
5193 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:295194 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565195 return error::kNoError;
5196 }
5197 GLsizei padded_row_size = temp_size - unpadded_row_size;
5198 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:295199 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565200 return error::kNoError;
5201 }
5202
5203 GLint dest_x_offset = std::max(-x, 0);
5204 uint32 dest_row_offset;
5205 if (!GLES2Util::ComputeImageDataSize(
5206 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:295207 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:565208 return error::kNoError;
5209 }
5210
5211 // Copy each row into the larger dest rect.
5212 int8* dst = static_cast<int8*>(pixels);
5213 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:025214 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:565215 GLint read_width = read_end_x - read_x;
5216 for (GLint yy = 0; yy < height; ++yy) {
5217 GLint ry = y + yy;
5218
5219 // Clear the row.
5220 memset(dst, 0, unpadded_row_size);
5221
5222 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:025223 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:565224 glReadPixels(
5225 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
5226 }
5227 dst += padded_row_size;
5228 }
5229 } else {
5230 glReadPixels(x, y, width, height, format, type, pixels);
5231 }
[email protected]1002c2d2011-06-28 22:39:045232 GLenum error = PeekGLError();
[email protected]a51788e2010-02-24 21:54:255233 if (error == GL_NO_ERROR) {
5234 *result = true;
[email protected]4848b9f82011-03-10 18:37:565235
5236 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5237 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5238 if ((channels_exist & 0x0008) == 0) {
5239 // Set the alpha to 255 because some drivers are buggy in this regard.
5240 uint32 temp_size;
5241 if (!GLES2Util::ComputeImageDataSize(
5242 width, 1, format, type, pack_alignment_, &temp_size)) {
5243 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5244 return error::kNoError;
5245 }
5246 GLsizei unpadded_row_size = temp_size;
5247 if (!GLES2Util::ComputeImageDataSize(
5248 width, 2, format, type, pack_alignment_, &temp_size)) {
5249 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5250 return error::kNoError;
5251 }
5252 GLsizei padded_row_size = temp_size - unpadded_row_size;
5253 if (padded_row_size < 0 || unpadded_row_size < 0) {
5254 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
5255 return error::kNoError;
5256 }
5257 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
5258 // of this implementation.
5259 if (type != GL_UNSIGNED_BYTE) {
5260 SetGLError(GL_INVALID_OPERATION, "unsupported readPixel format");
5261 return error::kNoError;
5262 }
5263 switch (format) {
5264 case GL_RGBA:
[email protected]297ca1c2011-06-20 23:08:465265 case GL_BGRA_EXT:
[email protected]4848b9f82011-03-10 18:37:565266 case GL_ALPHA: {
5267 int offset = (format == GL_ALPHA) ? 0 : 3;
5268 int step = (format == GL_ALPHA) ? 1 : 4;
5269 uint8* dst = static_cast<uint8*>(pixels) + offset;
5270 for (GLint yy = 0; yy < height; ++yy) {
5271 uint8* end = dst + unpadded_row_size;
5272 for (uint8* d = dst; d < end; d += step) {
5273 *d = 255;
5274 }
5275 dst += padded_row_size;
5276 }
5277 break;
5278 }
5279 default:
5280 break;
5281 }
5282 }
[email protected]a51788e2010-02-24 21:54:255283 }
[email protected]4848b9f82011-03-10 18:37:565284
[email protected]f7a64ee2010-02-01 22:24:145285 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325286}
5287
[email protected]f7a64ee2010-02-01 22:24:145288error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:195289 uint32 immediate_data_size, const gles2::PixelStorei& c) {
5290 GLenum pname = c.pname;
5291 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:055292 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:295293 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125294 return error::kNoError;
5295 }
[email protected]9438b012010-06-15 22:55:055296 if (!validators_->pixel_store_alignment.IsValid(param)) {
[email protected]8eee29c2010-04-29 03:38:295297 SetGLError(GL_INVALID_VALUE, "glPixelSTore: param GL_INVALID_VALUE");
[email protected]f7a64ee2010-02-01 22:24:145298 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195299 }
5300 glPixelStorei(pname, param);
5301 switch (pname) {
5302 case GL_PACK_ALIGNMENT:
5303 pack_alignment_ = param;
5304 break;
5305 case GL_UNPACK_ALIGNMENT:
5306 unpack_alignment_ = param;
5307 break;
5308 default:
5309 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:375310 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:195311 break;
5312 }
[email protected]f7a64ee2010-02-01 22:24:145313 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195314}
5315
[email protected]558847a2010-03-24 07:02:545316error::Error GLES2DecoderImpl::GetAttribLocationHelper(
5317 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5318 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:585319 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5320 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:035321 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145322 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195323 }
[email protected]ae51d192010-04-27 00:48:035324 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295325 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255326 return error::kNoError;
5327 }
[email protected]b9849abf2009-11-25 19:13:195328 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:545329 location_shm_id, location_shm_offset, sizeof(GLint));
5330 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:145331 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195332 }
[email protected]558847a2010-03-24 07:02:545333 // Require the client to init this incase the context is lost and we are no
5334 // longer executing commands.
5335 if (*location != -1) {
5336 return error::kGenericError;
5337 }
[email protected]0bfd9882010-02-05 23:02:255338 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:145339 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195340}
5341
[email protected]558847a2010-03-24 07:02:545342error::Error GLES2DecoderImpl::HandleGetAttribLocation(
5343 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
5344 uint32 name_size = c.data_size;
5345 const char* name = GetSharedMemoryAs<const char*>(
5346 c.name_shm_id, c.name_shm_offset, name_size);
5347 if (!name) {
5348 return error::kOutOfBounds;
5349 }
5350 String name_str(name, name_size);
5351 return GetAttribLocationHelper(
5352 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5353}
5354
[email protected]f7a64ee2010-02-01 22:24:145355error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:195356 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:545357 uint32 name_size = c.data_size;
5358 const char* name = GetImmediateDataAs<const char*>(
5359 c, name_size, immediate_data_size);
5360 if (!name) {
5361 return error::kOutOfBounds;
5362 }
5363 String name_str(name, name_size);
5364 return GetAttribLocationHelper(
5365 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5366}
5367
5368error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
5369 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
5370 Bucket* bucket = GetBucket(c.name_bucket_id);
5371 if (!bucket) {
5372 return error::kInvalidArguments;
5373 }
5374 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185375 if (!bucket->GetAsString(&name_str)) {
5376 return error::kInvalidArguments;
5377 }
[email protected]558847a2010-03-24 07:02:545378 return GetAttribLocationHelper(
5379 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5380}
5381
5382error::Error GLES2DecoderImpl::GetUniformLocationHelper(
5383 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
5384 const std::string& name_str) {
[email protected]6b8cf1a2010-05-06 16:13:585385 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5386 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:035387 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:145388 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195389 }
[email protected]ae51d192010-04-27 00:48:035390 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:295391 SetGLError(GL_INVALID_OPERATION,
5392 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:255393 return error::kNoError;
5394 }
[email protected]b9849abf2009-11-25 19:13:195395 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:545396 location_shm_id, location_shm_offset, sizeof(GLint));
5397 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:145398 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195399 }
[email protected]558847a2010-03-24 07:02:545400 // Require the client to init this incase the context is lost an we are no
5401 // longer executing commands.
5402 if (*location != -1) {
5403 return error::kGenericError;
5404 }
5405 *location = info->GetUniformLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:145406 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195407}
5408
[email protected]f7a64ee2010-02-01 22:24:145409error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:195410 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:195411 uint32 name_size = c.data_size;
5412 const char* name = GetSharedMemoryAs<const char*>(
5413 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:545414 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:145415 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195416 }
5417 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:545418 return GetUniformLocationHelper(
5419 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195420}
5421
[email protected]f7a64ee2010-02-01 22:24:145422error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:195423 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:195424 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:305425 const char* name = GetImmediateDataAs<const char*>(
5426 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:545427 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:145428 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195429 }
5430 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:545431 return GetUniformLocationHelper(
5432 c.program, c.location_shm_id, c.location_shm_offset, name_str);
5433}
5434
5435error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
5436 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
5437 Bucket* bucket = GetBucket(c.name_bucket_id);
5438 if (!bucket) {
5439 return error::kInvalidArguments;
5440 }
5441 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:185442 if (!bucket->GetAsString(&name_str)) {
5443 return error::kInvalidArguments;
5444 }
[email protected]558847a2010-03-24 07:02:545445 return GetUniformLocationHelper(
5446 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:195447}
5448
[email protected]ddd968b82010-03-02 00:44:295449error::Error GLES2DecoderImpl::HandleGetString(
5450 uint32 immediate_data_size, const gles2::GetString& c) {
5451 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:055452 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:295453 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:295454 return error::kNoError;
5455 }
[email protected]1958e0e2010-04-22 05:17:155456 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
5457 const char* str = NULL;
5458 switch (name) {
5459 case GL_VERSION:
5460 str = "OpenGL ES 2.0 Chromium";
5461 break;
5462 case GL_SHADING_LANGUAGE_VERSION:
5463 str = "OpenGL ES GLSL ES 1.0 Chromium";
5464 break;
5465 case GL_EXTENSIONS:
[email protected]915a59a12010-09-30 21:29:115466 str = feature_info_->extensions().c_str();
[email protected]1958e0e2010-04-22 05:17:155467 break;
5468 default:
5469 str = gl_str;
5470 break;
5471 }
[email protected]ddd968b82010-03-02 00:44:295472 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:155473 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:295474 return error::kNoError;
5475}
5476
[email protected]0c86dbf2010-03-05 08:14:115477void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:155478 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:055479 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295480 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
5481 return;
5482 }
[email protected]9438b012010-06-15 22:55:055483 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:295484 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:115485 return;
[email protected]3b6ec202010-03-05 05:16:235486 }
5487 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:295488 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:285489 return;
[email protected]3b6ec202010-03-05 05:16:235490 }
5491 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
5492 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295493 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285494 return;
[email protected]3b6ec202010-03-05 05:16:235495 }
5496 // Clear the buffer to 0 if no initial data was passed in.
5497 scoped_array<int8> zero;
5498 if (!data) {
5499 zero.reset(new int8[size]);
5500 memset(zero.get(), 0, size);
5501 data = zero.get();
5502 }
[email protected]473c01ccb2011-06-07 01:33:305503
5504 if (!bufferdata_faster_than_buffersubdata_ &&
5505 size == info->size() && usage == info->usage()) {
5506 glBufferSubData(target, 0, size, data);
5507 info->SetRange(0, size, data);
5508 return;
5509 }
5510
[email protected]3b6ec202010-03-05 05:16:235511 CopyRealGLErrorsToWrapper();
5512 glBufferData(target, size, data, usage);
[email protected]1002c2d2011-06-28 22:39:045513 GLenum error = PeekGLError();
5514 if (error == GL_NO_ERROR) {
[email protected]473c01ccb2011-06-07 01:33:305515 buffer_manager()->SetInfo(info, size, usage);
[email protected]0c86dbf2010-03-05 08:14:115516 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:235517 }
[email protected]0c86dbf2010-03-05 08:14:115518}
5519
5520error::Error GLES2DecoderImpl::HandleBufferData(
5521 uint32 immediate_data_size, const gles2::BufferData& c) {
5522 GLenum target = static_cast<GLenum>(c.target);
5523 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
5524 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5525 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5526 GLenum usage = static_cast<GLenum>(c.usage);
5527 const void* data = NULL;
5528 if (data_shm_id != 0 || data_shm_offset != 0) {
5529 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
5530 if (!data) {
5531 return error::kOutOfBounds;
5532 }
5533 }
5534 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:145535 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195536}
5537
[email protected]f7a64ee2010-02-01 22:24:145538error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:195539 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
5540 GLenum target = static_cast<GLenum>(c.target);
5541 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:305542 const void* data = GetImmediateDataAs<const void*>(
5543 c, size, immediate_data_size);
5544 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145545 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:305546 }
[email protected]b9849abf2009-11-25 19:13:195547 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:115548 DoBufferData(target, size, data, usage);
5549 return error::kNoError;
5550}
5551
5552void GLES2DecoderImpl::DoBufferSubData(
5553 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:505554 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475555 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295556 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:285557 return;
[email protected]a93bb842010-02-16 23:03:475558 }
[email protected]0c86dbf2010-03-05 08:14:115559 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:295560 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]473c01ccb2011-06-07 01:33:305561 return;
[email protected]07f54fcc2009-12-22 02:46:305562 }
[email protected]473c01ccb2011-06-07 01:33:305563 if (bufferdata_faster_than_buffersubdata_ &&
5564 offset == 0 && size == info->size()) {
5565 glBufferData(target, size, data, info->usage());
5566 return;
5567 }
5568 glBufferSubData(target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:195569}
5570
[email protected]a93bb842010-02-16 23:03:475571error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
5572 GLenum target,
5573 GLint level,
5574 GLenum internal_format,
5575 GLsizei width,
5576 GLsizei height,
5577 GLint border,
5578 GLsizei image_size,
5579 const void* data) {
[email protected]a93bb842010-02-16 23:03:475580 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:055581 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295582 SetGLError(GL_INVALID_ENUM,
5583 "glCompressedTexImage2D: target GL_INVALID_ENUM");
5584 return error::kNoError;
5585 }
[email protected]9438b012010-06-15 22:55:055586 if (!validators_->compressed_texture_format.IsValid(
5587 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295588 SetGLError(GL_INVALID_ENUM,
5589 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:475590 return error::kNoError;
5591 }
[email protected]915a59a12010-09-30 21:29:115592 if (!texture_manager()->ValidForTarget(
5593 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475594 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295595 SetGLError(GL_INVALID_VALUE,
5596 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475597 return error::kNoError;
5598 }
[email protected]3916c97e2010-02-25 03:20:505599 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475600 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295601 SetGLError(GL_INVALID_VALUE,
5602 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:475603 return error::kNoError;
5604 }
5605 scoped_array<int8> zero;
5606 if (!data) {
5607 zero.reset(new int8[image_size]);
5608 memset(zero.get(), 0, image_size);
5609 data = zero.get();
5610 }
[email protected]cadde4a2010-07-31 17:10:435611 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:475612 glCompressedTexImage2D(
5613 target, level, internal_format, width, height, border, image_size, data);
[email protected]1002c2d2011-06-28 22:39:045614 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:435615 if (error == GL_NO_ERROR) {
5616 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:115617 feature_info_,
[email protected]cadde4a2010-07-31 17:10:435618 info, target, level, internal_format, width, height, 1, border, 0, 0);
5619 }
[email protected]a93bb842010-02-16 23:03:475620 return error::kNoError;
5621}
5622
[email protected]f7a64ee2010-02-01 22:24:145623error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195624 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
5625 GLenum target = static_cast<GLenum>(c.target);
5626 GLint level = static_cast<GLint>(c.level);
5627 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5628 GLsizei width = static_cast<GLsizei>(c.width);
5629 GLsizei height = static_cast<GLsizei>(c.height);
5630 GLint border = static_cast<GLint>(c.border);
5631 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
5632 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
5633 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
5634 const void* data = NULL;
5635 if (data_shm_id != 0 || data_shm_offset != 0) {
5636 data = GetSharedMemoryAs<const void*>(
5637 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:465638 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145639 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195640 }
5641 }
[email protected]a93bb842010-02-16 23:03:475642 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195643 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:195644}
5645
[email protected]f7a64ee2010-02-01 22:24:145646error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195647 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
5648 GLenum target = static_cast<GLenum>(c.target);
5649 GLint level = static_cast<GLint>(c.level);
5650 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5651 GLsizei width = static_cast<GLsizei>(c.width);
5652 GLsizei height = static_cast<GLsizei>(c.height);
5653 GLint border = static_cast<GLint>(c.border);
5654 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:305655 const void* data = GetImmediateDataAs<const void*>(
5656 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465657 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145658 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465659 }
[email protected]a93bb842010-02-16 23:03:475660 return DoCompressedTexImage2D(
5661 target, level, internal_format, width, height, border, image_size, data);
5662}
5663
[email protected]b6140d02010-05-17 14:47:165664error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
5665 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
5666 GLenum target = static_cast<GLenum>(c.target);
5667 GLint level = static_cast<GLint>(c.level);
5668 GLenum internal_format = static_cast<GLenum>(c.internalformat);
5669 GLsizei width = static_cast<GLsizei>(c.width);
5670 GLsizei height = static_cast<GLsizei>(c.height);
5671 GLint border = static_cast<GLint>(c.border);
5672 Bucket* bucket = GetBucket(c.bucket_id);
5673 return DoCompressedTexImage2D(
5674 target, level, internal_format, width, height, border,
5675 bucket->size(), bucket->GetData(0, bucket->size()));
5676}
5677
5678error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
5679 uint32 immediate_data_size,
5680 const gles2::CompressedTexSubImage2DBucket& c) {
5681 GLenum target = static_cast<GLenum>(c.target);
5682 GLint level = static_cast<GLint>(c.level);
5683 GLint xoffset = static_cast<GLint>(c.xoffset);
5684 GLint yoffset = static_cast<GLint>(c.yoffset);
5685 GLsizei width = static_cast<GLsizei>(c.width);
5686 GLsizei height = static_cast<GLsizei>(c.height);
5687 GLenum format = static_cast<GLenum>(c.format);
5688 Bucket* bucket = GetBucket(c.bucket_id);
5689 uint32 data_size = bucket->size();
5690 GLsizei imageSize = data_size;
5691 const void* data = bucket->GetData(0, data_size);
[email protected]9438b012010-06-15 22:55:055692 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:165693 SetGLError(
5694 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
5695 return error::kNoError;
5696 }
[email protected]9438b012010-06-15 22:55:055697 if (!validators_->compressed_texture_format.IsValid(format)) {
5698 SetGLError(GL_INVALID_ENUM,
5699 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
5700 return error::kNoError;
5701 }
[email protected]b6140d02010-05-17 14:47:165702 if (width < 0) {
5703 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
5704 return error::kNoError;
5705 }
5706 if (height < 0) {
5707 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
5708 return error::kNoError;
5709 }
5710 if (imageSize < 0) {
5711 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
5712 return error::kNoError;
5713 }
[email protected]cadde4a2010-07-31 17:10:435714 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:165715 target, level, xoffset, yoffset, width, height, format, imageSize, data);
5716 return error::kNoError;
5717}
5718
[email protected]a93bb842010-02-16 23:03:475719error::Error GLES2DecoderImpl::DoTexImage2D(
5720 GLenum target,
5721 GLint level,
5722 GLenum internal_format,
5723 GLsizei width,
5724 GLsizei height,
5725 GLint border,
5726 GLenum format,
5727 GLenum type,
5728 const void* pixels,
5729 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:055730 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:295731 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
5732 return error::kNoError;
5733 }
[email protected]9438b012010-06-15 22:55:055734 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:295735 SetGLError(GL_INVALID_ENUM,
5736 "glTexImage2D: internal_format GL_INVALID_ENUM");
5737 return error::kNoError;
5738 }
[email protected]9438b012010-06-15 22:55:055739 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295740 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
5741 return error::kNoError;
5742 }
[email protected]9438b012010-06-15 22:55:055743 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295744 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:145745 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195746 }
[email protected]7b92c412010-07-20 17:48:255747 if (format != internal_format) {
5748 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
5749 return error::kNoError;
5750 }
[email protected]915a59a12010-09-30 21:29:115751 if (!texture_manager()->ValidForTarget(
5752 feature_info_, target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:475753 border != 0) {
[email protected]8eee29c2010-04-29 03:38:295754 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:475755 return error::kNoError;
5756 }
[email protected]3916c97e2010-02-25 03:20:505757 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:475758 if (!info) {
[email protected]8eee29c2010-04-29 03:38:295759 SetGLError(GL_INVALID_OPERATION,
5760 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:475761 return error::kNoError;
5762 }
[email protected]0226c112011-07-22 03:25:075763
5764 GLsizei tex_width = 0;
5765 GLsizei tex_height = 0;
5766 GLenum tex_type = 0;
5767 GLenum tex_format = 0;
5768 bool level_is_same =
5769 info->GetLevelSize(target, level, &tex_width, &tex_height) &&
5770 info->GetLevelType(target, level, &tex_type, &tex_format) &&
5771 width == tex_width && height == tex_height &&
5772 type == tex_type && format == tex_format;
5773
5774 if (level_is_same && !pixels) {
[email protected]ea72ed222011-08-17 18:58:435775 tex_image_2d_failed_ = false;
[email protected]0226c112011-07-22 03:25:075776 return error::kNoError;
5777 }
5778
[email protected]a93bb842010-02-16 23:03:475779 scoped_array<int8> zero;
5780 if (!pixels) {
5781 zero.reset(new int8[pixels_size]);
5782 memset(zero.get(), 0, pixels_size);
5783 pixels = zero.get();
5784 }
[email protected]876f6fee2010-08-02 23:10:325785
[email protected]297ca1c2011-06-20 23:08:465786 if (info->IsAttachedToFramebuffer()) {
5787 state_dirty_ = true;
5788 }
5789
[email protected]0226c112011-07-22 03:25:075790 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same) {
5791 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
5792 tex_image_2d_failed_ = false;
5793 return error::kNoError;
[email protected]7488d962010-07-16 02:41:585794 }
[email protected]876f6fee2010-08-02 23:10:325795
[email protected]cadde4a2010-07-31 17:10:435796 CopyRealGLErrorsToWrapper();
[email protected]473c01ccb2011-06-07 01:33:305797 WrappedTexImage2D(
5798 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475799 pixels);
[email protected]1002c2d2011-06-28 22:39:045800 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:435801 if (error == GL_NO_ERROR) {
[email protected]915a59a12010-09-30 21:29:115802 texture_manager()->SetLevelInfo(feature_info_, info,
[email protected]cadde4a2010-07-31 17:10:435803 target, level, internal_format, width, height, 1, border, format, type);
[email protected]b493ee622011-04-13 23:52:005804 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:435805 }
[email protected]f7a64ee2010-02-01 22:24:145806 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:195807}
5808
[email protected]f7a64ee2010-02-01 22:24:145809error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195810 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]366ae242011-05-10 02:23:585811 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:005812 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:195813 GLenum target = static_cast<GLenum>(c.target);
5814 GLint level = static_cast<GLint>(c.level);
5815 GLint internal_format = static_cast<GLint>(c.internalformat);
5816 GLsizei width = static_cast<GLsizei>(c.width);
5817 GLsizei height = static_cast<GLsizei>(c.height);
5818 GLint border = static_cast<GLint>(c.border);
5819 GLenum format = static_cast<GLenum>(c.format);
5820 GLenum type = static_cast<GLenum>(c.type);
5821 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
5822 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:185823 uint32 pixels_size;
5824 if (!GLES2Util::ComputeImageDataSize(
5825 width, height, format, type, unpack_alignment_, &pixels_size)) {
5826 return error::kOutOfBounds;
5827 }
[email protected]b9849abf2009-11-25 19:13:195828 const void* pixels = NULL;
5829 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
5830 pixels = GetSharedMemoryAs<const void*>(
5831 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:465832 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145833 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:195834 }
5835 }
[email protected]a93bb842010-02-16 23:03:475836 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:195837 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475838 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:195839}
5840
[email protected]f7a64ee2010-02-01 22:24:145841error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:195842 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
5843 GLenum target = static_cast<GLenum>(c.target);
5844 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:465845 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:195846 GLsizei width = static_cast<GLsizei>(c.width);
5847 GLsizei height = static_cast<GLsizei>(c.height);
5848 GLint border = static_cast<GLint>(c.border);
5849 GLenum format = static_cast<GLenum>(c.format);
5850 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:185851 uint32 size;
5852 if (!GLES2Util::ComputeImageDataSize(
5853 width, height, format, type, unpack_alignment_, &size)) {
5854 return error::kOutOfBounds;
5855 }
[email protected]07f54fcc2009-12-22 02:46:305856 const void* pixels = GetImmediateDataAs<const void*>(
5857 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465858 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:145859 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465860 }
[email protected]a93bb842010-02-16 23:03:475861 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:465862 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:475863 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:145864 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325865}
5866
[email protected]cadde4a2010-07-31 17:10:435867void GLES2DecoderImpl::DoCompressedTexSubImage2D(
5868 GLenum target,
5869 GLint level,
5870 GLint xoffset,
5871 GLint yoffset,
5872 GLsizei width,
5873 GLsizei height,
5874 GLenum format,
5875 GLsizei image_size,
5876 const void * data) {
5877 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5878 if (!info) {
5879 SetGLError(GL_INVALID_OPERATION,
5880 "glCompressedTexSubImage2D: unknown texture for target");
5881 return;
5882 }
5883 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:525884 GLenum internal_format = 0;
5885 if (!info->GetLevelType(target, level, &type, &internal_format)) {
5886 SetGLError(
5887 GL_INVALID_OPERATION,
5888 "glCompressdTexSubImage2D: level does not exist.");
5889 return;
5890 }
5891 if (internal_format != format) {
5892 SetGLError(
5893 GL_INVALID_OPERATION,
5894 "glCompressdTexSubImage2D: format does not match internal format.");
5895 return;
5896 }
5897 if (!info->ValidForTexture(
5898 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:435899 SetGLError(GL_INVALID_VALUE,
5900 "glCompressdTexSubImage2D: bad dimensions.");
5901 return;
5902 }
5903 glCompressedTexSubImage2D(
5904 target, level, xoffset, yoffset, width, height, format, image_size, data);
5905}
5906
[email protected]6e288612010-12-21 20:45:035907static void Clip(
5908 GLint start, GLint range, GLint sourceRange,
5909 GLint* out_start, GLint* out_range) {
5910 DCHECK(out_start);
5911 DCHECK(out_range);
5912 if (start < 0) {
5913 range += start;
5914 start = 0;
5915 }
5916 GLint end = start + range;
5917 if (end > sourceRange) {
5918 range -= end - sourceRange;
5919 }
5920 *out_start = start;
5921 *out_range = range;
5922}
5923
5924
[email protected]cadde4a2010-07-31 17:10:435925void GLES2DecoderImpl::DoCopyTexImage2D(
5926 GLenum target,
5927 GLint level,
5928 GLenum internal_format,
5929 GLint x,
5930 GLint y,
5931 GLsizei width,
5932 GLsizei height,
5933 GLint border) {
5934 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
5935 if (!info) {
5936 SetGLError(GL_INVALID_OPERATION,
5937 "glCopyTexImage2D: unknown texture for target");
5938 return;
5939 }
[email protected]915a59a12010-09-30 21:29:115940 if (!texture_manager()->ValidForTarget(
5941 feature_info_, target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:185942 border != 0) {
5943 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
5944 return;
5945 }
5946
[email protected]9edc6b22010-12-23 02:00:265947 // Check we have compatible formats.
5948 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
5949 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
5950 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
5951
5952 if ((channels_needed & channels_exist) != channels_needed) {
5953 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
5954 return;
5955 }
5956
[email protected]cadde4a2010-07-31 17:10:435957 CopyRealGLErrorsToWrapper();
[email protected]de26b3c2011-08-03 21:54:275958 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:035959 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:265960
[email protected]297ca1c2011-06-20 23:08:465961 if (info->IsAttachedToFramebuffer()) {
5962 state_dirty_ = true;
5963 }
5964
[email protected]9edc6b22010-12-23 02:00:265965 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:035966 GLint copyX = 0;
5967 GLint copyY = 0;
5968 GLint copyWidth = 0;
5969 GLint copyHeight = 0;
5970 Clip(x, width, size.width(), &copyX, &copyWidth);
5971 Clip(y, height, size.height(), &copyY, &copyHeight);
5972
5973 if (copyX != x ||
5974 copyY != y ||
5975 copyWidth != width ||
5976 copyHeight != height) {
5977 // some part was clipped so clear the texture.
5978 uint32 pixels_size = 0;
5979 if (!GLES2Util::ComputeImageDataSize(
5980 width, height, internal_format, GL_UNSIGNED_BYTE,
5981 unpack_alignment_, &pixels_size)) {
5982 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions too large");
5983 return;
5984 }
5985 scoped_array<char> zero(new char[pixels_size]);
5986 memset(zero.get(), 0, pixels_size);
5987 glTexImage2D(target, level, internal_format, width, height, 0,
5988 internal_format, GL_UNSIGNED_BYTE, zero.get());
5989 if (copyHeight > 0 && copyWidth > 0) {
5990 GLint dx = copyX - x;
5991 GLint dy = copyY - y;
5992 GLint destX = dx;
5993 GLint destY = dy;
5994 glCopyTexSubImage2D(target, level,
5995 destX, destY, copyX, copyY,
5996 copyWidth, copyHeight);
5997 }
5998 } else {
5999 glCopyTexImage2D(target, level, internal_format,
6000 copyX, copyY, copyWidth, copyHeight, border);
6001 }
[email protected]1002c2d2011-06-28 22:39:046002 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436003 if (error == GL_NO_ERROR) {
6004 texture_manager()->SetLevelInfo(
[email protected]915a59a12010-09-30 21:29:116005 feature_info_, info, target, level, internal_format, width, height, 1,
6006 border, internal_format, GL_UNSIGNED_BYTE);
[email protected]cadde4a2010-07-31 17:10:436007 }
6008}
6009
6010void GLES2DecoderImpl::DoCopyTexSubImage2D(
6011 GLenum target,
6012 GLint level,
6013 GLint xoffset,
6014 GLint yoffset,
6015 GLint x,
6016 GLint y,
6017 GLsizei width,
6018 GLsizei height) {
6019 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6020 if (!info) {
6021 SetGLError(GL_INVALID_OPERATION,
6022 "glCopyTexSubImage2D: unknown texture for target");
6023 return;
6024 }
6025 GLenum type = 0;
6026 GLenum format = 0;
6027 if (!info->GetLevelType(target, level, &type, &format) ||
6028 !info->ValidForTexture(
6029 target, level, xoffset, yoffset, width, height, format, type)) {
6030 SetGLError(GL_INVALID_VALUE,
6031 "glCopyTexSubImage2D: bad dimensions.");
6032 return;
6033 }
[email protected]9edc6b22010-12-23 02:00:266034
6035 // Check we have compatible formats.
6036 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6037 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6038 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
6039
6040 if ((channels_needed & channels_exist) != channels_needed) {
6041 SetGLError(
6042 GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
6043 return;
6044 }
6045
[email protected]de26b3c2011-08-03 21:54:276046 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:036047 gfx::Size size = GetBoundReadFrameBufferSize();
6048 GLint copyX = 0;
6049 GLint copyY = 0;
6050 GLint copyWidth = 0;
6051 GLint copyHeight = 0;
6052 Clip(x, width, size.width(), &copyX, &copyWidth);
6053 Clip(y, height, size.height(), &copyY, &copyHeight);
6054 if (copyX != x ||
6055 copyY != y ||
6056 copyWidth != width ||
6057 copyHeight != height) {
6058 // some part was clipped so clear the texture.
6059 uint32 pixels_size = 0;
6060 if (!GLES2Util::ComputeImageDataSize(
6061 width, height, format, type, unpack_alignment_, &pixels_size)) {
6062 SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large");
6063 return;
6064 }
6065 scoped_array<char> zero(new char[pixels_size]);
6066 memset(zero.get(), 0, pixels_size);
6067 glTexSubImage2D(
6068 target, level, xoffset, yoffset, width, height,
6069 format, type, zero.get());
6070 }
6071 if (copyHeight > 0 && copyWidth > 0) {
6072 GLint dx = copyX - x;
6073 GLint dy = copyY - y;
6074 GLint destX = xoffset + dx;
6075 GLint destY = yoffset + dy;
6076 glCopyTexSubImage2D(target, level,
6077 destX, destY, copyX, copyY,
6078 copyWidth, copyHeight);
6079 }
[email protected]cadde4a2010-07-31 17:10:436080}
6081
6082void GLES2DecoderImpl::DoTexSubImage2D(
6083 GLenum target,
6084 GLint level,
6085 GLint xoffset,
6086 GLint yoffset,
6087 GLsizei width,
6088 GLsizei height,
6089 GLenum format,
6090 GLenum type,
6091 const void * data) {
6092 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6093 if (!info) {
6094 SetGLError(GL_INVALID_OPERATION,
6095 "glTexSubImage2D: unknown texture for target");
6096 return;
6097 }
[email protected]df6cf1ad2011-01-29 01:20:526098 GLenum current_type = 0;
6099 GLenum internal_format = 0;
6100 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
6101 SetGLError(
6102 GL_INVALID_OPERATION,
6103 "glTexSubImage2D: level does not exist.");
6104 return;
6105 }
6106 if (format != internal_format) {
6107 SetGLError(GL_INVALID_OPERATION,
6108 "glTexSubImage2D: format does not match internal format.");
6109 return;
6110 }
6111 if (type != current_type) {
6112 SetGLError(GL_INVALID_OPERATION,
6113 "glTexSubImage2D: type does not match type of texture.");
6114 return;
6115 }
6116
[email protected]cadde4a2010-07-31 17:10:436117 if (!info->ValidForTexture(
6118 target, level, xoffset, yoffset, width, height, format, type)) {
6119 SetGLError(GL_INVALID_VALUE,
6120 "glTexSubImage2D: bad dimensions.");
6121 return;
6122 }
[email protected]473c01ccb2011-06-07 01:33:306123
6124 // See if we can call glTexImage2D instead since it appears to be faster.
6125 if (teximage2d_faster_than_texsubimage2d_ && xoffset == 0 && yoffset == 0) {
6126 GLsizei tex_width = 0;
6127 GLsizei tex_height = 0;
6128 bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height);
6129 DCHECK(ok);
6130 if (width == tex_width && height == tex_height) {
6131 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
6132 // same as internal_foramt. If that changes we'll need to look them up.
6133 WrappedTexImage2D(
6134 target, level, format, width, height, 0, format, type, data);
6135 return;
6136 }
6137 }
[email protected]cadde4a2010-07-31 17:10:436138 glTexSubImage2D(
6139 target, level, xoffset, yoffset, width, height, format, type, data);
6140}
6141
[email protected]b493ee622011-04-13 23:52:006142error::Error GLES2DecoderImpl::HandleTexSubImage2D(
6143 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]366ae242011-05-10 02:23:586144 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:006145 GLboolean internal = static_cast<GLboolean>(c.internal);
6146 if (internal == GL_TRUE && tex_image_2d_failed_)
6147 return error::kNoError;
6148
6149 GLenum target = static_cast<GLenum>(c.target);
6150 GLint level = static_cast<GLint>(c.level);
6151 GLint xoffset = static_cast<GLint>(c.xoffset);
6152 GLint yoffset = static_cast<GLint>(c.yoffset);
6153 GLsizei width = static_cast<GLsizei>(c.width);
6154 GLsizei height = static_cast<GLsizei>(c.height);
6155 GLenum format = static_cast<GLenum>(c.format);
6156 GLenum type = static_cast<GLenum>(c.type);
6157 uint32 data_size;
6158 if (!GLES2Util::ComputeImageDataSize(
6159 width, height, format, type, unpack_alignment_, &data_size)) {
6160 return error::kOutOfBounds;
6161 }
6162 const void* pixels = GetSharedMemoryAs<const void*>(
6163 c.pixels_shm_id, c.pixels_shm_offset, data_size);
6164 if (!validators_->texture_target.IsValid(target)) {
6165 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
6166 return error::kNoError;
6167 }
6168 if (width < 0) {
6169 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
6170 return error::kNoError;
6171 }
6172 if (height < 0) {
6173 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
6174 return error::kNoError;
6175 }
6176 if (!validators_->texture_format.IsValid(format)) {
6177 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
6178 return error::kNoError;
6179 }
6180 if (!validators_->pixel_type.IsValid(type)) {
6181 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
6182 return error::kNoError;
6183 }
6184 if (pixels == NULL) {
6185 return error::kOutOfBounds;
6186 }
6187 DoTexSubImage2D(
6188 target, level, xoffset, yoffset, width, height, format, type, pixels);
6189 return error::kNoError;
6190}
6191
6192error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
6193 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
6194 GLboolean internal = static_cast<GLboolean>(c.internal);
6195 if (internal == GL_TRUE && tex_image_2d_failed_)
6196 return error::kNoError;
6197
6198 GLenum target = static_cast<GLenum>(c.target);
6199 GLint level = static_cast<GLint>(c.level);
6200 GLint xoffset = static_cast<GLint>(c.xoffset);
6201 GLint yoffset = static_cast<GLint>(c.yoffset);
6202 GLsizei width = static_cast<GLsizei>(c.width);
6203 GLsizei height = static_cast<GLsizei>(c.height);
6204 GLenum format = static_cast<GLenum>(c.format);
6205 GLenum type = static_cast<GLenum>(c.type);
6206 uint32 data_size;
6207 if (!GLES2Util::ComputeImageDataSize(
6208 width, height, format, type, unpack_alignment_, &data_size)) {
6209 return error::kOutOfBounds;
6210 }
6211 const void* pixels = GetImmediateDataAs<const void*>(
6212 c, data_size, immediate_data_size);
6213 if (!validators_->texture_target.IsValid(target)) {
6214 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
6215 return error::kNoError;
6216 }
6217 if (width < 0) {
6218 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
6219 return error::kNoError;
6220 }
6221 if (height < 0) {
6222 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
6223 return error::kNoError;
6224 }
6225 if (!validators_->texture_format.IsValid(format)) {
6226 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
6227 return error::kNoError;
6228 }
6229 if (!validators_->pixel_type.IsValid(type)) {
6230 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
6231 return error::kNoError;
6232 }
6233 if (pixels == NULL) {
6234 return error::kOutOfBounds;
6235 }
6236 DoTexSubImage2D(
6237 target, level, xoffset, yoffset, width, height, format, type, pixels);
6238 return error::kNoError;
6239}
6240
[email protected]f7a64ee2010-02-01 22:24:146241error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:196242 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:366243 GLuint index = static_cast<GLuint>(c.index);
6244 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:256245 typedef gles2::GetVertexAttribPointerv::Result Result;
6246 Result* result = GetSharedMemoryAs<Result*>(
6247 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:366248 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:146249 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:366250 }
[email protected]07d0cc82010-02-17 04:51:406251 // Check that the client initialized the result.
6252 if (result->size != 0) {
6253 return error::kInvalidArguments;
6254 }
[email protected]9438b012010-06-15 22:55:056255 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:296256 SetGLError(GL_INVALID_ENUM,
6257 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:146258 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:366259 }
[email protected]3916c97e2010-02-25 03:20:506260 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:296261 SetGLError(GL_INVALID_VALUE,
6262 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:146263 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:366264 }
[email protected]0bfd9882010-02-05 23:02:256265 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:086266 *result->GetData() =
6267 vertex_attrib_manager_.GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:146268 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326269}
6270
[email protected]f7b85372010-02-03 01:11:376271bool GLES2DecoderImpl::GetUniformSetup(
6272 GLuint program, GLint location,
6273 uint32 shm_id, uint32 shm_offset,
[email protected]939e7362010-05-13 20:49:106274 error::Error* error, GLuint* service_id, void** result_pointer,
6275 GLenum* result_type) {
6276 DCHECK(error);
6277 DCHECK(service_id);
6278 DCHECK(result_pointer);
6279 DCHECK(result_type);
[email protected]f7b85372010-02-03 01:11:376280 *error = error::kNoError;
6281 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:256282 SizedResult<GLint>* result;
6283 result = GetSharedMemoryAs<SizedResult<GLint>*>(
6284 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
6285 if (!result) {
[email protected]f7b85372010-02-03 01:11:376286 *error = error::kOutOfBounds;
6287 return false;
6288 }
[email protected]0bfd9882010-02-05 23:02:256289 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:376290 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:256291 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:586292 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6293 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:376294 if (!info) {
[email protected]ae51d192010-04-27 00:48:036295 return false;
6296 }
6297 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:376298 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:296299 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:376300 return false;
6301 }
[email protected]ae51d192010-04-27 00:48:036302 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:366303 GLint array_index = -1;
6304 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
6305 info->GetUniformInfoByLocation(location, &array_index);
6306 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:376307 // No such location.
[email protected]8eee29c2010-04-29 03:38:296308 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:376309 return false;
6310 }
[email protected]43c2f1f2011-03-25 18:35:366311 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:506312 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:376313 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:296314 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:376315 return false;
6316 }
[email protected]0bfd9882010-02-05 23:02:256317 result = GetSharedMemoryAs<SizedResult<GLint>*>(
6318 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
6319 if (!result) {
[email protected]f7b85372010-02-03 01:11:376320 *error = error::kOutOfBounds;
6321 return false;
6322 }
[email protected]0bfd9882010-02-05 23:02:256323 result->size = size;
[email protected]939e7362010-05-13 20:49:106324 *result_type = type;
[email protected]f7b85372010-02-03 01:11:376325 return true;
6326}
6327
[email protected]f7a64ee2010-02-01 22:24:146328error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:196329 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:376330 GLuint program = c.program;
6331 GLint location = c.location;
6332 GLuint service_id;
[email protected]939e7362010-05-13 20:49:106333 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:376334 Error error;
[email protected]0bfd9882010-02-05 23:02:256335 void* result;
[email protected]f7b85372010-02-03 01:11:376336 if (GetUniformSetup(
6337 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:106338 &error, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:256339 glGetUniformiv(
6340 service_id, location,
6341 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:376342 }
6343 return error;
[email protected]96449d2c2009-11-25 00:01:326344}
6345
[email protected]f7a64ee2010-02-01 22:24:146346error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:196347 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:376348 GLuint program = c.program;
6349 GLint location = c.location;
6350 GLuint service_id;
6351 Error error;
[email protected]0bfd9882010-02-05 23:02:256352 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:106353 Result* result;
6354 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:376355 if (GetUniformSetup(
6356 program, location, c.params_shm_id, c.params_shm_offset,
[email protected]939e7362010-05-13 20:49:106357 &error, &service_id, reinterpret_cast<void**>(&result), &result_type)) {
6358 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
6359 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
6360 GLsizei num_values = result->GetNumResults();
6361 scoped_array<GLint> temp(new GLint[num_values]);
6362 glGetUniformiv(service_id, location, temp.get());
6363 GLfloat* dst = result->GetData();
6364 for (GLsizei ii = 0; ii < num_values; ++ii) {
6365 dst[ii] = (temp[ii] != 0);
6366 }
6367 } else {
6368 glGetUniformfv(service_id, location, result->GetData());
6369 }
[email protected]f7b85372010-02-03 01:11:376370 }
6371 return error;
[email protected]96449d2c2009-11-25 00:01:326372}
6373
[email protected]f7a64ee2010-02-01 22:24:146374error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:196375 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:256376 GLenum shader_type = static_cast<GLenum>(c.shadertype);
6377 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
6378 typedef gles2::GetShaderPrecisionFormat::Result Result;
6379 Result* result = GetSharedMemoryAs<Result*>(
6380 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6381 if (!result) {
6382 return error::kOutOfBounds;
6383 }
[email protected]07d0cc82010-02-17 04:51:406384 // Check that the client initialized the result.
6385 if (result->success != 0) {
6386 return error::kInvalidArguments;
6387 }
[email protected]9438b012010-06-15 22:55:056388 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:296389 SetGLError(GL_INVALID_ENUM,
6390 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
6391 return error::kNoError;
6392 }
[email protected]9438b012010-06-15 22:55:056393 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:296394 SetGLError(GL_INVALID_ENUM,
6395 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
6396 return error::kNoError;
6397 }
6398
6399 result->success = 1; // true
6400 switch (precision_type) {
6401 case GL_LOW_INT:
6402 case GL_MEDIUM_INT:
6403 case GL_HIGH_INT:
6404 result->min_range = -31;
6405 result->max_range = 31;
6406 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:106407 break;
[email protected]8eee29c2010-04-29 03:38:296408 case GL_LOW_FLOAT:
6409 case GL_MEDIUM_FLOAT:
6410 case GL_HIGH_FLOAT:
6411 result->min_range = -62;
6412 result->max_range = 62;
6413 result->precision = -16;
6414 break;
6415 default:
6416 NOTREACHED();
6417 break;
[email protected]0bfd9882010-02-05 23:02:256418 }
[email protected]f7a64ee2010-02-01 22:24:146419 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326420}
6421
[email protected]f7a64ee2010-02-01 22:24:146422error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:196423 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:256424 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:586425 GLuint program = static_cast<GLuint>(c.program);
6426 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6427 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:036428 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256429 return error::kNoError;
6430 }
6431 typedef gles2::GetAttachedShaders::Result Result;
6432 uint32 max_count = Result::ComputeMaxResults(result_size);
6433 Result* result = GetSharedMemoryAs<Result*>(
6434 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
6435 if (!result) {
6436 return error::kOutOfBounds;
6437 }
[email protected]07d0cc82010-02-17 04:51:406438 // Check that the client initialized the result.
6439 if (result->size != 0) {
6440 return error::kInvalidArguments;
6441 }
[email protected]0bfd9882010-02-05 23:02:256442 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:036443 glGetAttachedShaders(
6444 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:256445 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:036446 if (!shader_manager()->GetClientId(result->GetData()[ii],
6447 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:256448 NOTREACHED();
6449 return error::kGenericError;
6450 }
6451 }
6452 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:146453 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326454}
6455
[email protected]f7a64ee2010-02-01 22:24:146456error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:196457 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:256458 GLuint program = c.program;
6459 GLuint index = c.index;
6460 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:256461 typedef gles2::GetActiveUniform::Result Result;
6462 Result* result = GetSharedMemoryAs<Result*>(
6463 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6464 if (!result) {
6465 return error::kOutOfBounds;
6466 }
[email protected]07d0cc82010-02-17 04:51:406467 // Check that the client initialized the result.
6468 if (result->success != 0) {
6469 return error::kInvalidArguments;
6470 }
[email protected]6b8cf1a2010-05-06 16:13:586471 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6472 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:036473 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256474 return error::kNoError;
6475 }
6476 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
6477 info->GetUniformInfo(index);
6478 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:296479 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:256480 return error::kNoError;
6481 }
6482 result->success = 1; // true.
6483 result->size = uniform_info->size;
6484 result->type = uniform_info->type;
6485 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:296486 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:146487 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326488}
6489
[email protected]f7a64ee2010-02-01 22:24:146490error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:196491 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:256492 GLuint program = c.program;
6493 GLuint index = c.index;
6494 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:256495 typedef gles2::GetActiveAttrib::Result Result;
6496 Result* result = GetSharedMemoryAs<Result*>(
6497 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6498 if (!result) {
6499 return error::kOutOfBounds;
6500 }
[email protected]07d0cc82010-02-17 04:51:406501 // Check that the client initialized the result.
6502 if (result->success != 0) {
6503 return error::kInvalidArguments;
6504 }
[email protected]6b8cf1a2010-05-06 16:13:586505 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6506 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:036507 if (!info) {
[email protected]0bfd9882010-02-05 23:02:256508 return error::kNoError;
6509 }
6510 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
6511 info->GetAttribInfo(index);
6512 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:296513 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:256514 return error::kNoError;
6515 }
6516 result->success = 1; // true.
6517 result->size = attrib_info->size;
6518 result->type = attrib_info->type;
6519 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:296520 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:146521 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326522}
6523
[email protected]b273e432010-04-12 17:23:586524error::Error GLES2DecoderImpl::HandleShaderBinary(
6525 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
6526#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:296527 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:586528 return error::kNoError;
6529#else
6530 GLsizei n = static_cast<GLsizei>(c.n);
6531 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:296532 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:586533 return error::kNoError;
6534 }
6535 GLsizei length = static_cast<GLsizei>(c.length);
6536 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:296537 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:586538 return error::kNoError;
6539 }
6540 uint32 data_size;
6541 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
6542 return error::kOutOfBounds;
6543 }
6544 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
6545 c.shaders_shm_id, c.shaders_shm_offset, data_size);
6546 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
6547 const void* binary = GetSharedMemoryAs<const void*>(
6548 c.binary_shm_id, c.binary_shm_offset, length);
6549 if (shaders == NULL || binary == NULL) {
6550 return error::kOutOfBounds;
6551 }
6552 scoped_array<GLuint> service_ids(new GLuint[n]);
6553 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:036554 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
6555 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296556 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:586557 return error::kNoError;
6558 }
[email protected]ae51d192010-04-27 00:48:036559 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:586560 }
6561 // TODO(gman): call glShaderBinary
6562 return error::kNoError;
6563#endif
6564}
6565
[email protected]6217d392010-03-25 22:08:356566error::Error GLES2DecoderImpl::HandleSwapBuffers(
6567 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:496568 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
6569 int this_frame_number = frame_number_++;
6570 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
6571 "offscreen", is_offscreen,
6572 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:356573 // If offscreen then don't actually SwapBuffers to the display. Just copy
6574 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:496575 if (is_offscreen) {
[email protected]6217d392010-03-25 22:08:356576 ScopedGLErrorSuppressor suppressor(this);
6577
[email protected]34ff8b0c2010-10-01 20:06:026578 if (IsOffscreenBufferMultisampled()) {
6579 // For multisampled buffers, bind the resolved frame buffer so that
6580 // callbacks can call ReadPixels or CopyTexImage2D.
[email protected]de26b3c2011-08-03 21:54:276581 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]34ff8b0c2010-10-01 20:06:026582 if (swap_buffers_callback_.get()) {
6583 swap_buffers_callback_->Run();
6584 }
[email protected]89d6ed02011-04-20 00:23:236585 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:486586 } else {
[email protected]0c8c9d22010-06-25 17:36:396587 ScopedFrameBufferBinder binder(this,
6588 offscreen_target_frame_buffer_->id());
[email protected]c007aa02010-09-02 22:22:406589
[email protected]9a5afa432011-07-22 18:16:396590 if (surface_->IsOffscreen()) {
[email protected]b86b14982010-10-11 18:45:486591 // Copy the target frame buffer to the saved offscreen texture.
6592 offscreen_saved_color_texture_->Copy(
[email protected]3a4d0c52011-06-29 23:11:586593 offscreen_saved_color_texture_->size(),
6594 offscreen_saved_color_format_);
[email protected]b86b14982010-10-11 18:45:486595
[email protected]a3ded6d2010-10-19 06:44:396596 // Ensure the side effects of the copy are visible to the parent
6597 // context. There is no need to do this for ANGLE because it uses a
6598 // single D3D device for all contexts.
[email protected]b86b14982010-10-11 18:45:486599 if (!IsAngle())
6600 glFlush();
6601 }
6602
6603 // Run the callback with |binder| in scope, so that the callback can call
6604 // ReadPixels or CopyTexImage2D.
6605 if (swap_buffers_callback_.get()) {
6606 swap_buffers_callback_->Run();
6607 }
[email protected]89d6ed02011-04-20 00:23:236608 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:396609 }
[email protected]6217d392010-03-25 22:08:356610 } else {
[email protected]64ace852011-05-19 21:49:496611 TRACE_EVENT1("gpu", "GLContext::SwapBuffers", "frame", this_frame_number);
[email protected]f62a5ab2011-05-23 20:34:156612 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:016613 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:026614 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:016615 }
[email protected]6217d392010-03-25 22:08:356616 }
6617
6618 if (swap_buffers_callback_.get()) {
6619 swap_buffers_callback_->Run();
6620 }
6621
[email protected]89d6ed02011-04-20 00:23:236622 return error::kNoError;
[email protected]6217d392010-03-25 22:08:356623}
6624
[email protected]d4239852011-08-12 04:51:226625error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
6626 uint32 immediate_data_size, const gles2::EnableFeatureCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:186627 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]d4239852011-08-12 04:51:226628 typedef gles2::EnableFeatureCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:186629 Result* result = GetSharedMemoryAs<Result*>(
6630 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6631 if (!result) {
6632 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:106633 }
[email protected]b1d2dcb2010-05-17 19:24:186634 // Check that the client initialized the result.
6635 if (*result != 0) {
6636 return error::kInvalidArguments;
6637 }
6638 std::string feature_str;
6639 if (!bucket->GetAsString(&feature_str)) {
6640 return error::kInvalidArguments;
6641 }
6642
6643 // TODO(gman): make this some kind of table to function pointer thingy.
[email protected]d4239852011-08-12 04:51:226644 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
[email protected]b1d2dcb2010-05-17 19:24:186645 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]d4239852011-08-12 04:51:226646 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
[email protected]8fbedc02010-11-18 18:43:406647 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
6648 // TODO(gman): decide how to remove the need for this const_cast.
6649 // I could make validators_ non const but that seems bad as this is the only
6650 // place it is needed. I could make some special friend class of validators
6651 // just to allow this to set them. That seems silly. I could refactor this
6652 // code to use the extension mechanism or the initialization attributes to
6653 // turn this feature on. Given that the only real point of this is to make
6654 // the conformance tests pass and given that there is lots of real work that
6655 // needs to be done it seems like refactoring for one to one of those
6656 // methods is a very low priority.
6657 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]b1d2dcb2010-05-17 19:24:186658 } else {
6659 return error::kNoError;
6660 }
6661
6662 *result = 1; // true.
6663 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:106664}
6665
[email protected]c2f8c8402010-12-06 18:07:246666error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
6667 uint32 immediate_data_size,
6668 const gles2::GetRequestableExtensionsCHROMIUM& c) {
6669 Bucket* bucket = CreateBucket(c.bucket_id);
6670 scoped_ptr<FeatureInfo> info(new FeatureInfo());
[email protected]c410da802011-03-14 19:17:416671 info->Initialize(disallowed_extensions_, NULL);
[email protected]c2f8c8402010-12-06 18:07:246672 bucket->SetFromString(info->extensions().c_str());
6673 return error::kNoError;
6674}
6675
6676error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
6677 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
6678 Bucket* bucket = GetBucket(c.bucket_id);
6679 std::string feature_str;
6680 if (!bucket->GetAsString(&feature_str)) {
6681 return error::kInvalidArguments;
6682 }
6683
6684 bool std_derivatives_enabled =
6685 feature_info_->feature_flags().oes_standard_derivatives;
6686 bool webglsl_enabled =
6687 feature_info_->feature_flags().chromium_webglsl;
6688
6689 feature_info_->AddFeatures(feature_str.c_str());
6690
6691 // If we just enabled a feature which affects the shader translator,
6692 // we may need to re-initialize it.
6693 if (std_derivatives_enabled !=
6694 feature_info_->feature_flags().oes_standard_derivatives ||
6695 webglsl_enabled !=
6696 feature_info_->feature_flags().chromium_webglsl) {
6697 InitializeShaderTranslator();
6698 }
6699
[email protected]302ce6d2011-07-07 23:28:116700 UpdateCapabilities();
6701
[email protected]c2f8c8402010-12-06 18:07:246702 return error::kNoError;
6703}
6704
[email protected]372e0412011-06-28 16:08:566705error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
6706 uint32 immediate_data_size, const gles2::GetMultipleIntegervCHROMIUM& c) {
6707 GLuint count = c.count;
6708 uint32 pnames_size;
6709 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
6710 return error::kOutOfBounds;
6711 }
6712 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
6713 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
6714 if (pnames == NULL) {
6715 return error::kOutOfBounds;
6716 }
6717
6718 // We have to copy them since we use them twice so the client
6719 // can't change them between the time we validate them and the time we use
6720 // them.
6721 scoped_array<GLenum> enums(new GLenum[count]);
6722 memcpy(enums.get(), pnames, pnames_size);
6723
6724 // Count up the space needed for the result.
6725 uint32 num_results = 0;
6726 for (GLuint ii = 0; ii < count; ++ii) {
6727 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
6728 if (num == 0) {
6729 SetGLError(GL_INVALID_ENUM,
6730 "glGetMulitpleCHROMIUM: pname GL_INVALID_ENUM");
6731 return error::kNoError;
6732 }
6733 // Num will never be more than 4.
6734 DCHECK_LE(num, 4u);
6735 if (!SafeAdd(num_results, num, &num_results)) {
6736 return error::kOutOfBounds;
6737 }
6738 }
6739
6740 uint32 result_size = 0;
6741 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
6742 return error::kOutOfBounds;
6743 }
6744
6745 if (result_size != static_cast<uint32>(c.size)) {
6746 SetGLError(GL_INVALID_VALUE,
6747 "glGetMulitpleCHROMIUM: bad size GL_INVALID_VALUE");
6748 return error::kNoError;
6749 }
6750
6751 GLint* results = GetSharedMemoryAs<GLint*>(
6752 c.results_shm_id, c.results_shm_offset, result_size);
6753 if (results == NULL) {
6754 return error::kOutOfBounds;
6755 }
6756
6757 // Check the results have been cleared in case the context was lost.
6758 for (uint32 ii = 0; ii < num_results; ++ii) {
6759 if (results[ii]) {
6760 return error::kInvalidArguments;
6761 }
6762 }
6763
6764 // Get each result.
6765 GLint* start = results;
6766 for (GLuint ii = 0; ii < count; ++ii) {
6767 GLsizei num_written = 0;
6768 if (!GetHelper(enums[ii], results, &num_written)) {
6769 glGetIntegerv(enums[ii], results);
6770 }
6771 results += num_written;
6772 }
6773
6774 // Just to verify. Should this be a DCHECK?
6775 if (static_cast<uint32>(results - start) != num_results) {
6776 return error::kOutOfBounds;
6777 }
6778
6779 return error::kNoError;
6780}
6781
[email protected]2318d342011-07-11 22:27:426782error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
6783 uint32 immediate_data_size, const gles2::GetProgramInfoCHROMIUM& c) {
6784 GLuint program = static_cast<GLuint>(c.program);
6785 uint32 bucket_id = c.bucket_id;
6786 Bucket* bucket = CreateBucket(bucket_id);
6787 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
6788 ProgramManager::ProgramInfo* info = NULL;
[email protected]9a14ae612011-08-08 17:51:466789 info = GetProgramInfo(program);
6790 if (!info || !info->IsValid()) {
6791 return error::kNoError;
[email protected]2318d342011-07-11 22:27:426792 }
6793 info->GetProgramInfo(bucket);
6794 return error::kNoError;
6795}
6796
[email protected]38d139d2011-07-14 00:38:436797error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
6798 switch (reset_status_) {
6799 case GL_NO_ERROR:
6800 // TODO(kbr): improve the precision of the error code in this case.
6801 // Consider delegating to context for error code if MakeCurrent fails.
6802 return error::kUnknown;
6803 case GL_GUILTY_CONTEXT_RESET_ARB:
6804 return error::kGuilty;
6805 case GL_INNOCENT_CONTEXT_RESET_ARB:
6806 return error::kInnocent;
6807 case GL_UNKNOWN_CONTEXT_RESET_ARB:
6808 return error::kUnknown;
6809 }
6810
6811 NOTREACHED();
6812 return error::kUnknown;
6813}
6814
6815bool GLES2DecoderImpl::WasContextLost() {
6816 if (context_->WasAllocatedUsingARBRobustness() && has_arb_robustness_) {
6817 GLenum status = glGetGraphicsResetStatusARB();
6818 if (status != GL_NO_ERROR) {
6819 // The graphics card was reset. Signal a lost context to the application.
6820 reset_status_ = status;
6821 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
6822 << " context lost via ARB_robustness. Reset status = 0x"
6823 << std::hex << status << std::dec;
6824 return true;
6825 }
6826 }
6827 return false;
6828}
6829
[email protected]96449d2c2009-11-25 00:01:326830// Include the auto-generated part of this file. We split this because it means
6831// we can easily edit the non-auto generated parts right here in this file
6832// instead of having to edit some template or the code generator.
6833#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
6834
6835} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:256836} // namespace gpu