blob: 9021bd1ef2421d478cb6599ad59bc4d3733cb620 [file] [log] [blame]
[email protected]529c6672012-01-04 02:18:261// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]96449d2c2009-11-25 00:01:322// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]8a837bb2010-01-05 00:21:245#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
[email protected]74470702010-01-06 18:51:166
7#include <stdio.h>
8
[email protected]1aef98132010-02-23 18:00:079#include <algorithm>
[email protected]f39f4b3f2010-05-12 17:04:0810#include <list>
[email protected]96449d2c2009-11-25 00:01:3211#include <map>
[email protected]f39f4b3f2010-05-12 17:04:0812#include <string>
13#include <vector>
[email protected]5a6db6c2010-04-22 18:32:0614
[email protected]1e6f58d2011-03-24 00:00:4015#include "base/atomicops.h"
[email protected]00eb49a2010-08-12 20:46:5716#include "base/at_exit.h"
[email protected]9d37f062011-11-22 01:24:5217#include "base/bind.h"
[email protected]e844ae22012-01-14 03:36:2618#include "base/command_line.h"
[email protected]1078f912011-12-23 13:12:1419#include "base/debug/trace_event.h"
[email protected]e51bdf32011-11-23 22:21:4620#if defined(OS_MACOSX)
21#include "base/mac/scoped_cftyperef.h"
22#endif
[email protected]3b63f8f42011-03-28 01:54:1523#include "base/memory/scoped_ptr.h"
24#include "base/memory/weak_ptr.h"
[email protected]d37231fa2010-04-09 21:16:0225#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3226#define GLES2_GPU_SERVICE 1
27#include "gpu/command_buffer/common/gles2_cmd_format.h"
28#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1029#include "gpu/command_buffer/common/id_allocator.h"
[email protected]3916c97e2010-02-25 03:20:5030#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3231#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5032#include "gpu/command_buffer/service/context_group.h"
[email protected]915a59a12010-09-30 21:29:1133#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5834#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3235#include "gpu/command_buffer/service/gl_utils.h"
[email protected]ba3176a2009-12-16 18:19:4636#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]e844ae22012-01-14 03:36:2637#include "gpu/command_buffer/service/gpu_switches.h"
[email protected]a93bb842010-02-16 23:03:4738#include "gpu/command_buffer/service/program_manager.h"
[email protected]882ba1e22012-03-08 19:02:5339#include "gpu/command_buffer/service/query_manager.h"
[email protected]a25fa872010-03-25 02:57:5840#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4741#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4542#include "gpu/command_buffer/service/shader_translator.h"
[email protected]b0af4f52011-09-28 22:04:4243#include "gpu/command_buffer/service/stream_texture.h"
44#include "gpu/command_buffer/service/stream_texture_manager.h"
[email protected]a93bb842010-02-16 23:03:4745#include "gpu/command_buffer/service/texture_manager.h"
[email protected]d8ea9772011-07-11 18:11:4346#include "gpu/command_buffer/service/vertex_attrib_manager.h"
[email protected]5ae0b282011-03-28 19:24:4947#include "ui/gfx/gl/gl_context.h"
48#include "ui/gfx/gl/gl_implementation.h"
[email protected]f62a5ab2011-05-23 20:34:1549#include "ui/gfx/gl/gl_surface.h"
[email protected]e51bdf32011-11-23 22:21:4650#if defined(OS_MACOSX)
51#include "ui/gfx/surface/io_surface_support_mac.h"
52#endif
[email protected]de17df392010-04-23 21:09:4153
[email protected]6217d392010-03-25 22:08:3554#if !defined(GL_DEPTH24_STENCIL8)
55#define GL_DEPTH24_STENCIL8 0x88F0
56#endif
57
[email protected]a7a27ace2009-12-12 00:11:2558namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3259namespace gles2 {
60
[email protected]f0d74742011-10-03 16:31:0461namespace {
62static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
63}
64
[email protected]6217d392010-03-25 22:08:3565class GLES2DecoderImpl;
66
[email protected]07f54fcc2009-12-22 02:46:3067// Check that certain assumptions the code makes are true. There are places in
68// the code where shared memory is passed direclty to GL. Example, glUniformiv,
69// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
70// a few others) are 32bits. If they are not 32bits the code will have to change
71// to call those GL functions with service side memory and then copy the results
72// to shared memory, converting the sizes.
73COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
74 GLint_not_same_size_as_uint32);
75COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
76 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3777COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
78 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3079
[email protected]43f28f832010-02-03 02:28:4880// TODO(kbr): the use of this anonymous namespace core dumps the
81// linker on Mac OS X 10.6 when the symbol ordering file is used
82// namespace {
[email protected]96449d2c2009-11-25 00:01:3283
84// Returns the address of the first byte after a struct.
85template <typename T>
86const void* AddressAfterStruct(const T& pod) {
87 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
88}
89
[email protected]07f54fcc2009-12-22 02:46:3090// Returns the address of the frst byte after the struct or NULL if size >
91// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3292template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3093RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
94 uint32 size,
95 uint32 immediate_data_size) {
96 return (size <= immediate_data_size) ?
97 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
98 NULL;
[email protected]96449d2c2009-11-25 00:01:3299}
100
[email protected]07f54fcc2009-12-22 02:46:30101// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:18102bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:32103 GLuint count,
104 size_t size,
[email protected]a76b0052010-03-05 00:33:18105 unsigned int elements_per_unit,
106 uint32* dst) {
107 uint32 value;
108 if (!SafeMultiplyUint32(count, size, &value)) {
109 return false;
110 }
111 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
112 return false;
113 }
114 *dst = value;
115 return true;
[email protected]96449d2c2009-11-25 00:01:32116}
117
118// A struct to hold info about each command.
119struct CommandInfo {
120 int arg_flags; // How to handle the arguments for this command
121 int arg_count; // How many arguments are expected for this command.
122};
123
124// A table of CommandInfo for all the commands.
125const CommandInfo g_command_info[] = {
126 #define GLES2_CMD_OP(name) { \
127 name::kArgFlags, \
128 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
129
130 GLES2_COMMAND_LIST(GLES2_CMD_OP)
131
132 #undef GLES2_CMD_OP
133};
134
[email protected]258a3313f2011-10-18 20:13:57135// Return true if a character belongs to the ASCII subset as defined in
136// GLSL ES 1.0 spec section 3.1.
137static bool CharacterIsValidForGLES(unsigned char c) {
138 // Printing characters are valid except " $ ` @ \ ' DEL.
139 if (c >= 32 && c <= 126 &&
140 c != '"' &&
141 c != '$' &&
142 c != '`' &&
143 c != '@' &&
144 c != '\\' &&
145 c != '\'') {
146 return true;
147 }
148 // Horizontal tab, line feed, vertical tab, form feed, carriage return
149 // are also valid.
150 if (c >= 9 && c <= 13) {
151 return true;
152 }
153
154 return false;
155}
156
157static bool StringIsValidForGLES(const char* str) {
158 for (; *str; ++str) {
159 if (!CharacterIsValidForGLES(*str)) {
160 return false;
161 }
162 }
163 return true;
164}
165
[email protected]f0e6a34f2012-01-04 20:53:40166static inline GLenum GetTexInternalFormat(GLenum internal_format) {
167 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
168 if (internal_format == GL_BGRA_EXT || internal_format == GL_BGRA8_EXT)
169 return GL_RGBA8;
170 }
171 return internal_format;
172}
173
[email protected]297ca1c2011-06-20 23:08:46174static void WrappedTexImage2D(
[email protected]473c01ccb2011-06-07 01:33:30175 GLenum target,
176 GLint level,
177 GLenum internal_format,
178 GLsizei width,
179 GLsizei height,
180 GLint border,
181 GLenum format,
182 GLenum type,
183 const void* pixels) {
[email protected]f0e6a34f2012-01-04 20:53:40184 GLenum gl_internal_format = GetTexInternalFormat(internal_format);
[email protected]473c01ccb2011-06-07 01:33:30185 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]f0e6a34f2012-01-04 20:53:40186 if (type == GL_FLOAT) {
[email protected]58b75f92012-03-20 21:15:43187 switch (format) {
188 case GL_RGBA:
189 gl_internal_format = GL_RGBA32F_ARB;
190 break;
191 case GL_RGB:
192 gl_internal_format = GL_RGB32F_ARB;
193 break;
194 case GL_LUMINANCE_ALPHA:
195 gl_internal_format = GL_LUMINANCE_ALPHA32F_ARB;
196 break;
197 case GL_LUMINANCE:
198 gl_internal_format = GL_LUMINANCE32F_ARB;
199 break;
200 case GL_ALPHA:
201 gl_internal_format = GL_ALPHA32F_ARB;
202 break;
203 default:
204 NOTREACHED();
205 break;
[email protected]473c01ccb2011-06-07 01:33:30206 }
207 } else if (type == GL_HALF_FLOAT_OES) {
[email protected]58b75f92012-03-20 21:15:43208 switch (format) {
209 case GL_RGBA:
210 gl_internal_format = GL_RGBA16F_ARB;
211 break;
212 case GL_RGB:
213 gl_internal_format = GL_RGB16F_ARB;
214 break;
215 case GL_LUMINANCE_ALPHA:
216 gl_internal_format = GL_LUMINANCE_ALPHA16F_ARB;
217 break;
218 case GL_LUMINANCE:
219 gl_internal_format = GL_LUMINANCE16F_ARB;
220 break;
221 case GL_ALPHA:
222 gl_internal_format = GL_ALPHA16F_ARB;
223 break;
224 default:
225 NOTREACHED();
226 break;
[email protected]473c01ccb2011-06-07 01:33:30227 }
228 }
229 }
230 glTexImage2D(
231 target, level, gl_internal_format, width, height, border, format, type,
232 pixels);
233}
234
[email protected]297ca1c2011-06-20 23:08:46235// Wrapper for glEnable/glDisable that doesn't suck.
236static void EnableDisable(GLenum pname, bool enable) {
237 if (enable) {
238 glEnable(pname);
239 } else {
240 glDisable(pname);
241 }
242}
243
[email protected]6217d392010-03-25 22:08:35244// This class prevents any GL errors that occur when it is in scope from
245// being reported to the client.
246class ScopedGLErrorSuppressor {
247 public:
248 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
249 ~ScopedGLErrorSuppressor();
250 private:
251 GLES2DecoderImpl* decoder_;
252 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
253};
254
255// Temporarily changes a decoder's bound 2D texture and restore it when this
256// object goes out of scope. Also temporarily switches to using active texture
257// unit zero in case the client has changed that to something invalid.
258class ScopedTexture2DBinder {
259 public:
260 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
261 ~ScopedTexture2DBinder();
262
263 private:
264 GLES2DecoderImpl* decoder_;
265 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
266};
267
268// Temporarily changes a decoder's bound render buffer and restore it when this
269// object goes out of scope.
270class ScopedRenderBufferBinder {
271 public:
272 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
273 ~ScopedRenderBufferBinder();
274
275 private:
276 GLES2DecoderImpl* decoder_;
277 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
278};
279
280// Temporarily changes a decoder's bound frame buffer and restore it when this
281// object goes out of scope.
282class ScopedFrameBufferBinder {
283 public:
284 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
285 ~ScopedFrameBufferBinder();
286
287 private:
288 GLES2DecoderImpl* decoder_;
289 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
290};
291
[email protected]34ff8b0c2010-10-01 20:06:02292// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52293// the multisampled offscreen render buffer if that buffer is multisampled, and,
[email protected]de26b3c2011-08-03 21:54:27294// if it is bound or enforce_internal_framebuffer is true. If internal is
295// true, the resolved framebuffer is not visible to the parent.
[email protected]34ff8b0c2010-10-01 20:06:02296class ScopedResolvedFrameBufferBinder {
297 public:
[email protected]e7e38032011-07-26 17:25:25298 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
[email protected]de26b3c2011-08-03 21:54:27299 bool enforce_internal_framebuffer,
300 bool internal);
[email protected]34ff8b0c2010-10-01 20:06:02301 ~ScopedResolvedFrameBufferBinder();
302
303 private:
304 GLES2DecoderImpl* decoder_;
305 bool resolve_and_bind_;
306 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
307};
308
[email protected]6217d392010-03-25 22:08:35309// Encapsulates an OpenGL texture.
310class Texture {
311 public:
312 explicit Texture(GLES2DecoderImpl* decoder);
313 ~Texture();
314
315 // Create a new render texture.
316 void Create();
317
318 // Set the initial size and format of a render texture or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02319 bool AllocateStorage(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35320
321 // Copy the contents of the currently bound frame buffer.
[email protected]3a4d0c52011-06-29 23:11:58322 void Copy(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35323
324 // Destroy the render texture. This must be explicitly called before
325 // destroying this object.
326 void Destroy();
327
[email protected]97872062010-11-03 19:07:05328 // Invalidate the texture. This can be used when a context is lost and it is
329 // not possible to make it current in order to free the resource.
330 void Invalidate();
331
[email protected]6217d392010-03-25 22:08:35332 GLuint id() const {
333 return id_;
334 }
335
[email protected]d37231fa2010-04-09 21:16:02336 gfx::Size size() const {
337 return size_;
338 }
339
[email protected]1078f912011-12-23 13:12:14340 size_t estimated_size() const {
341 return estimated_size_;
342 }
343
[email protected]6217d392010-03-25 22:08:35344 private:
345 GLES2DecoderImpl* decoder_;
346 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02347 gfx::Size size_;
[email protected]1078f912011-12-23 13:12:14348 size_t estimated_size_;
[email protected]6217d392010-03-25 22:08:35349 DISALLOW_COPY_AND_ASSIGN(Texture);
350};
351
352// Encapsulates an OpenGL render buffer of any format.
353class RenderBuffer {
354 public:
355 explicit RenderBuffer(GLES2DecoderImpl* decoder);
356 ~RenderBuffer();
357
358 // Create a new render buffer.
359 void Create();
360
361 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02362 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35363
364 // Destroy the render buffer. This must be explicitly called before destroying
365 // this object.
366 void Destroy();
367
[email protected]97872062010-11-03 19:07:05368 // Invalidate the render buffer. This can be used when a context is lost and
369 // it is not possible to make it current in order to free the resource.
370 void Invalidate();
371
[email protected]6217d392010-03-25 22:08:35372 GLuint id() const {
373 return id_;
374 }
375
[email protected]1078f912011-12-23 13:12:14376 size_t estimated_size() const {
377 return estimated_size_;
378 }
379
[email protected]6217d392010-03-25 22:08:35380 private:
381 GLES2DecoderImpl* decoder_;
382 GLuint id_;
[email protected]1078f912011-12-23 13:12:14383 size_t estimated_size_;
[email protected]6217d392010-03-25 22:08:35384 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
385};
386
387// Encapsulates an OpenGL frame buffer.
388class FrameBuffer {
389 public:
390 explicit FrameBuffer(GLES2DecoderImpl* decoder);
391 ~FrameBuffer();
392
393 // Create a new frame buffer.
394 void Create();
395
396 // Attach a color render buffer to a frame buffer.
397 void AttachRenderTexture(Texture* texture);
398
[email protected]b9363b22010-06-09 22:06:15399 // Attach a render buffer to a frame buffer. Note that this unbinds any
400 // currently bound frame buffer.
401 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35402
[email protected]6217d392010-03-25 22:08:35403 // Destroy the frame buffer. This must be explicitly called before destroying
404 // this object.
405 void Destroy();
406
[email protected]97872062010-11-03 19:07:05407 // Invalidate the frame buffer. This can be used when a context is lost and it
408 // is not possible to make it current in order to free the resource.
409 void Invalidate();
410
[email protected]6217d392010-03-25 22:08:35411 // See glCheckFramebufferStatusEXT.
412 GLenum CheckStatus();
413
414 GLuint id() const {
415 return id_;
416 }
417
418 private:
419 GLES2DecoderImpl* decoder_;
420 GLuint id_;
421 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
422};
[email protected]34ff8b0c2010-10-01 20:06:02423
[email protected]43f28f832010-02-03 02:28:48424// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32425
[email protected]ddb1e5a2010-12-13 20:10:45426bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
427 uint32* service_texture_id) {
428 return false;
429}
430
[email protected]a3ded6d2010-10-19 06:44:39431GLES2Decoder::GLES2Decoder()
[email protected]e844ae22012-01-14 03:36:26432 : debug_(false),
[email protected]b5d647c2012-02-10 01:41:32433 log_commands_(false),
434 log_synthesized_gl_errors_(true) {
[email protected]96449d2c2009-11-25 00:01:32435}
436
[email protected]3916c97e2010-02-25 03:20:50437GLES2Decoder::~GLES2Decoder() {
438}
439
[email protected]57edfdad2012-02-07 04:57:15440bool GLES2Decoder::testing_force_is_angle_;
441
442void GLES2Decoder::set_testing_force_is_angle(bool force) {
443 testing_force_is_angle_ = force;
444}
445
446bool GLES2Decoder::IsAngle() {
447#if defined(OS_WIN)
448 return testing_force_is_angle_ ||
449 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
450#else
451 return testing_force_is_angle_;
452#endif
453}
454
[email protected]f39f4b3f2010-05-12 17:04:08455// This class implements GLES2Decoder so we don't have to expose all the GLES2
456// cmd stuff to outside this class.
457class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
458 public GLES2Decoder {
459 public:
[email protected]aa7666122011-09-02 19:45:52460 explicit GLES2DecoderImpl(ContextGroup* group);
[email protected]80eb6b52012-01-19 00:14:41461 ~GLES2DecoderImpl();
[email protected]f39f4b3f2010-05-12 17:04:08462
[email protected]96449d2c2009-11-25 00:01:32463 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14464 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50465 unsigned int arg_count,
466 const void* args);
[email protected]96449d2c2009-11-25 00:01:32467
468 // Overridden from AsyncAPIInterface.
469 virtual const char* GetCommandName(unsigned int command_id) const;
470
471 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38472 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
473 const scoped_refptr<gfx::GLContext>& context,
[email protected]6217d392010-03-25 22:08:35474 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:29475 const DisallowedFeatures& disallowed_features,
[email protected]a3ded6d2010-10-19 06:44:39476 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:24477 const std::vector<int32>& attribs);
[email protected]96449d2c2009-11-25 00:01:32478 virtual void Destroy();
[email protected]3c644d82011-06-20 19:58:24479 virtual bool SetParent(GLES2Decoder* parent_decoder,
480 uint32 parent_texture_id);
[email protected]799b4b22011-08-22 17:09:59481 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]9a5afa432011-07-22 18:16:39482 void UpdateParentTextureInfo();
[email protected]eb54a562010-01-20 21:55:18483 virtual bool MakeCurrent();
[email protected]a96a6022011-11-04 00:58:12484 virtual void ReleaseCurrent();
[email protected]56ac89b2010-03-17 21:16:55485 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30486 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]f62a5ab2011-05-23 20:34:15487 virtual gfx::GLSurface* GetGLSurface() { return surface_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39488 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]882ba1e22012-03-08 19:02:53489 virtual QueryManager* GetQueryManager() { return query_manager_.get(); }
[email protected]22e3f552012-03-13 01:54:19490 virtual bool ProcessPendingQueries();
[email protected]43f28f832010-02-03 02:28:48491
[email protected]0d6bfdc2011-11-02 01:32:20492 virtual void SetGLError(GLenum error, const char* msg);
[email protected]9d37f062011-11-22 01:24:52493 virtual void SetResizeCallback(
494 const base::Callback<void(gfx::Size)>& callback);
[email protected]22f320a2011-08-30 01:17:00495
[email protected]6b6e7ee2011-12-13 08:04:52496 virtual void SetMsgCallback(const MsgCallback& callback);
[email protected]22f320a2011-08-30 01:17:00497
[email protected]b0af4f52011-09-28 22:04:42498 virtual void SetStreamTextureManager(StreamTextureManager* manager);
[email protected]1318e922010-09-17 22:03:16499 virtual bool GetServiceTextureId(uint32 client_texture_id,
500 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48501
[email protected]8e3e0662010-08-23 18:46:30502 // Restores the current state to the user's settings.
503 void RestoreCurrentFramebufferBindings();
504 void RestoreCurrentRenderbufferBindings();
505 void RestoreCurrentTexture2DBindings();
506
[email protected]297ca1c2011-06-20 23:08:46507 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
508 void ApplyDirtyState();
509
510 // These check the state of the currently bound framebuffer or the
511 // backbuffer if no framebuffer is bound.
512 bool BoundFramebufferHasColorAttachmentWithAlpha();
513 bool BoundFramebufferHasDepthAttachment();
514 bool BoundFramebufferHasStencilAttachment();
515
[email protected]38d139d2011-07-14 00:38:43516 virtual error::ContextLostReason GetContextLostReason();
517
[email protected]96449d2c2009-11-25 00:01:32518 private:
[email protected]6217d392010-03-25 22:08:35519 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02520 friend class ScopedResolvedFrameBufferBinder;
[email protected]1078f912011-12-23 13:12:14521 friend class Texture;
[email protected]6217d392010-03-25 22:08:35522 friend class RenderBuffer;
523 friend class FrameBuffer;
524
[email protected]3916c97e2010-02-25 03:20:50525 // State associated with each texture unit.
526 struct TextureUnit {
527 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
528
529 // The last target that was bound to this texture unit.
530 GLenum bind_target;
531
532 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
533 TextureManager::TextureInfo::Ref bound_texture_2d;
534
535 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
536 // glBindTexture
537 TextureManager::TextureInfo::Ref bound_texture_cube_map;
[email protected]61eeb33f2011-07-26 15:30:31538
539 // texture currently bound to this unit's GL_TEXTURE_EXTERNAL_OES with
540 // glBindTexture
541 TextureManager::TextureInfo::Ref bound_texture_external_oes;
542
[email protected]e51bdf32011-11-23 22:21:46543 // texture currently bound to this unit's GL_TEXTURE_RECTANGLE_ARB with
544 // glBindTexture
545 TextureManager::TextureInfo::Ref bound_texture_rectangle_arb;
546
[email protected]61eeb33f2011-07-26 15:30:31547 TextureManager::TextureInfo::Ref GetInfoForSamplerType(GLenum type) {
548 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:46549 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
550 switch (type) {
551 case GL_SAMPLER_2D:
552 return bound_texture_2d;
553 case GL_SAMPLER_CUBE:
554 return bound_texture_cube_map;
555 case GL_SAMPLER_EXTERNAL_OES:
556 return bound_texture_external_oes;
557 case GL_SAMPLER_2D_RECT_ARB:
558 return bound_texture_rectangle_arb;
559 }
560
561 NOTREACHED();
562 return NULL;
[email protected]61eeb33f2011-07-26 15:30:31563 }
[email protected]a0b78dc2011-11-11 10:43:10564
565 void Unbind(TextureManager::TextureInfo* texture) {
566 if (bound_texture_2d == texture) {
567 bound_texture_2d = NULL;
568 }
569 if (bound_texture_cube_map == texture) {
570 bound_texture_cube_map = NULL;
571 }
572 if (bound_texture_external_oes == texture) {
573 bound_texture_external_oes = NULL;
574 }
575 }
[email protected]3916c97e2010-02-25 03:20:50576 };
577
[email protected]c2f8c8402010-12-06 18:07:24578 // Initialize or re-initialize the shader translator.
579 bool InitializeShaderTranslator();
580
[email protected]302ce6d2011-07-07 23:28:11581 void UpdateCapabilities();
582
[email protected]ae51d192010-04-27 00:48:03583 // Helpers for the glGen and glDelete functions.
584 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
585 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
586 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
587 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
588 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
589 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
590 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
591 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]882ba1e22012-03-08 19:02:53592 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
593 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47594
[email protected]3916c97e2010-02-25 03:20:50595 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50596 BufferManager* buffer_manager() {
597 return group_->buffer_manager();
598 }
599
[email protected]a25fa872010-03-25 02:57:58600 RenderbufferManager* renderbuffer_manager() {
601 return group_->renderbuffer_manager();
602 }
603
604 FramebufferManager* framebuffer_manager() {
605 return group_->framebuffer_manager();
606 }
607
[email protected]3916c97e2010-02-25 03:20:50608 ProgramManager* program_manager() {
609 return group_->program_manager();
610 }
611
612 ShaderManager* shader_manager() {
613 return group_->shader_manager();
614 }
615
616 TextureManager* texture_manager() {
617 return group_->texture_manager();
618 }
619
[email protected]34ff8b0c2010-10-01 20:06:02620 bool IsOffscreenBufferMultisampled() const {
621 return offscreen_target_samples_ > 1;
622 }
623
[email protected]a93bb842010-02-16 23:03:47624 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03625 TextureManager::TextureInfo* CreateTextureInfo(
626 GLuint client_id, GLuint service_id) {
[email protected]80eb6b52012-01-19 00:14:41627 return texture_manager()->CreateTextureInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47628 }
629
630 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03631 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50632 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03633 texture_manager()->GetTextureInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10634 return info;
[email protected]a93bb842010-02-16 23:03:47635 }
636
637 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03638 void RemoveTextureInfo(GLuint client_id) {
[email protected]80eb6b52012-01-19 00:14:41639 texture_manager()->RemoveTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50640 }
[email protected]a93bb842010-02-16 23:03:47641
[email protected]d37231fa2010-04-09 21:16:02642 // Get the size (in pixels) of the currently bound frame buffer (either FBO
643 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30644 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02645
[email protected]9edc6b22010-12-23 02:00:26646 // Get the format of the currently bound frame buffer (either FBO or regular
647 // back buffer)
648 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46649 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26650
[email protected]a93bb842010-02-16 23:03:47651 // Wrapper for CompressedTexImage2D commands.
652 error::Error DoCompressedTexImage2D(
653 GLenum target,
654 GLint level,
655 GLenum internal_format,
656 GLsizei width,
657 GLsizei height,
658 GLint border,
659 GLsizei image_size,
660 const void* data);
661
[email protected]cadde4a2010-07-31 17:10:43662 // Wrapper for CompressedTexSubImage2D.
663 void DoCompressedTexSubImage2D(
664 GLenum target,
665 GLint level,
666 GLint xoffset,
667 GLint yoffset,
668 GLsizei width,
669 GLsizei height,
670 GLenum format,
671 GLsizei imageSize,
672 const void * data);
673
674 // Wrapper for CopyTexImage2D.
675 void DoCopyTexImage2D(
676 GLenum target,
677 GLint level,
678 GLenum internal_format,
679 GLint x,
680 GLint y,
681 GLsizei width,
682 GLsizei height,
683 GLint border);
684
685 // Wrapper for CopyTexSubImage2D.
686 void DoCopyTexSubImage2D(
687 GLenum target,
688 GLint level,
689 GLint xoffset,
690 GLint yoffset,
691 GLint x,
692 GLint y,
693 GLsizei width,
694 GLsizei height);
695
[email protected]a93bb842010-02-16 23:03:47696 // Wrapper for TexImage2D commands.
697 error::Error DoTexImage2D(
698 GLenum target,
699 GLint level,
700 GLenum internal_format,
701 GLsizei width,
702 GLsizei height,
703 GLint border,
704 GLenum format,
705 GLenum type,
706 const void* pixels,
707 uint32 pixels_size);
708
[email protected]cadde4a2010-07-31 17:10:43709 // Wrapper for TexSubImage2D.
710 void DoTexSubImage2D(
711 GLenum target,
712 GLint level,
713 GLint xoffset,
714 GLint yoffset,
715 GLsizei width,
716 GLsizei height,
717 GLenum format,
718 GLenum type,
719 const void * data);
720
[email protected]e51bdf32011-11-23 22:21:46721 // Wrapper for TexImageIOSurface2DCHROMIUM.
722 void DoTexImageIOSurface2DCHROMIUM(
723 GLenum target,
724 GLsizei width,
725 GLsizei height,
726 GLuint io_surface_id,
727 GLuint plane);
728
[email protected]97dc7cbe2011-12-06 17:26:17729 // Wrapper for TexStorage2DEXT.
730 void DoTexStorage2DEXT(
731 GLenum target,
732 GLint levels,
733 GLenum internal_format,
734 GLsizei width,
735 GLsizei height);
736
[email protected]a93bb842010-02-16 23:03:47737 // Creates a ProgramInfo for the given program.
[email protected]d685a682011-04-29 16:19:57738 ProgramManager::ProgramInfo* CreateProgramInfo(
739 GLuint client_id, GLuint service_id) {
740 return program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47741 }
742
[email protected]07f54fcc2009-12-22 02:46:30743 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03744 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14745 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46746 }
[email protected]07f54fcc2009-12-22 02:46:30747
[email protected]6b8cf1a2010-05-06 16:13:58748 // Gets the program info for the given program. If it's not a program
749 // generates a GL error. Returns NULL if not program.
750 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
751 GLuint client_id, const char* function_name) {
752 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
753 if (!info) {
754 if (GetShaderInfo(client_id)) {
755 SetGLError(GL_INVALID_OPERATION,
756 (std::string(function_name) +
757 ": shader passed for program").c_str());
758 } else {
759 SetGLError(GL_INVALID_VALUE,
760 (std::string(function_name) + ": unknown program").c_str());
761 }
762 }
763 return info;
764 }
765
766
[email protected]45bf5152010-02-12 00:11:31767 // Creates a ShaderInfo for the given shader.
[email protected]d685a682011-04-29 16:19:57768 ShaderManager::ShaderInfo* CreateShaderInfo(
769 GLuint client_id,
770 GLuint service_id,
771 GLenum shader_type) {
772 return shader_manager()->CreateShaderInfo(
773 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31774 }
775
776 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03777 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14778 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31779 }
780
[email protected]6b8cf1a2010-05-06 16:13:58781 // Gets the shader info for the given shader. If it's not a shader generates a
782 // GL error. Returns NULL if not shader.
783 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
784 GLuint client_id, const char* function_name) {
785 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
786 if (!info) {
787 if (GetProgramInfo(client_id)) {
788 SetGLError(
789 GL_INVALID_OPERATION,
790 (std::string(function_name) +
791 ": program passed for shader").c_str());
792 } else {
793 SetGLError(GL_INVALID_VALUE,
794 (std::string(function_name) + ": unknown shader").c_str());
795 }
796 }
797 return info;
798 }
799
[email protected]a93bb842010-02-16 23:03:47800 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03801 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
802 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47803 }
804
[email protected]07f54fcc2009-12-22 02:46:30805 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03806 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
807 BufferManager::BufferInfo* info =
808 buffer_manager()->GetBufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10809 return info;
[email protected]1d32bc82010-01-13 22:06:46810 }
[email protected]07f54fcc2009-12-22 02:46:30811
[email protected]a93bb842010-02-16 23:03:47812 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
813 // on glDeleteBuffers so we can make sure the user does not try to render
814 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03815 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47816
[email protected]a25fa872010-03-25 02:57:58817 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03818 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
819 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58820 }
821
822 // Gets the framebuffer info for the given framebuffer.
823 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03824 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58825 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03826 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10827 return info;
[email protected]a25fa872010-03-25 02:57:58828 }
829
830 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03831 void RemoveFramebufferInfo(GLuint client_id) {
832 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58833 }
834
835 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03836 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
837 return renderbuffer_manager()->CreateRenderbufferInfo(
838 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58839 }
840
841 // Gets the renderbuffer info for the given renderbuffer.
842 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03843 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58844 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03845 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10846 return info;
[email protected]a25fa872010-03-25 02:57:58847 }
848
849 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03850 void RemoveRenderbufferInfo(GLuint client_id) {
851 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58852 }
853
[email protected]258a3313f2011-10-18 20:13:57854 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
855
[email protected]558847a2010-03-24 07:02:54856 error::Error GetAttribLocationHelper(
857 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
858 const std::string& name_str);
859
860 error::Error GetUniformLocationHelper(
861 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
862 const std::string& name_str);
863
[email protected]3916c97e2010-02-25 03:20:50864 // Helper for glShaderSource.
865 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03866 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30867
[email protected]0d6bfdc2011-11-02 01:32:20868 // Clear any textures used by the current program.
869 bool ClearUnclearedTextures();
870
871 // Clear any uncleared level in texture.
872 // Returns false if there was a generated GL error.
873 bool ClearTexture(TextureManager::TextureInfo* info);
874
875 // Clears any uncleared attachments attached to the given frame buffer.
876 // Returns false if there was a generated GL error.
877 void ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:30878 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28879
[email protected]0d6bfdc2011-11-02 01:32:20880 // overridden from GLES2Decoder
881 virtual bool ClearLevel(
882 unsigned service_id,
883 unsigned bind_target,
884 unsigned target,
885 int level,
886 unsigned format,
887 unsigned type,
888 int width,
[email protected]4502e6492011-12-14 19:39:15889 int height,
890 bool is_texture_immutable);
[email protected]0d6bfdc2011-11-02 01:32:20891
[email protected]c007aa02010-09-02 22:22:40892 // Restore all GL state that affects clearing.
893 void RestoreClearState();
894
[email protected]3a2e7c7b2010-08-06 01:12:28895 // Remembers the state of some capabilities.
[email protected]297ca1c2011-06-20 23:08:46896 // Returns: true if glEnable/glDisable should actually be called.
897 bool SetCapabilityState(GLenum cap, bool enabled);
[email protected]3a2e7c7b2010-08-06 01:12:28898
[email protected]0d6bfdc2011-11-02 01:32:20899 // Check that the currently bound framebuffers are valid.
900 // Generates GL error if not.
901 bool CheckBoundFramebuffersValid(const char* func_name);
902
903 // Check if a framebuffer meets our requirements.
904 bool CheckFramebufferValid(
905 FramebufferManager::FramebufferInfo* framebuffer,
906 GLenum target,
907 const char* func_name);
[email protected]3a03a8f2011-03-19 00:51:27908
[email protected]939e7362010-05-13 20:49:10909 // Checks if the current program exists and is valid. If not generates the
910 // appropriate GL error. Returns true if the current program is in a usable
911 // state.
912 bool CheckCurrentProgram(const char* function_name);
913
914 // Checks if the current program exists and is valid and that location is not
915 // -1. If the current program is not valid generates the appropriate GL
916 // error. Returns true if the current program is in a usable state and
917 // location is not -1.
918 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
919
920 // Gets the type of a uniform for a location in the current program. Sets GL
921 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:36922 // program is valid and the location exists. Adjusts count so it
923 // does not overflow the uniform.
924 bool PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:12925 GLint fake_location, const char* function_name,
926 GLint* real_location, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:10927
[email protected]b177ae22011-11-01 03:29:11928 // Gets the service id for any simulated backbuffer fbo.
929 GLuint GetBackbufferServiceId();
930
[email protected]b273e432010-04-12 17:23:58931 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
932 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
933
[email protected]96449d2c2009-11-25 00:01:32934 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03935 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32936
937 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03938 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32939
[email protected]3916c97e2010-02-25 03:20:50940 // Wrapper for glActiveTexture
941 void DoActiveTexture(GLenum texture_unit);
942
[email protected]ae51d192010-04-27 00:48:03943 // Wrapper for glAttachShader
944 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
945
[email protected]96449d2c2009-11-25 00:01:32946 // Wrapper for glBindBuffer since we need to track the current targets.
947 void DoBindBuffer(GLenum target, GLuint buffer);
948
[email protected]86093972010-03-11 00:13:56949 // Wrapper for glBindFramebuffer since we need to track the current targets.
950 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
951
952 // Wrapper for glBindRenderbuffer since we need to track the current targets.
953 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
954
[email protected]a93bb842010-02-16 23:03:47955 // Wrapper for glBindTexture since we need to track the current targets.
956 void DoBindTexture(GLenum target, GLuint texture);
957
[email protected]8e3e0662010-08-23 18:46:30958 // Wrapper for glBlitFramebufferEXT.
959 void DoBlitFramebufferEXT(
960 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
961 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
962 GLbitfield mask, GLenum filter);
963
[email protected]36cef8ce2010-03-16 07:34:45964 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:11965 void DoBufferData(
966 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
967
[email protected]36cef8ce2010-03-16 07:34:45968 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:11969 void DoBufferSubData(
970 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
971
[email protected]36cef8ce2010-03-16 07:34:45972 // Wrapper for glCheckFramebufferStatus
973 GLenum DoCheckFramebufferStatus(GLenum target);
974
[email protected]3a03a8f2011-03-19 00:51:27975 // Wrapper for glClear
976 void DoClear(GLbitfield mask);
977
[email protected]3a2e7c7b2010-08-06 01:12:28978 // Wrappers for clear and mask settings functions.
979 void DoClearColor(
980 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
981 void DoClearDepthf(GLclampf depth);
982 void DoClearStencil(GLint s);
983 void DoColorMask(
984 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
985 void DoDepthMask(GLboolean depth);
986 void DoStencilMask(GLuint mask);
987 void DoStencilMaskSeparate(GLenum face, GLuint mask);
988
[email protected]45bf5152010-02-12 00:11:31989 // Wrapper for glCompileShader.
990 void DoCompileShader(GLuint shader);
991
[email protected]269200b12010-11-18 22:53:06992 // Helper for DeleteSharedIdsCHROMIUM commands.
993 void DoDeleteSharedIdsCHROMIUM(
994 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:10995
[email protected]ae51d192010-04-27 00:48:03996 // Wrapper for glDetachShader
997 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
998
[email protected]3a2e7c7b2010-08-06 01:12:28999 // Wrapper for glDisable
1000 void DoDisable(GLenum cap);
1001
[email protected]07f54fcc2009-12-22 02:46:301002 // Wrapper for glDisableVertexAttribArray.
1003 void DoDisableVertexAttribArray(GLuint index);
1004
[email protected]3a2e7c7b2010-08-06 01:12:281005 // Wrapper for glEnable
1006 void DoEnable(GLenum cap);
1007
[email protected]07f54fcc2009-12-22 02:46:301008 // Wrapper for glEnableVertexAttribArray.
1009 void DoEnableVertexAttribArray(GLuint index);
1010
[email protected]882ba1e22012-03-08 19:02:531011 // Wrapper for glFinish.
1012 void DoFinish();
1013
1014 // Wrapper for glFlush.
1015 void DoFlush();
1016
[email protected]36cef8ce2010-03-16 07:34:451017 // Wrapper for glFramebufferRenderbufffer.
1018 void DoFramebufferRenderbuffer(
1019 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1020 GLuint renderbuffer);
1021
1022 // Wrapper for glFramebufferTexture2D.
1023 void DoFramebufferTexture2D(
1024 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1025 GLint level);
1026
[email protected]a93bb842010-02-16 23:03:471027 // Wrapper for glGenerateMipmap
1028 void DoGenerateMipmap(GLenum target);
1029
[email protected]269200b12010-11-18 22:53:061030 // Helper for GenSharedIdsCHROMIUM commands.
1031 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:101032 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1033
[email protected]b273e432010-04-12 17:23:581034 // Wrapper for DoGetBooleanv.
1035 void DoGetBooleanv(GLenum pname, GLboolean* params);
1036
1037 // Wrapper for DoGetFloatv.
1038 void DoGetFloatv(GLenum pname, GLfloat* params);
1039
[email protected]36cef8ce2010-03-16 07:34:451040 // Wrapper for glGetFramebufferAttachmentParameteriv.
1041 void DoGetFramebufferAttachmentParameteriv(
1042 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1043
[email protected]a0c3e972010-04-21 00:49:131044 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581045 void DoGetIntegerv(GLenum pname, GLint* params);
1046
[email protected]29a9eb52010-04-13 09:04:231047 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:061048 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:231049 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1050
[email protected]a0c3e972010-04-21 00:49:131051 // Wrapper for glGetProgramiv.
1052 void DoGetProgramiv(
1053 GLuint program_id, GLenum pname, GLint* params);
1054
[email protected]36cef8ce2010-03-16 07:34:451055 // Wrapper for glRenderbufferParameteriv.
1056 void DoGetRenderbufferParameteriv(
1057 GLenum target, GLenum pname, GLint* params);
1058
[email protected]ddd968b82010-03-02 00:44:291059 // Wrapper for glGetShaderiv
1060 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1061
[email protected]b1122982010-05-17 23:04:241062 // Wrappers for glGetVertexAttrib.
1063 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1064 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1065
[email protected]1958e0e2010-04-22 05:17:151066 // Wrappers for glIsXXX functions.
1067 bool DoIsBuffer(GLuint client_id);
1068 bool DoIsFramebuffer(GLuint client_id);
1069 bool DoIsProgram(GLuint client_id);
1070 bool DoIsRenderbuffer(GLuint client_id);
1071 bool DoIsShader(GLuint client_id);
1072 bool DoIsTexture(GLuint client_id);
1073
[email protected]07f54fcc2009-12-22 02:46:301074 // Wrapper for glLinkProgram
1075 void DoLinkProgram(GLuint program);
1076
[email protected]269200b12010-11-18 22:53:061077 // Helper for RegisterSharedIdsCHROMIUM.
1078 void DoRegisterSharedIdsCHROMIUM(
1079 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101080
[email protected]36cef8ce2010-03-16 07:34:451081 // Wrapper for glRenderbufferStorage.
1082 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031083 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451084
[email protected]8e3e0662010-08-23 18:46:301085 // Wrapper for glRenderbufferStorageMultisampleEXT.
1086 void DoRenderbufferStorageMultisample(
1087 GLenum target, GLsizei samples, GLenum internalformat,
1088 GLsizei width, GLsizei height);
1089
[email protected]b273e432010-04-12 17:23:581090 // Wrapper for glReleaseShaderCompiler.
1091 void DoReleaseShaderCompiler() { }
1092
[email protected]3916c97e2010-02-25 03:20:501093 // Wrappers for glTexParameter functions.
1094 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1095 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1096 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1097 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1098
1099 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1100 // spec only these 2 functions can be used to set sampler uniforms.
[email protected]1b0a6752012-02-22 03:44:121101 void DoUniform1i(GLint fake_location, GLint v0);
1102 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1103 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1104 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1105 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101106
1107 // Wrappers for glUniformfv because some drivers don't correctly accept
1108 // bool uniforms.
[email protected]1b0a6752012-02-22 03:44:121109 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1110 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1111 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1112 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501113
[email protected]43c2f1f2011-03-25 18:35:361114 void DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:121115 GLint fake_location, GLsizei count, GLboolean transpose,
1116 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361117 void DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:121118 GLint fake_location, GLsizei count, GLboolean transpose,
1119 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361120 void DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:121121 GLint fake_location, GLsizei count, GLboolean transpose,
1122 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361123
[email protected]b1122982010-05-17 23:04:241124 // Wrappers for glVertexAttrib??
1125 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1126 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1127 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1128 void DoVertexAttrib4f(
1129 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1130 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1131 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1132 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1133 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1134
[email protected]07f54fcc2009-12-22 02:46:301135 // Wrapper for glUseProgram
1136 void DoUseProgram(GLuint program);
1137
[email protected]ae51d192010-04-27 00:48:031138 // Wrapper for glValidateProgram.
1139 void DoValidateProgram(GLuint program_client_id);
1140
[email protected]4e8a5b122010-05-08 22:00:101141 // Gets the number of values that will be returned by glGetXXX. Returns
1142 // false if pname is unknown.
1143 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1144
[email protected]96449d2c2009-11-25 00:01:321145 // Gets the GLError through our wrapper.
1146 GLenum GetGLError();
1147
[email protected]1002c2d2011-06-28 22:39:041148 // Gets the GLError and stores it in our wrapper. Effectively
1149 // this lets us peek at the error without losing it.
1150 GLenum PeekGLError();
1151
[email protected]07f54fcc2009-12-22 02:46:301152 // Copies the real GL errors to the wrapper. This is so we can
1153 // make sure there are no native GL errors before calling some GL function
1154 // so that on return we know any error generated was for that specific
1155 // command.
1156 void CopyRealGLErrorsToWrapper();
1157
[email protected]6217d392010-03-25 22:08:351158 // Clear all real GL errors. This is to prevent the client from seeing any
1159 // errors caused by GL calls that it was not responsible for issuing.
1160 void ClearRealGLErrors();
1161
[email protected]07f54fcc2009-12-22 02:46:301162 // Checks if the current program and vertex attributes are valid for drawing.
[email protected]c6aef902012-02-14 03:31:421163 bool IsDrawValid(GLuint max_vertex_accessed, GLsizei primcount);
[email protected]07f54fcc2009-12-22 02:46:301164
[email protected]c13e1da62011-09-09 21:48:301165 // Returns true if successful, simulated will be true if attrib0 was
1166 // simulated.
[email protected]c6aef902012-02-14 03:31:421167 bool SimulateAttrib0(
1168 GLuint max_vertex_accessed, bool* simulated);
[email protected]b1122982010-05-17 23:04:241169 void RestoreStateForSimulatedAttrib0();
1170
[email protected]ef526492010-06-02 23:12:251171 // Returns true if textures were set.
1172 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501173 void RestoreStateForNonRenderableTextures();
1174
[email protected]8fbedc02010-11-18 18:43:401175 // Returns true if GL_FIXED attribs were simulated.
[email protected]c6aef902012-02-14 03:31:421176 bool SimulateFixedAttribs(
1177 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
[email protected]8fbedc02010-11-18 18:43:401178 void RestoreStateForSimulatedFixedAttribs();
1179
[email protected]c6aef902012-02-14 03:31:421180 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1181 // cases (primcount is 0 for non-instanced).
1182 error::Error DoDrawArrays(
1183 bool instanced, GLenum mode, GLint first, GLsizei count,
1184 GLsizei primcount);
1185 error::Error DoDrawElements(
1186 bool instanced, GLenum mode, GLsizei count, GLenum type,
1187 int32 offset, GLsizei primcount);
1188
[email protected]07f54fcc2009-12-22 02:46:301189 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501190 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301191 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501192 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1193 bound_array_buffer_ : bound_element_array_buffer_;
[email protected]a0b78dc2011-11-11 10:43:101194 return info;
[email protected]07f54fcc2009-12-22 02:46:301195 }
1196
[email protected]a93bb842010-02-16 23:03:471197 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501198 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1199 TextureUnit& unit = texture_units_[active_texture_unit_];
1200 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471201 switch (target) {
1202 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501203 info = unit.bound_texture_2d;
1204 break;
[email protected]a93bb842010-02-16 23:03:471205 case GL_TEXTURE_CUBE_MAP:
1206 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1207 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1208 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1209 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1210 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1211 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501212 info = unit.bound_texture_cube_map;
1213 break;
[email protected]61eeb33f2011-07-26 15:30:311214 case GL_TEXTURE_EXTERNAL_OES:
1215 info = unit.bound_texture_external_oes;
1216 break;
[email protected]e51bdf32011-11-23 22:21:461217 case GL_TEXTURE_RECTANGLE_ARB:
1218 info = unit.bound_texture_rectangle_arb;
1219 break;
[email protected]a93bb842010-02-16 23:03:471220 default:
1221 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501222 return NULL;
[email protected]a93bb842010-02-16 23:03:471223 }
[email protected]a0b78dc2011-11-11 10:43:101224 return info;
[email protected]a93bb842010-02-16 23:03:471225 }
1226
[email protected]61eeb33f2011-07-26 15:30:311227 GLenum GetBindTargetForSamplerType(GLenum type) {
1228 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:461229 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1230 switch (type) {
1231 case GL_SAMPLER_2D:
1232 return GL_TEXTURE_2D;
1233 case GL_SAMPLER_CUBE:
1234 return GL_TEXTURE_CUBE_MAP;
1235 case GL_SAMPLER_EXTERNAL_OES:
1236 return GL_TEXTURE_EXTERNAL_OES;
1237 case GL_SAMPLER_2D_RECT_ARB:
1238 return GL_TEXTURE_RECTANGLE_ARB;
1239 }
1240
1241 NOTREACHED();
1242 return 0;
[email protected]61eeb33f2011-07-26 15:30:311243 }
1244
[email protected]8e3e0662010-08-23 18:46:301245 // Gets the framebuffer info for a particular target.
1246 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1247 GLenum target) {
1248 FramebufferManager::FramebufferInfo* info = NULL;
1249 switch (target) {
1250 case GL_FRAMEBUFFER:
1251 case GL_DRAW_FRAMEBUFFER:
1252 info = bound_draw_framebuffer_;
1253 break;
1254 case GL_READ_FRAMEBUFFER:
1255 info = bound_read_framebuffer_;
1256 break;
1257 default:
1258 NOTREACHED();
1259 break;
1260 }
[email protected]a0b78dc2011-11-11 10:43:101261 return info;
[email protected]8e3e0662010-08-23 18:46:301262 }
1263
[email protected]0d6bfdc2011-11-02 01:32:201264 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfoForTarget(
1265 GLenum target) {
1266 RenderbufferManager::RenderbufferInfo* info = NULL;
1267 switch (target) {
1268 case GL_RENDERBUFFER:
1269 info = bound_renderbuffer_;
1270 break;
1271 default:
1272 NOTREACHED();
1273 break;
1274 }
[email protected]a0b78dc2011-11-11 10:43:101275 return info;
[email protected]0d6bfdc2011-11-02 01:32:201276 }
1277
[email protected]f7b85372010-02-03 01:11:371278 // Validates the program and location for a glGetUniform call and returns
1279 // a SizeResult setup to receive the result. Returns true if glGetUniform
1280 // should be called.
1281 bool GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:121282 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:371283 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:121284 error::Error* error, GLint* real_location, GLuint* service_id,
1285 void** result, GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371286
[email protected]1078f912011-12-23 13:12:141287 // Computes the estimated memory used for the backbuffer and passes it to
1288 // the tracing system.
1289 void UpdateBackbufferMemoryAccounting();
1290
[email protected]38d139d2011-07-14 00:38:431291 // Returns true if the context was just lost due to e.g. GL_ARB_robustness.
1292 bool WasContextLost();
1293
[email protected]e51bdf32011-11-23 22:21:461294#if defined(OS_MACOSX)
1295 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1296#endif
1297
[email protected]96449d2c2009-11-25 00:01:321298 // Generate a member function prototype for each command in an automated and
1299 // typesafe way.
1300 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141301 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191302 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321303 const gles2::name& args); \
1304
1305 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1306
1307 #undef GLES2_CMD_OP
1308
[email protected]2f2d7042010-04-14 21:45:581309 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381310 scoped_refptr<gfx::GLSurface> surface_;
1311 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021312
[email protected]a3ded6d2010-10-19 06:44:391313 // The ContextGroup for this decoder uses to track resources.
1314 ContextGroup::Ref group_;
1315
[email protected]6217d392010-03-25 22:08:351316 // A parent decoder can access this decoders saved offscreen frame buffer.
1317 // The parent pointer is reset if the parent is destroyed.
1318 base::WeakPtr<GLES2DecoderImpl> parent_;
1319
[email protected]34ff8b0c2010-10-01 20:06:021320 // Current width and height of the offscreen frame buffer.
1321 gfx::Size offscreen_size_;
1322
[email protected]96449d2c2009-11-25 00:01:321323 // Current GL error bits.
1324 uint32 error_bits_;
1325
[email protected]96449d2c2009-11-25 00:01:321326 // Util to help with GL.
1327 GLES2Util util_;
1328
1329 // pack alignment as last set by glPixelStorei
1330 GLint pack_alignment_;
1331
1332 // unpack alignment as last set by glPixelStorei
1333 GLint unpack_alignment_;
1334
1335 // The currently bound array buffer. If this is 0 it is illegal to call
1336 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501337 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321338
1339 // The currently bound element array buffer. If this is 0 it is illegal
1340 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501341 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301342
[email protected]f39f4b3f2010-05-12 17:04:081343 // Class that manages vertex attribs.
[email protected]3757a372012-01-19 05:20:441344 scoped_ptr<VertexAttribManager> vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301345
[email protected]b1122982010-05-17 23:04:241346 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1347 GLuint attrib_0_buffer_id_;
1348
1349 // The value currently in attrib_0.
1350 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1351
[email protected]fc753442011-02-04 19:49:491352 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1353 bool attrib_0_buffer_matches_value_;
1354
[email protected]b1122982010-05-17 23:04:241355 // The size of attrib 0.
1356 GLsizei attrib_0_size_;
1357
[email protected]8fbedc02010-11-18 18:43:401358 // The buffer used to simulate GL_FIXED attribs.
1359 GLuint fixed_attrib_buffer_id_;
1360
1361 // The size of fiixed attrib buffer.
1362 GLsizei fixed_attrib_buffer_size_;
1363
[email protected]3916c97e2010-02-25 03:20:501364 // Current active texture by 0 - n index.
1365 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1366 // be 2.
1367 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301368
[email protected]3916c97e2010-02-25 03:20:501369 // Which textures are bound to texture units through glActiveTexture.
1370 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471371
[email protected]3a2e7c7b2010-08-06 01:12:281372 // state saved for clearing so we can clear render buffers and then
1373 // restore to these values.
1374 GLclampf clear_red_;
1375 GLclampf clear_green_;
1376 GLclampf clear_blue_;
1377 GLclampf clear_alpha_;
1378 GLboolean mask_red_;
1379 GLboolean mask_green_;
1380 GLboolean mask_blue_;
1381 GLboolean mask_alpha_;
1382 GLint clear_stencil_;
1383 GLuint mask_stencil_front_;
1384 GLuint mask_stencil_back_;
1385 GLclampf clear_depth_;
1386 GLboolean mask_depth_;
1387 bool enable_scissor_test_;
[email protected]297ca1c2011-06-20 23:08:461388 bool enable_depth_test_;
1389 bool enable_stencil_test_;
1390 bool state_dirty_;
[email protected]3a2e7c7b2010-08-06 01:12:281391
[email protected]1d32bc82010-01-13 22:06:461392 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501393 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301394
[email protected]8e3e0662010-08-23 18:46:301395 // The currently bound framebuffers
1396 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1397 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561398
1399 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081400 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561401
[email protected]b9363b22010-06-09 22:06:151402 // The offscreen frame buffer that the client renders to. With EGL, the
1403 // depth and stencil buffers are separate. With regular GL there is a single
1404 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1405 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351406 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1407 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021408 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151409 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1410 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021411 GLenum offscreen_target_color_format_;
1412 GLenum offscreen_target_depth_format_;
1413 GLenum offscreen_target_stencil_format_;
1414 GLsizei offscreen_target_samples_;
[email protected]8a61d872012-01-20 12:43:561415 GLboolean offscreen_target_buffer_preserved_;
[email protected]6217d392010-03-25 22:08:351416
[email protected]de26b3c2011-08-03 21:54:271417 // The copy that is saved when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021418 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351419 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]8a61d872012-01-20 12:43:561420 TextureManager::TextureInfo::Ref offscreen_saved_color_texture_info_;
[email protected]de26b3c2011-08-03 21:54:271421
1422 // The copy that is used as the destination for multi-sample resolves.
1423 scoped_ptr<FrameBuffer> offscreen_resolved_frame_buffer_;
1424 scoped_ptr<Texture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051425 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351426
[email protected]882ba1e22012-03-08 19:02:531427 scoped_ptr<QueryManager> query_manager_;
1428 QueryManager::Query::Ref current_query_;
1429
[email protected]9d37f062011-11-22 01:24:521430 base::Callback<void(gfx::Size)> resize_callback_;
[email protected]22f320a2011-08-30 01:17:001431
[email protected]6b6e7ee2011-12-13 08:04:521432 MsgCallback msg_callback_;
[email protected]43f28f832010-02-03 02:28:481433
[email protected]b0af4f52011-09-28 22:04:421434 StreamTextureManager* stream_texture_manager_;
1435
[email protected]32fe9aa2011-01-21 23:47:131436 // The format of the back buffer_
1437 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461438 bool back_buffer_has_depth_;
1439 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131440
[email protected]473c01ccb2011-06-07 01:33:301441 bool teximage2d_faster_than_texsubimage2d_;
1442 bool bufferdata_faster_than_buffersubdata_;
1443
[email protected]8eee29c2010-04-29 03:38:291444 // The last error message set.
1445 std::string last_error_;
1446
[email protected]a3a93e7b2010-08-28 00:48:561447 // The current decoder error.
1448 error::Error current_decoder_error_;
1449
[email protected]b1d2dcb2010-05-17 19:24:181450 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451451 scoped_ptr<ShaderTranslator> vertex_translator_;
1452 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181453
[email protected]e82fb792011-09-22 00:33:291454 DisallowedFeatures disallowed_features_;
[email protected]c410da802011-03-14 19:17:411455
[email protected]915a59a12010-09-30 21:29:111456 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051457 const Validators* validators_;
[email protected]80eb6b52012-01-19 00:14:411458 FeatureInfo::Ref feature_info_;
[email protected]9438b012010-06-15 22:55:051459
[email protected]b493ee622011-04-13 23:52:001460 // This indicates all the following texSubImage2D calls that are part of the
1461 // failed texImage2D call should be ignored.
1462 bool tex_image_2d_failed_;
1463
[email protected]65225772011-05-12 21:10:241464 int frame_number_;
1465
[email protected]38d139d2011-07-14 00:38:431466 bool has_arb_robustness_;
1467 GLenum reset_status_;
1468
[email protected]75c023c2011-08-22 23:54:511469 bool needs_mac_nvidia_driver_workaround_;
[email protected]a2a0fe762011-09-20 00:59:121470 bool needs_glsl_built_in_function_emulation_;
[email protected]75c023c2011-08-22 23:54:511471
[email protected]f0d74742011-10-03 16:31:041472 // These flags are used to override the state of the shared feature_info_
1473 // member. Because the same FeatureInfo instance may be shared among many
1474 // contexts, the assumptions on the availablity of extensions in WebGL
1475 // contexts may be broken. These flags override the shared state to preserve
1476 // WebGL semantics.
1477 bool force_webgl_glsl_validation_;
1478 bool derivatives_explicitly_enabled_;
1479
[email protected]062c38b2012-01-18 03:25:101480 bool compile_shader_always_succeeds_;
1481
[email protected]e51bdf32011-11-23 22:21:461482#if defined(OS_MACOSX)
1483 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1484 TextureToIOSurfaceMap texture_to_io_surface_map_;
1485#endif
1486
[email protected]c826d732012-02-09 04:40:261487 typedef std::vector<GLES2DecoderImpl*> ChildList;
1488 ChildList children_;
1489
[email protected]96449d2c2009-11-25 00:01:321490 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1491};
1492
[email protected]6217d392010-03-25 22:08:351493ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1494 : decoder_(decoder) {
1495 decoder_->CopyRealGLErrorsToWrapper();
1496}
1497
1498ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1499 decoder_->ClearRealGLErrors();
1500}
1501
1502ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1503 GLuint id)
1504 : decoder_(decoder) {
1505 ScopedGLErrorSuppressor suppressor(decoder_);
1506
1507 // TODO(apatrick): Check if there are any other states that need to be reset
1508 // before binding a new texture.
1509 glActiveTexture(GL_TEXTURE0);
1510 glBindTexture(GL_TEXTURE_2D, id);
1511}
1512
1513ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1514 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301515 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351516}
1517
1518ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1519 GLuint id)
1520 : decoder_(decoder) {
1521 ScopedGLErrorSuppressor suppressor(decoder_);
1522 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1523}
1524
1525ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1526 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301527 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351528}
1529
1530ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1531 GLuint id)
1532 : decoder_(decoder) {
1533 ScopedGLErrorSuppressor suppressor(decoder_);
1534 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1535}
1536
1537ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1538 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301539 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351540}
1541
[email protected]34ff8b0c2010-10-01 20:06:021542ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271543 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521544 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021545 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1546 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]c0701082011-04-20 00:34:521547 (!decoder_->bound_read_framebuffer_.get() ||
1548 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021549 if (!resolve_and_bind_)
1550 return;
1551
1552 ScopedGLErrorSuppressor suppressor(decoder_);
1553 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1554 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271555 GLuint targetid;
1556 if (internal) {
1557 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1558 decoder_->offscreen_resolved_frame_buffer_.reset(
1559 new FrameBuffer(decoder_));
1560 decoder_->offscreen_resolved_frame_buffer_->Create();
1561 decoder_->offscreen_resolved_color_texture_.reset(new Texture(decoder_));
1562 decoder_->offscreen_resolved_color_texture_->Create();
1563
1564 DCHECK(decoder_->offscreen_saved_color_format_);
1565 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1566 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_);
[email protected]de26b3c2011-08-03 21:54:271567 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1568 decoder_->offscreen_resolved_color_texture_.get());
1569 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1570 GL_FRAMEBUFFER_COMPLETE) {
1571 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1572 << "because offscreen resolved FBO was incomplete.";
1573 return;
1574 }
1575 }
1576 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1577 } else {
1578 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1579 }
1580 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021581 const int width = decoder_->offscreen_size_.width();
1582 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181583 glDisable(GL_SCISSOR_TEST);
[email protected]57edfdad2012-02-07 04:57:151584 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021585 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1586 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1587 } else {
1588 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1589 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1590 }
[email protected]de26b3c2011-08-03 21:54:271591 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021592}
1593
1594ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1595 if (!resolve_and_bind_)
1596 return;
1597
1598 ScopedGLErrorSuppressor suppressor(decoder_);
1599 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181600 if (decoder_->enable_scissor_test_) {
1601 glEnable(GL_SCISSOR_TEST);
1602 }
[email protected]34ff8b0c2010-10-01 20:06:021603}
1604
[email protected]6217d392010-03-25 22:08:351605Texture::Texture(GLES2DecoderImpl* decoder)
1606 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141607 id_(0),
1608 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351609}
1610
1611Texture::~Texture() {
1612 // This does not destroy the render texture because that would require that
1613 // the associated GL context was current. Just check that it was explicitly
1614 // destroyed.
1615 DCHECK_EQ(id_, 0u);
1616}
1617
1618void Texture::Create() {
1619 ScopedGLErrorSuppressor suppressor(decoder_);
1620 Destroy();
1621 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581622 ScopedTexture2DBinder binder(decoder_, id_);
1623 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1624 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1625 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1626 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]62788802011-10-03 17:57:161627
1628 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1629 // never called on an offscreen context, no data will ever be uploaded to the
1630 // saved offscreen color texture (it is deferred until to when SwapBuffers
1631 // is called). My idea is that some nvidia drivers might have a bug where
1632 // deleting a texture that has never been populated might cause a
1633 // crash.
1634 glTexImage2D(
1635 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
[email protected]1078f912011-12-23 13:12:141636 estimated_size_ = 16u * 16u * 4u;
1637 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351638}
1639
[email protected]34ff8b0c2010-10-01 20:06:021640bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351641 DCHECK_NE(id_, 0u);
1642 ScopedGLErrorSuppressor suppressor(decoder_);
1643 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]6217d392010-03-25 22:08:351644
[email protected]f0e6a34f2012-01-04 20:53:401645 WrappedTexImage2D(GL_TEXTURE_2D,
1646 0, // mip level
1647 format,
1648 size.width(),
1649 size.height(),
1650 0, // border
1651 format,
1652 GL_UNSIGNED_BYTE,
1653 NULL);
[email protected]6217d392010-03-25 22:08:351654
[email protected]d37231fa2010-04-09 21:16:021655 size_ = size;
1656
[email protected]1078f912011-12-23 13:12:141657 bool success = glGetError() == GL_NO_ERROR;
1658 if (success) {
1659 uint32 image_size = 0;
1660 GLES2Util::ComputeImageDataSize(
1661 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 4, &image_size);
1662 estimated_size_ = image_size;
1663 decoder_->UpdateBackbufferMemoryAccounting();
1664 }
1665 return success;
[email protected]6217d392010-03-25 22:08:351666}
1667
[email protected]3a4d0c52011-06-29 23:11:581668void Texture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351669 DCHECK_NE(id_, 0u);
1670 ScopedGLErrorSuppressor suppressor(decoder_);
1671 ScopedTexture2DBinder binder(decoder_, id_);
1672 glCopyTexImage2D(GL_TEXTURE_2D,
1673 0, // level
[email protected]3a4d0c52011-06-29 23:11:581674 format,
[email protected]6217d392010-03-25 22:08:351675 0, 0,
1676 size.width(),
1677 size.height(),
1678 0); // border
1679}
1680
1681void Texture::Destroy() {
1682 if (id_ != 0) {
1683 ScopedGLErrorSuppressor suppressor(decoder_);
1684 glDeleteTextures(1, &id_);
1685 id_ = 0;
[email protected]1078f912011-12-23 13:12:141686 estimated_size_ = 0;
1687 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351688 }
1689}
1690
[email protected]97872062010-11-03 19:07:051691void Texture::Invalidate() {
1692 id_ = 0;
1693}
1694
[email protected]6217d392010-03-25 22:08:351695RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1696 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141697 id_(0),
1698 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351699}
1700
1701RenderBuffer::~RenderBuffer() {
1702 // This does not destroy the render buffer because that would require that
1703 // the associated GL context was current. Just check that it was explicitly
1704 // destroyed.
1705 DCHECK_EQ(id_, 0u);
1706}
1707
1708void RenderBuffer::Create() {
1709 ScopedGLErrorSuppressor suppressor(decoder_);
1710 Destroy();
1711 glGenRenderbuffersEXT(1, &id_);
1712}
1713
[email protected]34ff8b0c2010-10-01 20:06:021714bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1715 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351716 ScopedGLErrorSuppressor suppressor(decoder_);
1717 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021718 if (samples <= 1) {
1719 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1720 format,
1721 size.width(),
1722 size.height());
1723 } else {
[email protected]57edfdad2012-02-07 04:57:151724 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021725 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1726 samples,
1727 format,
1728 size.width(),
1729 size.height());
1730 } else {
1731 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1732 samples,
1733 format,
1734 size.width(),
1735 size.height());
1736 }
1737 }
[email protected]1078f912011-12-23 13:12:141738 bool success = glGetError() == GL_NO_ERROR;
1739 if (success) {
1740 estimated_size_ = size.width() * size.height() * samples *
1741 GLES2Util::RenderbufferBytesPerPixel(format);
1742 decoder_->UpdateBackbufferMemoryAccounting();
1743 }
1744 return success;
[email protected]6217d392010-03-25 22:08:351745}
1746
1747void RenderBuffer::Destroy() {
1748 if (id_ != 0) {
1749 ScopedGLErrorSuppressor suppressor(decoder_);
1750 glDeleteRenderbuffersEXT(1, &id_);
1751 id_ = 0;
[email protected]1078f912011-12-23 13:12:141752 estimated_size_ = 0;
1753 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351754 }
1755}
1756
[email protected]97872062010-11-03 19:07:051757void RenderBuffer::Invalidate() {
1758 id_ = 0;
1759}
1760
[email protected]6217d392010-03-25 22:08:351761FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1762 : decoder_(decoder),
1763 id_(0) {
1764}
1765
1766FrameBuffer::~FrameBuffer() {
1767 // This does not destroy the frame buffer because that would require that
1768 // the associated GL context was current. Just check that it was explicitly
1769 // destroyed.
1770 DCHECK_EQ(id_, 0u);
1771}
1772
1773void FrameBuffer::Create() {
1774 ScopedGLErrorSuppressor suppressor(decoder_);
1775 Destroy();
1776 glGenFramebuffersEXT(1, &id_);
1777}
1778
1779void FrameBuffer::AttachRenderTexture(Texture* texture) {
1780 DCHECK_NE(id_, 0u);
1781 ScopedGLErrorSuppressor suppressor(decoder_);
1782 ScopedFrameBufferBinder binder(decoder_, id_);
1783 GLuint attach_id = texture ? texture->id() : 0;
1784 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1785 GL_COLOR_ATTACHMENT0,
1786 GL_TEXTURE_2D,
1787 attach_id,
1788 0);
1789}
1790
[email protected]b9363b22010-06-09 22:06:151791void FrameBuffer::AttachRenderBuffer(GLenum target,
1792 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351793 DCHECK_NE(id_, 0u);
1794 ScopedGLErrorSuppressor suppressor(decoder_);
1795 ScopedFrameBufferBinder binder(decoder_, id_);
1796 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1797 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151798 target,
[email protected]6217d392010-03-25 22:08:351799 GL_RENDERBUFFER,
1800 attach_id);
1801}
1802
[email protected]6217d392010-03-25 22:08:351803void FrameBuffer::Destroy() {
1804 if (id_ != 0) {
1805 ScopedGLErrorSuppressor suppressor(decoder_);
1806 glDeleteFramebuffersEXT(1, &id_);
1807 id_ = 0;
1808 }
1809}
1810
[email protected]97872062010-11-03 19:07:051811void FrameBuffer::Invalidate() {
1812 id_ = 0;
1813}
1814
[email protected]6217d392010-03-25 22:08:351815GLenum FrameBuffer::CheckStatus() {
1816 DCHECK_NE(id_, 0u);
1817 ScopedGLErrorSuppressor suppressor(decoder_);
1818 ScopedFrameBufferBinder binder(decoder_, id_);
1819 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1820}
1821
[email protected]aa7666122011-09-02 19:45:521822GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1823 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321824}
1825
[email protected]aa7666122011-09-02 19:45:521826GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391827 : GLES2Decoder(),
[email protected]3b1ecc262011-08-03 22:49:571828 group_(group),
[email protected]96449d2c2009-11-25 00:01:321829 error_bits_(0),
[email protected]96449d2c2009-11-25 00:01:321830 pack_alignment_(4),
1831 unpack_alignment_(4),
[email protected]b1122982010-05-17 23:04:241832 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491833 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241834 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401835 fixed_attrib_buffer_id_(0),
1836 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501837 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281838 clear_red_(0),
1839 clear_green_(0),
1840 clear_blue_(0),
1841 clear_alpha_(0),
1842 mask_red_(true),
1843 mask_green_(true),
1844 mask_blue_(true),
1845 mask_alpha_(true),
1846 clear_stencil_(0),
1847 mask_stencil_front_(-1),
1848 mask_stencil_back_(-1),
1849 clear_depth_(1.0f),
1850 mask_depth_(true),
1851 enable_scissor_test_(false),
[email protected]297ca1c2011-06-20 23:08:461852 enable_depth_test_(false),
1853 enable_stencil_test_(false),
1854 state_dirty_(true),
[email protected]34ff8b0c2010-10-01 20:06:021855 offscreen_target_color_format_(0),
1856 offscreen_target_depth_format_(0),
1857 offscreen_target_stencil_format_(0),
1858 offscreen_target_samples_(0),
[email protected]8a61d872012-01-20 12:43:561859 offscreen_target_buffer_preserved_(true),
[email protected]97872062010-11-03 19:07:051860 offscreen_saved_color_format_(0),
[email protected]b0af4f52011-09-28 22:04:421861 stream_texture_manager_(NULL),
[email protected]32fe9aa2011-01-21 23:47:131862 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:461863 back_buffer_has_depth_(false),
1864 back_buffer_has_stencil_(false),
[email protected]473c01ccb2011-06-07 01:33:301865 teximage2d_faster_than_texsubimage2d_(true),
1866 bufferdata_faster_than_buffersubdata_(true),
[email protected]a3a93e7b2010-08-28 00:48:561867 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051868 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111869 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001870 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241871 tex_image_2d_failed_(false),
[email protected]38d139d2011-07-14 00:38:431872 frame_number_(0),
1873 has_arb_robustness_(false),
[email protected]75c023c2011-08-22 23:54:511874 reset_status_(GL_NO_ERROR),
[email protected]a2a0fe762011-09-20 00:59:121875 needs_mac_nvidia_driver_workaround_(false),
[email protected]f0d74742011-10-03 16:31:041876 needs_glsl_built_in_function_emulation_(false),
1877 force_webgl_glsl_validation_(false),
[email protected]062c38b2012-01-18 03:25:101878 derivatives_explicitly_enabled_(false),
1879 compile_shader_always_succeeds_(false) {
[email protected]3b1ecc262011-08-03 22:49:571880 DCHECK(group);
1881
[email protected]b1122982010-05-17 23:04:241882 attrib_0_value_.v[0] = 0.0f;
1883 attrib_0_value_.v[1] = 0.0f;
1884 attrib_0_value_.v[2] = 0.0f;
1885 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151886
[email protected]c2f8c8402010-12-06 18:07:241887 // The shader translator is used for WebGL even when running on EGL
1888 // because additional restrictions are needed (like only enabling
1889 // GL_OES_standard_derivatives on demand). It is used for the unit
1890 // tests because
1891 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1892 // empty string to CompileShader and this is not a valid shader.
1893 // TODO(apatrick): fix this test.
1894 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:041895 !feature_info_->feature_flags().chromium_webglsl &&
1896 !force_webgl_glsl_validation_) ||
[email protected]39ba4f02012-03-26 01:16:001897 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
1898 CommandLine::ForCurrentProcess()->HasSwitch(
1899 switches::kDisableGLSLTranslator)) {
[email protected]b9363b22010-06-09 22:06:151900 use_shader_translator_ = false;
1901 }
[email protected]473c01ccb2011-06-07 01:33:301902
1903 // TODO(gman): Consider setting these based on GPU and/or driver.
1904 if (IsAngle()) {
1905 teximage2d_faster_than_texsubimage2d_ = false;
1906 bufferdata_faster_than_buffersubdata_ = false;
1907 }
[email protected]96449d2c2009-11-25 00:01:321908}
1909
[email protected]80eb6b52012-01-19 00:14:411910GLES2DecoderImpl::~GLES2DecoderImpl() {
1911}
1912
[email protected]c410da802011-03-14 19:17:411913bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:381914 const scoped_refptr<gfx::GLSurface>& surface,
1915 const scoped_refptr<gfx::GLContext>& context,
[email protected]c410da802011-03-14 19:17:411916 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:291917 const DisallowedFeatures& disallowed_features,
[email protected]c410da802011-03-14 19:17:411918 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:241919 const std::vector<int32>& attribs) {
[email protected]4bedba72010-04-20 22:08:541920 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301921 DCHECK(!context_.get());
1922
[email protected]e844ae22012-01-14 03:36:261923 if (CommandLine::ForCurrentProcess()->HasSwitch(
1924 switches::kEnableGPUDebugging)) {
1925 set_debug(true);
1926 }
1927
[email protected]39ba4f02012-03-26 01:16:001928 if (CommandLine::ForCurrentProcess()->HasSwitch(
1929 switches::kEnableGPUCommandLogging)) {
1930 set_log_commands(true);
1931 }
1932
[email protected]062c38b2012-01-18 03:25:101933 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
1934 switches::kCompileShaderAlwaysSucceeds);
1935
[email protected]fbe20372011-06-01 01:46:381936 // Take ownership of the GLSurface. TODO(apatrick): once the parent / child
1937 // context is retired, the decoder should not take an initial surface as
1938 // an argument to this function.
1939 // Maybe create a short lived offscreen GLSurface for the purpose of
1940 // initializing the decoder's GLContext.
1941 surface_ = surface;
[email protected]f62a5ab2011-05-23 20:34:151942
[email protected]66791e382010-07-14 20:48:301943 // Take ownership of the GLContext.
[email protected]fbe20372011-06-01 01:46:381944 context_ = context;
[email protected]d37231fa2010-04-09 21:16:021945
[email protected]246a70452010-03-05 21:53:501946 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:011947 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
1948 << "MakeCurrent failed.";
[email protected]1871a092011-10-10 21:46:421949 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]246a70452010-03-05 21:53:501950 Destroy();
1951 return false;
[email protected]eb54a562010-01-20 21:55:181952 }
1953
[email protected]e82fb792011-09-22 00:33:291954 if (!group_->Initialize(disallowed_features, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:221955 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:391956 << "failed to initialize.";
[email protected]1871a092011-10-10 21:46:421957 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]a3ded6d2010-10-19 06:44:391958 Destroy();
[email protected]ae1741092010-11-17 19:16:031959 return false;
[email protected]a3ded6d2010-10-19 06:44:391960 }
1961
[email protected]246a70452010-03-05 21:53:501962 CHECK_GL_ERROR();
[email protected]e82fb792011-09-22 00:33:291963 disallowed_features_ = disallowed_features;
[email protected]246a70452010-03-05 21:53:501964
[email protected]3757a372012-01-19 05:20:441965 vertex_attrib_manager_.reset(new VertexAttribManager());
1966 vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:321967
[email protected]c45f1972012-03-14 07:27:361968 query_manager_.reset(new QueryManager(this, feature_info_->feature_flags(
1969 ).use_arb_occlusion_query2_for_occlusion_query_boolean));
[email protected]882ba1e22012-03-08 19:02:531970
[email protected]302ce6d2011-07-07 23:28:111971 util_.set_num_compressed_texture_formats(
1972 validators_->compressed_texture_format.GetValues().size());
1973
[email protected]1071e572011-02-09 20:00:121974 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
1975 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
1976 // OpenGL ES 2.0 does not have this issue.
1977 glEnableVertexAttribArray(0);
1978 }
[email protected]b1122982010-05-17 23:04:241979 glGenBuffersARB(1, &attrib_0_buffer_id_);
1980 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
1981 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
1982 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:401983 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:081984
[email protected]246a70452010-03-05 21:53:501985 texture_units_.reset(
1986 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:151987 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:491988 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:311989 // We want the last bind to be 2D.
1990 TextureManager::TextureInfo* info;
1991 if (feature_info_->feature_flags().oes_egl_image_external) {
1992 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_EXTERNAL_OES);
1993 texture_units_[tt].bound_texture_external_oes = info;
1994 glBindTexture(GL_TEXTURE_EXTERNAL_OES, info->service_id());
1995 }
[email protected]e51bdf32011-11-23 22:21:461996 if (feature_info_->feature_flags().arb_texture_rectangle) {
1997 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_RECTANGLE_ARB);
1998 texture_units_[tt].bound_texture_rectangle_arb = info;
1999 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, info->service_id());
2000 }
[email protected]61eeb33f2011-07-26 15:30:312001 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:492002 texture_units_[tt].bound_texture_cube_map = info;
2003 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
2004 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2005 texture_units_[tt].bound_texture_2d = info;
2006 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:152007 }
[email protected]00f893d2010-08-24 18:55:492008 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:502009 CHECK_GL_ERROR();
2010
[email protected]297ca1c2011-06-20 23:08:462011 ContextCreationAttribParser attrib_parser;
2012 if (!attrib_parser.Parse(attribs))
2013 return false;
[email protected]41c56362011-06-14 16:47:432014
[email protected]297ca1c2011-06-20 23:08:462015 // These are NOT if the back buffer has these proprorties. They are
2016 // if we want the command buffer to enforce them regardless of what
2017 // the real backbuffer is assuming the real back buffer gives us more than
2018 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2019 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2020 // can't do anything about that.
2021
2022 GLint v = 0;
2023 glGetIntegerv(GL_ALPHA_BITS, &v);
2024 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2025 // user requested RGB then RGB. If the user did not specify a preference than
2026 // use whatever we were given. Same for DEPTH and STENCIL.
2027 back_buffer_color_format_ =
2028 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2029 glGetIntegerv(GL_DEPTH_BITS, &v);
2030 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2031 glGetIntegerv(GL_STENCIL_BITS, &v);
2032 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2033
2034 if (surface_->IsOffscreen()) {
[email protected]34ff8b0c2010-10-01 20:06:022035 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:542036 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:022037 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
2038 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:432039 // max_sample_count must be initialized to a sane value. If
2040 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2041 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:022042 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2043 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2044 max_sample_count);
2045 } else {
2046 offscreen_target_samples_ = 1;
2047 }
[email protected]8a61d872012-01-20 12:43:562048 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
[email protected]34ff8b0c2010-10-01 20:06:022049
2050 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2051 const bool rgb8_supported =
2052 context_->HasExtension("GL_OES_rgb8_rgba8");
2053 // The only available default render buffer formats in GLES2 have very
2054 // little precision. Don't enable multisampling unless 8-bit render
2055 // buffer formats are available--instead fall back to 8-bit textures.
2056 if (rgb8_supported && offscreen_target_samples_ > 1) {
2057 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2058 GL_RGBA8 : GL_RGB8;
2059 } else {
2060 offscreen_target_samples_ = 1;
2061 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2062 GL_RGBA : GL_RGB;
2063 }
2064
2065 // ANGLE only supports packed depth/stencil formats, so use it if it is
2066 // available.
2067 const bool depth24_stencil8_supported =
2068 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272069 VLOG(1) << "GL_OES_packed_depth_stencil "
2070 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:002071 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2072 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022073 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2074 offscreen_target_stencil_format_ = 0;
2075 } else {
2076 // It may be the case that this depth/stencil combination is not
2077 // supported, but this will be checked later by CheckFramebufferStatus.
2078 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2079 GL_DEPTH_COMPONENT16 : 0;
2080 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2081 GL_STENCIL_INDEX8 : 0;
2082 }
2083 } else {
2084 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2085 GL_RGBA : GL_RGB;
2086
2087 // If depth is requested at all, use the packed depth stencil format if
2088 // it's available, as some desktop GL drivers don't support any non-packed
2089 // formats for depth attachments.
2090 const bool depth24_stencil8_supported =
2091 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272092 VLOG(1) << "GL_EXT_packed_depth_stencil "
2093 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:022094
[email protected]71ee3642010-10-14 18:08:002095 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2096 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022097 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2098 offscreen_target_stencil_format_ = 0;
2099 } else {
2100 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2101 GL_DEPTH_COMPONENT : 0;
2102 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2103 GL_STENCIL_INDEX : 0;
2104 }
2105 }
2106
[email protected]97872062010-11-03 19:07:052107 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2108 GL_RGBA : GL_RGB;
2109
[email protected]6217d392010-03-25 22:08:352110 // Create the target frame buffer. This is the one that the client renders
2111 // directly to.
2112 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
2113 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022114 // Due to GLES2 format limitations, either the color texture (for
2115 // non-multisampling) or the color render buffer (for multisampling) will be
2116 // attached to the offscreen frame buffer. The render buffer has more
2117 // limited formats available to it, but the texture can't do multisampling.
2118 if (IsOffscreenBufferMultisampled()) {
2119 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
2120 offscreen_target_color_render_buffer_->Create();
2121 } else {
2122 offscreen_target_color_texture_.reset(new Texture(this));
2123 offscreen_target_color_texture_->Create();
2124 }
2125 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152126 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022127 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152128 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:352129
2130 // Create the saved offscreen texture. The target frame buffer is copied
2131 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:022132 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
2133 offscreen_saved_frame_buffer_->Create();
2134 //
[email protected]6217d392010-03-25 22:08:352135 offscreen_saved_color_texture_.reset(new Texture(this));
2136 offscreen_saved_color_texture_->Create();
2137
[email protected]6217d392010-03-25 22:08:352138 // Allocate the render buffers at their initial size and check the status
2139 // of the frame buffers is okay.
[email protected]799b4b22011-08-22 17:09:592140 if (!ResizeOffscreenFrameBuffer(size)) {
[email protected]d0498742010-09-20 20:27:012141 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:352142 Destroy();
2143 return false;
2144 }
2145
2146 // Bind to the new default frame buffer (the offscreen target frame buffer).
2147 // This should now be associated with ID zero.
2148 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2149 }
2150
[email protected]295faf4b2012-01-25 23:31:412151 // Clear the backbuffer.
2152 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2153
[email protected]76a0ee102010-04-07 21:03:042154 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2155 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2156 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372157 // mailing list archives. It also implicitly enables the desktop GL
2158 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2159 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152160 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2161 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372162 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152163 }
[email protected]de17df392010-04-23 21:09:412164
[email protected]38d139d2011-07-14 00:38:432165 has_arb_robustness_ = context->HasExtension("GL_ARB_robustness");
2166
[email protected]e82fb792011-09-22 00:33:292167 if (!disallowed_features_.driver_bug_workarounds) {
[email protected]75c023c2011-08-22 23:54:512168#if defined(OS_MACOSX)
[email protected]a2a0fe762011-09-20 00:59:122169 const char* vendor_str = reinterpret_cast<const char*>(
2170 glGetString(GL_VENDOR));
2171 needs_mac_nvidia_driver_workaround_ =
2172 vendor_str && strstr(vendor_str, "NVIDIA");
2173 needs_glsl_built_in_function_emulation_ =
2174 vendor_str && (strstr(vendor_str, "ATI") || strstr(vendor_str, "AMD"));
2175#elif defined(OS_WIN)
2176 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
2177 needs_glsl_built_in_function_emulation_ = true;
[email protected]75c023c2011-08-22 23:54:512178#endif
[email protected]a2a0fe762011-09-20 00:59:122179 }
[email protected]75c023c2011-08-22 23:54:512180
[email protected]c2f8c8402010-12-06 18:07:242181 if (!InitializeShaderTranslator()) {
2182 return false;
[email protected]de17df392010-04-23 21:09:412183 }
[email protected]76a0ee102010-04-07 21:03:042184
[email protected]246a70452010-03-05 21:53:502185 return true;
[email protected]96449d2c2009-11-25 00:01:322186}
2187
[email protected]302ce6d2011-07-07 23:28:112188void GLES2DecoderImpl::UpdateCapabilities() {
2189 util_.set_num_compressed_texture_formats(
2190 validators_->compressed_texture_format.GetValues().size());
2191 util_.set_num_shader_binary_formats(
2192 validators_->shader_binary_format.GetValues().size());
2193}
2194
[email protected]c2f8c8402010-12-06 18:07:242195bool GLES2DecoderImpl::InitializeShaderTranslator() {
2196 // Re-check the state of use_shader_translator_ each time this is called.
2197 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:042198 (feature_info_->feature_flags().chromium_webglsl ||
2199 force_webgl_glsl_validation_) &&
[email protected]c2f8c8402010-12-06 18:07:242200 !use_shader_translator_) {
2201 use_shader_translator_ = true;
2202 }
2203 if (!use_shader_translator_) {
2204 return true;
2205 }
2206 ShBuiltInResources resources;
2207 ShInitBuiltInResources(&resources);
2208 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2209 resources.MaxVertexUniformVectors =
2210 group_->max_vertex_uniform_vectors();
2211 resources.MaxVaryingVectors = group_->max_varying_vectors();
2212 resources.MaxVertexTextureImageUnits =
2213 group_->max_vertex_texture_image_units();
2214 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2215 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2216 resources.MaxFragmentUniformVectors =
2217 group_->max_fragment_uniform_vectors();
2218 resources.MaxDrawBuffers = 1;
[email protected]f0d74742011-10-03 16:31:042219
2220 if (force_webgl_glsl_validation_) {
2221 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2222 } else {
2223 resources.OES_standard_derivatives =
2224 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
[email protected]e51bdf32011-11-23 22:21:462225 resources.ARB_texture_rectangle =
2226 feature_info_->feature_flags().arb_texture_rectangle ? 1 : 0;
[email protected]f0d74742011-10-03 16:31:042227 }
2228
[email protected]c2f8c8402010-12-06 18:07:242229 vertex_translator_.reset(new ShaderTranslator);
[email protected]f0d74742011-10-03 16:31:042230 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ||
2231 feature_info_->feature_flags().chromium_webglsl ?
2232 SH_WEBGL_SPEC : SH_GLES2_SPEC;
[email protected]a2a0fe762011-09-20 00:59:122233 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2234 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2235 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2236 ShaderTranslatorInterface::GlslBuiltInFunctionBehavior function_behavior =
2237 needs_glsl_built_in_function_emulation_ ?
2238 ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated :
2239 ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal;
[email protected]c2f8c8402010-12-06 18:07:242240 if (!vertex_translator_->Init(
[email protected]a2a0fe762011-09-20 00:59:122241 SH_VERTEX_SHADER, shader_spec, &resources,
2242 implementation_type, function_behavior)) {
[email protected]c2f8c8402010-12-06 18:07:242243 LOG(ERROR) << "Could not initialize vertex shader translator.";
2244 Destroy();
2245 return false;
2246 }
2247 fragment_translator_.reset(new ShaderTranslator);
2248 if (!fragment_translator_->Init(
[email protected]a2a0fe762011-09-20 00:59:122249 SH_FRAGMENT_SHADER, shader_spec, &resources,
2250 implementation_type, function_behavior)) {
[email protected]c2f8c8402010-12-06 18:07:242251 LOG(ERROR) << "Could not initialize fragment shader translator.";
2252 Destroy();
2253 return false;
2254 }
2255 return true;
2256}
2257
[email protected]ae51d192010-04-27 00:48:032258bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472259 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032260 if (GetBufferInfo(client_ids[ii])) {
2261 return false;
2262 }
2263 }
2264 scoped_array<GLuint> service_ids(new GLuint[n]);
2265 glGenBuffersARB(n, service_ids.get());
2266 for (GLsizei ii = 0; ii < n; ++ii) {
2267 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2268 }
2269 return true;
2270}
2271
2272bool GLES2DecoderImpl::GenFramebuffersHelper(
2273 GLsizei n, const GLuint* client_ids) {
2274 for (GLsizei ii = 0; ii < n; ++ii) {
2275 if (GetFramebufferInfo(client_ids[ii])) {
2276 return false;
2277 }
2278 }
2279 scoped_array<GLuint> service_ids(new GLuint[n]);
2280 glGenFramebuffersEXT(n, service_ids.get());
2281 for (GLsizei ii = 0; ii < n; ++ii) {
2282 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2283 }
2284 return true;
2285}
2286
2287bool GLES2DecoderImpl::GenRenderbuffersHelper(
2288 GLsizei n, const GLuint* client_ids) {
2289 for (GLsizei ii = 0; ii < n; ++ii) {
2290 if (GetRenderbufferInfo(client_ids[ii])) {
2291 return false;
2292 }
2293 }
2294 scoped_array<GLuint> service_ids(new GLuint[n]);
2295 glGenRenderbuffersEXT(n, service_ids.get());
2296 for (GLsizei ii = 0; ii < n; ++ii) {
2297 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2298 }
2299 return true;
2300}
2301
2302bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2303 for (GLsizei ii = 0; ii < n; ++ii) {
2304 if (GetTextureInfo(client_ids[ii])) {
2305 return false;
2306 }
2307 }
2308 scoped_array<GLuint> service_ids(new GLuint[n]);
2309 glGenTextures(n, service_ids.get());
2310 for (GLsizei ii = 0; ii < n; ++ii) {
2311 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2312 }
2313 return true;
2314}
2315
2316void GLES2DecoderImpl::DeleteBuffersHelper(
2317 GLsizei n, const GLuint* client_ids) {
2318 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102319 BufferManager::BufferInfo* buffer = GetBufferInfo(client_ids[ii]);
2320 if (buffer && !buffer->IsDeleted()) {
[email protected]3757a372012-01-19 05:20:442321 vertex_attrib_manager_->Unbind(buffer);
[email protected]a0b78dc2011-11-11 10:43:102322 if (bound_array_buffer_ == buffer) {
2323 bound_array_buffer_ = NULL;
2324 }
2325 if (bound_element_array_buffer_ == buffer) {
2326 bound_element_array_buffer_ = NULL;
2327 }
[email protected]ae51d192010-04-27 00:48:032328 RemoveBufferInfo(client_ids[ii]);
2329 }
[email protected]a93bb842010-02-16 23:03:472330 }
[email protected]07f54fcc2009-12-22 02:46:302331}
2332
[email protected]ae51d192010-04-27 00:48:032333void GLES2DecoderImpl::DeleteFramebuffersHelper(
2334 GLsizei n, const GLuint* client_ids) {
[email protected]b177ae22011-11-01 03:29:112335 bool supports_seperate_framebuffer_binds =
2336 feature_info_->feature_flags().chromium_framebuffer_multisample;
2337
[email protected]a25fa872010-03-25 02:57:582338 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102339 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ae51d192010-04-27 00:48:032340 GetFramebufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102341 if (framebuffer && !framebuffer->IsDeleted()) {
2342 if (framebuffer == bound_draw_framebuffer_) {
[email protected]297ca1c2011-06-20 23:08:462343 bound_draw_framebuffer_ = NULL;
2344 state_dirty_ = true;
[email protected]b177ae22011-11-01 03:29:112345 GLenum target = supports_seperate_framebuffer_binds ?
2346 GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER;
2347 glBindFramebufferEXT(target, GetBackbufferServiceId());
2348 }
[email protected]a0b78dc2011-11-11 10:43:102349 if (framebuffer == bound_read_framebuffer_) {
[email protected]b177ae22011-11-01 03:29:112350 bound_read_framebuffer_ = NULL;
2351 GLenum target = supports_seperate_framebuffer_binds ?
2352 GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER;
2353 glBindFramebufferEXT(target, GetBackbufferServiceId());
[email protected]297ca1c2011-06-20 23:08:462354 }
[email protected]a0b78dc2011-11-11 10:43:102355 GLuint service_id = framebuffer->service_id();
[email protected]ae51d192010-04-27 00:48:032356 glDeleteFramebuffersEXT(1, &service_id);
2357 RemoveFramebufferInfo(client_ids[ii]);
2358 }
[email protected]a25fa872010-03-25 02:57:582359 }
[email protected]07f54fcc2009-12-22 02:46:302360}
2361
[email protected]ae51d192010-04-27 00:48:032362void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2363 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102364 bool supports_seperate_framebuffer_binds =
2365 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a25fa872010-03-25 02:57:582366 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102367 RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]ae51d192010-04-27 00:48:032368 GetRenderbufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102369 if (renderbuffer && !renderbuffer->IsDeleted()) {
2370 if (bound_renderbuffer_ == renderbuffer) {
2371 bound_renderbuffer_ = NULL;
2372 }
2373 // Unbind from current framebuffers.
2374 if (supports_seperate_framebuffer_binds) {
2375 if (bound_read_framebuffer_) {
2376 bound_read_framebuffer_->UnbindRenderbuffer(
2377 GL_READ_FRAMEBUFFER, renderbuffer);
2378 }
2379 if (bound_draw_framebuffer_) {
2380 bound_draw_framebuffer_->UnbindRenderbuffer(
2381 GL_DRAW_FRAMEBUFFER, renderbuffer);
2382 }
2383 } else {
2384 if (bound_draw_framebuffer_) {
2385 bound_draw_framebuffer_->UnbindRenderbuffer(
2386 GL_FRAMEBUFFER, renderbuffer);
2387 }
2388 }
[email protected]297ca1c2011-06-20 23:08:462389 state_dirty_ = true;
[email protected]a0b78dc2011-11-11 10:43:102390 GLuint service_id = renderbuffer->service_id();
[email protected]ae51d192010-04-27 00:48:032391 glDeleteRenderbuffersEXT(1, &service_id);
2392 RemoveRenderbufferInfo(client_ids[ii]);
2393 }
[email protected]a25fa872010-03-25 02:57:582394 }
[email protected]07f54fcc2009-12-22 02:46:302395}
2396
[email protected]ae51d192010-04-27 00:48:032397void GLES2DecoderImpl::DeleteTexturesHelper(
2398 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102399 bool supports_seperate_framebuffer_binds =
2400 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a93bb842010-02-16 23:03:472401 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102402 TextureManager::TextureInfo* texture = GetTextureInfo(client_ids[ii]);
2403 if (texture && !texture->IsDeleted()) {
2404 if (texture->IsAttachedToFramebuffer()) {
[email protected]297ca1c2011-06-20 23:08:462405 state_dirty_ = true;
2406 }
[email protected]a0b78dc2011-11-11 10:43:102407 // Unbind texture from texture units.
2408 for (size_t jj = 0; jj < group_->max_texture_units(); ++jj) {
2409 texture_units_[ii].Unbind(texture);
2410 }
2411 // Unbind from current framebuffers.
2412 if (supports_seperate_framebuffer_binds) {
2413 if (bound_read_framebuffer_) {
2414 bound_read_framebuffer_->UnbindTexture(GL_READ_FRAMEBUFFER, texture);
2415 }
2416 if (bound_draw_framebuffer_) {
2417 bound_draw_framebuffer_->UnbindTexture(GL_DRAW_FRAMEBUFFER, texture);
2418 }
2419 } else {
2420 if (bound_draw_framebuffer_) {
2421 bound_draw_framebuffer_->UnbindTexture(GL_FRAMEBUFFER, texture);
2422 }
2423 }
2424 GLuint service_id = texture->service_id();
2425 if (texture->IsStreamTexture() && stream_texture_manager_) {
[email protected]b0af4f52011-09-28 22:04:422426 stream_texture_manager_->DestroyStreamTexture(service_id);
2427 }
[email protected]e51bdf32011-11-23 22:21:462428#if defined(OS_MACOSX)
2429 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2430 ReleaseIOSurfaceForTexture(service_id);
2431 }
2432#endif
[email protected]5f4f2a732011-07-30 00:47:552433 glDeleteTextures(1, &service_id);
[email protected]ae51d192010-04-27 00:48:032434 RemoveTextureInfo(client_ids[ii]);
2435 }
[email protected]a93bb842010-02-16 23:03:472436 }
[email protected]07f54fcc2009-12-22 02:46:302437}
2438
[email protected]43f28f832010-02-03 02:28:482439// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322440
[email protected]eb54a562010-01-20 21:55:182441bool GLES2DecoderImpl::MakeCurrent() {
[email protected]38d139d2011-07-14 00:38:432442 bool result = context_.get() ? context_->MakeCurrent(surface_.get()) : false;
2443 if (result && WasContextLost()) {
2444 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2445 result = false;
2446 }
2447
2448 return result;
[email protected]eb54a562010-01-20 21:55:182449}
2450
[email protected]a96a6022011-11-04 00:58:122451void GLES2DecoderImpl::ReleaseCurrent() {
2452 if (context_.get())
2453 context_->ReleaseCurrent(surface_.get());
2454}
2455
[email protected]8e3e0662010-08-23 18:46:302456void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
[email protected]0d6bfdc2011-11-02 01:32:202457 RenderbufferManager::RenderbufferInfo* renderbuffer =
2458 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
[email protected]8e3e0662010-08-23 18:46:302459 glBindRenderbufferEXT(
[email protected]0d6bfdc2011-11-02 01:32:202460 GL_RENDERBUFFER, renderbuffer ? renderbuffer->service_id() : 0);
[email protected]8e3e0662010-08-23 18:46:302461}
2462
2463static void RebindCurrentFramebuffer(
2464 GLenum target,
2465 FramebufferManager::FramebufferInfo* info,
[email protected]a3783712012-01-20 22:18:242466 GLuint back_buffer_service_id) {
[email protected]8e3e0662010-08-23 18:46:302467 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462468
[email protected]a3783712012-01-20 22:18:242469 if (framebuffer_id == 0) {
2470 framebuffer_id = back_buffer_service_id;
[email protected]8e3e0662010-08-23 18:46:302471 }
[email protected]297ca1c2011-06-20 23:08:462472
[email protected]8e3e0662010-08-23 18:46:302473 glBindFramebufferEXT(target, framebuffer_id);
2474}
2475
2476void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]297ca1c2011-06-20 23:08:462477 state_dirty_ = true;
2478
[email protected]a3ded6d2010-10-19 06:44:392479 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302480 RebindCurrentFramebuffer(
2481 GL_FRAMEBUFFER,
2482 bound_draw_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242483 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302484 } else {
2485 RebindCurrentFramebuffer(
2486 GL_READ_FRAMEBUFFER_EXT,
2487 bound_read_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242488 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302489 RebindCurrentFramebuffer(
2490 GL_DRAW_FRAMEBUFFER_EXT,
2491 bound_draw_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242492 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302493 }
2494}
2495
2496void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2497 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2498 GLuint last_id;
2499 if (info.bound_texture_2d) {
2500 last_id = info.bound_texture_2d->service_id();
2501 } else {
2502 last_id = 0;
2503 }
2504
2505 glBindTexture(GL_TEXTURE_2D, last_id);
2506 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2507}
2508
[email protected]0d6bfdc2011-11-02 01:32:202509bool GLES2DecoderImpl::CheckFramebufferValid(
2510 FramebufferManager::FramebufferInfo* framebuffer,
2511 GLenum target, const char* func_name) {
[email protected]a0b78dc2011-11-11 10:43:102512 if (!framebuffer) {
[email protected]0d6bfdc2011-11-02 01:32:202513 return true;
2514 }
2515
[email protected]968351b2011-12-20 08:26:512516 if (framebuffer_manager()->IsComplete(framebuffer)) {
2517 return true;
2518 }
2519
[email protected]0d6bfdc2011-11-02 01:32:202520 GLenum completeness = framebuffer->IsPossiblyComplete();
2521 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
2522 SetGLError(
2523 GL_INVALID_FRAMEBUFFER_OPERATION,
2524 (std::string(func_name) + " framebuffer incomplete").c_str());
[email protected]3a03a8f2011-03-19 00:51:272525 return false;
2526 }
[email protected]0d6bfdc2011-11-02 01:32:202527
2528 // Are all the attachments cleared?
2529 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2530 texture_manager()->HaveUnclearedMips()) {
2531 if (!framebuffer->IsCleared()) {
2532 // Can we clear them?
2533 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2534 SetGLError(
2535 GL_INVALID_FRAMEBUFFER_OPERATION,
2536 (std::string(func_name) +
2537 " framebuffer incomplete (clear)").c_str());
2538 return false;
2539 }
2540 ClearUnclearedAttachments(target, framebuffer);
2541 }
2542 }
2543
[email protected]968351b2011-12-20 08:26:512544 if (!framebuffer_manager()->IsComplete(framebuffer)) {
2545 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2546 SetGLError(
2547 GL_INVALID_FRAMEBUFFER_OPERATION,
2548 (std::string(func_name) +
2549 " framebuffer incomplete (check)").c_str());
2550 return false;
2551 }
2552 framebuffer_manager()->MarkAsComplete(framebuffer);
2553 }
2554
[email protected]0d6bfdc2011-11-02 01:32:202555 // NOTE: At this point we don't know if the framebuffer is complete but
2556 // we DO know that everything that needs to be cleared has been cleared.
[email protected]3a03a8f2011-03-19 00:51:272557 return true;
2558}
2559
[email protected]0d6bfdc2011-11-02 01:32:202560bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
2561 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
2562 return CheckFramebufferValid(
2563 bound_draw_framebuffer_, GL_FRAMEBUFFER_EXT, func_name);
2564 }
2565 return CheckFramebufferValid(
2566 bound_draw_framebuffer_, GL_DRAW_FRAMEBUFFER_EXT, func_name) &&
2567 CheckFramebufferValid(
2568 bound_read_framebuffer_, GL_READ_FRAMEBUFFER_EXT, func_name);
2569}
2570
[email protected]8e3e0662010-08-23 18:46:302571gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
[email protected]0d6bfdc2011-11-02 01:32:202572 FramebufferManager::FramebufferInfo* framebuffer =
2573 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2574 if (framebuffer != NULL) {
[email protected]9edc6b22010-12-23 02:00:262575 const FramebufferManager::FramebufferInfo::Attachment* attachment =
[email protected]0d6bfdc2011-11-02 01:32:202576 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
[email protected]9edc6b22010-12-23 02:00:262577 if (attachment) {
2578 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502579 }
[email protected]9edc6b22010-12-23 02:00:262580 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022581 } else if (offscreen_target_frame_buffer_.get()) {
2582 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352583 } else {
[email protected]f62a5ab2011-05-23 20:34:152584 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022585 }
[email protected]246a70452010-03-05 21:53:502586}
2587
[email protected]9edc6b22010-12-23 02:00:262588GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202589 FramebufferManager::FramebufferInfo* framebuffer =
2590 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2591 if (framebuffer != NULL) {
2592 return framebuffer->GetColorAttachmentFormat();
[email protected]297ca1c2011-06-20 23:08:462593 } else if (offscreen_target_frame_buffer_.get()) {
2594 return offscreen_target_color_format_;
2595 } else {
2596 return back_buffer_color_format_;
2597 }
2598}
2599
2600GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202601 FramebufferManager::FramebufferInfo* framebuffer =
2602 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
2603 if (framebuffer != NULL) {
2604 return framebuffer->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262605 } else if (offscreen_target_frame_buffer_.get()) {
2606 return offscreen_target_color_format_;
2607 } else {
[email protected]32fe9aa2011-01-21 23:47:132608 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262609 }
2610}
2611
[email protected]9a5afa432011-07-22 18:16:392612void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]34ff8b0c2010-10-01 20:06:022613 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582614 // Update the info about the offscreen saved color texture in the parent.
2615 // The reference to the parent is a weak pointer and will become null if the
2616 // parent is later destroyed.
[email protected]262d7aa2010-12-03 22:07:292617 TextureManager* parent_texture_manager = parent_->texture_manager();
[email protected]262d7aa2010-12-03 22:07:292618 parent_texture_manager->SetLevelInfo(
[email protected]8a61d872012-01-20 12:43:562619 offscreen_saved_color_texture_info_,
[email protected]ef526492010-06-02 23:12:252620 GL_TEXTURE_2D,
2621 0, // level
2622 GL_RGBA,
[email protected]799b4b22011-08-22 17:09:592623 offscreen_size_.width(),
2624 offscreen_size_.height(),
[email protected]ef526492010-06-02 23:12:252625 1, // depth
2626 0, // border
2627 GL_RGBA,
[email protected]0d6bfdc2011-11-02 01:32:202628 GL_UNSIGNED_BYTE,
2629 true);
[email protected]262d7aa2010-12-03 22:07:292630 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562631 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042632 GL_TEXTURE_MAG_FILTER,
2633 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292634 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562635 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042636 GL_TEXTURE_MIN_FILTER,
2637 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292638 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562639 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042640 GL_TEXTURE_WRAP_S,
2641 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292642 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562643 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042644 GL_TEXTURE_WRAP_T,
2645 GL_CLAMP_TO_EDGE);
[email protected]8a61d872012-01-20 12:43:562646 } else {
2647 offscreen_saved_color_texture_info_ = NULL;
[email protected]0c8c9d22010-06-25 17:36:392648 }
[email protected]6217d392010-03-25 22:08:352649}
2650
[email protected]799b4b22011-08-22 17:09:592651void GLES2DecoderImpl::SetResizeCallback(
[email protected]9d37f062011-11-22 01:24:522652 const base::Callback<void(gfx::Size)>& callback) {
2653 resize_callback_ = callback;
[email protected]7ff86b92010-11-25 17:50:002654}
2655
[email protected]6b6e7ee2011-12-13 08:04:522656void GLES2DecoderImpl::SetMsgCallback(const MsgCallback& callback) {
2657 msg_callback_ = callback;
2658}
2659
[email protected]b0af4f52011-09-28 22:04:422660void GLES2DecoderImpl::SetStreamTextureManager(StreamTextureManager* manager) {
2661 stream_texture_manager_ = manager;
2662}
2663
[email protected]1318e922010-09-17 22:03:162664bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2665 uint32* service_texture_id) {
2666 TextureManager::TextureInfo* texture =
2667 texture_manager()->GetTextureInfo(client_texture_id);
2668 if (texture) {
2669 *service_texture_id = texture->service_id();
2670 return true;
2671 }
2672 return false;
2673}
2674
[email protected]96449d2c2009-11-25 00:01:322675void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392676 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052677
[email protected]c826d732012-02-09 04:40:262678 ChildList children = children_;
2679 for (ChildList::iterator it = children.begin(); it != children.end(); ++it)
2680 (*it)->SetParent(NULL, 0);
2681 DCHECK(children_.empty());
[email protected]3c644d82011-06-20 19:58:242682 SetParent(NULL, 0);
2683
[email protected]80eb6b52012-01-19 00:14:412684 // Unbind everything.
[email protected]3757a372012-01-19 05:20:442685 vertex_attrib_manager_.reset();
[email protected]80eb6b52012-01-19 00:14:412686 texture_units_.reset();
2687 bound_array_buffer_ = NULL;
2688 bound_element_array_buffer_ = NULL;
[email protected]882ba1e22012-03-08 19:02:532689 current_query_ = NULL;
[email protected]80eb6b52012-01-19 00:14:412690 current_program_ = NULL;
2691 bound_read_framebuffer_ = NULL;
2692 bound_draw_framebuffer_ = NULL;
2693 bound_renderbuffer_ = NULL;
2694
[email protected]eadc96792010-10-27 19:39:392695 if (have_context) {
[email protected]ca488e12010-12-13 20:06:142696 if (current_program_) {
2697 program_manager()->UnuseProgram(shader_manager(), current_program_);
2698 current_program_ = NULL;
2699 }
2700
[email protected]b1122982010-05-17 23:04:242701 if (attrib_0_buffer_id_) {
2702 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2703 }
[email protected]8fbedc02010-11-18 18:43:402704 if (fixed_attrib_buffer_id_) {
2705 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2706 }
[email protected]b1122982010-05-17 23:04:242707
[email protected]97872062010-11-03 19:07:052708 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542709 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052710 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542711 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052712 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022713 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052714 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152715 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052716 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152717 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052718 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022719 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052720 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542721 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:272722 if (offscreen_resolved_frame_buffer_.get())
2723 offscreen_resolved_frame_buffer_->Destroy();
2724 if (offscreen_resolved_color_texture_.get())
2725 offscreen_resolved_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052726 } else {
2727 if (offscreen_target_frame_buffer_.get())
2728 offscreen_target_frame_buffer_->Invalidate();
2729 if (offscreen_target_color_texture_.get())
2730 offscreen_target_color_texture_->Invalidate();
2731 if (offscreen_target_color_render_buffer_.get())
2732 offscreen_target_color_render_buffer_->Invalidate();
2733 if (offscreen_target_depth_render_buffer_.get())
2734 offscreen_target_depth_render_buffer_->Invalidate();
2735 if (offscreen_target_stencil_render_buffer_.get())
2736 offscreen_target_stencil_render_buffer_->Invalidate();
2737 if (offscreen_saved_frame_buffer_.get())
2738 offscreen_saved_frame_buffer_->Invalidate();
2739 if (offscreen_saved_color_texture_.get())
2740 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:272741 if (offscreen_resolved_frame_buffer_.get())
2742 offscreen_resolved_frame_buffer_->Invalidate();
2743 if (offscreen_resolved_color_texture_.get())
2744 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022745 }
[email protected]97872062010-11-03 19:07:052746
[email protected]882ba1e22012-03-08 19:02:532747 if (query_manager_.get()) {
2748 query_manager_->Destroy(have_context);
2749 query_manager_.reset();
2750 }
2751
[email protected]1871a092011-10-10 21:46:422752 if (group_) {
2753 group_->Destroy(have_context);
2754 group_ = NULL;
2755 }
[email protected]3ae019382011-10-05 19:42:412756
[email protected]fe871662011-06-16 20:43:052757 if (context_.get()) {
2758 context_->ReleaseCurrent(NULL);
[email protected]79311e82011-09-20 00:40:502759 context_ = NULL;
[email protected]fe871662011-06-16 20:43:052760 }
[email protected]0fc35742011-04-13 17:57:542761
[email protected]97872062010-11-03 19:07:052762 offscreen_target_frame_buffer_.reset();
2763 offscreen_target_color_texture_.reset();
2764 offscreen_target_color_render_buffer_.reset();
2765 offscreen_target_depth_render_buffer_.reset();
2766 offscreen_target_stencil_render_buffer_.reset();
2767 offscreen_saved_frame_buffer_.reset();
2768 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:272769 offscreen_resolved_frame_buffer_.reset();
2770 offscreen_resolved_color_texture_.reset();
[email protected]e51bdf32011-11-23 22:21:462771
2772#if defined(OS_MACOSX)
2773 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
2774 it != texture_to_io_surface_map_.end(); ++it) {
2775 CFRelease(it->second);
2776 }
2777 texture_to_io_surface_map_.clear();
2778#endif
[email protected]96449d2c2009-11-25 00:01:322779}
2780
[email protected]3c644d82011-06-20 19:58:242781bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
2782 uint32 new_parent_texture_id) {
[email protected]9a5afa432011-07-22 18:16:392783 if (!offscreen_saved_color_texture_.get())
2784 return false;
2785
[email protected]3c644d82011-06-20 19:58:242786 // Remove the saved frame buffer mapping from the parent decoder. The
2787 // parent pointer is a weak pointer so it will be null if the parent has
2788 // already been destroyed.
2789 if (parent_) {
[email protected]c826d732012-02-09 04:40:262790 ChildList::iterator it = std::find(
2791 parent_->children_.begin(),
2792 parent_->children_.end(),
2793 this);
2794 DCHECK(it != parent_->children_.end());
2795 parent_->children_.erase(it);
[email protected]3c644d82011-06-20 19:58:242796 // First check the texture has been mapped into the parent. This might not
2797 // be the case if initialization failed midway through.
2798 GLuint service_id = offscreen_saved_color_texture_->id();
2799 GLuint client_id = 0;
2800 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
[email protected]80eb6b52012-01-19 00:14:412801 parent_->texture_manager()->RemoveTextureInfo(client_id);
[email protected]3c644d82011-06-20 19:58:242802 }
2803 }
2804
2805 GLES2DecoderImpl* new_parent_impl = static_cast<GLES2DecoderImpl*>(
2806 new_parent);
2807 if (new_parent_impl) {
[email protected]c826d732012-02-09 04:40:262808#ifndef NDEBUG
2809 ChildList::iterator it = std::find(
2810 new_parent_impl->children_.begin(),
2811 new_parent_impl->children_.end(),
2812 this);
2813 DCHECK(it == new_parent_impl->children_.end());
2814#endif
2815 new_parent_impl->children_.push_back(this);
[email protected]3c644d82011-06-20 19:58:242816 // Map the ID of the saved offscreen texture into the parent so that
2817 // it can reference it.
2818 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]98687862011-07-11 23:31:302819
2820 // Replace texture info when ID is already in use by parent.
2821 if (new_parent_impl->texture_manager()->GetTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412822 new_parent_texture_id))
[email protected]98687862011-07-11 23:31:302823 new_parent_impl->texture_manager()->RemoveTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412824 new_parent_texture_id);
[email protected]98687862011-07-11 23:31:302825
[email protected]8a61d872012-01-20 12:43:562826 offscreen_saved_color_texture_info_ =
[email protected]5f4f2a732011-07-30 00:47:552827 new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id);
[email protected]8a61d872012-01-20 12:43:562828 offscreen_saved_color_texture_info_->SetNotOwned();
2829 new_parent_impl->texture_manager()->
2830 SetInfoTarget(offscreen_saved_color_texture_info_, GL_TEXTURE_2D);
[email protected]3c644d82011-06-20 19:58:242831
2832 parent_ = new_parent_impl->AsWeakPtr();
[email protected]9a5afa432011-07-22 18:16:392833
2834 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:242835 } else {
2836 parent_.reset();
[email protected]8a61d872012-01-20 12:43:562837 offscreen_saved_color_texture_info_ = NULL;
[email protected]3c644d82011-06-20 19:58:242838 }
2839
2840 return true;
2841}
2842
[email protected]1078f912011-12-23 13:12:142843void GLES2DecoderImpl::UpdateBackbufferMemoryAccounting() {
2844 size_t total = 0;
2845 if (offscreen_target_frame_buffer_.get()) {
2846 if (offscreen_target_color_texture_.get()) {
2847 total += offscreen_target_color_texture_->estimated_size();
2848 }
2849 if (offscreen_target_color_render_buffer_.get()) {
2850 total += offscreen_target_color_render_buffer_->estimated_size();
2851 }
2852 if (offscreen_target_depth_render_buffer_.get()) {
2853 total += offscreen_target_depth_render_buffer_->estimated_size();
2854 }
2855 if (offscreen_target_stencil_render_buffer_.get()) {
2856 total += offscreen_target_stencil_render_buffer_->estimated_size();
2857 }
2858 if (offscreen_saved_color_texture_.get()) {
2859 total += offscreen_saved_color_texture_->estimated_size();
2860 }
2861 if (offscreen_resolved_color_texture_.get()) {
2862 total += offscreen_resolved_color_texture_->estimated_size();
2863 }
2864 } else {
2865 gfx::Size size = surface_->GetSize();
2866 total += size.width() * size.height() *
2867 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_);
2868 }
2869 TRACE_COUNTER_ID1(
2870 "GLES2DecoderImpl", "BackbufferMemory", this, total);
2871}
2872
[email protected]799b4b22011-08-22 17:09:592873bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2874 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
2875 if (!is_offscreen) {
2876 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
2877 << " with an onscreen framebuffer.";
2878 return false;
2879 }
2880
2881 if (offscreen_size_ == size)
2882 return true;
2883
2884 offscreen_size_ = size;
2885 int w = offscreen_size_.width();
2886 int h = offscreen_size_.height();
2887 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
2888 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2889 << "to allocate storage due to excessive dimensions.";
2890 return false;
2891 }
2892
2893 // Reallocate the offscreen target buffers.
2894 DCHECK(offscreen_target_color_format_);
2895 if (IsOffscreenBufferMultisampled()) {
2896 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2897 offscreen_size_, offscreen_target_color_format_,
2898 offscreen_target_samples_)) {
2899 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2900 << "to allocate storage for offscreen target color buffer.";
2901 return false;
2902 }
2903 } else {
2904 if (!offscreen_target_color_texture_->AllocateStorage(
2905 offscreen_size_, offscreen_target_color_format_)) {
2906 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2907 << "to allocate storage for offscreen target color texture.";
2908 return false;
2909 }
2910 }
2911 if (offscreen_target_depth_format_ &&
2912 !offscreen_target_depth_render_buffer_->AllocateStorage(
2913 offscreen_size_, offscreen_target_depth_format_,
2914 offscreen_target_samples_)) {
2915 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2916 << "to allocate storage for offscreen target depth buffer.";
2917 return false;
2918 }
2919 if (offscreen_target_stencil_format_ &&
2920 !offscreen_target_stencil_render_buffer_->AllocateStorage(
2921 offscreen_size_, offscreen_target_stencil_format_,
2922 offscreen_target_samples_)) {
2923 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2924 << "to allocate storage for offscreen target stencil buffer.";
2925 return false;
2926 }
[email protected]1078f912011-12-23 13:12:142927 UpdateBackbufferMemoryAccounting();
[email protected]799b4b22011-08-22 17:09:592928
2929 // Attach the offscreen target buffers to the target frame buffer.
2930 if (IsOffscreenBufferMultisampled()) {
2931 offscreen_target_frame_buffer_->AttachRenderBuffer(
2932 GL_COLOR_ATTACHMENT0,
2933 offscreen_target_color_render_buffer_.get());
2934 } else {
2935 offscreen_target_frame_buffer_->AttachRenderTexture(
2936 offscreen_target_color_texture_.get());
2937 }
2938 if (offscreen_target_depth_format_) {
2939 offscreen_target_frame_buffer_->AttachRenderBuffer(
2940 GL_DEPTH_ATTACHMENT,
2941 offscreen_target_depth_render_buffer_.get());
2942 }
2943 const bool packed_depth_stencil =
2944 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
2945 if (packed_depth_stencil) {
2946 offscreen_target_frame_buffer_->AttachRenderBuffer(
2947 GL_STENCIL_ATTACHMENT,
2948 offscreen_target_depth_render_buffer_.get());
2949 } else if (offscreen_target_stencil_format_) {
2950 offscreen_target_frame_buffer_->AttachRenderBuffer(
2951 GL_STENCIL_ATTACHMENT,
2952 offscreen_target_stencil_render_buffer_.get());
2953 }
2954
2955 if (offscreen_target_frame_buffer_->CheckStatus() !=
2956 GL_FRAMEBUFFER_COMPLETE) {
2957 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2958 << "because offscreen FBO was incomplete.";
2959 return false;
2960 }
2961
2962 // Clear the target frame buffer.
2963 {
2964 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
2965 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2966 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
2967 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2968 glClearStencil(0);
2969 glStencilMaskSeparate(GL_FRONT, -1);
2970 glStencilMaskSeparate(GL_BACK, -1);
2971 glClearDepth(0);
2972 glDepthMask(GL_TRUE);
2973 glDisable(GL_SCISSOR_TEST);
2974 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2975 RestoreClearState();
2976 }
[email protected]d85ef76d2011-09-08 22:21:432977
2978 // Destroy the offscreen resolved framebuffers.
2979 if (offscreen_resolved_frame_buffer_.get())
2980 offscreen_resolved_frame_buffer_->Destroy();
2981 if (offscreen_resolved_color_texture_.get())
2982 offscreen_resolved_color_texture_->Destroy();
2983 offscreen_resolved_color_texture_.reset();
2984 offscreen_resolved_frame_buffer_.reset();
2985
[email protected]799b4b22011-08-22 17:09:592986 return true;
[email protected]6217d392010-03-25 22:08:352987}
2988
[email protected]799b4b22011-08-22 17:09:592989error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
2990 uint32 immediate_data_size, const gles2::ResizeCHROMIUM& c) {
2991 GLuint width = static_cast<GLuint>(c.width);
2992 GLuint height = static_cast<GLuint>(c.height);
2993 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
[email protected]a0d989162011-11-22 13:15:072994#if defined(OS_POSIX) && !defined(OS_MACOSX) && \
2995 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
[email protected]7ff86b92010-11-25 17:50:002996 // Make sure that we are done drawing to the back buffer before resizing.
2997 glFinish();
2998#endif
[email protected]799b4b22011-08-22 17:09:592999 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3000 if (is_offscreen) {
3001 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height)))
3002 return error::kLostContext;
[email protected]7ff86b92010-11-25 17:50:003003 }
[email protected]799b4b22011-08-22 17:09:593004
[email protected]9d37f062011-11-22 01:24:523005 if (!resize_callback_.is_null()) {
3006 resize_callback_.Run(gfx::Size(width, height));
[email protected]c777de52011-09-09 23:08:563007 DCHECK(context_->IsCurrent(surface_.get()));
3008 if (!context_->IsCurrent(surface_.get()))
[email protected]658f7562011-09-09 05:24:053009 return error::kLostContext;
[email protected]658f7562011-09-09 05:24:053010 }
[email protected]799b4b22011-08-22 17:09:593011
[email protected]1078f912011-12-23 13:12:143012 UpdateBackbufferMemoryAccounting();
3013
[email protected]799b4b22011-08-22 17:09:593014 return error::kNoError;
[email protected]43ecf372010-11-16 19:19:393015}
3016
[email protected]96449d2c2009-11-25 00:01:323017const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3018 if (command_id > kStartPoint && command_id < kNumCommands) {
3019 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3020 }
3021 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3022}
3023
3024// Decode command with its arguments, and call the corresponding GL function.
3025// Note: args is a pointer to the command buffer. As such, it could be changed
3026// by a (malicious) client at any time, so if validation has to happen, it
3027// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:143028error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:323029 unsigned int command,
3030 unsigned int arg_count,
3031 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:143032 error::Error result = error::kNoError;
[email protected]e844ae22012-01-14 03:36:263033 if (log_commands()) {
[email protected]39ba4f02012-03-26 01:16:003034 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3035 // LOG(INFO), tried VLOG(1), no luck.
3036 LOG(ERROR) << "[" << this << "]" << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193037 }
[email protected]96449d2c2009-11-25 00:01:323038 unsigned int command_index = command - kStartPoint - 1;
3039 if (command_index < arraysize(g_command_info)) {
3040 const CommandInfo& info = g_command_info[command_index];
3041 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3042 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3043 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:193044 uint32 immediate_data_size =
3045 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:323046 switch (command) {
3047 #define GLES2_CMD_OP(name) \
3048 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:193049 result = Handle ## name( \
3050 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:323051 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:193052 break; \
[email protected]96449d2c2009-11-25 00:01:323053
3054 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:323055 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:383056 }
3057 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:303058 GLenum error;
3059 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]39ba4f02012-03-26 01:16:003060 LOG(ERROR) << "[" << this << "] "
3061 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3062 << GetCommandName(command);
[email protected]e844ae22012-01-14 03:36:263063 SetGLError(error, "GL error from driver");
[email protected]b9849abf2009-11-25 19:13:193064 }
[email protected]96449d2c2009-11-25 00:01:323065 }
3066 } else {
[email protected]f7a64ee2010-02-01 22:24:143067 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:323068 }
[email protected]b9849abf2009-11-25 19:13:193069 } else {
3070 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:323071 }
[email protected]a3a93e7b2010-08-28 00:48:563072 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3073 result = current_decoder_error_;
3074 current_decoder_error_ = error::kNoError;
3075 }
[email protected]b9849abf2009-11-25 19:13:193076 return result;
[email protected]96449d2c2009-11-25 00:01:323077}
3078
[email protected]ae51d192010-04-27 00:48:033079void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
3080 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:503081}
3082
[email protected]ae51d192010-04-27 00:48:033083bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3084 if (GetProgramInfo(client_id)) {
3085 return false;
3086 }
[email protected]96449d2c2009-11-25 00:01:323087 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:033088 if (service_id != 0) {
3089 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:323090 }
[email protected]ae51d192010-04-27 00:48:033091 return true;
[email protected]96449d2c2009-11-25 00:01:323092}
3093
[email protected]ae51d192010-04-27 00:48:033094bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3095 if (GetShaderInfo(client_id)) {
3096 return false;
[email protected]96449d2c2009-11-25 00:01:323097 }
[email protected]ae51d192010-04-27 00:48:033098 GLuint service_id = glCreateShader(type);
3099 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:383100 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:033101 }
3102 return true;
[email protected]96449d2c2009-11-25 00:01:323103}
3104
[email protected]882ba1e22012-03-08 19:02:533105void GLES2DecoderImpl::DoFinish() {
3106 glFinish();
[email protected]22e3f552012-03-13 01:54:193107 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533108}
3109
3110void GLES2DecoderImpl::DoFlush() {
3111 glFlush();
[email protected]22e3f552012-03-13 01:54:193112 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533113}
3114
[email protected]3916c97e2010-02-25 03:20:503115void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:453116 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]660858b2011-07-13 23:16:143117 if (texture_index >= group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:293118 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:503119 return;
3120 }
[email protected]36cef8ce2010-03-16 07:34:453121 active_texture_unit_ = texture_index;
3122 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:503123}
3124
[email protected]051b1372010-04-12 02:42:083125void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:503126 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083127 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033128 if (client_id != 0) {
3129 info = GetBufferInfo(client_id);
3130 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353131 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153132 LOG(ERROR) << "glBindBuffer: id not generated by glGenBuffers";
3133 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353134 return;
3135 }
3136
[email protected]ae51d192010-04-27 00:48:033137 // It's a new id so make a buffer info for it.
3138 glGenBuffersARB(1, &service_id);
3139 CreateBufferInfo(client_id, service_id);
3140 info = GetBufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573141 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103142 group_->GetIdAllocator(id_namespaces::kBuffers);
3143 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033144 }
[email protected]051b1372010-04-12 02:42:083145 }
[email protected]ae51d192010-04-27 00:48:033146 if (info) {
[email protected]4e8a5b122010-05-08 22:00:103147 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:293148 SetGLError(GL_INVALID_OPERATION,
3149 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:473150 return;
3151 }
[email protected]ae51d192010-04-27 00:48:033152 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:473153 }
[email protected]96449d2c2009-11-25 00:01:323154 switch (target) {
3155 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503156 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323157 break;
3158 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503159 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323160 break;
3161 default:
[email protected]a93bb842010-02-16 23:03:473162 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:323163 break;
3164 }
[email protected]051b1372010-04-12 02:42:083165 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:323166}
3167
[email protected]297ca1c2011-06-20 23:08:463168bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
3169 return (GLES2Util::GetChannelsForFormat(
3170 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3171}
3172
3173bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203174 FramebufferManager::FramebufferInfo* framebuffer =
3175 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3176 if (framebuffer) {
3177 return framebuffer->HasDepthAttachment();
[email protected]297ca1c2011-06-20 23:08:463178 }
3179 if (offscreen_target_frame_buffer_.get()) {
3180 return offscreen_target_depth_format_ != 0;
3181 }
3182 return back_buffer_has_depth_;
3183}
3184
3185bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203186 FramebufferManager::FramebufferInfo* framebuffer =
3187 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3188 if (framebuffer) {
3189 return framebuffer->HasStencilAttachment();
[email protected]297ca1c2011-06-20 23:08:463190 }
3191 if (offscreen_target_frame_buffer_.get()) {
3192 return offscreen_target_stencil_format_ != 0 ||
3193 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3194 }
3195 return back_buffer_has_stencil_;
3196}
3197
3198void GLES2DecoderImpl::ApplyDirtyState() {
3199 if (state_dirty_) {
3200 glColorMask(
3201 mask_red_, mask_green_, mask_blue_,
3202 mask_alpha_ && BoundFramebufferHasColorAttachmentWithAlpha());
3203 bool have_depth = BoundFramebufferHasDepthAttachment();
3204 glDepthMask(mask_depth_ && have_depth);
3205 EnableDisable(GL_DEPTH_TEST, enable_depth_test_ && have_depth);
3206 bool have_stencil = BoundFramebufferHasStencilAttachment();
3207 glStencilMaskSeparate(GL_FRONT, have_stencil ? mask_stencil_front_ : 0);
3208 glStencilMaskSeparate(GL_BACK, have_stencil ? mask_stencil_back_ : 0);
3209 EnableDisable(GL_STENCIL_TEST, enable_stencil_test_ && have_stencil);
3210 state_dirty_ = false;
3211 }
3212}
3213
[email protected]b177ae22011-11-01 03:29:113214GLuint GLES2DecoderImpl::GetBackbufferServiceId() {
3215 return (offscreen_target_frame_buffer_.get()) ?
3216 offscreen_target_frame_buffer_->id() :
3217 surface_->GetBackingFrameBufferObject();
3218}
3219
[email protected]051b1372010-04-12 02:42:083220void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3221 FramebufferManager::FramebufferInfo* info = NULL;
3222 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033223 if (client_id != 0) {
3224 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083225 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353226 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153227 LOG(ERROR)
3228 << "glBindFramebuffer: id not generated by glGenFramebuffers";
3229 current_decoder_error_ = error::kGenericError;
3230 return;
[email protected]bf5a8d132011-08-16 08:39:353231 }
3232
[email protected]ae51d192010-04-27 00:48:033233 // It's a new id so make a framebuffer info for it.
3234 glGenFramebuffersEXT(1, &service_id);
3235 CreateFramebufferInfo(client_id, service_id);
3236 info = GetFramebufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573237 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103238 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3239 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033240 } else {
3241 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083242 }
[email protected]06c8b082011-01-05 18:00:363243 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083244 }
[email protected]8e3e0662010-08-23 18:46:303245
3246 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
3247 bound_draw_framebuffer_ = info;
3248 }
3249 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
3250 bound_read_framebuffer_ = info;
3251 }
[email protected]6217d392010-03-25 22:08:353252
[email protected]297ca1c2011-06-20 23:08:463253 state_dirty_ = true;
3254
[email protected]b177ae22011-11-01 03:29:113255 // If we are rendering to the backbuffer get the FBO id for any simulated
3256 // backbuffer.
3257 if (info == NULL) {
3258 service_id = GetBackbufferServiceId();
[email protected]297ca1c2011-06-20 23:08:463259 }
[email protected]6217d392010-03-25 22:08:353260
[email protected]051b1372010-04-12 02:42:083261 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563262}
3263
[email protected]051b1372010-04-12 02:42:083264void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
3265 RenderbufferManager::RenderbufferInfo* info = NULL;
3266 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033267 if (client_id != 0) {
3268 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083269 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353270 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153271 LOG(ERROR)
3272 << "glBindRenderbuffer: id not generated by glGenRenderbuffers";
3273 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353274 return;
3275 }
3276
[email protected]ae51d192010-04-27 00:48:033277 // It's a new id so make a renderbuffer info for it.
3278 glGenRenderbuffersEXT(1, &service_id);
3279 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:103280 info = GetRenderbufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573281 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103282 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3283 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033284 } else {
3285 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083286 }
[email protected]06c8b082011-01-05 18:00:363287 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083288 }
3289 bound_renderbuffer_ = info;
3290 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563291}
3292
[email protected]051b1372010-04-12 02:42:083293void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033294 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083295 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033296 if (client_id != 0) {
3297 info = GetTextureInfo(client_id);
3298 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353299 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153300 LOG(ERROR) << "glBindTexture: id not generated by glGenTextures";
3301 current_decoder_error_ = error::kGenericError;
3302 return;
[email protected]bf5a8d132011-08-16 08:39:353303 }
3304
[email protected]ae51d192010-04-27 00:48:033305 // It's a new id so make a texture info for it.
3306 glGenTextures(1, &service_id);
[email protected]80eb6b52012-01-19 00:14:413307 DCHECK_NE(0u, service_id);
[email protected]ae51d192010-04-27 00:48:033308 CreateTextureInfo(client_id, service_id);
3309 info = GetTextureInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573310 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103311 group_->GetIdAllocator(id_namespaces::kTextures);
3312 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033313 }
3314 } else {
3315 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:083316 }
[email protected]ae51d192010-04-27 00:48:033317
[email protected]1958e0e2010-04-22 05:17:153318 // Check the texture exists
3319 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:033320 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:293321 SetGLError(GL_INVALID_OPERATION,
3322 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:153323 return;
3324 }
[email protected]b0af4f52011-09-28 22:04:423325 if (info->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
3326 SetGLError(GL_INVALID_OPERATION,
3327 "glBindTexture: illegal target for stream texture.");
3328 return;
3329 }
[email protected]1958e0e2010-04-22 05:17:153330 if (info->target() == 0) {
[email protected]80eb6b52012-01-19 00:14:413331 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:473332 }
[email protected]ae51d192010-04-27 00:48:033333 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:503334 TextureUnit& unit = texture_units_[active_texture_unit_];
3335 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:473336 switch (target) {
3337 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:503338 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:473339 break;
3340 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:503341 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:473342 break;
[email protected]61eeb33f2011-07-26 15:30:313343 case GL_TEXTURE_EXTERNAL_OES:
3344 unit.bound_texture_external_oes = info;
[email protected]b0af4f52011-09-28 22:04:423345 if (info->IsStreamTexture()) {
3346 DCHECK(stream_texture_manager_);
3347 StreamTexture* stream_tex =
3348 stream_texture_manager_->LookupStreamTexture(info->service_id());
3349 if (stream_tex)
3350 stream_tex->Update();
3351 }
[email protected]61eeb33f2011-07-26 15:30:313352 break;
[email protected]e51bdf32011-11-23 22:21:463353 case GL_TEXTURE_RECTANGLE_ARB:
3354 unit.bound_texture_rectangle_arb = info;
3355 break;
[email protected]a93bb842010-02-16 23:03:473356 default:
3357 NOTREACHED(); // Validation should prevent us getting here.
3358 break;
3359 }
3360}
3361
[email protected]07f54fcc2009-12-22 02:46:303362void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443363 if (vertex_attrib_manager_->Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:123364 if (index != 0 ||
3365 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:243366 glDisableVertexAttribArray(index);
3367 }
[email protected]07f54fcc2009-12-22 02:46:303368 } else {
[email protected]8eee29c2010-04-29 03:38:293369 SetGLError(GL_INVALID_VALUE,
3370 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:303371 }
3372}
3373
3374void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443375 if (vertex_attrib_manager_->Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:303376 glEnableVertexAttribArray(index);
3377 } else {
[email protected]8eee29c2010-04-29 03:38:293378 SetGLError(GL_INVALID_VALUE,
3379 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:303380 }
3381}
3382
[email protected]a93bb842010-02-16 23:03:473383void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:503384 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]97dc7cbe2011-12-06 17:26:173385 if (!info ||
[email protected]80eb6b52012-01-19 00:14:413386 !texture_manager()->MarkMipmapsGenerated(info)) {
[email protected]8eee29c2010-04-29 03:38:293387 SetGLError(GL_INVALID_OPERATION,
[email protected]237bad712012-04-05 20:04:023388 "glGenerateMipmaps: Can not generate mips");
[email protected]a93bb842010-02-16 23:03:473389 return;
3390 }
[email protected]59f3ca02011-03-26 22:24:193391 // Workaround for Mac driver bug. In the large scheme of things setting
3392 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
[email protected]a8bad262011-10-21 18:28:563393 // hit so there's probably no need to make this conditional. The bug appears
3394 // to be that if the filtering mode is set to something that doesn't require
3395 // mipmaps for rendering, or is never set to something other than the default,
3396 // then glGenerateMipmap misbehaves.
3397 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
[email protected]a93bb842010-02-16 23:03:473398 glGenerateMipmapEXT(target);
[email protected]59f3ca02011-03-26 22:24:193399 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
[email protected]a93bb842010-02-16 23:03:473400}
3401
[email protected]b273e432010-04-12 17:23:583402bool GLES2DecoderImpl::GetHelper(
3403 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:583404 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:153405 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
3406 switch (pname) {
[email protected]b273e432010-04-12 17:23:583407 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
3408 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103409 if (params) {
[email protected]5094b0f2010-11-09 19:45:243410 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:103411 }
[email protected]b273e432010-04-12 17:23:583412 return true;
3413 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3414 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103415 if (params) {
[email protected]5094b0f2010-11-09 19:45:243416 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:103417 }
[email protected]b273e432010-04-12 17:23:583418 return true;
3419 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
3420 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103421 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483422 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:103423 }
[email protected]b273e432010-04-12 17:23:583424 return true;
3425 case GL_MAX_VARYING_VECTORS:
3426 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103427 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483428 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:103429 }
[email protected]b273e432010-04-12 17:23:583430 return true;
3431 case GL_MAX_VERTEX_UNIFORM_VECTORS:
3432 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103433 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483434 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:103435 }
[email protected]b273e432010-04-12 17:23:583436 return true;
[email protected]5cb735d2011-10-13 01:37:233437 }
3438 }
3439 switch (pname) {
[email protected]5094b0f2010-11-09 19:45:243440 case GL_MAX_VIEWPORT_DIMS:
3441 if (offscreen_target_frame_buffer_.get()) {
3442 *num_written = 2;
3443 if (params) {
3444 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3445 params[1] = renderbuffer_manager()->max_renderbuffer_size();
3446 }
3447 return true;
3448 }
[email protected]5cb735d2011-10-13 01:37:233449 return false;
[email protected]84afefa2011-10-19 21:45:533450 case GL_MAX_SAMPLES:
3451 *num_written = 1;
3452 if (params) {
3453 params[0] = renderbuffer_manager()->max_samples();
3454 }
3455 return true;
3456 case GL_MAX_RENDERBUFFER_SIZE:
3457 *num_written = 1;
3458 if (params) {
3459 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3460 }
3461 return true;
[email protected]5cb735d2011-10-13 01:37:233462 case GL_MAX_TEXTURE_SIZE:
3463 *num_written = 1;
3464 if (params) {
3465 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
3466 }
3467 return true;
3468 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
3469 *num_written = 1;
3470 if (params) {
3471 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
3472 }
3473 return true;
[email protected]297ca1c2011-06-20 23:08:463474 case GL_COLOR_WRITEMASK:
3475 *num_written = 4;
3476 if (params) {
3477 params[0] = mask_red_;
3478 params[1] = mask_green_;
3479 params[2] = mask_blue_;
3480 params[3] = mask_alpha_;
3481 }
3482 return true;
3483 case GL_DEPTH_WRITEMASK:
3484 *num_written = 1;
3485 if (params) {
3486 params[0] = mask_depth_;
3487 }
3488 return true;
3489 case GL_STENCIL_BACK_WRITEMASK:
3490 *num_written = 1;
3491 if (params) {
3492 params[0] = mask_stencil_back_;
3493 }
3494 return true;
3495 case GL_STENCIL_WRITEMASK:
3496 *num_written = 1;
3497 if (params) {
3498 params[0] = mask_stencil_front_;
3499 }
3500 return true;
3501 case GL_DEPTH_TEST:
3502 *num_written = 1;
3503 if (params) {
3504 params[0] = enable_depth_test_;
3505 }
3506 return true;
3507 case GL_STENCIL_TEST:
3508 *num_written = 1;
3509 if (params) {
3510 params[0] = enable_stencil_test_;
3511 }
3512 return true;
3513 case GL_ALPHA_BITS:
3514 *num_written = 1;
3515 if (params) {
3516 GLint v = 0;
3517 glGetIntegerv(GL_ALPHA_BITS, &v);
3518 params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0;
3519 }
3520 return true;
3521 case GL_DEPTH_BITS:
3522 *num_written = 1;
3523 if (params) {
3524 GLint v = 0;
3525 glGetIntegerv(GL_DEPTH_BITS, &v);
3526 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
3527 }
3528 return true;
3529 case GL_STENCIL_BITS:
3530 *num_written = 1;
3531 if (params) {
3532 GLint v = 0;
3533 glGetIntegerv(GL_STENCIL_BITS, &v);
3534 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
3535 }
3536 return true;
[email protected]656dcaad2010-05-07 17:18:373537 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113538 *num_written = validators_->compressed_texture_format.GetValues().size();
3539 if (params) {
3540 for (GLint ii = 0; ii < *num_written; ++ii) {
3541 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
3542 }
3543 }
[email protected]656dcaad2010-05-07 17:18:373544 return true;
[email protected]b273e432010-04-12 17:23:583545 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
3546 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103547 if (params) {
[email protected]302ce6d2011-07-07 23:28:113548 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103549 }
[email protected]b273e432010-04-12 17:23:583550 return true;
3551 case GL_NUM_SHADER_BINARY_FORMATS:
3552 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103553 if (params) {
[email protected]302ce6d2011-07-07 23:28:113554 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103555 }
[email protected]b273e432010-04-12 17:23:583556 return true;
3557 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113558 *num_written = validators_->shader_binary_format.GetValues().size();
3559 if (params) {
3560 for (GLint ii = 0; ii < *num_written; ++ii) {
3561 params[ii] = validators_->shader_binary_format.GetValues()[ii];
3562 }
3563 }
3564 return true;
[email protected]b273e432010-04-12 17:23:583565 case GL_SHADER_COMPILER:
3566 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103567 if (params) {
3568 *params = GL_TRUE;
3569 }
[email protected]b273e432010-04-12 17:23:583570 return true;
[email protected]6b8cf1a2010-05-06 16:13:583571 case GL_ARRAY_BUFFER_BINDING:
3572 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103573 if (params) {
3574 if (bound_array_buffer_) {
3575 GLuint client_id = 0;
3576 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
3577 &client_id);
3578 *params = client_id;
3579 } else {
3580 *params = 0;
3581 }
[email protected]6b8cf1a2010-05-06 16:13:583582 }
3583 return true;
3584 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3585 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103586 if (params) {
3587 if (bound_element_array_buffer_) {
3588 GLuint client_id = 0;
3589 buffer_manager()->GetClientId(
3590 bound_element_array_buffer_->service_id(),
3591 &client_id);
3592 *params = client_id;
3593 } else {
3594 *params = 0;
3595 }
[email protected]6b8cf1a2010-05-06 16:13:583596 }
3597 return true;
3598 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:303599 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:583600 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103601 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203602 FramebufferManager::FramebufferInfo* framebuffer =
3603 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3604 if (framebuffer) {
[email protected]4e8a5b122010-05-08 22:00:103605 GLuint client_id = 0;
3606 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203607 framebuffer->service_id(), &client_id);
[email protected]8e3e0662010-08-23 18:46:303608 *params = client_id;
3609 } else {
3610 *params = 0;
3611 }
3612 }
3613 return true;
3614 case GL_READ_FRAMEBUFFER_BINDING:
3615 *num_written = 1;
3616 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203617 FramebufferManager::FramebufferInfo* framebuffer =
3618 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
3619 if (framebuffer) {
[email protected]8e3e0662010-08-23 18:46:303620 GLuint client_id = 0;
3621 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203622 framebuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103623 *params = client_id;
3624 } else {
3625 *params = 0;
3626 }
[email protected]6b8cf1a2010-05-06 16:13:583627 }
3628 return true;
3629 case GL_RENDERBUFFER_BINDING:
3630 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103631 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203632 RenderbufferManager::RenderbufferInfo* renderbuffer =
3633 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
3634 if (renderbuffer) {
[email protected]4e8a5b122010-05-08 22:00:103635 GLuint client_id = 0;
3636 renderbuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203637 renderbuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103638 *params = client_id;
3639 } else {
3640 *params = 0;
3641 }
[email protected]6b8cf1a2010-05-06 16:13:583642 }
3643 return true;
3644 case GL_CURRENT_PROGRAM:
3645 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103646 if (params) {
3647 if (current_program_) {
3648 GLuint client_id = 0;
3649 program_manager()->GetClientId(
3650 current_program_->service_id(), &client_id);
3651 *params = client_id;
3652 } else {
3653 *params = 0;
3654 }
[email protected]6b8cf1a2010-05-06 16:13:583655 }
3656 return true;
[email protected]4e8a5b122010-05-08 22:00:103657 case GL_TEXTURE_BINDING_2D:
3658 *num_written = 1;
3659 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583660 TextureUnit& unit = texture_units_[active_texture_unit_];
3661 if (unit.bound_texture_2d) {
3662 GLuint client_id = 0;
3663 texture_manager()->GetClientId(
3664 unit.bound_texture_2d->service_id(), &client_id);
3665 *params = client_id;
3666 } else {
3667 *params = 0;
3668 }
[email protected]6b8cf1a2010-05-06 16:13:583669 }
[email protected]4e8a5b122010-05-08 22:00:103670 return true;
3671 case GL_TEXTURE_BINDING_CUBE_MAP:
3672 *num_written = 1;
3673 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583674 TextureUnit& unit = texture_units_[active_texture_unit_];
3675 if (unit.bound_texture_cube_map) {
3676 GLuint client_id = 0;
3677 texture_manager()->GetClientId(
3678 unit.bound_texture_cube_map->service_id(), &client_id);
3679 *params = client_id;
3680 } else {
3681 *params = 0;
3682 }
[email protected]6b8cf1a2010-05-06 16:13:583683 }
[email protected]4e8a5b122010-05-08 22:00:103684 return true;
[email protected]61eeb33f2011-07-26 15:30:313685 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3686 *num_written = 1;
3687 if (params) {
3688 TextureUnit& unit = texture_units_[active_texture_unit_];
3689 if (unit.bound_texture_external_oes) {
3690 GLuint client_id = 0;
3691 texture_manager()->GetClientId(
3692 unit.bound_texture_external_oes->service_id(), &client_id);
3693 *params = client_id;
3694 } else {
3695 *params = 0;
3696 }
3697 }
3698 return true;
[email protected]e51bdf32011-11-23 22:21:463699 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
3700 *num_written = 1;
3701 if (params) {
3702 TextureUnit& unit = texture_units_[active_texture_unit_];
3703 if (unit.bound_texture_rectangle_arb) {
3704 GLuint client_id = 0;
3705 texture_manager()->GetClientId(
3706 unit.bound_texture_rectangle_arb->service_id(), &client_id);
3707 *params = client_id;
3708 } else {
3709 *params = 0;
3710 }
3711 }
3712 return true;
[email protected]b273e432010-04-12 17:23:583713 default:
[email protected]4e8a5b122010-05-08 22:00:103714 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533715 return false;
[email protected]b273e432010-04-12 17:23:583716 }
3717}
3718
[email protected]4e8a5b122010-05-08 22:00:103719bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3720 GLenum pname, GLsizei* num_values) {
3721 return GetHelper(pname, NULL, num_values);
3722}
3723
[email protected]b273e432010-04-12 17:23:583724void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3725 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103726 GLsizei num_written = 0;
3727 if (GetHelper(pname, NULL, &num_written)) {
3728 scoped_array<GLint> values(new GLint[num_written]);
3729 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583730 for (GLsizei ii = 0; ii < num_written; ++ii) {
3731 params[ii] = static_cast<GLboolean>(values[ii]);
3732 }
3733 } else {
3734 glGetBooleanv(pname, params);
3735 }
3736}
3737
3738void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3739 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103740 GLsizei num_written = 0;
3741 if (GetHelper(pname, NULL, &num_written)) {
3742 scoped_array<GLint> values(new GLint[num_written]);
3743 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583744 for (GLsizei ii = 0; ii < num_written; ++ii) {
3745 params[ii] = static_cast<GLfloat>(values[ii]);
3746 }
3747 } else {
3748 glGetFloatv(pname, params);
3749 }
3750}
3751
3752void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3753 DCHECK(params);
3754 GLsizei num_written;
3755 if (!GetHelper(pname, params, &num_written)) {
3756 glGetIntegerv(pname, params);
3757 }
3758}
3759
[email protected]a0c3e972010-04-21 00:49:133760void GLES2DecoderImpl::DoGetProgramiv(
3761 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583762 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3763 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133764 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133765 return;
3766 }
3767 info->GetProgramiv(pname, params);
3768}
3769
[email protected]258a3313f2011-10-18 20:13:573770void GLES2DecoderImpl::DoBindAttribLocation(
3771 GLuint program, GLuint index, const char* name) {
3772 if (!StringIsValidForGLES(name)) {
3773 SetGLError(GL_INVALID_VALUE, "glBindAttribLocation: Invalid character");
3774 return;
3775 }
[email protected]6b8cf1a2010-05-06 16:13:583776 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3777 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033778 if (!info) {
[email protected]258a3313f2011-10-18 20:13:573779 return;
[email protected]558847a2010-03-24 07:02:543780 }
[email protected]c3e4c4e2012-03-02 19:23:243781 info->SetAttribLocationBinding(name, static_cast<GLint>(index));
[email protected]258a3313f2011-10-18 20:13:573782 glBindAttribLocation(info->service_id(), index, name);
3783}
3784
3785error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3786 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
3787 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543788 GLuint index = static_cast<GLuint>(c.index);
3789 uint32 name_size = c.data_size;
3790 const char* name = GetSharedMemoryAs<const char*>(
3791 c.name_shm_id, c.name_shm_offset, name_size);
3792 if (name == NULL) {
3793 return error::kOutOfBounds;
3794 }
3795 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573796 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543797 return error::kNoError;
3798}
3799
3800error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3801 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583802 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543803 GLuint index = static_cast<GLuint>(c.index);
3804 uint32 name_size = c.data_size;
3805 const char* name = GetImmediateDataAs<const char*>(
3806 c, name_size, immediate_data_size);
3807 if (name == NULL) {
3808 return error::kOutOfBounds;
3809 }
3810 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573811 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543812 return error::kNoError;
3813}
3814
3815error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3816 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583817 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543818 GLuint index = static_cast<GLuint>(c.index);
3819 Bucket* bucket = GetBucket(c.name_bucket_id);
3820 if (!bucket || bucket->size() == 0) {
3821 return error::kInvalidArguments;
3822 }
3823 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183824 if (!bucket->GetAsString(&name_str)) {
3825 return error::kInvalidArguments;
3826 }
[email protected]258a3313f2011-10-18 20:13:573827 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543828 return error::kNoError;
3829}
3830
[email protected]f7a64ee2010-02-01 22:24:143831error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463832 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033833 GLuint client_id = c.shader;
3834 if (client_id) {
3835 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3836 if (info) {
[email protected]ca488e12010-12-13 20:06:143837 if (!info->IsDeleted()) {
3838 glDeleteShader(info->service_id());
3839 shader_manager()->MarkAsDeleted(info);
3840 }
[email protected]ae51d192010-04-27 00:48:033841 } else {
[email protected]8eee29c2010-04-29 03:38:293842 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033843 }
[email protected]96449d2c2009-11-25 00:01:323844 }
[email protected]f7a64ee2010-02-01 22:24:143845 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323846}
3847
[email protected]f7a64ee2010-02-01 22:24:143848error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463849 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033850 GLuint client_id = c.program;
3851 if (client_id) {
3852 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3853 if (info) {
[email protected]ca488e12010-12-13 20:06:143854 if (!info->IsDeleted()) {
3855 glDeleteProgram(info->service_id());
3856 program_manager()->MarkAsDeleted(shader_manager(), info);
3857 }
[email protected]ae51d192010-04-27 00:48:033858 } else {
[email protected]8eee29c2010-04-29 03:38:293859 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033860 }
[email protected]96449d2c2009-11-25 00:01:323861 }
[email protected]f7a64ee2010-02-01 22:24:143862 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323863}
3864
[email protected]269200b12010-11-18 22:53:063865void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103866 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573867 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103868 for (GLsizei ii = 0; ii < n; ++ii) {
3869 id_allocator->FreeID(ids[ii]);
3870 }
3871}
3872
[email protected]269200b12010-11-18 22:53:063873error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
3874 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103875 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3876 GLsizei n = static_cast<GLsizei>(c.n);
3877 uint32 data_size;
3878 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3879 return error::kOutOfBounds;
3880 }
3881 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3882 c.ids_shm_id, c.ids_shm_offset, data_size);
3883 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063884 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103885 return error::kNoError;
3886 }
3887 if (ids == NULL) {
3888 return error::kOutOfBounds;
3889 }
[email protected]269200b12010-11-18 22:53:063890 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103891 return error::kNoError;
3892}
3893
[email protected]269200b12010-11-18 22:53:063894void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103895 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573896 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103897 if (id_offset == 0) {
3898 for (GLsizei ii = 0; ii < n; ++ii) {
3899 ids[ii] = id_allocator->AllocateID();
3900 }
3901 } else {
3902 for (GLsizei ii = 0; ii < n; ++ii) {
3903 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
3904 id_offset = ids[ii] + 1;
3905 }
3906 }
3907}
3908
[email protected]269200b12010-11-18 22:53:063909error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
3910 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103911 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3912 GLuint id_offset = static_cast<GLuint>(c.id_offset);
3913 GLsizei n = static_cast<GLsizei>(c.n);
3914 uint32 data_size;
3915 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3916 return error::kOutOfBounds;
3917 }
3918 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3919 c.ids_shm_id, c.ids_shm_offset, data_size);
3920 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063921 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103922 return error::kNoError;
3923 }
3924 if (ids == NULL) {
3925 return error::kOutOfBounds;
3926 }
[email protected]269200b12010-11-18 22:53:063927 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:103928 return error::kNoError;
3929}
3930
[email protected]269200b12010-11-18 22:53:063931void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103932 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573933 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103934 for (GLsizei ii = 0; ii < n; ++ii) {
3935 if (!id_allocator->MarkAsUsed(ids[ii])) {
3936 for (GLsizei jj = 0; jj < ii; ++jj) {
3937 id_allocator->FreeID(ids[jj]);
3938 }
3939 SetGLError(
3940 GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:063941 "RegisterSharedIdsCHROMIUM: attempt to register "
3942 "id that already exists");
[email protected]066849e32010-05-03 19:14:103943 return;
3944 }
3945 }
3946}
3947
[email protected]269200b12010-11-18 22:53:063948error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
3949 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103950 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3951 GLsizei n = static_cast<GLsizei>(c.n);
3952 uint32 data_size;
3953 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3954 return error::kOutOfBounds;
3955 }
3956 GLuint* ids = GetSharedMemoryAs<GLuint*>(
3957 c.ids_shm_id, c.ids_shm_offset, data_size);
3958 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063959 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103960 return error::kNoError;
3961 }
3962 if (ids == NULL) {
3963 return error::kOutOfBounds;
3964 }
[email protected]269200b12010-11-18 22:53:063965 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103966 return error::kNoError;
3967}
3968
[email protected]3a03a8f2011-03-19 00:51:273969void GLES2DecoderImpl::DoClear(GLbitfield mask) {
[email protected]0d6bfdc2011-11-02 01:32:203970 if (CheckBoundFramebuffersValid("glClear")) {
[email protected]529c6672012-01-04 02:18:263971 UNSHIPPED_TRACE_EVENT_INSTANT2("test_gpu", "DoClear", "red", clear_red_,
3972 "green", clear_green_);
[email protected]297ca1c2011-06-20 23:08:463973 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:273974 glClear(mask);
3975 }
3976}
3977
[email protected]36cef8ce2010-03-16 07:34:453978void GLES2DecoderImpl::DoFramebufferRenderbuffer(
3979 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:033980 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:303981 FramebufferManager::FramebufferInfo* framebuffer_info =
3982 GetFramebufferInfoForTarget(target);
3983 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:293984 SetGLError(GL_INVALID_OPERATION,
3985 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:453986 return;
3987 }
[email protected]ae51d192010-04-27 00:48:033988 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:283989 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:033990 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:283991 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:033992 if (!info) {
[email protected]8eee29c2010-04-29 03:38:293993 SetGLError(GL_INVALID_OPERATION,
3994 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:033995 return;
3996 }
3997 service_id = info->service_id();
3998 }
[email protected]9edc6b22010-12-23 02:00:263999 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034000 glFramebufferRenderbufferEXT(
4001 target, attachment, renderbuffertarget, service_id);
[email protected]1002c2d2011-06-28 22:39:044002 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264003 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:304004 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]3a2e7c7b2010-08-06 01:12:284005 }
[email protected]297ca1c2011-06-20 23:08:464006 if (framebuffer_info == bound_draw_framebuffer_) {
4007 state_dirty_ = true;
4008 }
[email protected]3a2e7c7b2010-08-06 01:12:284009}
4010
[email protected]297ca1c2011-06-20 23:08:464011bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
[email protected]3a2e7c7b2010-08-06 01:12:284012 switch (cap) {
4013 case GL_SCISSOR_TEST:
4014 enable_scissor_test_ = enabled;
[email protected]297ca1c2011-06-20 23:08:464015 return true;
4016 case GL_DEPTH_TEST: {
4017 if (enable_depth_test_ != enabled) {
4018 enable_depth_test_ = enabled;
4019 state_dirty_ = true;
4020 }
4021 return false;
4022 }
4023 case GL_STENCIL_TEST:
4024 if (enable_stencil_test_ != enabled) {
4025 enable_stencil_test_ = enabled;
4026 state_dirty_ = true;
4027 }
4028 return false;
[email protected]3a2e7c7b2010-08-06 01:12:284029 default:
[email protected]297ca1c2011-06-20 23:08:464030 return true;
[email protected]3a2e7c7b2010-08-06 01:12:284031 }
4032}
4033
4034void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464035 if (SetCapabilityState(cap, false)) {
4036 glDisable(cap);
4037 }
[email protected]3a2e7c7b2010-08-06 01:12:284038}
4039
4040void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464041 if (SetCapabilityState(cap, true)) {
4042 glEnable(cap);
4043 }
[email protected]3a2e7c7b2010-08-06 01:12:284044}
4045
4046void GLES2DecoderImpl::DoClearColor(
4047 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
4048 clear_red_ = red;
4049 clear_green_ = green;
4050 clear_blue_ = blue;
4051 clear_alpha_ = alpha;
4052 glClearColor(red, green, blue, alpha);
4053}
4054
4055void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
4056 clear_depth_ = depth;
4057 glClearDepth(depth);
4058}
4059
4060void GLES2DecoderImpl::DoClearStencil(GLint s) {
4061 clear_stencil_ = s;
4062 glClearStencil(s);
4063}
4064
4065void GLES2DecoderImpl::DoColorMask(
4066 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
4067 mask_red_ = red;
4068 mask_green_ = green;
4069 mask_blue_ = blue;
4070 mask_alpha_ = alpha;
[email protected]297ca1c2011-06-20 23:08:464071 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284072}
4073
4074void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
4075 mask_depth_ = depth;
[email protected]297ca1c2011-06-20 23:08:464076 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284077}
4078
4079void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
4080 mask_stencil_front_ = mask;
4081 mask_stencil_back_ = mask;
[email protected]297ca1c2011-06-20 23:08:464082 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284083}
4084
4085void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
[email protected]297ca1c2011-06-20 23:08:464086 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284087 mask_stencil_front_ = mask;
[email protected]297ca1c2011-06-20 23:08:464088 }
4089 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284090 mask_stencil_back_ = mask;
4091 }
[email protected]297ca1c2011-06-20 23:08:464092 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284093}
4094
[email protected]0d6bfdc2011-11-02 01:32:204095// Assumes framebuffer is complete.
4096void GLES2DecoderImpl::ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:304097 GLenum target, FramebufferManager::FramebufferInfo* info) {
4098 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204099 // bind this to the DRAW point, clear then bind back to READ
4100 // TODO(gman): I don't think there is any guarantee that an FBO that
4101 // is complete on the READ attachment will be complete as a DRAW
4102 // attachment.
4103 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
4104 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, info->service_id());
[email protected]8e3e0662010-08-23 18:46:304105 }
[email protected]3a2e7c7b2010-08-06 01:12:284106 GLbitfield clear_bits = 0;
4107 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:464108 glClearColor(
[email protected]0d6bfdc2011-11-02 01:32:204109 0.0f, 0.0f, 0.0f,
[email protected]297ca1c2011-06-20 23:08:464110 (GLES2Util::GetChannelsForFormat(
[email protected]0d6bfdc2011-11-02 01:32:204111 info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f : 1.0f);
[email protected]3a2e7c7b2010-08-06 01:12:284112 glColorMask(true, true, true, true);
4113 clear_bits |= GL_COLOR_BUFFER_BIT;
4114 }
4115
4116 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4117 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4118 glClearStencil(0);
4119 glStencilMask(-1);
4120 clear_bits |= GL_STENCIL_BUFFER_BIT;
4121 }
4122
4123 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4124 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4125 glClearDepth(1.0f);
4126 glDepthMask(true);
4127 clear_bits |= GL_DEPTH_BUFFER_BIT;
4128 }
4129
4130 glDisable(GL_SCISSOR_TEST);
4131 glClear(clear_bits);
4132
[email protected]968351b2011-12-20 08:26:514133 framebuffer_manager()->MarkAttachmentsAsCleared(
4134 info, renderbuffer_manager(), texture_manager());
[email protected]3a2e7c7b2010-08-06 01:12:284135
[email protected]c007aa02010-09-02 22:22:404136 RestoreClearState();
4137
4138 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204139 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, info->service_id());
[email protected]87d1a3fe2011-12-01 04:25:484140 FramebufferManager::FramebufferInfo* framebuffer =
4141 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4142 GLuint service_id =
4143 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
4144 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
[email protected]c007aa02010-09-02 22:22:404145 }
4146}
4147
4148void GLES2DecoderImpl::RestoreClearState() {
[email protected]297ca1c2011-06-20 23:08:464149 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284150 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
[email protected]3a2e7c7b2010-08-06 01:12:284151 glClearStencil(clear_stencil_);
[email protected]3a2e7c7b2010-08-06 01:12:284152 glClearDepth(clear_depth_);
[email protected]3a2e7c7b2010-08-06 01:12:284153 if (enable_scissor_test_) {
4154 glEnable(GL_SCISSOR_TEST);
4155 }
[email protected]36cef8ce2010-03-16 07:34:454156}
4157
4158GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]0d6bfdc2011-11-02 01:32:204159 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]8e3e0662010-08-23 18:46:304160 GetFramebufferInfoForTarget(target);
[email protected]0d6bfdc2011-11-02 01:32:204161 if (!framebuffer) {
[email protected]36cef8ce2010-03-16 07:34:454162 return GL_FRAMEBUFFER_COMPLETE;
4163 }
[email protected]0d6bfdc2011-11-02 01:32:204164 GLenum completeness = framebuffer->IsPossiblyComplete();
4165 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4166 return completeness;
4167 }
[email protected]36cef8ce2010-03-16 07:34:454168 return glCheckFramebufferStatusEXT(target);
4169}
4170
4171void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:034172 GLenum target, GLenum attachment, GLenum textarget,
4173 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:304174 FramebufferManager::FramebufferInfo* framebuffer_info =
4175 GetFramebufferInfoForTarget(target);
4176 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294177 SetGLError(GL_INVALID_OPERATION,
4178 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:454179 return;
4180 }
[email protected]ae51d192010-04-27 00:48:034181 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:284182 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:034183 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:284184 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:034185 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294186 SetGLError(GL_INVALID_OPERATION,
4187 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:034188 return;
4189 }
4190 service_id = info->service_id();
4191 }
[email protected]0d6bfdc2011-11-02 01:32:204192
[email protected]80eb6b52012-01-19 00:14:414193 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
[email protected]0d6bfdc2011-11-02 01:32:204194 SetGLError(GL_INVALID_VALUE,
4195 "glFramebufferTexture2D: level out of range");
4196 return;
4197 }
4198
[email protected]9edc6b22010-12-23 02:00:264199 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034200 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]1002c2d2011-06-28 22:39:044201 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264202 if (error == GL_NO_ERROR) {
4203 framebuffer_info->AttachTexture(attachment, info, textarget, level);
[email protected]3a2e7c7b2010-08-06 01:12:284204 }
[email protected]297ca1c2011-06-20 23:08:464205 if (framebuffer_info == bound_draw_framebuffer_) {
4206 state_dirty_ = true;
4207 }
[email protected]36cef8ce2010-03-16 07:34:454208}
4209
4210void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4211 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:304212 FramebufferManager::FramebufferInfo* framebuffer_info =
4213 GetFramebufferInfoForTarget(target);
4214 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294215 SetGLError(GL_INVALID_OPERATION,
4216 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454217 return;
4218 }
4219 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:574220 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4221 GLint type = 0;
4222 GLuint client_id = 0;
4223 glGetFramebufferAttachmentParameterivEXT(
4224 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
4225 switch (type) {
4226 case GL_RENDERBUFFER: {
4227 renderbuffer_manager()->GetClientId(*params, &client_id);
4228 break;
4229 }
4230 case GL_TEXTURE: {
4231 texture_manager()->GetClientId(*params, &client_id);
4232 break;
4233 }
4234 default:
4235 break;
4236 }
4237 *params = client_id;
4238 }
[email protected]36cef8ce2010-03-16 07:34:454239}
4240
4241void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4242 GLenum target, GLenum pname, GLint* params) {
[email protected]0d6bfdc2011-11-02 01:32:204243 RenderbufferManager::RenderbufferInfo* renderbuffer =
4244 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4245 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294246 SetGLError(GL_INVALID_OPERATION,
4247 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454248 return;
4249 }
[email protected]3a03a8f2011-03-19 00:51:274250 switch (pname) {
4251 case GL_RENDERBUFFER_INTERNAL_FORMAT:
[email protected]0d6bfdc2011-11-02 01:32:204252 *params = renderbuffer->internal_format();
[email protected]3a03a8f2011-03-19 00:51:274253 break;
4254 case GL_RENDERBUFFER_WIDTH:
[email protected]0d6bfdc2011-11-02 01:32:204255 *params = renderbuffer->width();
[email protected]3a03a8f2011-03-19 00:51:274256 break;
4257 case GL_RENDERBUFFER_HEIGHT:
[email protected]0d6bfdc2011-11-02 01:32:204258 *params = renderbuffer->height();
[email protected]3a03a8f2011-03-19 00:51:274259 break;
4260 default:
4261 glGetRenderbufferParameterivEXT(target, pname, params);
4262 break;
[email protected]b71f52c2010-06-18 22:20:204263 }
[email protected]36cef8ce2010-03-16 07:34:454264}
4265
[email protected]8e3e0662010-08-23 18:46:304266void GLES2DecoderImpl::DoBlitFramebufferEXT(
4267 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
4268 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
4269 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:394270 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304271 SetGLError(GL_INVALID_OPERATION,
4272 "glBlitFramebufferEXT: function not available");
4273 }
[email protected]5094b0f2010-11-09 19:45:244274 if (IsAngle()) {
4275 glBlitFramebufferANGLE(
4276 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4277 } else {
4278 glBlitFramebufferEXT(
4279 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4280 }
[email protected]529c6672012-01-04 02:18:264281 UNSHIPPED_TRACE_EVENT_INSTANT1("test_gpu", "DoBlit", "width", srcX1 - srcX0);
[email protected]8e3e0662010-08-23 18:46:304282}
4283
4284void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
4285 GLenum target, GLsizei samples, GLenum internalformat,
4286 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:394287 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304288 SetGLError(GL_INVALID_OPERATION,
4289 "glRenderbufferStorageMultisampleEXT: function not available");
4290 return;
4291 }
[email protected]8e3e0662010-08-23 18:46:304292
[email protected]0d6bfdc2011-11-02 01:32:204293 RenderbufferManager::RenderbufferInfo* renderbuffer =
4294 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4295 if (!renderbuffer) {
4296 SetGLError(GL_INVALID_OPERATION,
4297 "glGetRenderbufferStorageMultisample: no renderbuffer bound");
4298 return;
4299 }
4300
[email protected]84afefa2011-10-19 21:45:534301 if (samples > renderbuffer_manager()->max_samples()) {
4302 SetGLError(GL_INVALID_VALUE,
4303 "glGetRenderbufferStorageMultisample: samples too large");
4304 return;
4305 }
4306
4307 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4308 height > renderbuffer_manager()->max_renderbuffer_size()) {
4309 SetGLError(GL_INVALID_VALUE,
4310 "glGetRenderbufferStorageMultisample: size too large");
4311 return;
4312 }
4313
[email protected]9edc6b22010-12-23 02:00:264314 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:304315 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264316 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:304317 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264318 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:304319 break;
4320 case GL_RGBA4:
4321 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264322 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:304323 break;
4324 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264325 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:304326 break;
4327 }
4328 }
4329
[email protected]9edc6b22010-12-23 02:00:264330 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:084331 if (IsAngle()) {
4332 glRenderbufferStorageMultisampleANGLE(
4333 target, samples, impl_format, width, height);
4334 } else {
4335 glRenderbufferStorageMultisampleEXT(
4336 target, samples, impl_format, width, height);
4337 }
[email protected]1002c2d2011-06-28 22:39:044338 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264339 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514340 // TODO(gman): If renderbuffers tracked which framebuffers they were
4341 // attached to we could just mark those framebuffers as not complete.
4342 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204343 renderbuffer_manager()->SetInfo(
4344 renderbuffer, samples, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264345 }
[email protected]8e3e0662010-08-23 18:46:304346}
4347
[email protected]36cef8ce2010-03-16 07:34:454348void GLES2DecoderImpl::DoRenderbufferStorage(
4349 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]0d6bfdc2011-11-02 01:32:204350 RenderbufferManager::RenderbufferInfo* renderbuffer =
4351 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4352 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294353 SetGLError(GL_INVALID_OPERATION,
4354 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454355 return;
4356 }
[email protected]876f6fee2010-08-02 23:10:324357
[email protected]84afefa2011-10-19 21:45:534358 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4359 height > renderbuffer_manager()->max_renderbuffer_size()) {
4360 SetGLError(GL_INVALID_VALUE,
4361 "glGetRenderbufferStorage: size too large");
4362 return;
4363 }
4364
[email protected]9edc6b22010-12-23 02:00:264365 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:324366 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264367 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:324368 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264369 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:324370 break;
4371 case GL_RGBA4:
4372 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264373 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:324374 break;
4375 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264376 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:324377 break;
4378 }
[email protected]b71f52c2010-06-18 22:20:204379 }
[email protected]876f6fee2010-08-02 23:10:324380
[email protected]9edc6b22010-12-23 02:00:264381 CopyRealGLErrorsToWrapper();
4382 glRenderbufferStorageEXT(target, impl_format, width, height);
[email protected]1002c2d2011-06-28 22:39:044383 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264384 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514385 // TODO(gman): If tetxures tracked which framebuffers they were attached to
4386 // we could just mark those framebuffers as not complete.
4387 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204388 renderbuffer_manager()->SetInfo(
4389 renderbuffer, 0, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264390 }
[email protected]36cef8ce2010-03-16 07:34:454391}
4392
[email protected]07f54fcc2009-12-22 02:46:304393void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]0c8fabf2011-06-14 19:35:224394 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]6b8cf1a2010-05-06 16:13:584395 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4396 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:474397 if (!info) {
[email protected]a93bb842010-02-16 23:03:474398 return;
4399 }
[email protected]05afda12011-01-20 00:17:344400
[email protected]d685a682011-04-29 16:19:574401 info->Link();
[email protected]07f54fcc2009-12-22 02:46:304402};
4403
[email protected]3916c97e2010-02-25 03:20:504404void GLES2DecoderImpl::DoTexParameterf(
4405 GLenum target, GLenum pname, GLfloat param) {
4406 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:304407 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294408 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244409 return;
[email protected]07f54fcc2009-12-22 02:46:304410 }
[email protected]cbb22e42011-05-12 23:36:244411
4412 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414413 info, pname, static_cast<GLint>(param))) {
[email protected]cbb22e42011-05-12 23:36:244414 SetGLError(GL_INVALID_ENUM, "glTexParameterf: param GL_INVALID_ENUM");
4415 return;
4416 }
4417 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:304418}
4419
[email protected]3916c97e2010-02-25 03:20:504420void GLES2DecoderImpl::DoTexParameteri(
4421 GLenum target, GLenum pname, GLint param) {
4422 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4423 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294424 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244425 return;
[email protected]3916c97e2010-02-25 03:20:504426 }
[email protected]cbb22e42011-05-12 23:36:244427
[email protected]80eb6b52012-01-19 00:14:414428 if (!texture_manager()->SetParameter(info, pname, param)) {
[email protected]cbb22e42011-05-12 23:36:244429 SetGLError(GL_INVALID_ENUM, "glTexParameteri: param GL_INVALID_ENUM");
4430 return;
4431 }
4432 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:504433}
4434
4435void GLES2DecoderImpl::DoTexParameterfv(
4436 GLenum target, GLenum pname, const GLfloat* params) {
4437 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4438 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294439 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244440 return;
[email protected]3916c97e2010-02-25 03:20:504441 }
[email protected]cbb22e42011-05-12 23:36:244442
4443 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414444 info, pname, static_cast<GLint>(params[0]))) {
[email protected]cbb22e42011-05-12 23:36:244445 SetGLError(GL_INVALID_ENUM, "glTexParameterfv: param GL_INVALID_ENUM");
4446 return;
4447 }
4448 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504449}
4450
4451void GLES2DecoderImpl::DoTexParameteriv(
4452 GLenum target, GLenum pname, const GLint* params) {
4453 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4454 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294455 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244456 return;
[email protected]3916c97e2010-02-25 03:20:504457 }
[email protected]cbb22e42011-05-12 23:36:244458
[email protected]80eb6b52012-01-19 00:14:414459 if (!texture_manager()->SetParameter(info, pname, *params)) {
[email protected]cbb22e42011-05-12 23:36:244460 SetGLError(GL_INVALID_ENUM, "glTexParameteriv: param GL_INVALID_ENUM");
4461 return;
4462 }
4463 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504464}
4465
[email protected]939e7362010-05-13 20:49:104466bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:144467 if (!current_program_) {
[email protected]939e7362010-05-13 20:49:104468 // The program does not exist.
4469 SetGLError(GL_INVALID_OPERATION,
4470 (std::string(function_name) + ": no program in use").c_str());
4471 return false;
4472 }
[email protected]ca488e12010-12-13 20:06:144473 if (!current_program_->InUse()) {
[email protected]939e7362010-05-13 20:49:104474 SetGLError(GL_INVALID_OPERATION,
4475 (std::string(function_name) + ": program not linked").c_str());
4476 return false;
4477 }
4478 return true;
4479}
4480
4481bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
4482 GLint location, const char* function_name) {
4483 if (!CheckCurrentProgram(function_name)) {
4484 return false;
4485 }
4486 return location != -1;
4487}
4488
[email protected]43c2f1f2011-03-25 18:35:364489bool GLES2DecoderImpl::PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124490 GLint fake_location, const char* function_name,
4491 GLint* real_location, GLenum* type, GLsizei* count) {
[email protected]43c2f1f2011-03-25 18:35:364492 DCHECK(type);
4493 DCHECK(count);
[email protected]1b0a6752012-02-22 03:44:124494 DCHECK(real_location);
4495 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
[email protected]939e7362010-05-13 20:49:104496 return false;
4497 }
[email protected]43c2f1f2011-03-25 18:35:364498 GLint array_index = -1;
4499 const ProgramManager::ProgramInfo::UniformInfo* info =
[email protected]1b0a6752012-02-22 03:44:124500 current_program_->GetUniformInfoByFakeLocation(
4501 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:364502 if (!info) {
[email protected]939e7362010-05-13 20:49:104503 SetGLError(GL_INVALID_OPERATION,
[email protected]43c2f1f2011-03-25 18:35:364504 (std::string(function_name) + ": unknown location").c_str());
[email protected]939e7362010-05-13 20:49:104505 return false;
4506 }
[email protected]43c2f1f2011-03-25 18:35:364507 if (*count > 1 && !info->is_array) {
4508 SetGLError(
4509 GL_INVALID_OPERATION,
4510 (std::string(function_name) + ": count > 1 for non-array").c_str());
4511 return false;
4512 }
4513 *count = std::min(info->size - array_index, *count);
4514 if (*count <= 0) {
4515 return false;
4516 }
4517 *type = info->type;
[email protected]939e7362010-05-13 20:49:104518 return true;
4519}
4520
[email protected]1b0a6752012-02-22 03:44:124521void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
4522 GLenum type = 0;
4523 GLsizei count = 1;
4524 GLint real_location = -1;
4525 if (!PrepForSetUniformByLocation(
4526 fake_location, "glUniform1iv", &real_location, &type, &count)) {
[email protected]3916c97e2010-02-25 03:20:504527 return;
4528 }
[email protected]1b0a6752012-02-22 03:44:124529 current_program_->SetSamplers(fake_location, 1, &v0);
4530 glUniform1i(real_location, v0);
[email protected]3916c97e2010-02-25 03:20:504531}
4532
4533void GLES2DecoderImpl::DoUniform1iv(
[email protected]1b0a6752012-02-22 03:44:124534 GLint fake_location, GLsizei count, const GLint *value) {
[email protected]43c2f1f2011-03-25 18:35:364535 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124536 GLint real_location = -1;
4537 if (!PrepForSetUniformByLocation(
4538 fake_location, "glUniform1iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364539 return;
4540 }
[email protected]61eeb33f2011-07-26 15:30:314541 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
4542 type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]1b0a6752012-02-22 03:44:124543 current_program_->SetSamplers(fake_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364544 }
[email protected]1b0a6752012-02-22 03:44:124545 glUniform1iv(real_location, count, value);
[email protected]3916c97e2010-02-25 03:20:504546}
4547
[email protected]939e7362010-05-13 20:49:104548void GLES2DecoderImpl::DoUniform1fv(
[email protected]1b0a6752012-02-22 03:44:124549 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364550 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124551 GLint real_location = -1;
4552 if (!PrepForSetUniformByLocation(
4553 fake_location, "glUniform1fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104554 return;
4555 }
4556 if (type == GL_BOOL) {
4557 scoped_array<GLint> temp(new GLint[count]);
4558 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:534559 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104560 }
[email protected]1b0a6752012-02-22 03:44:124561 DoUniform1iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104562 } else {
[email protected]1b0a6752012-02-22 03:44:124563 glUniform1fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104564 }
4565}
4566
4567void GLES2DecoderImpl::DoUniform2fv(
[email protected]1b0a6752012-02-22 03:44:124568 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364569 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124570 GLint real_location = -1;
4571 if (!PrepForSetUniformByLocation(
4572 fake_location, "glUniform2fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104573 return;
4574 }
4575 if (type == GL_BOOL_VEC2) {
4576 GLsizei num_values = count * 2;
4577 scoped_array<GLint> temp(new GLint[num_values]);
4578 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534579 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104580 }
[email protected]1b0a6752012-02-22 03:44:124581 glUniform2iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104582 } else {
[email protected]1b0a6752012-02-22 03:44:124583 glUniform2fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104584 }
4585}
4586
4587void GLES2DecoderImpl::DoUniform3fv(
[email protected]1b0a6752012-02-22 03:44:124588 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364589 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124590 GLint real_location = -1;
4591 if (!PrepForSetUniformByLocation(
4592 fake_location, "glUniform3fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104593 return;
4594 }
4595 if (type == GL_BOOL_VEC3) {
4596 GLsizei num_values = count * 3;
4597 scoped_array<GLint> temp(new GLint[num_values]);
4598 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534599 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104600 }
[email protected]1b0a6752012-02-22 03:44:124601 glUniform3iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104602 } else {
[email protected]1b0a6752012-02-22 03:44:124603 glUniform3fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104604 }
4605}
4606
4607void GLES2DecoderImpl::DoUniform4fv(
[email protected]1b0a6752012-02-22 03:44:124608 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364609 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124610 GLint real_location = -1;
4611 if (!PrepForSetUniformByLocation(
4612 fake_location, "glUniform4fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104613 return;
4614 }
4615 if (type == GL_BOOL_VEC4) {
4616 GLsizei num_values = count * 4;
4617 scoped_array<GLint> temp(new GLint[num_values]);
4618 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534619 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104620 }
[email protected]1b0a6752012-02-22 03:44:124621 glUniform4iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104622 } else {
[email protected]1b0a6752012-02-22 03:44:124623 glUniform4fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104624 }
4625}
4626
[email protected]43c2f1f2011-03-25 18:35:364627void GLES2DecoderImpl::DoUniform2iv(
[email protected]1b0a6752012-02-22 03:44:124628 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364629 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124630 GLint real_location = -1;
4631 if (!PrepForSetUniformByLocation(
4632 fake_location, "glUniform2iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364633 return;
4634 }
[email protected]1b0a6752012-02-22 03:44:124635 glUniform2iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364636}
4637
4638void GLES2DecoderImpl::DoUniform3iv(
[email protected]1b0a6752012-02-22 03:44:124639 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364640 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124641 GLint real_location = -1;
4642 if (!PrepForSetUniformByLocation(
4643 fake_location, "glUniform3iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364644 return;
4645 }
[email protected]1b0a6752012-02-22 03:44:124646 glUniform3iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364647}
4648
4649void GLES2DecoderImpl::DoUniform4iv(
[email protected]1b0a6752012-02-22 03:44:124650 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364651 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124652 GLint real_location = -1;
4653 if (!PrepForSetUniformByLocation(
4654 fake_location, "glUniform4iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364655 return;
4656 }
[email protected]1b0a6752012-02-22 03:44:124657 glUniform4iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364658}
4659
4660void GLES2DecoderImpl::DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:124661 GLint fake_location, GLsizei count, GLboolean transpose,
4662 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364663 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124664 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364665 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124666 fake_location, "glUniformMatrix2fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364667 return;
4668 }
[email protected]1b0a6752012-02-22 03:44:124669 glUniformMatrix2fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364670}
4671
4672void GLES2DecoderImpl::DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:124673 GLint fake_location, GLsizei count, GLboolean transpose,
4674 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364675 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124676 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364677 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124678 fake_location, "glUniformMatrix3fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364679 return;
4680 }
[email protected]1b0a6752012-02-22 03:44:124681 glUniformMatrix3fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364682}
4683
4684void GLES2DecoderImpl::DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:124685 GLint fake_location, GLsizei count, GLboolean transpose,
4686 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364687 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124688 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364689 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124690 fake_location, "glUniformMatrix4fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364691 return;
4692 }
[email protected]1b0a6752012-02-22 03:44:124693 glUniformMatrix4fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364694}
4695
[email protected]3916c97e2010-02-25 03:20:504696void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:034697 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:504698 ProgramManager::ProgramInfo* info = NULL;
4699 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:584700 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:504701 if (!info) {
[email protected]ae51d192010-04-27 00:48:034702 return;
4703 }
4704 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:504705 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:294706 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:504707 return;
4708 }
[email protected]ae51d192010-04-27 00:48:034709 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:504710 }
[email protected]ca488e12010-12-13 20:06:144711 if (current_program_) {
4712 program_manager()->UnuseProgram(shader_manager(), current_program_);
4713 }
[email protected]3916c97e2010-02-25 03:20:504714 current_program_ = info;
[email protected]ca488e12010-12-13 20:06:144715 if (current_program_) {
4716 program_manager()->UseProgram(current_program_);
4717 }
[email protected]ae51d192010-04-27 00:48:034718 glUseProgram(service_id);
[email protected]3916c97e2010-02-25 03:20:504719}
4720
[email protected]96449d2c2009-11-25 00:01:324721GLenum GLES2DecoderImpl::GetGLError() {
4722 // Check the GL error first, then our wrapped error.
4723 GLenum error = glGetError();
4724 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:374725 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:324726 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:294727 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:324728 break;
4729 }
4730 }
4731 }
4732
4733 if (error != GL_NO_ERROR) {
4734 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:294735 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324736 }
4737 return error;
4738}
4739
[email protected]1002c2d2011-06-28 22:39:044740GLenum GLES2DecoderImpl::PeekGLError() {
4741 GLenum error = glGetError();
4742 if (error != GL_NO_ERROR) {
4743 SetGLError(error, "");
4744 }
4745 return error;
4746}
4747
[email protected]8eee29c2010-04-29 03:38:294748void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
4749 if (msg) {
4750 last_error_ = msg;
[email protected]b5d647c2012-02-10 01:41:324751 // LOG this unless logging is turned off as any chromium code that generates
4752 // these errors probably has a bug.
4753 if (log_synthesized_gl_errors()) {
4754 LOG(ERROR) << last_error_;
4755 }
[email protected]6b6e7ee2011-12-13 08:04:524756 if (!msg_callback_.is_null()) {
4757 msg_callback_.Run(0, GLES2Util::GetStringEnum(error) + " : " + msg);
4758 }
[email protected]8eee29c2010-04-29 03:38:294759 }
[email protected]ddd968b82010-03-02 00:44:294760 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324761}
4762
[email protected]07f54fcc2009-12-22 02:46:304763void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
4764 GLenum error;
4765 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294766 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:304767 }
4768}
4769
[email protected]6217d392010-03-25 22:08:354770void GLES2DecoderImpl::ClearRealGLErrors() {
4771 GLenum error;
4772 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]3ed14d112011-12-13 22:05:514773 if (error != GL_OUT_OF_MEMORY) {
4774 // GL_OUT_OF_MEMORY can legally happen on lost device.
4775 NOTREACHED() << "GL error " << error << " was unhandled.";
4776 }
[email protected]6217d392010-03-25 22:08:354777 }
4778}
4779
[email protected]ef526492010-06-02 23:12:254780bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:504781 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:254782 // Only check if there are some unrenderable textures.
4783 if (!texture_manager()->HaveUnrenderableTextures()) {
4784 return false;
4785 }
4786 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:504787 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4788 current_program_->sampler_indices();
4789 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4790 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4791 current_program_->GetUniformInfo(sampler_indices[ii]);
4792 DCHECK(uniform_info);
4793 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4794 GLuint texture_unit_index = uniform_info->texture_units[jj];
4795 if (texture_unit_index < group_->max_texture_units()) {
4796 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4797 TextureManager::TextureInfo* texture_info =
[email protected]61eeb33f2011-07-26 15:30:314798 texture_unit.GetInfoForSamplerType(uniform_info->type);
[email protected]80eb6b52012-01-19 00:14:414799 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]ef526492010-06-02 23:12:254800 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:504801 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4802 glBindTexture(
[email protected]61eeb33f2011-07-26 15:30:314803 GetBindTargetForSamplerType(uniform_info->type),
[email protected]00f893d2010-08-24 18:55:494804 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:504805 }
4806 }
4807 // else: should this be an error?
4808 }
4809 }
[email protected]ef526492010-06-02 23:12:254810 return textures_set;
[email protected]3916c97e2010-02-25 03:20:504811}
4812
4813void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
4814 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:504815 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4816 current_program_->sampler_indices();
4817 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4818 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4819 current_program_->GetUniformInfo(sampler_indices[ii]);
4820 DCHECK(uniform_info);
4821 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4822 GLuint texture_unit_index = uniform_info->texture_units[jj];
4823 if (texture_unit_index < group_->max_texture_units()) {
4824 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4825 TextureManager::TextureInfo* texture_info =
4826 uniform_info->type == GL_SAMPLER_2D ?
4827 texture_unit.bound_texture_2d :
4828 texture_unit.bound_texture_cube_map;
[email protected]80eb6b52012-01-19 00:14:414829 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]3916c97e2010-02-25 03:20:504830 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4831 // Get the texture info that was previously bound here.
4832 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
4833 texture_unit.bound_texture_2d :
4834 texture_unit.bound_texture_cube_map;
4835 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:034836 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:504837 }
4838 }
4839 }
4840 }
4841 // Set the active texture back to whatever the user had it as.
4842 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:304843}
4844
[email protected]0d6bfdc2011-11-02 01:32:204845bool GLES2DecoderImpl::ClearUnclearedTextures() {
4846 // Only check if there are some uncleared textures.
4847 if (!texture_manager()->HaveUnsafeTextures()) {
4848 return true;
4849 }
4850
4851 // 1: Check all textures we are about to render with.
4852 if (current_program_) {
4853 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4854 current_program_->sampler_indices();
4855 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4856 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4857 current_program_->GetUniformInfo(sampler_indices[ii]);
4858 DCHECK(uniform_info);
4859 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4860 GLuint texture_unit_index = uniform_info->texture_units[jj];
4861 if (texture_unit_index < group_->max_texture_units()) {
4862 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4863 TextureManager::TextureInfo* texture_info =
4864 texture_unit.GetInfoForSamplerType(uniform_info->type);
4865 if (texture_info && !texture_info->SafeToRenderFrom()) {
4866 if (!texture_manager()->ClearRenderableLevels(this, texture_info)) {
4867 return false;
4868 }
4869 }
4870 }
4871 }
4872 }
4873 }
4874 return true;
4875}
4876
[email protected]c6aef902012-02-14 03:31:424877bool GLES2DecoderImpl::IsDrawValid(
4878 GLuint max_vertex_accessed, GLsizei primcount) {
[email protected]689fa1c52010-06-09 18:35:034879 // NOTE: We specifically do not check current_program->IsValid() because
4880 // it could never be invalid since glUseProgram would have failed. While
4881 // glLinkProgram could later mark the program as invalid the previous
4882 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:144883 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:504884 // The program does not exist.
4885 // But GL says no ERROR.
4886 return false;
4887 }
[email protected]c6aef902012-02-14 03:31:424888
4889 // true if any enabled, used divisor is zero
4890 bool divisor0 = false;
[email protected]f39f4b3f2010-05-12 17:04:084891 // Validate all attribs currently enabled. If they are used by the current
4892 // program then check that they have enough elements to handle the draw call.
4893 // If they are not used by the current program check that they have a buffer
4894 // assigned.
4895 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:444896 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]f39f4b3f2010-05-12 17:04:084897 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:404898 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:084899 const VertexAttribManager::VertexAttribInfo* info = *it;
4900 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
4901 current_program_->GetAttribInfoByLocation(info->index());
4902 if (attrib_info) {
[email protected]c6aef902012-02-14 03:31:424903 divisor0 |= (info->divisor() == 0);
4904 GLuint count = info->MaxVertexAccessed(primcount, max_vertex_accessed);
[email protected]f39f4b3f2010-05-12 17:04:084905 // This attrib is used in the current program.
[email protected]c6aef902012-02-14 03:31:424906 if (!info->CanAccess(count)) {
[email protected]f39f4b3f2010-05-12 17:04:084907 SetGLError(GL_INVALID_OPERATION,
4908 "glDrawXXX: attempt to access out of range vertices");
4909 return false;
4910 }
4911 } else {
4912 // This attrib is not used in the current program.
[email protected]a0b78dc2011-11-11 10:43:104913 if (!info->buffer()) {
[email protected]f39f4b3f2010-05-12 17:04:084914 SetGLError(
4915 GL_INVALID_OPERATION,
4916 "glDrawXXX: attempt to render with no buffer attached to enabled "
4917 "attrib");
4918 return false;
4919 }
[email protected]1d32bc82010-01-13 22:06:464920 }
[email protected]07f54fcc2009-12-22 02:46:304921 }
[email protected]c6aef902012-02-14 03:31:424922
4923 if (primcount && !divisor0) {
4924 SetGLError(
4925 GL_INVALID_OPERATION,
4926 "glDrawXXX: attempt instanced render with all attributes having "
4927 "non-zero divisors");
4928 return false;
4929 }
4930
[email protected]3916c97e2010-02-25 03:20:504931 return true;
[email protected]b1122982010-05-17 23:04:244932}
4933
[email protected]c13e1da62011-09-09 21:48:304934bool GLES2DecoderImpl::SimulateAttrib0(
4935 GLuint max_vertex_accessed, bool* simulated) {
4936 DCHECK(simulated);
4937 *simulated = false;
4938
[email protected]876f6fee2010-08-02 23:10:324939 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
[email protected]c13e1da62011-09-09 21:48:304940 return true;
[email protected]876f6fee2010-08-02 23:10:324941
[email protected]b1122982010-05-17 23:04:244942 const VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:444943 vertex_attrib_manager_->GetVertexAttribInfo(0);
[email protected]b1122982010-05-17 23:04:244944 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:494945 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
4946 if (info->enabled() && attrib_0_used) {
[email protected]c13e1da62011-09-09 21:48:304947 return true;
[email protected]b1122982010-05-17 23:04:244948 }
4949
[email protected]b1122982010-05-17 23:04:244950 // Make a buffer with a single repeated vec4 value enough to
4951 // simulate the constant value that is supposed to be here.
4952 // This is required to emulate GLES2 on GL.
[email protected]c13e1da62011-09-09 21:48:304953 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
4954
4955 GLuint num_vertices = max_vertex_accessed + 1;
4956 GLuint size_needed = 0;
4957
4958 if (num_vertices == 0 ||
4959 !SafeMultiply(num_vertices, static_cast<GLuint>(sizeof(Vec4)),
4960 &size_needed) ||
4961 size_needed > 0x7FFFFFFFU) {
4962 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
4963 return false;
4964 }
4965
4966 CopyRealGLErrorsToWrapper();
4967 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
4968
4969 if (static_cast<GLsizei>(size_needed) > attrib_0_size_) {
[email protected]fc753442011-02-04 19:49:494970 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:304971 GLenum error = glGetError();
4972 if (error != GL_NO_ERROR) {
4973 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
4974 return false;
4975 }
[email protected]fc753442011-02-04 19:49:494976 attrib_0_buffer_matches_value_ = false;
4977 }
4978 if (attrib_0_used &&
4979 (!attrib_0_buffer_matches_value_ ||
4980 (info->value().v[0] != attrib_0_value_.v[0] ||
4981 info->value().v[1] != attrib_0_value_.v[1] ||
4982 info->value().v[2] != attrib_0_value_.v[2] ||
4983 info->value().v[3] != attrib_0_value_.v[3]))) {
4984 std::vector<Vec4> temp(num_vertices, info->value());
4985 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
4986 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:244987 attrib_0_value_ = info->value();
4988 attrib_0_size_ = size_needed;
4989 }
4990
4991 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4992
[email protected]c6aef902012-02-14 03:31:424993 if (info->divisor())
4994 glVertexAttribDivisorANGLE(0, 0);
4995
[email protected]c13e1da62011-09-09 21:48:304996 *simulated = true;
[email protected]b1122982010-05-17 23:04:244997 return true;
[email protected]b1122982010-05-17 23:04:244998}
4999
5000void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
5001 const VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445002 vertex_attrib_manager_->GetVertexAttribInfo(0);
[email protected]b1122982010-05-17 23:04:245003 const void* ptr = reinterpret_cast<const void*>(info->offset());
5004 BufferManager::BufferInfo* buffer_info = info->buffer();
5005 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
5006 glVertexAttribPointer(
5007 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
5008 ptr);
[email protected]c6aef902012-02-14 03:31:425009 if (info->divisor())
5010 glVertexAttribDivisorANGLE(0, info->divisor());
[email protected]b1122982010-05-17 23:04:245011 glBindBuffer(GL_ARRAY_BUFFER,
5012 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
5013}
[email protected]07f54fcc2009-12-22 02:46:305014
[email protected]8fbedc02010-11-18 18:43:405015bool GLES2DecoderImpl::SimulateFixedAttribs(
[email protected]c6aef902012-02-14 03:31:425016 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
[email protected]8fbedc02010-11-18 18:43:405017 DCHECK(simulated);
5018 *simulated = false;
5019 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
5020 return true;
5021
[email protected]3757a372012-01-19 05:20:445022 if (!vertex_attrib_manager_->HaveFixedAttribs()) {
[email protected]8fbedc02010-11-18 18:43:405023 return true;
5024 }
5025
5026 // NOTE: we could be smart and try to check if a buffer is used
5027 // twice in 2 different attribs, find the overlapping parts and therefore
5028 // duplicate the minimum amount of data but this whole code path is not meant
5029 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
5030 // tests so we just add to the buffer attrib used.
5031
[email protected]c13e1da62011-09-09 21:48:305032 GLuint elements_needed = 0;
[email protected]8fbedc02010-11-18 18:43:405033 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:445034 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]8fbedc02010-11-18 18:43:405035 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5036 infos.begin(); it != infos.end(); ++it) {
5037 const VertexAttribManager::VertexAttribInfo* info = *it;
5038 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5039 current_program_->GetAttribInfoByLocation(info->index());
[email protected]c6aef902012-02-14 03:31:425040 GLuint max_accessed = info->MaxVertexAccessed(primcount,
5041 max_vertex_accessed);
5042 GLuint num_vertices = max_accessed + 1;
5043 if (num_vertices == 0) {
5044 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
5045 return false;
5046 }
[email protected]8fbedc02010-11-18 18:43:405047 if (attrib_info &&
[email protected]c6aef902012-02-14 03:31:425048 info->CanAccess(max_accessed) &&
[email protected]8fbedc02010-11-18 18:43:405049 info->type() == GL_FIXED) {
[email protected]c13e1da62011-09-09 21:48:305050 GLuint elements_used = 0;
5051 if (!SafeMultiply(num_vertices,
5052 static_cast<GLuint>(info->size()), &elements_used) ||
[email protected]8fbedc02010-11-18 18:43:405053 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
5054 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5055 return false;
5056 }
5057 }
5058 }
5059
[email protected]c13e1da62011-09-09 21:48:305060 const GLuint kSizeOfFloat = sizeof(float); // NOLINT
5061 GLuint size_needed = 0;
5062 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed) ||
5063 size_needed > 0x7FFFFFFFU) {
[email protected]8fbedc02010-11-18 18:43:405064 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5065 return false;
5066 }
5067
[email protected]c13e1da62011-09-09 21:48:305068 CopyRealGLErrorsToWrapper();
[email protected]8fbedc02010-11-18 18:43:405069
5070 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
[email protected]c13e1da62011-09-09 21:48:305071 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
[email protected]8fbedc02010-11-18 18:43:405072 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305073 GLenum error = glGetError();
5074 if (error != GL_NO_ERROR) {
5075 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5076 return false;
5077 }
[email protected]8fbedc02010-11-18 18:43:405078 }
5079
5080 // Copy the elements and convert to float
5081 GLintptr offset = 0;
5082 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5083 infos.begin(); it != infos.end(); ++it) {
5084 const VertexAttribManager::VertexAttribInfo* info = *it;
5085 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5086 current_program_->GetAttribInfoByLocation(info->index());
[email protected]c6aef902012-02-14 03:31:425087 GLuint max_accessed = info->MaxVertexAccessed(primcount,
5088 max_vertex_accessed);
5089 GLuint num_vertices = max_accessed + 1;
5090 if (num_vertices == 0) {
5091 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
5092 return false;
5093 }
[email protected]8fbedc02010-11-18 18:43:405094 if (attrib_info &&
[email protected]c6aef902012-02-14 03:31:425095 info->CanAccess(max_accessed) &&
[email protected]8fbedc02010-11-18 18:43:405096 info->type() == GL_FIXED) {
5097 int num_elements = info->size() * kSizeOfFloat;
5098 int size = num_elements * num_vertices;
5099 scoped_array<float> data(new float[size]);
5100 const int32* src = reinterpret_cast<const int32 *>(
5101 info->buffer()->GetRange(info->offset(), size));
5102 const int32* end = src + num_elements;
5103 float* dst = data.get();
5104 while (src != end) {
5105 *dst++ = static_cast<float>(*src++) / 65536.0f;
5106 }
5107 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
5108 glVertexAttribPointer(
5109 info->index(), info->size(), GL_FLOAT, false, 0,
5110 reinterpret_cast<GLvoid*>(offset));
5111 offset += size;
5112 }
5113 }
5114 *simulated = true;
5115 return true;
5116}
5117
5118void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
5119 // There's no need to call glVertexAttribPointer because we shadow all the
5120 // settings and passing GL_FIXED to it will not work.
5121 glBindBuffer(GL_ARRAY_BUFFER,
5122 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
5123}
5124
[email protected]c6aef902012-02-14 03:31:425125error::Error GLES2DecoderImpl::DoDrawArrays(bool instanced,
5126 GLenum mode,
5127 GLint first,
5128 GLsizei count,
5129 GLsizei primcount) {
[email protected]38d139d2011-07-14 00:38:435130 if (!validators_->draw_mode.IsValid(mode)) {
5131 SetGLError(GL_INVALID_ENUM, "glDrawArrays: mode GL_INVALID_ENUM");
5132 return error::kNoError;
5133 }
5134 if (count < 0) {
5135 SetGLError(GL_INVALID_VALUE, "glDrawArrays: count < 0");
5136 return error::kNoError;
5137 }
[email protected]c6aef902012-02-14 03:31:425138 if (primcount < 0) {
5139 SetGLError(GL_INVALID_VALUE, "glDrawArrays: primcount < 0");
5140 return error::kNoError;
5141 }
[email protected]0d6bfdc2011-11-02 01:32:205142 if (!CheckBoundFramebuffersValid("glDrawArrays")) {
[email protected]38d139d2011-07-14 00:38:435143 return error::kNoError;
5144 }
5145 // We have to check this here because the prototype for glDrawArrays
5146 // is GLint not GLsizei.
5147 if (first < 0) {
5148 SetGLError(GL_INVALID_VALUE, "glDrawArrays: first < 0");
5149 return error::kNoError;
5150 }
5151
[email protected]c6aef902012-02-14 03:31:425152 if (count == 0 || (instanced && primcount == 0)) {
[email protected]38d139d2011-07-14 00:38:435153 return error::kNoError;
5154 }
5155
5156 GLuint max_vertex_accessed = first + count - 1;
[email protected]c6aef902012-02-14 03:31:425157 if (IsDrawValid(max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:205158 if (!ClearUnclearedTextures()) {
5159 SetGLError(GL_INVALID_VALUE, "glDrawArrays: out of memory");
5160 return error::kNoError;
5161 }
[email protected]c13e1da62011-09-09 21:48:305162 bool simulated_attrib_0 = false;
5163 if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
5164 return error::kNoError;
5165 }
[email protected]38d139d2011-07-14 00:38:435166 bool simulated_fixed_attribs = false;
[email protected]c6aef902012-02-14 03:31:425167 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs,
5168 primcount)) {
[email protected]38d139d2011-07-14 00:38:435169 bool textures_set = SetBlackTextureForNonRenderableTextures();
5170 ApplyDirtyState();
[email protected]c6aef902012-02-14 03:31:425171 if (!instanced) {
5172 glDrawArrays(mode, first, count);
5173 } else {
5174 glDrawArraysInstancedANGLE(mode, first, count, primcount);
5175 }
[email protected]22e3f552012-03-13 01:54:195176 ProcessPendingQueries();
[email protected]38d139d2011-07-14 00:38:435177 if (textures_set) {
5178 RestoreStateForNonRenderableTextures();
5179 }
5180 if (simulated_fixed_attribs) {
5181 RestoreStateForSimulatedFixedAttribs();
5182 }
5183 }
5184 if (simulated_attrib_0) {
5185 RestoreStateForSimulatedAttrib0();
5186 }
5187 if (WasContextLost()) {
5188 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawArrays.";
5189 return error::kLostContext;
5190 }
5191 }
5192 return error::kNoError;
5193}
5194
[email protected]c6aef902012-02-14 03:31:425195error::Error GLES2DecoderImpl::HandleDrawArrays(
5196 uint32 immediate_data_size, const gles2::DrawArrays& c) {
5197 return DoDrawArrays(false,
5198 static_cast<GLenum>(c.mode),
5199 static_cast<GLint>(c.first),
5200 static_cast<GLsizei>(c.count),
5201 0);
5202}
5203
5204error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
5205 uint32 immediate_data_size, const gles2::DrawArraysInstancedANGLE& c) {
5206 if (!feature_info_->feature_flags().angle_instanced_arrays) {
5207 SetGLError(GL_INVALID_OPERATION,
5208 "glDrawArraysInstancedANGLE: function not available");
5209 return error::kNoError;
5210 }
5211 return DoDrawArrays(true,
5212 static_cast<GLenum>(c.mode),
5213 static_cast<GLint>(c.first),
5214 static_cast<GLsizei>(c.count),
5215 static_cast<GLsizei>(c.primcount));
5216}
5217
5218error::Error GLES2DecoderImpl::DoDrawElements(bool instanced,
5219 GLenum mode,
5220 GLsizei count,
5221 GLenum type,
5222 int32 offset,
5223 GLsizei primcount) {
[email protected]a0b78dc2011-11-11 10:43:105224 if (!bound_element_array_buffer_) {
[email protected]8eee29c2010-04-29 03:38:295225 SetGLError(GL_INVALID_OPERATION,
5226 "glDrawElements: No element array buffer bound");
5227 return error::kNoError;
5228 }
5229
[email protected]8eee29c2010-04-29 03:38:295230 if (count < 0) {
5231 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
5232 return error::kNoError;
5233 }
5234 if (offset < 0) {
5235 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
5236 return error::kNoError;
5237 }
[email protected]9438b012010-06-15 22:55:055238 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:295239 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
5240 return error::kNoError;
5241 }
[email protected]9438b012010-06-15 22:55:055242 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295243 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
5244 return error::kNoError;
5245 }
[email protected]c6aef902012-02-14 03:31:425246 if (primcount < 0) {
5247 SetGLError(GL_INVALID_VALUE, "glDrawElements: primcount < 0");
5248 return error::kNoError;
5249 }
[email protected]8eee29c2010-04-29 03:38:295250
[email protected]0d6bfdc2011-11-02 01:32:205251 if (!CheckBoundFramebuffersValid("glDrawElements")) {
[email protected]3a03a8f2011-03-19 00:51:275252 return error::kNoError;
5253 }
5254
[email protected]c6aef902012-02-14 03:31:425255 if (count == 0 || (instanced && primcount == 0)) {
[email protected]6c788fb72010-08-26 02:16:315256 return error::kNoError;
5257 }
5258
[email protected]8eee29c2010-04-29 03:38:295259 GLuint max_vertex_accessed;
5260 if (!bound_element_array_buffer_->GetMaxValueForRange(
5261 offset, count, type, &max_vertex_accessed)) {
5262 SetGLError(GL_INVALID_OPERATION,
5263 "glDrawElements: range out of bounds for buffer");
5264 return error::kNoError;
5265 }
5266
[email protected]c6aef902012-02-14 03:31:425267 if (IsDrawValid(max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:205268 if (!ClearUnclearedTextures()) {
5269 SetGLError(GL_INVALID_VALUE, "glDrawElements: out of memory");
5270 return error::kNoError;
5271 }
[email protected]c13e1da62011-09-09 21:48:305272 bool simulated_attrib_0 = false;
5273 if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
5274 return error::kNoError;
5275 }
[email protected]8fbedc02010-11-18 18:43:405276 bool simulated_fixed_attribs = false;
[email protected]c6aef902012-02-14 03:31:425277 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs,
5278 primcount)) {
[email protected]8fbedc02010-11-18 18:43:405279 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:465280 ApplyDirtyState();
[email protected]8fbedc02010-11-18 18:43:405281 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
[email protected]c6aef902012-02-14 03:31:425282 if (!instanced) {
5283 glDrawElements(mode, count, type, indices);
5284 } else {
5285 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
5286 }
[email protected]22e3f552012-03-13 01:54:195287 ProcessPendingQueries();
[email protected]8fbedc02010-11-18 18:43:405288 if (textures_set) {
5289 RestoreStateForNonRenderableTextures();
5290 }
5291 if (simulated_fixed_attribs) {
5292 RestoreStateForSimulatedFixedAttribs();
5293 }
[email protected]ba3176a2009-12-16 18:19:465294 }
[email protected]b1122982010-05-17 23:04:245295 if (simulated_attrib_0) {
5296 RestoreStateForSimulatedAttrib0();
5297 }
[email protected]38d139d2011-07-14 00:38:435298 if (WasContextLost()) {
5299 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawElements.";
5300 return error::kLostContext;
5301 }
[email protected]96449d2c2009-11-25 00:01:325302 }
[email protected]f7a64ee2010-02-01 22:24:145303 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325304}
5305
[email protected]c6aef902012-02-14 03:31:425306error::Error GLES2DecoderImpl::HandleDrawElements(
5307 uint32 immediate_data_size, const gles2::DrawElements& c) {
5308 return DoDrawElements(false,
5309 static_cast<GLenum>(c.mode),
5310 static_cast<GLsizei>(c.count),
5311 static_cast<GLenum>(c.type),
5312 static_cast<int32>(c.index_offset),
5313 0);
5314}
5315
5316error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
5317 uint32 immediate_data_size, const gles2::DrawElementsInstancedANGLE& c) {
5318 if (!feature_info_->feature_flags().angle_instanced_arrays) {
5319 SetGLError(GL_INVALID_OPERATION,
5320 "glDrawElementsInstancedANGLE: function not available");
5321 return error::kNoError;
5322 }
5323 return DoDrawElements(true,
5324 static_cast<GLenum>(c.mode),
5325 static_cast<GLsizei>(c.count),
5326 static_cast<GLenum>(c.type),
5327 static_cast<int32>(c.index_offset),
5328 static_cast<GLsizei>(c.primcount));
5329}
5330
[email protected]269200b12010-11-18 22:53:065331GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:235332 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
5333 GLuint max_vertex_accessed = 0;
5334 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:295335 if (!info) {
[email protected]ae51d192010-04-27 00:48:035336 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:295337 SetGLError(GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:065338 "GetMaxValueInBufferCHROMIUM: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:235339 } else {
5340 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:035341 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:065342 SetGLError(
5343 GL_INVALID_OPERATION,
5344 "GetMaxValueInBufferCHROMIUM: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:235345 }
5346 }
5347 return max_vertex_accessed;
5348}
5349
[email protected]96449d2c2009-11-25 00:01:325350// Calls glShaderSource for the various versions of the ShaderSource command.
5351// Assumes that data / data_size points to a piece of memory that is in range
5352// of whatever context it came from (shared memory, immediate memory, bucket
5353// memory.)
[email protected]45bf5152010-02-12 00:11:315354error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035355 GLuint client_id, const char* data, uint32 data_size) {
[email protected]258a3313f2011-10-18 20:13:575356 std::string str(data, data + data_size);
[email protected]6b8cf1a2010-05-06 16:13:585357 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5358 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:315359 if (!info) {
[email protected]45bf5152010-02-12 00:11:315360 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325361 }
[email protected]45bf5152010-02-12 00:11:315362 // Note: We don't actually call glShaderSource here. We wait until
5363 // the call to glCompileShader.
[email protected]258a3313f2011-10-18 20:13:575364 info->UpdateSource(str.c_str());
[email protected]f7a64ee2010-02-01 22:24:145365 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325366}
5367
[email protected]f7a64ee2010-02-01 22:24:145368error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:195369 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:325370 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315371 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:325372 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:465373 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145374 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325375 }
[email protected]ae51d192010-04-27 00:48:035376 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:325377}
5378
[email protected]f7a64ee2010-02-01 22:24:145379error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:195380 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:325381 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315382 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:305383 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465384 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145385 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325386 }
[email protected]ae51d192010-04-27 00:48:035387 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:315388}
5389
[email protected]558847a2010-03-24 07:02:545390error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
5391 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:545392 Bucket* bucket = GetBucket(c.data_bucket_id);
5393 if (!bucket || bucket->size() == 0) {
5394 return error::kInvalidArguments;
5395 }
5396 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035397 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:545398 bucket->size() - 1);
5399}
5400
[email protected]ae51d192010-04-27 00:48:035401void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]0c8fabf2011-06-14 19:35:225402 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]6b8cf1a2010-05-06 16:13:585403 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5404 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:315405 if (!info) {
[email protected]45bf5152010-02-12 00:11:315406 return;
5407 }
[email protected]de17df392010-04-23 21:09:415408 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
5409 // glShaderSource and then glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:525410 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:345411 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:185412 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:345413 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:455414 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:235415
[email protected]a550584e2010-09-17 18:01:455416 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:345417 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:185418 return;
5419 }
[email protected]a550584e2010-09-17 18:01:455420 shader_src = translator->translated_shader();
[email protected]93297702011-11-05 05:09:465421 if (!feature_info_->feature_flags().angle_translated_shader_source)
[email protected]d6a53e42011-10-05 00:09:365422 info->UpdateTranslatedSource(shader_src);
[email protected]de17df392010-04-23 21:09:415423 }
[email protected]de17df392010-04-23 21:09:415424
[email protected]ae51d192010-04-27 00:48:035425 glShaderSource(info->service_id(), 1, &shader_src, NULL);
5426 glCompileShader(info->service_id());
[email protected]93297702011-11-05 05:09:465427 if (feature_info_->feature_flags().angle_translated_shader_source) {
[email protected]d6a53e42011-10-05 00:09:365428 GLint max_len = 0;
5429 glGetShaderiv(info->service_id(),
5430 GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
5431 &max_len);
5432 scoped_array<char> temp(new char[max_len]);
5433 GLint len = 0;
5434 glGetTranslatedShaderSourceANGLE(
5435 info->service_id(), max_len, &len, temp.get());
5436 DCHECK(max_len == 0 || len < max_len);
5437 DCHECK(len == 0 || temp[len] == '\0');
5438 info->UpdateTranslatedSource(temp.get());
5439 }
5440
[email protected]e5186162010-06-14 18:54:415441 GLint status = GL_FALSE;
5442 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
5443 if (status) {
[email protected]f57bb282010-11-12 00:51:345444 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:415445 } else {
[email protected]d9977d42010-09-01 20:27:025446 // We cannot reach here if we are using the shader translator.
5447 // All invalid shaders must be rejected by the translator.
5448 // All translated shaders must compile.
5449 LOG_IF(ERROR, use_shader_translator_)
5450 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:335451 GLint max_len = 0;
5452 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
5453 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:415454 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:335455 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
5456 DCHECK(max_len == 0 || len < max_len);
[email protected]d6a53e42011-10-05 00:09:365457 DCHECK(len == 0 || temp[len] == '\0');
[email protected]df6cf1ad2011-01-29 01:20:525458 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
[email protected]e5186162010-06-14 18:54:415459 }
[email protected]45bf5152010-02-12 00:11:315460};
5461
[email protected]ddd968b82010-03-02 00:44:295462void GLES2DecoderImpl::DoGetShaderiv(
5463 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:585464 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5465 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:295466 if (!info) {
[email protected]ddd968b82010-03-02 00:44:295467 return;
5468 }
[email protected]8f1ccdac2010-05-19 21:01:485469 switch (pname) {
5470 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525471 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:485472 return;
5473 case GL_COMPILE_STATUS:
[email protected]062c38b2012-01-18 03:25:105474 *params = compile_shader_always_succeeds_ ? true : info->IsValid();
[email protected]e5186162010-06-14 18:54:415475 return;
[email protected]8f1ccdac2010-05-19 21:01:485476 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525477 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:415478 return;
[email protected]d6a53e42011-10-05 00:09:365479 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5480 *params = info->translated_source() ?
5481 info->translated_source()->size() + 1 : 0;
5482 return;
[email protected]8f1ccdac2010-05-19 21:01:485483 default:
5484 break;
[email protected]ddd968b82010-03-02 00:44:295485 }
[email protected]8f1ccdac2010-05-19 21:01:485486 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:295487}
5488
[email protected]ae51d192010-04-27 00:48:035489error::Error GLES2DecoderImpl::HandleGetShaderSource(
5490 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
5491 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:035492 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5493 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:585494 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5495 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:525496 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:295497 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:295498 return error::kNoError;
5499 }
[email protected]df6cf1ad2011-01-29 01:20:525500 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:035501 return error::kNoError;
5502}
5503
[email protected]d6a53e42011-10-05 00:09:365504error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
5505 uint32 immediate_data_size,
5506 const gles2::GetTranslatedShaderSourceANGLE& c) {
5507 GLuint shader = c.shader;
5508
5509 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5510 Bucket* bucket = CreateBucket(bucket_id);
5511 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5512 shader, "glTranslatedGetShaderSourceANGLE");
5513 if (!info) {
5514 bucket->SetSize(0);
5515 return error::kNoError;
5516 }
5517
5518 bucket->SetFromString(info->translated_source() ?
5519 info->translated_source()->c_str() : NULL);
5520 return error::kNoError;
5521}
5522
[email protected]ae51d192010-04-27 00:48:035523error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
5524 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
5525 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:585526 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5527 Bucket* bucket = CreateBucket(bucket_id);
5528 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5529 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525530 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465531 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035532 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:315533 }
[email protected]df6cf1ad2011-01-29 01:20:525534 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035535 return error::kNoError;
5536}
5537
5538error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
5539 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
5540 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:585541 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5542 Bucket* bucket = CreateBucket(bucket_id);
5543 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5544 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525545 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465546 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035547 return error::kNoError;
5548 }
[email protected]df6cf1ad2011-01-29 01:20:525549 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035550 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325551}
5552
[email protected]1958e0e2010-04-22 05:17:155553bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105554 const BufferManager::BufferInfo* buffer = GetBufferInfo(client_id);
5555 return buffer && buffer->IsValid() && !buffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155556}
5557
5558bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105559 const FramebufferManager::FramebufferInfo* framebuffer =
[email protected]06c8b082011-01-05 18:00:365560 GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105561 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155562}
5563
5564bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365565 // IsProgram is true for programs as soon as they are created, until they are
5566 // deleted and no longer in use.
[email protected]a0b78dc2011-11-11 10:43:105567 const ProgramManager::ProgramInfo* program = GetProgramInfo(client_id);
5568 return program != NULL && !program->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155569}
5570
5571bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105572 const RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]06c8b082011-01-05 18:00:365573 GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105574 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155575}
5576
5577bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365578 // IsShader is true for shaders as soon as they are created, until they
5579 // are deleted and not attached to any programs.
[email protected]a0b78dc2011-11-11 10:43:105580 const ShaderManager::ShaderInfo* shader = GetShaderInfo(client_id);
5581 return shader != NULL && !shader->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155582}
5583
5584bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105585 const TextureManager::TextureInfo* texture = GetTextureInfo(client_id);
5586 return texture && texture->IsValid() && !texture->IsDeleted();
[email protected]ae51d192010-04-27 00:48:035587}
5588
5589void GLES2DecoderImpl::DoAttachShader(
5590 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585591 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5592 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035593 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035594 return;
[email protected]1958e0e2010-04-22 05:17:155595 }
[email protected]6b8cf1a2010-05-06 16:13:585596 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5597 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035598 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035599 return;
5600 }
[email protected]ca488e12010-12-13 20:06:145601 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:315602 SetGLError(GL_INVALID_OPERATION,
5603 "glAttachShader: can not attach more than"
5604 " one shader of the same type.");
5605 return;
5606 }
[email protected]ae51d192010-04-27 00:48:035607 glAttachShader(program_info->service_id(), shader_info->service_id());
5608}
5609
5610void GLES2DecoderImpl::DoDetachShader(
5611 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585612 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5613 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035614 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035615 return;
5616 }
[email protected]6b8cf1a2010-05-06 16:13:585617 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5618 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035619 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035620 return;
5621 }
[email protected]9a0ccd42011-03-16 23:58:225622 if (!program_info->DetachShader(shader_manager(), shader_info)) {
5623 SetGLError(GL_INVALID_OPERATION,
5624 "glDetachShader: shader not attached to program");
5625 return;
5626 }
[email protected]ae51d192010-04-27 00:48:035627 glDetachShader(program_info->service_id(), shader_info->service_id());
5628}
5629
5630void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585631 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5632 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:035633 if (!info) {
[email protected]ae51d192010-04-27 00:48:035634 return;
5635 }
[email protected]d685a682011-04-29 16:19:575636 info->Validate();
[email protected]1958e0e2010-04-22 05:17:155637}
5638
[email protected]b1122982010-05-17 23:04:245639void GLES2DecoderImpl::DoGetVertexAttribfv(
5640 GLuint index, GLenum pname, GLfloat* params) {
5641 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445642 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245643 if (!info) {
5644 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
5645 return;
5646 }
5647 switch (pname) {
5648 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5649 BufferManager::BufferInfo* buffer = info->buffer();
5650 if (buffer && !buffer->IsDeleted()) {
5651 GLuint client_id;
5652 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5653 *params = static_cast<GLfloat>(client_id);
5654 }
5655 break;
5656 }
5657 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5658 *params = static_cast<GLfloat>(info->enabled());
5659 break;
5660 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5661 *params = static_cast<GLfloat>(info->size());
5662 break;
5663 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5664 *params = static_cast<GLfloat>(info->gl_stride());
5665 break;
5666 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5667 *params = static_cast<GLfloat>(info->type());
5668 break;
5669 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5670 *params = static_cast<GLfloat>(info->normalized());
5671 break;
5672 case GL_CURRENT_VERTEX_ATTRIB:
5673 params[0] = info->value().v[0];
5674 params[1] = info->value().v[1];
5675 params[2] = info->value().v[2];
5676 params[3] = info->value().v[3];
5677 break;
[email protected]c6aef902012-02-14 03:31:425678 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
5679 *params = static_cast<GLfloat>(info->divisor());
5680 break;
[email protected]b1122982010-05-17 23:04:245681 default:
5682 NOTREACHED();
5683 break;
5684 }
5685}
5686
5687void GLES2DecoderImpl::DoGetVertexAttribiv(
5688 GLuint index, GLenum pname, GLint* params) {
5689 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445690 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245691 if (!info) {
5692 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
5693 return;
5694 }
5695 switch (pname) {
5696 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5697 BufferManager::BufferInfo* buffer = info->buffer();
5698 if (buffer && !buffer->IsDeleted()) {
5699 GLuint client_id;
5700 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5701 *params = client_id;
5702 }
5703 break;
5704 }
5705 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5706 *params = info->enabled();
5707 break;
5708 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5709 *params = info->size();
5710 break;
5711 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5712 *params = info->gl_stride();
5713 break;
5714 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5715 *params = info->type();
5716 break;
5717 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5718 *params = static_cast<GLint>(info->normalized());
5719 break;
[email protected]c6aef902012-02-14 03:31:425720 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
5721 *params = info->divisor();
5722 break;
[email protected]b1122982010-05-17 23:04:245723 case GL_CURRENT_VERTEX_ATTRIB:
5724 params[0] = static_cast<GLint>(info->value().v[0]);
5725 params[1] = static_cast<GLint>(info->value().v[1]);
5726 params[2] = static_cast<GLint>(info->value().v[2]);
5727 params[3] = static_cast<GLint>(info->value().v[3]);
5728 break;
5729 default:
5730 NOTREACHED();
5731 break;
5732 }
5733}
5734
5735void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
5736 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445737 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245738 if (!info) {
5739 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
5740 return;
5741 }
5742 VertexAttribManager::VertexAttribInfo::Vec4 value;
5743 value.v[0] = v0;
5744 value.v[1] = 0.0f;
5745 value.v[2] = 0.0f;
5746 value.v[3] = 1.0f;
5747 info->set_value(value);
5748 glVertexAttrib1f(index, v0);
5749}
5750
5751void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
5752 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445753 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245754 if (!info) {
5755 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
5756 return;
5757 }
5758 VertexAttribManager::VertexAttribInfo::Vec4 value;
5759 value.v[0] = v0;
5760 value.v[1] = v1;
5761 value.v[2] = 0.0f;
5762 value.v[3] = 1.0f;
5763 info->set_value(value);
5764 glVertexAttrib2f(index, v0, v1);
5765}
5766
5767void GLES2DecoderImpl::DoVertexAttrib3f(
5768 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
5769 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445770 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245771 if (!info) {
5772 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
5773 return;
5774 }
5775 VertexAttribManager::VertexAttribInfo::Vec4 value;
5776 value.v[0] = v0;
5777 value.v[1] = v1;
5778 value.v[2] = v2;
5779 value.v[3] = 1.0f;
5780 info->set_value(value);
5781 glVertexAttrib3f(index, v0, v1, v2);
5782}
5783
5784void GLES2DecoderImpl::DoVertexAttrib4f(
5785 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
5786 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445787 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245788 if (!info) {
5789 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
5790 return;
5791 }
5792 VertexAttribManager::VertexAttribInfo::Vec4 value;
5793 value.v[0] = v0;
5794 value.v[1] = v1;
5795 value.v[2] = v2;
5796 value.v[3] = v3;
5797 info->set_value(value);
5798 glVertexAttrib4f(index, v0, v1, v2, v3);
5799}
5800
5801void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
5802 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445803 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245804 if (!info) {
5805 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
5806 return;
5807 }
5808 VertexAttribManager::VertexAttribInfo::Vec4 value;
5809 value.v[0] = v[0];
5810 value.v[1] = 0.0f;
5811 value.v[2] = 0.0f;
5812 value.v[3] = 1.0f;
5813 info->set_value(value);
5814 glVertexAttrib1fv(index, v);
5815}
5816
5817void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
5818 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445819 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245820 if (!info) {
5821 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
5822 return;
5823 }
5824 VertexAttribManager::VertexAttribInfo::Vec4 value;
5825 value.v[0] = v[0];
5826 value.v[1] = v[1];
5827 value.v[2] = 0.0f;
5828 value.v[3] = 1.0f;
5829 info->set_value(value);
5830 glVertexAttrib2fv(index, v);
5831}
5832
5833void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
5834 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445835 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245836 if (!info) {
5837 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
5838 return;
5839 }
5840 VertexAttribManager::VertexAttribInfo::Vec4 value;
5841 value.v[0] = v[0];
5842 value.v[1] = v[1];
5843 value.v[2] = v[2];
5844 value.v[3] = 1.0f;
5845 info->set_value(value);
5846 glVertexAttrib3fv(index, v);
5847}
5848
5849void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
5850 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445851 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245852 if (!info) {
5853 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
5854 return;
5855 }
5856 VertexAttribManager::VertexAttribInfo::Vec4 value;
5857 value.v[0] = v[0];
5858 value.v[1] = v[1];
5859 value.v[2] = v[2];
5860 value.v[3] = v[3];
5861 info->set_value(value);
5862 glVertexAttrib4fv(index, v);
5863}
5864
[email protected]f7a64ee2010-02-01 22:24:145865error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:195866 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:295867 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
5868 SetGLError(GL_INVALID_VALUE,
5869 "glVertexAttribPointer: no array buffer bound");
5870 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325871 }
[email protected]8eee29c2010-04-29 03:38:295872
5873 GLuint indx = c.indx;
5874 GLint size = c.size;
5875 GLenum type = c.type;
5876 GLboolean normalized = c.normalized;
5877 GLsizei stride = c.stride;
5878 GLsizei offset = c.offset;
5879 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:055880 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295881 SetGLError(GL_INVALID_ENUM,
5882 "glVertexAttribPointer: type GL_INVALID_ENUM");
5883 return error::kNoError;
5884 }
[email protected]9438b012010-06-15 22:55:055885 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:315886 SetGLError(GL_INVALID_VALUE,
[email protected]8eee29c2010-04-29 03:38:295887 "glVertexAttribPointer: size GL_INVALID_VALUE");
5888 return error::kNoError;
5889 }
5890 if (indx >= group_->max_vertex_attribs()) {
5891 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
5892 return error::kNoError;
5893 }
5894 if (stride < 0) {
5895 SetGLError(GL_INVALID_VALUE,
5896 "glVertexAttribPointer: stride < 0");
5897 return error::kNoError;
5898 }
5899 if (stride > 255) {
5900 SetGLError(GL_INVALID_VALUE,
5901 "glVertexAttribPointer: stride > 255");
5902 return error::kNoError;
5903 }
5904 if (offset < 0) {
5905 SetGLError(GL_INVALID_VALUE,
5906 "glVertexAttribPointer: offset < 0");
5907 return error::kNoError;
5908 }
5909 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:315910 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:295911 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:315912 SetGLError(GL_INVALID_OPERATION,
5913 "glVertexAttribPointer: offset not valid for type");
5914 return error::kNoError;
5915 }
5916 if (stride % component_size > 0) {
5917 SetGLError(GL_INVALID_OPERATION,
[email protected]8eee29c2010-04-29 03:38:295918 "glVertexAttribPointer: stride not valid for type");
5919 return error::kNoError;
5920 }
[email protected]3757a372012-01-19 05:20:445921 vertex_attrib_manager_->SetAttribInfo(
[email protected]8fbedc02010-11-18 18:43:405922 indx,
[email protected]8eee29c2010-04-29 03:38:295923 bound_array_buffer_,
5924 size,
5925 type,
[email protected]b1122982010-05-17 23:04:245926 normalized,
5927 stride,
5928 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:295929 offset);
[email protected]8fbedc02010-11-18 18:43:405930 if (type != GL_FIXED) {
5931 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
5932 }
[email protected]f7a64ee2010-02-01 22:24:145933 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325934}
5935
[email protected]c6aef902012-02-14 03:31:425936error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
5937 uint32 immediate_data_size, const gles2::VertexAttribDivisorANGLE& c) {
5938 if (!feature_info_->feature_flags().angle_instanced_arrays) {
5939 SetGLError(GL_INVALID_OPERATION,
5940 "glVertexAttribDivisorANGLE: function not available");
5941 }
5942 GLuint index = c.index;
5943 GLuint divisor = c.divisor;
5944 if (index >= group_->max_vertex_attribs()) {
5945 SetGLError(GL_INVALID_VALUE,
5946 "glVertexAttribDivisorANGLE: index out of range");
5947 return error::kNoError;
5948 }
5949
5950 vertex_attrib_manager_->SetDivisor(
5951 index,
5952 divisor);
5953 glVertexAttribDivisorANGLE(index, divisor);
5954 return error::kNoError;
5955}
5956
[email protected]f7a64ee2010-02-01 22:24:145957error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:195958 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:315959 GLint x = c.x;
5960 GLint y = c.y;
5961 GLsizei width = c.width;
5962 GLsizei height = c.height;
5963 GLenum format = c.format;
5964 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:565965 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:295966 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:565967 return error::kNoError;
5968 }
[email protected]a51788e2010-02-24 21:54:255969 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:185970 uint32 pixels_size;
5971 if (!GLES2Util::ComputeImageDataSize(
5972 width, height, format, type, pack_alignment_, &pixels_size)) {
5973 return error::kOutOfBounds;
5974 }
[email protected]612d2f82009-12-08 20:49:315975 void* pixels = GetSharedMemoryAs<void*>(
5976 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:255977 Result* result = GetSharedMemoryAs<Result*>(
5978 c.result_shm_id, c.result_shm_offset, sizeof(*result));
5979 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:145980 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:465981 }
[email protected]a51788e2010-02-24 21:54:255982
[email protected]9438b012010-06-15 22:55:055983 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:295984 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
5985 return error::kNoError;
5986 }
[email protected]9438b012010-06-15 22:55:055987 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295988 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:125989 return error::kNoError;
5990 }
[email protected]57f223832010-03-19 01:57:565991 if (width == 0 || height == 0) {
5992 return error::kNoError;
5993 }
5994
[email protected]57f223832010-03-19 01:57:565995 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:305996 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:565997
5998 GLint max_x;
5999 GLint max_y;
6000 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:296001 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:146002 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:316003 }
[email protected]57f223832010-03-19 01:57:566004
[email protected]0d6bfdc2011-11-02 01:32:206005 if (!CheckBoundFramebuffersValid("glReadPixels")) {
6006 return error::kNoError;
6007 }
6008
[email protected]a0b78dc2011-11-11 10:43:106009 CopyRealGLErrorsToWrapper();
6010
6011 ScopedResolvedFrameBufferBinder binder(this, false, true);
6012
[email protected]d37231fa2010-04-09 21:16:026013 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:566014 // The user requested an out of range area. Get the results 1 line
6015 // at a time.
6016 uint32 temp_size;
6017 if (!GLES2Util::ComputeImageDataSize(
6018 width, 1, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:296019 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:566020 return error::kNoError;
6021 }
6022 GLsizei unpadded_row_size = temp_size;
6023 if (!GLES2Util::ComputeImageDataSize(
6024 width, 2, format, type, pack_alignment_, &temp_size)) {
[email protected]8eee29c2010-04-29 03:38:296025 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:566026 return error::kNoError;
6027 }
6028 GLsizei padded_row_size = temp_size - unpadded_row_size;
6029 if (padded_row_size < 0 || unpadded_row_size < 0) {
[email protected]8eee29c2010-04-29 03:38:296030 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:566031 return error::kNoError;
6032 }
6033
6034 GLint dest_x_offset = std::max(-x, 0);
6035 uint32 dest_row_offset;
6036 if (!GLES2Util::ComputeImageDataSize(
6037 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
[email protected]8eee29c2010-04-29 03:38:296038 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:566039 return error::kNoError;
6040 }
6041
6042 // Copy each row into the larger dest rect.
6043 int8* dst = static_cast<int8*>(pixels);
6044 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:026045 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:566046 GLint read_width = read_end_x - read_x;
6047 for (GLint yy = 0; yy < height; ++yy) {
6048 GLint ry = y + yy;
6049
6050 // Clear the row.
6051 memset(dst, 0, unpadded_row_size);
6052
6053 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:026054 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:566055 glReadPixels(
6056 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
6057 }
6058 dst += padded_row_size;
6059 }
6060 } else {
6061 glReadPixels(x, y, width, height, format, type, pixels);
6062 }
[email protected]1002c2d2011-06-28 22:39:046063 GLenum error = PeekGLError();
[email protected]a51788e2010-02-24 21:54:256064 if (error == GL_NO_ERROR) {
6065 *result = true;
[email protected]4848b9f82011-03-10 18:37:566066
6067 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6068 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6069 if ((channels_exist & 0x0008) == 0) {
6070 // Set the alpha to 255 because some drivers are buggy in this regard.
6071 uint32 temp_size;
6072 if (!GLES2Util::ComputeImageDataSize(
6073 width, 1, format, type, pack_alignment_, &temp_size)) {
6074 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
6075 return error::kNoError;
6076 }
6077 GLsizei unpadded_row_size = temp_size;
6078 if (!GLES2Util::ComputeImageDataSize(
6079 width, 2, format, type, pack_alignment_, &temp_size)) {
6080 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
6081 return error::kNoError;
6082 }
6083 GLsizei padded_row_size = temp_size - unpadded_row_size;
6084 if (padded_row_size < 0 || unpadded_row_size < 0) {
6085 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
6086 return error::kNoError;
6087 }
6088 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
6089 // of this implementation.
6090 if (type != GL_UNSIGNED_BYTE) {
6091 SetGLError(GL_INVALID_OPERATION, "unsupported readPixel format");
6092 return error::kNoError;
6093 }
6094 switch (format) {
6095 case GL_RGBA:
[email protected]297ca1c2011-06-20 23:08:466096 case GL_BGRA_EXT:
[email protected]4848b9f82011-03-10 18:37:566097 case GL_ALPHA: {
6098 int offset = (format == GL_ALPHA) ? 0 : 3;
6099 int step = (format == GL_ALPHA) ? 1 : 4;
6100 uint8* dst = static_cast<uint8*>(pixels) + offset;
6101 for (GLint yy = 0; yy < height; ++yy) {
6102 uint8* end = dst + unpadded_row_size;
6103 for (uint8* d = dst; d < end; d += step) {
6104 *d = 255;
6105 }
6106 dst += padded_row_size;
6107 }
6108 break;
6109 }
6110 default:
6111 break;
6112 }
6113 }
[email protected]a51788e2010-02-24 21:54:256114 }
[email protected]4848b9f82011-03-10 18:37:566115
[email protected]f7a64ee2010-02-01 22:24:146116 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326117}
6118
[email protected]f7a64ee2010-02-01 22:24:146119error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:196120 uint32 immediate_data_size, const gles2::PixelStorei& c) {
6121 GLenum pname = c.pname;
6122 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:056123 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:296124 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:126125 return error::kNoError;
6126 }
[email protected]222471d2011-11-30 18:06:396127 switch (pname) {
6128 case GL_PACK_ALIGNMENT:
6129 case GL_UNPACK_ALIGNMENT:
6130 if (!validators_->pixel_store_alignment.IsValid(param)) {
6131 SetGLError(GL_INVALID_VALUE,
6132 "glPixelSTore: param GL_INVALID_VALUE");
6133 return error::kNoError;
6134 }
6135 default:
6136 break;
[email protected]b9849abf2009-11-25 19:13:196137 }
6138 glPixelStorei(pname, param);
6139 switch (pname) {
6140 case GL_PACK_ALIGNMENT:
6141 pack_alignment_ = param;
6142 break;
[email protected]222471d2011-11-30 18:06:396143 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
6144 break;
[email protected]b9849abf2009-11-25 19:13:196145 case GL_UNPACK_ALIGNMENT:
6146 unpack_alignment_ = param;
6147 break;
6148 default:
6149 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:376150 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:196151 break;
6152 }
[email protected]f7a64ee2010-02-01 22:24:146153 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196154}
6155
[email protected]1c75a3702011-11-11 14:15:286156error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
6157 uint32 immediate_data_size, const gles2::PostSubBufferCHROMIUM& c) {
6158 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
[email protected]aa258822011-11-22 13:52:256159 if (!context_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
[email protected]1c75a3702011-11-11 14:15:286160 SetGLError(GL_INVALID_OPERATION,
6161 "glPostSubBufferCHROMIUM: command not supported by surface");
6162 return error::kNoError;
6163 }
6164 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height))
6165 return error::kNoError;
6166 else
6167 return error::kLostContext;
6168}
6169
[email protected]558847a2010-03-24 07:02:546170error::Error GLES2DecoderImpl::GetAttribLocationHelper(
6171 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6172 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576173 if (!StringIsValidForGLES(name_str.c_str())) {
6174 SetGLError(GL_INVALID_VALUE, "glGetAttribLocation: Invalid character");
6175 return error::kNoError;
6176 }
[email protected]6b8cf1a2010-05-06 16:13:586177 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6178 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:036179 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146180 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196181 }
[email protected]ae51d192010-04-27 00:48:036182 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:296183 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:256184 return error::kNoError;
6185 }
[email protected]b9849abf2009-11-25 19:13:196186 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546187 location_shm_id, location_shm_offset, sizeof(GLint));
6188 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146189 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196190 }
[email protected]558847a2010-03-24 07:02:546191 // Require the client to init this incase the context is lost and we are no
6192 // longer executing commands.
6193 if (*location != -1) {
6194 return error::kGenericError;
6195 }
[email protected]0bfd9882010-02-05 23:02:256196 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:146197 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196198}
6199
[email protected]558847a2010-03-24 07:02:546200error::Error GLES2DecoderImpl::HandleGetAttribLocation(
6201 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
6202 uint32 name_size = c.data_size;
6203 const char* name = GetSharedMemoryAs<const char*>(
6204 c.name_shm_id, c.name_shm_offset, name_size);
6205 if (!name) {
6206 return error::kOutOfBounds;
6207 }
6208 String name_str(name, name_size);
6209 return GetAttribLocationHelper(
6210 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6211}
6212
[email protected]f7a64ee2010-02-01 22:24:146213error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196214 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:546215 uint32 name_size = c.data_size;
6216 const char* name = GetImmediateDataAs<const char*>(
6217 c, name_size, immediate_data_size);
6218 if (!name) {
6219 return error::kOutOfBounds;
6220 }
6221 String name_str(name, name_size);
6222 return GetAttribLocationHelper(
6223 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6224}
6225
6226error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
6227 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
6228 Bucket* bucket = GetBucket(c.name_bucket_id);
6229 if (!bucket) {
6230 return error::kInvalidArguments;
6231 }
6232 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186233 if (!bucket->GetAsString(&name_str)) {
6234 return error::kInvalidArguments;
6235 }
[email protected]558847a2010-03-24 07:02:546236 return GetAttribLocationHelper(
6237 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6238}
6239
6240error::Error GLES2DecoderImpl::GetUniformLocationHelper(
6241 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6242 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576243 if (!StringIsValidForGLES(name_str.c_str())) {
6244 SetGLError(GL_INVALID_VALUE, "glGetUniformLocation: Invalid character");
6245 return error::kNoError;
6246 }
[email protected]6b8cf1a2010-05-06 16:13:586247 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6248 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:036249 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146250 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196251 }
[email protected]ae51d192010-04-27 00:48:036252 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:296253 SetGLError(GL_INVALID_OPERATION,
6254 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:256255 return error::kNoError;
6256 }
[email protected]b9849abf2009-11-25 19:13:196257 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546258 location_shm_id, location_shm_offset, sizeof(GLint));
6259 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146260 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196261 }
[email protected]558847a2010-03-24 07:02:546262 // Require the client to init this incase the context is lost an we are no
6263 // longer executing commands.
6264 if (*location != -1) {
6265 return error::kGenericError;
6266 }
[email protected]5d4c6b22012-02-07 08:22:286267 *location = program_manager()->SwizzleLocation(
[email protected]1b0a6752012-02-22 03:44:126268 info->GetUniformFakeLocation(name_str));
[email protected]f7a64ee2010-02-01 22:24:146269 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196270}
6271
[email protected]f7a64ee2010-02-01 22:24:146272error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:196273 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:196274 uint32 name_size = c.data_size;
6275 const char* name = GetSharedMemoryAs<const char*>(
6276 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:546277 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146278 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196279 }
6280 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546281 return GetUniformLocationHelper(
6282 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196283}
6284
[email protected]f7a64ee2010-02-01 22:24:146285error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196286 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:196287 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:306288 const char* name = GetImmediateDataAs<const char*>(
6289 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:546290 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146291 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196292 }
6293 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546294 return GetUniformLocationHelper(
6295 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6296}
6297
6298error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
6299 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
6300 Bucket* bucket = GetBucket(c.name_bucket_id);
6301 if (!bucket) {
6302 return error::kInvalidArguments;
6303 }
6304 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186305 if (!bucket->GetAsString(&name_str)) {
6306 return error::kInvalidArguments;
6307 }
[email protected]558847a2010-03-24 07:02:546308 return GetUniformLocationHelper(
6309 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196310}
6311
[email protected]ddd968b82010-03-02 00:44:296312error::Error GLES2DecoderImpl::HandleGetString(
6313 uint32 immediate_data_size, const gles2::GetString& c) {
6314 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:056315 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:296316 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:296317 return error::kNoError;
6318 }
[email protected]1958e0e2010-04-22 05:17:156319 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
6320 const char* str = NULL;
[email protected]f0d74742011-10-03 16:31:046321 std::string extensions;
[email protected]1958e0e2010-04-22 05:17:156322 switch (name) {
6323 case GL_VERSION:
6324 str = "OpenGL ES 2.0 Chromium";
6325 break;
6326 case GL_SHADING_LANGUAGE_VERSION:
6327 str = "OpenGL ES GLSL ES 1.0 Chromium";
6328 break;
6329 case GL_EXTENSIONS:
[email protected]f0d74742011-10-03 16:31:046330 {
6331 // For WebGL contexts, strip out the OES derivatives extension if it has
6332 // not been enabled.
6333 if (force_webgl_glsl_validation_ &&
6334 !derivatives_explicitly_enabled_) {
6335 extensions = feature_info_->extensions();
6336 size_t offset = extensions.find(kOESDerivativeExtension);
6337 if (std::string::npos != offset) {
6338 extensions.replace(offset,
6339 offset + arraysize(kOESDerivativeExtension),
6340 std::string());
6341 }
6342 str = extensions.c_str();
6343 } else {
6344 str = feature_info_->extensions().c_str();
6345 }
[email protected]f0d74742011-10-03 16:31:046346 }
[email protected]1958e0e2010-04-22 05:17:156347 break;
6348 default:
6349 str = gl_str;
6350 break;
6351 }
[email protected]ddd968b82010-03-02 00:44:296352 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:156353 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:296354 return error::kNoError;
6355}
6356
[email protected]0c86dbf2010-03-05 08:14:116357void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:156358 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:056359 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296360 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
6361 return;
6362 }
[email protected]9438b012010-06-15 22:55:056363 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:296364 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:116365 return;
[email protected]3b6ec202010-03-05 05:16:236366 }
6367 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:296368 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:286369 return;
[email protected]3b6ec202010-03-05 05:16:236370 }
6371 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
6372 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296373 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:286374 return;
[email protected]3b6ec202010-03-05 05:16:236375 }
6376 // Clear the buffer to 0 if no initial data was passed in.
6377 scoped_array<int8> zero;
6378 if (!data) {
6379 zero.reset(new int8[size]);
6380 memset(zero.get(), 0, size);
6381 data = zero.get();
6382 }
[email protected]473c01ccb2011-06-07 01:33:306383
6384 if (!bufferdata_faster_than_buffersubdata_ &&
6385 size == info->size() && usage == info->usage()) {
6386 glBufferSubData(target, 0, size, data);
6387 info->SetRange(0, size, data);
6388 return;
6389 }
6390
[email protected]3b6ec202010-03-05 05:16:236391 CopyRealGLErrorsToWrapper();
6392 glBufferData(target, size, data, usage);
[email protected]1002c2d2011-06-28 22:39:046393 GLenum error = PeekGLError();
6394 if (error == GL_NO_ERROR) {
[email protected]473c01ccb2011-06-07 01:33:306395 buffer_manager()->SetInfo(info, size, usage);
[email protected]0c86dbf2010-03-05 08:14:116396 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:236397 }
[email protected]0c86dbf2010-03-05 08:14:116398}
6399
6400error::Error GLES2DecoderImpl::HandleBufferData(
6401 uint32 immediate_data_size, const gles2::BufferData& c) {
6402 GLenum target = static_cast<GLenum>(c.target);
6403 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
6404 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6405 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6406 GLenum usage = static_cast<GLenum>(c.usage);
6407 const void* data = NULL;
6408 if (data_shm_id != 0 || data_shm_offset != 0) {
6409 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
6410 if (!data) {
6411 return error::kOutOfBounds;
6412 }
6413 }
6414 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:146415 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196416}
6417
[email protected]f7a64ee2010-02-01 22:24:146418error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:196419 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
6420 GLenum target = static_cast<GLenum>(c.target);
6421 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:306422 const void* data = GetImmediateDataAs<const void*>(
6423 c, size, immediate_data_size);
6424 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146425 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:306426 }
[email protected]b9849abf2009-11-25 19:13:196427 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:116428 DoBufferData(target, size, data, usage);
6429 return error::kNoError;
6430}
6431
6432void GLES2DecoderImpl::DoBufferSubData(
6433 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:506434 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476435 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296436 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:286437 return;
[email protected]a93bb842010-02-16 23:03:476438 }
[email protected]0c86dbf2010-03-05 08:14:116439 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:296440 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]473c01ccb2011-06-07 01:33:306441 return;
[email protected]07f54fcc2009-12-22 02:46:306442 }
[email protected]473c01ccb2011-06-07 01:33:306443 if (bufferdata_faster_than_buffersubdata_ &&
6444 offset == 0 && size == info->size()) {
6445 glBufferData(target, size, data, info->usage());
6446 return;
6447 }
6448 glBufferSubData(target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:196449}
6450
[email protected]0d6bfdc2011-11-02 01:32:206451bool GLES2DecoderImpl::ClearLevel(
6452 unsigned service_id,
6453 unsigned bind_target,
6454 unsigned target,
6455 int level,
6456 unsigned format,
6457 unsigned type,
6458 int width,
[email protected]4502e6492011-12-14 19:39:156459 int height,
6460 bool is_texture_immutable) {
[email protected]0d6bfdc2011-11-02 01:32:206461 // Assumes the size has already been checked.
6462 uint32 pixels_size = 0;
6463 if (!GLES2Util::ComputeImageDataSize(
6464 width, height, format, type, unpack_alignment_, &pixels_size)) {
6465 return false;
6466 }
6467 scoped_array<char> zero(new char[pixels_size]);
6468 memset(zero.get(), 0, pixels_size);
6469 glBindTexture(bind_target, service_id);
[email protected]4502e6492011-12-14 19:39:156470 if (is_texture_immutable) {
6471 glTexSubImage2D(
6472 target, level, 0, 0, width, height, format, type, zero.get());
6473 } else {
6474 WrappedTexImage2D(
6475 target, level, format, width, height, 0, format, type, zero.get());
6476 }
[email protected]0d6bfdc2011-11-02 01:32:206477 TextureManager::TextureInfo* info = GetTextureInfoForTarget(bind_target);
6478 glBindTexture(bind_target, info ? info->service_id() : 0);
6479 return true;
6480}
6481
[email protected]a93bb842010-02-16 23:03:476482error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
6483 GLenum target,
6484 GLint level,
6485 GLenum internal_format,
6486 GLsizei width,
6487 GLsizei height,
6488 GLint border,
6489 GLsizei image_size,
6490 const void* data) {
[email protected]a93bb842010-02-16 23:03:476491 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:056492 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296493 SetGLError(GL_INVALID_ENUM,
6494 "glCompressedTexImage2D: target GL_INVALID_ENUM");
6495 return error::kNoError;
6496 }
[email protected]9438b012010-06-15 22:55:056497 if (!validators_->compressed_texture_format.IsValid(
6498 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296499 SetGLError(GL_INVALID_ENUM,
6500 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:476501 return error::kNoError;
6502 }
[email protected]80eb6b52012-01-19 00:14:416503 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476504 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296505 SetGLError(GL_INVALID_VALUE,
6506 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476507 return error::kNoError;
6508 }
[email protected]3916c97e2010-02-25 03:20:506509 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476510 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296511 SetGLError(GL_INVALID_VALUE,
6512 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:476513 return error::kNoError;
6514 }
[email protected]97dc7cbe2011-12-06 17:26:176515 if (info->IsImmutable()) {
6516 SetGLError(GL_INVALID_OPERATION,
6517 "glCompressedTexImage2D: texture is immutable");
6518 return error::kNoError;
6519 }
[email protected]968351b2011-12-20 08:26:516520
6521 if (info->IsAttachedToFramebuffer()) {
6522 state_dirty_ = true;
6523 // TODO(gman): If textures tracked which framebuffers they were attached to
6524 // we could just mark those framebuffers as not complete.
6525 framebuffer_manager()->IncFramebufferStateChangeCount();
6526 }
6527
[email protected]a93bb842010-02-16 23:03:476528 scoped_array<int8> zero;
6529 if (!data) {
6530 zero.reset(new int8[image_size]);
6531 memset(zero.get(), 0, image_size);
6532 data = zero.get();
6533 }
[email protected]cadde4a2010-07-31 17:10:436534 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:476535 glCompressedTexImage2D(
6536 target, level, internal_format, width, height, border, image_size, data);
[email protected]1002c2d2011-06-28 22:39:046537 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436538 if (error == GL_NO_ERROR) {
6539 texture_manager()->SetLevelInfo(
[email protected]0d6bfdc2011-11-02 01:32:206540 info, target, level, internal_format, width, height, 1, border, 0, 0,
6541 true);
[email protected]cadde4a2010-07-31 17:10:436542 }
[email protected]a93bb842010-02-16 23:03:476543 return error::kNoError;
6544}
6545
[email protected]f7a64ee2010-02-01 22:24:146546error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196547 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
6548 GLenum target = static_cast<GLenum>(c.target);
6549 GLint level = static_cast<GLint>(c.level);
6550 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6551 GLsizei width = static_cast<GLsizei>(c.width);
6552 GLsizei height = static_cast<GLsizei>(c.height);
6553 GLint border = static_cast<GLint>(c.border);
6554 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
6555 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6556 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6557 const void* data = NULL;
6558 if (data_shm_id != 0 || data_shm_offset != 0) {
6559 data = GetSharedMemoryAs<const void*>(
6560 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:466561 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146562 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196563 }
6564 }
[email protected]a93bb842010-02-16 23:03:476565 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196566 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:196567}
6568
[email protected]f7a64ee2010-02-01 22:24:146569error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:196570 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
6571 GLenum target = static_cast<GLenum>(c.target);
6572 GLint level = static_cast<GLint>(c.level);
6573 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6574 GLsizei width = static_cast<GLsizei>(c.width);
6575 GLsizei height = static_cast<GLsizei>(c.height);
6576 GLint border = static_cast<GLint>(c.border);
6577 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:306578 const void* data = GetImmediateDataAs<const void*>(
6579 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466580 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146581 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466582 }
[email protected]a93bb842010-02-16 23:03:476583 return DoCompressedTexImage2D(
6584 target, level, internal_format, width, height, border, image_size, data);
6585}
6586
[email protected]b6140d02010-05-17 14:47:166587error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
6588 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
6589 GLenum target = static_cast<GLenum>(c.target);
6590 GLint level = static_cast<GLint>(c.level);
6591 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6592 GLsizei width = static_cast<GLsizei>(c.width);
6593 GLsizei height = static_cast<GLsizei>(c.height);
6594 GLint border = static_cast<GLint>(c.border);
6595 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:286596 if (!bucket) {
6597 return error::kInvalidArguments;
6598 }
6599 uint32 data_size = bucket->size();
6600 GLsizei imageSize = data_size;
6601 const void* data = bucket->GetData(0, data_size);
6602 if (!data) {
6603 return error::kInvalidArguments;
6604 }
[email protected]b6140d02010-05-17 14:47:166605 return DoCompressedTexImage2D(
6606 target, level, internal_format, width, height, border,
[email protected]12f93d82011-10-17 21:16:286607 imageSize, data);
[email protected]b6140d02010-05-17 14:47:166608}
6609
6610error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
6611 uint32 immediate_data_size,
6612 const gles2::CompressedTexSubImage2DBucket& c) {
6613 GLenum target = static_cast<GLenum>(c.target);
6614 GLint level = static_cast<GLint>(c.level);
6615 GLint xoffset = static_cast<GLint>(c.xoffset);
6616 GLint yoffset = static_cast<GLint>(c.yoffset);
6617 GLsizei width = static_cast<GLsizei>(c.width);
6618 GLsizei height = static_cast<GLsizei>(c.height);
6619 GLenum format = static_cast<GLenum>(c.format);
6620 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:286621 if (!bucket) {
6622 return error::kInvalidArguments;
6623 }
[email protected]b6140d02010-05-17 14:47:166624 uint32 data_size = bucket->size();
6625 GLsizei imageSize = data_size;
6626 const void* data = bucket->GetData(0, data_size);
[email protected]12f93d82011-10-17 21:16:286627 if (!data) {
6628 return error::kInvalidArguments;
6629 }
[email protected]9438b012010-06-15 22:55:056630 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:166631 SetGLError(
6632 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
6633 return error::kNoError;
6634 }
[email protected]9438b012010-06-15 22:55:056635 if (!validators_->compressed_texture_format.IsValid(format)) {
6636 SetGLError(GL_INVALID_ENUM,
6637 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
6638 return error::kNoError;
6639 }
[email protected]b6140d02010-05-17 14:47:166640 if (width < 0) {
6641 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
6642 return error::kNoError;
6643 }
6644 if (height < 0) {
6645 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
6646 return error::kNoError;
6647 }
6648 if (imageSize < 0) {
6649 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
6650 return error::kNoError;
6651 }
[email protected]cadde4a2010-07-31 17:10:436652 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:166653 target, level, xoffset, yoffset, width, height, format, imageSize, data);
6654 return error::kNoError;
6655}
6656
[email protected]a93bb842010-02-16 23:03:476657error::Error GLES2DecoderImpl::DoTexImage2D(
6658 GLenum target,
6659 GLint level,
6660 GLenum internal_format,
6661 GLsizei width,
6662 GLsizei height,
6663 GLint border,
6664 GLenum format,
6665 GLenum type,
6666 const void* pixels,
6667 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:056668 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296669 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
6670 return error::kNoError;
6671 }
[email protected]9438b012010-06-15 22:55:056672 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296673 SetGLError(GL_INVALID_ENUM,
6674 "glTexImage2D: internal_format GL_INVALID_ENUM");
6675 return error::kNoError;
6676 }
[email protected]9438b012010-06-15 22:55:056677 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:296678 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
6679 return error::kNoError;
6680 }
[email protected]9438b012010-06-15 22:55:056681 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:296682 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:146683 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196684 }
[email protected]7b92c412010-07-20 17:48:256685 if (format != internal_format) {
6686 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
6687 return error::kNoError;
6688 }
[email protected]80eb6b52012-01-19 00:14:416689 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476690 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296691 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476692 return error::kNoError;
6693 }
[email protected]3916c97e2010-02-25 03:20:506694 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476695 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296696 SetGLError(GL_INVALID_OPERATION,
6697 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:476698 return error::kNoError;
6699 }
[email protected]0226c112011-07-22 03:25:076700
[email protected]97dc7cbe2011-12-06 17:26:176701 if (info->IsImmutable()) {
6702 SetGLError(GL_INVALID_OPERATION,
6703 "glTexImage2D: texture is immutable");
6704 return error::kNoError;
6705 }
6706
[email protected]0226c112011-07-22 03:25:076707 GLsizei tex_width = 0;
6708 GLsizei tex_height = 0;
6709 GLenum tex_type = 0;
6710 GLenum tex_format = 0;
6711 bool level_is_same =
6712 info->GetLevelSize(target, level, &tex_width, &tex_height) &&
6713 info->GetLevelType(target, level, &tex_type, &tex_format) &&
6714 width == tex_width && height == tex_height &&
6715 type == tex_type && format == tex_format;
6716
6717 if (level_is_same && !pixels) {
[email protected]1bed6222011-12-21 11:21:396718 // Just set the level info but mark the texture as uncleared.
6719 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416720 info,
[email protected]1bed6222011-12-21 11:21:396721 target, level, internal_format, width, height, 1, border, format, type,
6722 false);
[email protected]ea72ed222011-08-17 18:58:436723 tex_image_2d_failed_ = false;
[email protected]0226c112011-07-22 03:25:076724 return error::kNoError;
6725 }
6726
[email protected]297ca1c2011-06-20 23:08:466727 if (info->IsAttachedToFramebuffer()) {
6728 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:516729 // TODO(gman): If textures tracked which framebuffers they were attached to
6730 // we could just mark those framebuffers as not complete.
6731 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:466732 }
6733
[email protected]1bed6222011-12-21 11:21:396734 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same && pixels) {
[email protected]0226c112011-07-22 03:25:076735 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
[email protected]57edfdad2012-02-07 04:57:156736 texture_manager()->SetLevelCleared(info, target, level);
[email protected]0226c112011-07-22 03:25:076737 tex_image_2d_failed_ = false;
6738 return error::kNoError;
[email protected]7488d962010-07-16 02:41:586739 }
[email protected]876f6fee2010-08-02 23:10:326740
[email protected]cadde4a2010-07-31 17:10:436741 CopyRealGLErrorsToWrapper();
[email protected]473c01ccb2011-06-07 01:33:306742 WrappedTexImage2D(
6743 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476744 pixels);
[email protected]1002c2d2011-06-28 22:39:046745 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436746 if (error == GL_NO_ERROR) {
[email protected]0d6bfdc2011-11-02 01:32:206747 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416748 info,
[email protected]0d6bfdc2011-11-02 01:32:206749 target, level, internal_format, width, height, 1, border, format, type,
6750 pixels != NULL);
[email protected]b493ee622011-04-13 23:52:006751 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:436752 }
[email protected]f7a64ee2010-02-01 22:24:146753 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196754}
6755
[email protected]f7a64ee2010-02-01 22:24:146756error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196757 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]366ae242011-05-10 02:23:586758 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:006759 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:196760 GLenum target = static_cast<GLenum>(c.target);
6761 GLint level = static_cast<GLint>(c.level);
6762 GLint internal_format = static_cast<GLint>(c.internalformat);
6763 GLsizei width = static_cast<GLsizei>(c.width);
6764 GLsizei height = static_cast<GLsizei>(c.height);
6765 GLint border = static_cast<GLint>(c.border);
6766 GLenum format = static_cast<GLenum>(c.format);
6767 GLenum type = static_cast<GLenum>(c.type);
6768 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
6769 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:186770 uint32 pixels_size;
6771 if (!GLES2Util::ComputeImageDataSize(
6772 width, height, format, type, unpack_alignment_, &pixels_size)) {
6773 return error::kOutOfBounds;
6774 }
[email protected]b9849abf2009-11-25 19:13:196775 const void* pixels = NULL;
6776 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
6777 pixels = GetSharedMemoryAs<const void*>(
6778 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:466779 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146780 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196781 }
6782 }
[email protected]a93bb842010-02-16 23:03:476783 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196784 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476785 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:196786}
6787
[email protected]f7a64ee2010-02-01 22:24:146788error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:196789 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
6790 GLenum target = static_cast<GLenum>(c.target);
6791 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:466792 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:196793 GLsizei width = static_cast<GLsizei>(c.width);
6794 GLsizei height = static_cast<GLsizei>(c.height);
6795 GLint border = static_cast<GLint>(c.border);
6796 GLenum format = static_cast<GLenum>(c.format);
6797 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:186798 uint32 size;
6799 if (!GLES2Util::ComputeImageDataSize(
6800 width, height, format, type, unpack_alignment_, &size)) {
6801 return error::kOutOfBounds;
6802 }
[email protected]07f54fcc2009-12-22 02:46:306803 const void* pixels = GetImmediateDataAs<const void*>(
6804 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466805 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146806 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466807 }
[email protected]a93bb842010-02-16 23:03:476808 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:466809 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476810 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:146811 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326812}
6813
[email protected]cadde4a2010-07-31 17:10:436814void GLES2DecoderImpl::DoCompressedTexSubImage2D(
6815 GLenum target,
6816 GLint level,
6817 GLint xoffset,
6818 GLint yoffset,
6819 GLsizei width,
6820 GLsizei height,
6821 GLenum format,
6822 GLsizei image_size,
6823 const void * data) {
6824 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6825 if (!info) {
6826 SetGLError(GL_INVALID_OPERATION,
6827 "glCompressedTexSubImage2D: unknown texture for target");
6828 return;
6829 }
6830 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:526831 GLenum internal_format = 0;
6832 if (!info->GetLevelType(target, level, &type, &internal_format)) {
6833 SetGLError(
6834 GL_INVALID_OPERATION,
[email protected]4502e6492011-12-14 19:39:156835 "glCompressedTexSubImage2D: level does not exist.");
[email protected]df6cf1ad2011-01-29 01:20:526836 return;
6837 }
6838 if (internal_format != format) {
6839 SetGLError(
6840 GL_INVALID_OPERATION,
[email protected]4502e6492011-12-14 19:39:156841 "glCompressedTexSubImage2D: format does not match internal format.");
[email protected]df6cf1ad2011-01-29 01:20:526842 return;
6843 }
6844 if (!info->ValidForTexture(
6845 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:436846 SetGLError(GL_INVALID_VALUE,
[email protected]4502e6492011-12-14 19:39:156847 "glCompressedTexSubImage2D: bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:436848 return;
6849 }
[email protected]0d6bfdc2011-11-02 01:32:206850 // Note: There is no need to deal with texture cleared tracking here
6851 // because the validation above means you can only get here if the level
6852 // is already a matching compressed format and in that case
6853 // CompressedTexImage2D already cleared the texture.
[email protected]cadde4a2010-07-31 17:10:436854 glCompressedTexSubImage2D(
6855 target, level, xoffset, yoffset, width, height, format, image_size, data);
6856}
6857
[email protected]6e288612010-12-21 20:45:036858static void Clip(
6859 GLint start, GLint range, GLint sourceRange,
6860 GLint* out_start, GLint* out_range) {
6861 DCHECK(out_start);
6862 DCHECK(out_range);
6863 if (start < 0) {
6864 range += start;
6865 start = 0;
6866 }
6867 GLint end = start + range;
6868 if (end > sourceRange) {
6869 range -= end - sourceRange;
6870 }
6871 *out_start = start;
6872 *out_range = range;
6873}
6874
[email protected]cadde4a2010-07-31 17:10:436875void GLES2DecoderImpl::DoCopyTexImage2D(
6876 GLenum target,
6877 GLint level,
6878 GLenum internal_format,
6879 GLint x,
6880 GLint y,
6881 GLsizei width,
6882 GLsizei height,
6883 GLint border) {
6884 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6885 if (!info) {
6886 SetGLError(GL_INVALID_OPERATION,
6887 "glCopyTexImage2D: unknown texture for target");
6888 return;
6889 }
[email protected]97dc7cbe2011-12-06 17:26:176890 if (info->IsImmutable()) {
6891 SetGLError(GL_INVALID_OPERATION,
6892 "glCopyTexImage2D: texture is immutable");
6893 }
[email protected]80eb6b52012-01-19 00:14:416894 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:186895 border != 0) {
6896 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
6897 return;
6898 }
6899
[email protected]9edc6b22010-12-23 02:00:266900 // Check we have compatible formats.
6901 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6902 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6903 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
6904
6905 if ((channels_needed & channels_exist) != channels_needed) {
6906 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
6907 return;
6908 }
6909
[email protected]a0b78dc2011-11-11 10:43:106910 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
6911 return;
6912 }
6913
[email protected]cadde4a2010-07-31 17:10:436914 CopyRealGLErrorsToWrapper();
[email protected]de26b3c2011-08-03 21:54:276915 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:036916 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:266917
[email protected]297ca1c2011-06-20 23:08:466918 if (info->IsAttachedToFramebuffer()) {
6919 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:516920 // TODO(gman): If textures tracked which framebuffers they were attached to
6921 // we could just mark those framebuffers as not complete.
6922 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:466923 }
6924
[email protected]9edc6b22010-12-23 02:00:266925 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:036926 GLint copyX = 0;
6927 GLint copyY = 0;
6928 GLint copyWidth = 0;
6929 GLint copyHeight = 0;
6930 Clip(x, width, size.width(), &copyX, &copyWidth);
6931 Clip(y, height, size.height(), &copyY, &copyHeight);
6932
6933 if (copyX != x ||
6934 copyY != y ||
6935 copyWidth != width ||
6936 copyHeight != height) {
6937 // some part was clipped so clear the texture.
[email protected]0d6bfdc2011-11-02 01:32:206938 if (!ClearLevel(
6939 info->service_id(), info->target(),
[email protected]4502e6492011-12-14 19:39:156940 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
6941 info->IsImmutable())) {
[email protected]0d6bfdc2011-11-02 01:32:206942 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexImage2D: dimensions too big");
[email protected]6e288612010-12-21 20:45:036943 return;
6944 }
[email protected]6e288612010-12-21 20:45:036945 if (copyHeight > 0 && copyWidth > 0) {
6946 GLint dx = copyX - x;
6947 GLint dy = copyY - y;
6948 GLint destX = dx;
6949 GLint destY = dy;
6950 glCopyTexSubImage2D(target, level,
6951 destX, destY, copyX, copyY,
6952 copyWidth, copyHeight);
6953 }
6954 } else {
6955 glCopyTexImage2D(target, level, internal_format,
6956 copyX, copyY, copyWidth, copyHeight, border);
6957 }
[email protected]1002c2d2011-06-28 22:39:046958 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436959 if (error == GL_NO_ERROR) {
6960 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416961 info, target, level, internal_format, width, height, 1,
[email protected]0d6bfdc2011-11-02 01:32:206962 border, internal_format, GL_UNSIGNED_BYTE, true);
[email protected]cadde4a2010-07-31 17:10:436963 }
6964}
6965
6966void GLES2DecoderImpl::DoCopyTexSubImage2D(
6967 GLenum target,
6968 GLint level,
6969 GLint xoffset,
6970 GLint yoffset,
6971 GLint x,
6972 GLint y,
6973 GLsizei width,
6974 GLsizei height) {
6975 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6976 if (!info) {
6977 SetGLError(GL_INVALID_OPERATION,
6978 "glCopyTexSubImage2D: unknown texture for target");
6979 return;
6980 }
6981 GLenum type = 0;
6982 GLenum format = 0;
6983 if (!info->GetLevelType(target, level, &type, &format) ||
6984 !info->ValidForTexture(
6985 target, level, xoffset, yoffset, width, height, format, type)) {
6986 SetGLError(GL_INVALID_VALUE,
6987 "glCopyTexSubImage2D: bad dimensions.");
6988 return;
6989 }
[email protected]9edc6b22010-12-23 02:00:266990
6991 // Check we have compatible formats.
6992 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6993 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6994 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
6995
6996 if ((channels_needed & channels_exist) != channels_needed) {
6997 SetGLError(
6998 GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
6999 return;
7000 }
7001
[email protected]a0b78dc2011-11-11 10:43:107002 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
7003 return;
7004 }
7005
[email protected]de26b3c2011-08-03 21:54:277006 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:037007 gfx::Size size = GetBoundReadFrameBufferSize();
7008 GLint copyX = 0;
7009 GLint copyY = 0;
7010 GLint copyWidth = 0;
7011 GLint copyHeight = 0;
7012 Clip(x, width, size.width(), &copyX, &copyWidth);
7013 Clip(y, height, size.height(), &copyY, &copyHeight);
[email protected]0d6bfdc2011-11-02 01:32:207014
7015 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
7016 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D: dimensions too big");
7017 return;
7018 }
7019
[email protected]6e288612010-12-21 20:45:037020 if (copyX != x ||
7021 copyY != y ||
7022 copyWidth != width ||
7023 copyHeight != height) {
[email protected]0d6bfdc2011-11-02 01:32:207024 // some part was clipped so clear the sub rect.
[email protected]6e288612010-12-21 20:45:037025 uint32 pixels_size = 0;
7026 if (!GLES2Util::ComputeImageDataSize(
7027 width, height, format, type, unpack_alignment_, &pixels_size)) {
7028 SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large");
7029 return;
7030 }
7031 scoped_array<char> zero(new char[pixels_size]);
7032 memset(zero.get(), 0, pixels_size);
7033 glTexSubImage2D(
7034 target, level, xoffset, yoffset, width, height,
7035 format, type, zero.get());
7036 }
[email protected]0d6bfdc2011-11-02 01:32:207037
[email protected]6e288612010-12-21 20:45:037038 if (copyHeight > 0 && copyWidth > 0) {
7039 GLint dx = copyX - x;
7040 GLint dy = copyY - y;
7041 GLint destX = xoffset + dx;
7042 GLint destY = yoffset + dy;
7043 glCopyTexSubImage2D(target, level,
7044 destX, destY, copyX, copyY,
7045 copyWidth, copyHeight);
7046 }
[email protected]cadde4a2010-07-31 17:10:437047}
7048
7049void GLES2DecoderImpl::DoTexSubImage2D(
7050 GLenum target,
7051 GLint level,
7052 GLint xoffset,
7053 GLint yoffset,
7054 GLsizei width,
7055 GLsizei height,
7056 GLenum format,
7057 GLenum type,
7058 const void * data) {
7059 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7060 if (!info) {
7061 SetGLError(GL_INVALID_OPERATION,
7062 "glTexSubImage2D: unknown texture for target");
7063 return;
7064 }
[email protected]df6cf1ad2011-01-29 01:20:527065 GLenum current_type = 0;
7066 GLenum internal_format = 0;
7067 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
7068 SetGLError(
7069 GL_INVALID_OPERATION,
7070 "glTexSubImage2D: level does not exist.");
7071 return;
7072 }
7073 if (format != internal_format) {
7074 SetGLError(GL_INVALID_OPERATION,
7075 "glTexSubImage2D: format does not match internal format.");
7076 return;
7077 }
7078 if (type != current_type) {
7079 SetGLError(GL_INVALID_OPERATION,
7080 "glTexSubImage2D: type does not match type of texture.");
7081 return;
7082 }
7083
[email protected]cadde4a2010-07-31 17:10:437084 if (!info->ValidForTexture(
7085 target, level, xoffset, yoffset, width, height, format, type)) {
7086 SetGLError(GL_INVALID_VALUE,
7087 "glTexSubImage2D: bad dimensions.");
7088 return;
7089 }
[email protected]473c01ccb2011-06-07 01:33:307090
[email protected]4502e6492011-12-14 19:39:157091 GLsizei tex_width = 0;
7092 GLsizei tex_height = 0;
7093 bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height);
7094 DCHECK(ok);
7095 if (xoffset != 0 || yoffset != 0 ||
7096 width != tex_width || height != tex_height) {
7097 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
7098 SetGLError(GL_OUT_OF_MEMORY, "glTexSubImage2D: dimensions too big");
[email protected]473c01ccb2011-06-07 01:33:307099 return;
7100 }
[email protected]4502e6492011-12-14 19:39:157101 glTexSubImage2D(
7102 target, level, xoffset, yoffset, width, height, format, type, data);
[email protected]0d6bfdc2011-11-02 01:32:207103 return;
7104 }
[email protected]4502e6492011-12-14 19:39:157105
7106 if (teximage2d_faster_than_texsubimage2d_ && !info->IsImmutable()) {
7107 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
7108 // same as internal_foramt. If that changes we'll need to look them up.
7109 WrappedTexImage2D(
7110 target, level, format, width, height, 0, format, type, data);
7111 } else {
7112 glTexSubImage2D(
7113 target, level, xoffset, yoffset, width, height, format, type, data);
7114 }
7115 texture_manager()->SetLevelCleared(info, target, level);
[email protected]cadde4a2010-07-31 17:10:437116}
7117
[email protected]b493ee622011-04-13 23:52:007118error::Error GLES2DecoderImpl::HandleTexSubImage2D(
7119 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]366ae242011-05-10 02:23:587120 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:007121 GLboolean internal = static_cast<GLboolean>(c.internal);
7122 if (internal == GL_TRUE && tex_image_2d_failed_)
7123 return error::kNoError;
7124
7125 GLenum target = static_cast<GLenum>(c.target);
7126 GLint level = static_cast<GLint>(c.level);
7127 GLint xoffset = static_cast<GLint>(c.xoffset);
7128 GLint yoffset = static_cast<GLint>(c.yoffset);
7129 GLsizei width = static_cast<GLsizei>(c.width);
7130 GLsizei height = static_cast<GLsizei>(c.height);
7131 GLenum format = static_cast<GLenum>(c.format);
7132 GLenum type = static_cast<GLenum>(c.type);
7133 uint32 data_size;
7134 if (!GLES2Util::ComputeImageDataSize(
7135 width, height, format, type, unpack_alignment_, &data_size)) {
7136 return error::kOutOfBounds;
7137 }
7138 const void* pixels = GetSharedMemoryAs<const void*>(
7139 c.pixels_shm_id, c.pixels_shm_offset, data_size);
7140 if (!validators_->texture_target.IsValid(target)) {
7141 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
7142 return error::kNoError;
7143 }
7144 if (width < 0) {
7145 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
7146 return error::kNoError;
7147 }
7148 if (height < 0) {
7149 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
7150 return error::kNoError;
7151 }
7152 if (!validators_->texture_format.IsValid(format)) {
7153 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
7154 return error::kNoError;
7155 }
7156 if (!validators_->pixel_type.IsValid(type)) {
7157 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
7158 return error::kNoError;
7159 }
7160 if (pixels == NULL) {
7161 return error::kOutOfBounds;
7162 }
7163 DoTexSubImage2D(
7164 target, level, xoffset, yoffset, width, height, format, type, pixels);
7165 return error::kNoError;
7166}
7167
7168error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
7169 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
7170 GLboolean internal = static_cast<GLboolean>(c.internal);
7171 if (internal == GL_TRUE && tex_image_2d_failed_)
7172 return error::kNoError;
7173
7174 GLenum target = static_cast<GLenum>(c.target);
7175 GLint level = static_cast<GLint>(c.level);
7176 GLint xoffset = static_cast<GLint>(c.xoffset);
7177 GLint yoffset = static_cast<GLint>(c.yoffset);
7178 GLsizei width = static_cast<GLsizei>(c.width);
7179 GLsizei height = static_cast<GLsizei>(c.height);
7180 GLenum format = static_cast<GLenum>(c.format);
7181 GLenum type = static_cast<GLenum>(c.type);
7182 uint32 data_size;
7183 if (!GLES2Util::ComputeImageDataSize(
7184 width, height, format, type, unpack_alignment_, &data_size)) {
7185 return error::kOutOfBounds;
7186 }
7187 const void* pixels = GetImmediateDataAs<const void*>(
7188 c, data_size, immediate_data_size);
7189 if (!validators_->texture_target.IsValid(target)) {
7190 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
7191 return error::kNoError;
7192 }
7193 if (width < 0) {
7194 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
7195 return error::kNoError;
7196 }
7197 if (height < 0) {
7198 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
7199 return error::kNoError;
7200 }
7201 if (!validators_->texture_format.IsValid(format)) {
7202 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
7203 return error::kNoError;
7204 }
7205 if (!validators_->pixel_type.IsValid(type)) {
7206 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
7207 return error::kNoError;
7208 }
7209 if (pixels == NULL) {
7210 return error::kOutOfBounds;
7211 }
7212 DoTexSubImage2D(
7213 target, level, xoffset, yoffset, width, height, format, type, pixels);
7214 return error::kNoError;
7215}
7216
[email protected]f7a64ee2010-02-01 22:24:147217error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:197218 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:367219 GLuint index = static_cast<GLuint>(c.index);
7220 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:257221 typedef gles2::GetVertexAttribPointerv::Result Result;
7222 Result* result = GetSharedMemoryAs<Result*>(
7223 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:367224 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:147225 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:367226 }
[email protected]07d0cc82010-02-17 04:51:407227 // Check that the client initialized the result.
7228 if (result->size != 0) {
7229 return error::kInvalidArguments;
7230 }
[email protected]9438b012010-06-15 22:55:057231 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:297232 SetGLError(GL_INVALID_ENUM,
7233 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:147234 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367235 }
[email protected]3916c97e2010-02-25 03:20:507236 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:297237 SetGLError(GL_INVALID_VALUE,
7238 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:147239 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367240 }
[email protected]0bfd9882010-02-05 23:02:257241 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:087242 *result->GetData() =
[email protected]3757a372012-01-19 05:20:447243 vertex_attrib_manager_->GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:147244 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327245}
7246
[email protected]f7b85372010-02-03 01:11:377247bool GLES2DecoderImpl::GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127248 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:377249 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:127250 error::Error* error, GLint* real_location,
7251 GLuint* service_id, void** result_pointer, GLenum* result_type) {
[email protected]939e7362010-05-13 20:49:107252 DCHECK(error);
7253 DCHECK(service_id);
7254 DCHECK(result_pointer);
7255 DCHECK(result_type);
[email protected]1b0a6752012-02-22 03:44:127256 DCHECK(real_location);
[email protected]f7b85372010-02-03 01:11:377257 *error = error::kNoError;
7258 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:257259 SizedResult<GLint>* result;
7260 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7261 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
7262 if (!result) {
[email protected]f7b85372010-02-03 01:11:377263 *error = error::kOutOfBounds;
7264 return false;
7265 }
[email protected]0bfd9882010-02-05 23:02:257266 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:377267 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:257268 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:587269 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7270 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:377271 if (!info) {
[email protected]ae51d192010-04-27 00:48:037272 return false;
7273 }
7274 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:377275 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:297276 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:377277 return false;
7278 }
[email protected]ae51d192010-04-27 00:48:037279 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:367280 GLint array_index = -1;
7281 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
[email protected]1b0a6752012-02-22 03:44:127282 info->GetUniformInfoByFakeLocation(
7283 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:367284 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:377285 // No such location.
[email protected]8eee29c2010-04-29 03:38:297286 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:377287 return false;
7288 }
[email protected]43c2f1f2011-03-25 18:35:367289 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:507290 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:377291 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:297292 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:377293 return false;
7294 }
[email protected]0bfd9882010-02-05 23:02:257295 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7296 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
7297 if (!result) {
[email protected]f7b85372010-02-03 01:11:377298 *error = error::kOutOfBounds;
7299 return false;
7300 }
[email protected]0bfd9882010-02-05 23:02:257301 result->size = size;
[email protected]939e7362010-05-13 20:49:107302 *result_type = type;
[email protected]f7b85372010-02-03 01:11:377303 return true;
7304}
7305
[email protected]f7a64ee2010-02-01 22:24:147306error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:197307 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:377308 GLuint program = c.program;
[email protected]1b0a6752012-02-22 03:44:127309 GLint fake_location = program_manager()->UnswizzleLocation(c.location);
[email protected]f7b85372010-02-03 01:11:377310 GLuint service_id;
[email protected]939e7362010-05-13 20:49:107311 GLenum result_type;
[email protected]1b0a6752012-02-22 03:44:127312 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:377313 Error error;
[email protected]0bfd9882010-02-05 23:02:257314 void* result;
[email protected]f7b85372010-02-03 01:11:377315 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127316 program, fake_location, c.params_shm_id, c.params_shm_offset,
7317 &error, &real_location, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:257318 glGetUniformiv(
[email protected]1b0a6752012-02-22 03:44:127319 service_id, real_location,
[email protected]0bfd9882010-02-05 23:02:257320 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:377321 }
7322 return error;
[email protected]96449d2c2009-11-25 00:01:327323}
7324
[email protected]f7a64ee2010-02-01 22:24:147325error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:197326 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:377327 GLuint program = c.program;
[email protected]1b0a6752012-02-22 03:44:127328 GLint fake_location = program_manager()->UnswizzleLocation(c.location);
[email protected]f7b85372010-02-03 01:11:377329 GLuint service_id;
[email protected]1b0a6752012-02-22 03:44:127330 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:377331 Error error;
[email protected]0bfd9882010-02-05 23:02:257332 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:107333 Result* result;
7334 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:377335 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127336 program, fake_location, c.params_shm_id, c.params_shm_offset,
7337 &error, &real_location, &service_id,
7338 reinterpret_cast<void**>(&result), &result_type)) {
[email protected]939e7362010-05-13 20:49:107339 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
7340 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
7341 GLsizei num_values = result->GetNumResults();
7342 scoped_array<GLint> temp(new GLint[num_values]);
[email protected]1b0a6752012-02-22 03:44:127343 glGetUniformiv(service_id, real_location, temp.get());
[email protected]939e7362010-05-13 20:49:107344 GLfloat* dst = result->GetData();
7345 for (GLsizei ii = 0; ii < num_values; ++ii) {
7346 dst[ii] = (temp[ii] != 0);
7347 }
7348 } else {
[email protected]1b0a6752012-02-22 03:44:127349 glGetUniformfv(service_id, real_location, result->GetData());
[email protected]939e7362010-05-13 20:49:107350 }
[email protected]f7b85372010-02-03 01:11:377351 }
7352 return error;
[email protected]96449d2c2009-11-25 00:01:327353}
7354
[email protected]f7a64ee2010-02-01 22:24:147355error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:197356 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:257357 GLenum shader_type = static_cast<GLenum>(c.shadertype);
7358 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
7359 typedef gles2::GetShaderPrecisionFormat::Result Result;
7360 Result* result = GetSharedMemoryAs<Result*>(
7361 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7362 if (!result) {
7363 return error::kOutOfBounds;
7364 }
[email protected]07d0cc82010-02-17 04:51:407365 // Check that the client initialized the result.
7366 if (result->success != 0) {
7367 return error::kInvalidArguments;
7368 }
[email protected]9438b012010-06-15 22:55:057369 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:297370 SetGLError(GL_INVALID_ENUM,
7371 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
7372 return error::kNoError;
7373 }
[email protected]9438b012010-06-15 22:55:057374 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:297375 SetGLError(GL_INVALID_ENUM,
7376 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
7377 return error::kNoError;
7378 }
7379
7380 result->success = 1; // true
7381 switch (precision_type) {
7382 case GL_LOW_INT:
7383 case GL_MEDIUM_INT:
7384 case GL_HIGH_INT:
7385 result->min_range = -31;
7386 result->max_range = 31;
7387 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:107388 break;
[email protected]8eee29c2010-04-29 03:38:297389 case GL_LOW_FLOAT:
7390 case GL_MEDIUM_FLOAT:
7391 case GL_HIGH_FLOAT:
7392 result->min_range = -62;
7393 result->max_range = 62;
7394 result->precision = -16;
7395 break;
7396 default:
7397 NOTREACHED();
7398 break;
[email protected]0bfd9882010-02-05 23:02:257399 }
[email protected]f7a64ee2010-02-01 22:24:147400 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327401}
7402
[email protected]f7a64ee2010-02-01 22:24:147403error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:197404 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:257405 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:587406 GLuint program = static_cast<GLuint>(c.program);
7407 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7408 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:037409 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257410 return error::kNoError;
7411 }
7412 typedef gles2::GetAttachedShaders::Result Result;
7413 uint32 max_count = Result::ComputeMaxResults(result_size);
7414 Result* result = GetSharedMemoryAs<Result*>(
7415 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
7416 if (!result) {
7417 return error::kOutOfBounds;
7418 }
[email protected]07d0cc82010-02-17 04:51:407419 // Check that the client initialized the result.
7420 if (result->size != 0) {
7421 return error::kInvalidArguments;
7422 }
[email protected]0bfd9882010-02-05 23:02:257423 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:037424 glGetAttachedShaders(
7425 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:257426 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:037427 if (!shader_manager()->GetClientId(result->GetData()[ii],
7428 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:257429 NOTREACHED();
7430 return error::kGenericError;
7431 }
7432 }
7433 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:147434 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327435}
7436
[email protected]f7a64ee2010-02-01 22:24:147437error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:197438 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:257439 GLuint program = c.program;
7440 GLuint index = c.index;
7441 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:257442 typedef gles2::GetActiveUniform::Result Result;
7443 Result* result = GetSharedMemoryAs<Result*>(
7444 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7445 if (!result) {
7446 return error::kOutOfBounds;
7447 }
[email protected]07d0cc82010-02-17 04:51:407448 // Check that the client initialized the result.
7449 if (result->success != 0) {
7450 return error::kInvalidArguments;
7451 }
[email protected]6b8cf1a2010-05-06 16:13:587452 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7453 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:037454 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257455 return error::kNoError;
7456 }
7457 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
7458 info->GetUniformInfo(index);
7459 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:297460 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:257461 return error::kNoError;
7462 }
7463 result->success = 1; // true.
7464 result->size = uniform_info->size;
7465 result->type = uniform_info->type;
7466 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297467 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:147468 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327469}
7470
[email protected]f7a64ee2010-02-01 22:24:147471error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:197472 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:257473 GLuint program = c.program;
7474 GLuint index = c.index;
7475 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:257476 typedef gles2::GetActiveAttrib::Result Result;
7477 Result* result = GetSharedMemoryAs<Result*>(
7478 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7479 if (!result) {
7480 return error::kOutOfBounds;
7481 }
[email protected]07d0cc82010-02-17 04:51:407482 // Check that the client initialized the result.
7483 if (result->success != 0) {
7484 return error::kInvalidArguments;
7485 }
[email protected]6b8cf1a2010-05-06 16:13:587486 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7487 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:037488 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257489 return error::kNoError;
7490 }
7491 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
7492 info->GetAttribInfo(index);
7493 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:297494 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:257495 return error::kNoError;
7496 }
7497 result->success = 1; // true.
7498 result->size = attrib_info->size;
7499 result->type = attrib_info->type;
7500 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297501 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:147502 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327503}
7504
[email protected]b273e432010-04-12 17:23:587505error::Error GLES2DecoderImpl::HandleShaderBinary(
7506 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
7507#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:297508 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:587509 return error::kNoError;
7510#else
7511 GLsizei n = static_cast<GLsizei>(c.n);
7512 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:297513 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:587514 return error::kNoError;
7515 }
7516 GLsizei length = static_cast<GLsizei>(c.length);
7517 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:297518 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:587519 return error::kNoError;
7520 }
7521 uint32 data_size;
7522 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
7523 return error::kOutOfBounds;
7524 }
7525 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
7526 c.shaders_shm_id, c.shaders_shm_offset, data_size);
7527 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
7528 const void* binary = GetSharedMemoryAs<const void*>(
7529 c.binary_shm_id, c.binary_shm_offset, length);
7530 if (shaders == NULL || binary == NULL) {
7531 return error::kOutOfBounds;
7532 }
7533 scoped_array<GLuint> service_ids(new GLuint[n]);
7534 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:037535 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
7536 if (!info) {
[email protected]8eee29c2010-04-29 03:38:297537 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:587538 return error::kNoError;
7539 }
[email protected]ae51d192010-04-27 00:48:037540 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:587541 }
7542 // TODO(gman): call glShaderBinary
7543 return error::kNoError;
7544#endif
7545}
7546
[email protected]6217d392010-03-25 22:08:357547error::Error GLES2DecoderImpl::HandleSwapBuffers(
7548 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:497549 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7550 int this_frame_number = frame_number_++;
[email protected]da151512011-11-11 23:27:387551 // TRACE_EVENT for gpu tests:
[email protected]529c6672012-01-04 02:18:267552 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers",
7553 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
7554 "width", (is_offscreen ? offscreen_size_.width() :
7555 surface_->GetSize().width()));
[email protected]64ace852011-05-19 21:49:497556 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
7557 "offscreen", is_offscreen,
7558 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:357559 // If offscreen then don't actually SwapBuffers to the display. Just copy
7560 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:497561 if (is_offscreen) {
[email protected]1fb8c482011-08-31 01:01:537562 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
7563 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
7564 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
7565 // fix this.
7566 if (needs_mac_nvidia_driver_workaround_) {
7567 offscreen_saved_frame_buffer_->Create();
7568 glFinish();
7569 }
7570
7571 // Allocate the offscreen saved color texture.
7572 DCHECK(offscreen_saved_color_format_);
7573 offscreen_saved_color_texture_->AllocateStorage(
7574 offscreen_size_, offscreen_saved_color_format_);
[email protected]1078f912011-12-23 13:12:147575 UpdateBackbufferMemoryAccounting();
[email protected]1fb8c482011-08-31 01:01:537576
7577 offscreen_saved_frame_buffer_->AttachRenderTexture(
7578 offscreen_saved_color_texture_.get());
7579 if (offscreen_saved_frame_buffer_->CheckStatus() !=
7580 GL_FRAMEBUFFER_COMPLETE) {
7581 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
7582 << "because offscreen saved FBO was incomplete.";
7583 return error::kLostContext;
7584 }
7585
[email protected]1fb8c482011-08-31 01:01:537586 // Clear the offscreen color texture.
7587 // TODO(piman): Is this still necessary?
7588 {
7589 ScopedFrameBufferBinder binder(this,
7590 offscreen_saved_frame_buffer_->id());
7591 glClearColor(0, 0, 0, 0);
7592 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
7593 glDisable(GL_SCISSOR_TEST);
7594 glClear(GL_COLOR_BUFFER_BIT);
7595 RestoreClearState();
7596 }
7597
7598 UpdateParentTextureInfo();
7599 }
7600
[email protected]6217d392010-03-25 22:08:357601 ScopedGLErrorSuppressor suppressor(this);
7602
[email protected]34ff8b0c2010-10-01 20:06:027603 if (IsOffscreenBufferMultisampled()) {
[email protected]51411e32012-01-19 20:21:137604 // For multisampled buffers, resolve the frame buffer.
[email protected]de26b3c2011-08-03 21:54:277605 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]89d6ed02011-04-20 00:23:237606 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:487607 } else {
[email protected]9a5afa432011-07-22 18:16:397608 if (surface_->IsOffscreen()) {
[email protected]51411e32012-01-19 20:21:137609 ScopedFrameBufferBinder binder(this,
7610 offscreen_target_frame_buffer_->id());
7611
[email protected]8a61d872012-01-20 12:43:567612 if (offscreen_target_buffer_preserved_) {
7613 // Copy the target frame buffer to the saved offscreen texture.
7614 offscreen_saved_color_texture_->Copy(
7615 offscreen_saved_color_texture_->size(),
7616 offscreen_saved_color_format_);
7617 } else {
7618 // Flip the textures in the parent context via the texture manager.
7619 if (!!offscreen_saved_color_texture_info_.get())
7620 offscreen_saved_color_texture_info_->
7621 SetServiceId(offscreen_target_color_texture_->id());
7622
7623 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
7624 offscreen_target_frame_buffer_->AttachRenderTexture(
7625 offscreen_target_color_texture_.get());
7626 }
[email protected]b86b14982010-10-11 18:45:487627
[email protected]a3ded6d2010-10-19 06:44:397628 // Ensure the side effects of the copy are visible to the parent
7629 // context. There is no need to do this for ANGLE because it uses a
7630 // single D3D device for all contexts.
[email protected]b86b14982010-10-11 18:45:487631 if (!IsAngle())
7632 glFlush();
7633 }
[email protected]89d6ed02011-04-20 00:23:237634 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:397635 }
[email protected]6217d392010-03-25 22:08:357636 } else {
[email protected]64ace852011-05-19 21:49:497637 TRACE_EVENT1("gpu", "GLContext::SwapBuffers", "frame", this_frame_number);
[email protected]f62a5ab2011-05-23 20:34:157638 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:017639 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:027640 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:017641 }
[email protected]6217d392010-03-25 22:08:357642 }
7643
[email protected]89d6ed02011-04-20 00:23:237644 return error::kNoError;
[email protected]6217d392010-03-25 22:08:357645}
7646
[email protected]d4239852011-08-12 04:51:227647error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
7648 uint32 immediate_data_size, const gles2::EnableFeatureCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:187649 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287650 if (!bucket || bucket->size() == 0) {
7651 return error::kInvalidArguments;
7652 }
[email protected]d4239852011-08-12 04:51:227653 typedef gles2::EnableFeatureCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:187654 Result* result = GetSharedMemoryAs<Result*>(
7655 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7656 if (!result) {
7657 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:107658 }
[email protected]b1d2dcb2010-05-17 19:24:187659 // Check that the client initialized the result.
7660 if (*result != 0) {
7661 return error::kInvalidArguments;
7662 }
7663 std::string feature_str;
7664 if (!bucket->GetAsString(&feature_str)) {
7665 return error::kInvalidArguments;
7666 }
7667
7668 // TODO(gman): make this some kind of table to function pointer thingy.
[email protected]d4239852011-08-12 04:51:227669 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
[email protected]b1d2dcb2010-05-17 19:24:187670 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]d4239852011-08-12 04:51:227671 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
[email protected]8fbedc02010-11-18 18:43:407672 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
7673 // TODO(gman): decide how to remove the need for this const_cast.
7674 // I could make validators_ non const but that seems bad as this is the only
7675 // place it is needed. I could make some special friend class of validators
7676 // just to allow this to set them. That seems silly. I could refactor this
7677 // code to use the extension mechanism or the initialization attributes to
7678 // turn this feature on. Given that the only real point of this is to make
7679 // the conformance tests pass and given that there is lots of real work that
7680 // needs to be done it seems like refactoring for one to one of those
7681 // methods is a very low priority.
7682 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]f0d74742011-10-03 16:31:047683 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
7684 force_webgl_glsl_validation_ = true;
7685 InitializeShaderTranslator();
[email protected]b1d2dcb2010-05-17 19:24:187686 } else {
7687 return error::kNoError;
7688 }
7689
7690 *result = 1; // true.
7691 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:107692}
7693
[email protected]c2f8c8402010-12-06 18:07:247694error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
7695 uint32 immediate_data_size,
7696 const gles2::GetRequestableExtensionsCHROMIUM& c) {
7697 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]80eb6b52012-01-19 00:14:417698 FeatureInfo::Ref info(new FeatureInfo());
[email protected]e82fb792011-09-22 00:33:297699 info->Initialize(disallowed_features_, NULL);
[email protected]c2f8c8402010-12-06 18:07:247700 bucket->SetFromString(info->extensions().c_str());
7701 return error::kNoError;
7702}
7703
7704error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
7705 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
7706 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287707 if (!bucket || bucket->size() == 0) {
7708 return error::kInvalidArguments;
7709 }
[email protected]c2f8c8402010-12-06 18:07:247710 std::string feature_str;
7711 if (!bucket->GetAsString(&feature_str)) {
7712 return error::kInvalidArguments;
7713 }
7714
7715 bool std_derivatives_enabled =
7716 feature_info_->feature_flags().oes_standard_derivatives;
7717 bool webglsl_enabled =
7718 feature_info_->feature_flags().chromium_webglsl;
7719
7720 feature_info_->AddFeatures(feature_str.c_str());
7721
[email protected]f0d74742011-10-03 16:31:047722 bool initialization_required = false;
7723 if (force_webgl_glsl_validation_ && !derivatives_explicitly_enabled_) {
7724 size_t derivatives_offset = feature_str.find(kOESDerivativeExtension);
7725 if (std::string::npos != derivatives_offset) {
7726 derivatives_explicitly_enabled_ = true;
7727 initialization_required = true;
7728 }
7729 }
7730
[email protected]c2f8c8402010-12-06 18:07:247731 // If we just enabled a feature which affects the shader translator,
7732 // we may need to re-initialize it.
7733 if (std_derivatives_enabled !=
7734 feature_info_->feature_flags().oes_standard_derivatives ||
7735 webglsl_enabled !=
[email protected]f0d74742011-10-03 16:31:047736 feature_info_->feature_flags().chromium_webglsl ||
7737 initialization_required) {
[email protected]c2f8c8402010-12-06 18:07:247738 InitializeShaderTranslator();
7739 }
7740
[email protected]302ce6d2011-07-07 23:28:117741 UpdateCapabilities();
7742
[email protected]c2f8c8402010-12-06 18:07:247743 return error::kNoError;
7744}
7745
[email protected]372e0412011-06-28 16:08:567746error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
7747 uint32 immediate_data_size, const gles2::GetMultipleIntegervCHROMIUM& c) {
7748 GLuint count = c.count;
7749 uint32 pnames_size;
7750 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
7751 return error::kOutOfBounds;
7752 }
7753 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
7754 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
7755 if (pnames == NULL) {
7756 return error::kOutOfBounds;
7757 }
7758
7759 // We have to copy them since we use them twice so the client
7760 // can't change them between the time we validate them and the time we use
7761 // them.
7762 scoped_array<GLenum> enums(new GLenum[count]);
7763 memcpy(enums.get(), pnames, pnames_size);
7764
7765 // Count up the space needed for the result.
7766 uint32 num_results = 0;
7767 for (GLuint ii = 0; ii < count; ++ii) {
7768 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
7769 if (num == 0) {
7770 SetGLError(GL_INVALID_ENUM,
7771 "glGetMulitpleCHROMIUM: pname GL_INVALID_ENUM");
7772 return error::kNoError;
7773 }
7774 // Num will never be more than 4.
7775 DCHECK_LE(num, 4u);
7776 if (!SafeAdd(num_results, num, &num_results)) {
7777 return error::kOutOfBounds;
7778 }
7779 }
7780
7781 uint32 result_size = 0;
7782 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
7783 return error::kOutOfBounds;
7784 }
7785
7786 if (result_size != static_cast<uint32>(c.size)) {
7787 SetGLError(GL_INVALID_VALUE,
7788 "glGetMulitpleCHROMIUM: bad size GL_INVALID_VALUE");
7789 return error::kNoError;
7790 }
7791
7792 GLint* results = GetSharedMemoryAs<GLint*>(
7793 c.results_shm_id, c.results_shm_offset, result_size);
7794 if (results == NULL) {
7795 return error::kOutOfBounds;
7796 }
7797
7798 // Check the results have been cleared in case the context was lost.
7799 for (uint32 ii = 0; ii < num_results; ++ii) {
7800 if (results[ii]) {
7801 return error::kInvalidArguments;
7802 }
7803 }
7804
7805 // Get each result.
7806 GLint* start = results;
7807 for (GLuint ii = 0; ii < count; ++ii) {
7808 GLsizei num_written = 0;
7809 if (!GetHelper(enums[ii], results, &num_written)) {
7810 glGetIntegerv(enums[ii], results);
7811 }
7812 results += num_written;
7813 }
7814
7815 // Just to verify. Should this be a DCHECK?
7816 if (static_cast<uint32>(results - start) != num_results) {
7817 return error::kOutOfBounds;
7818 }
7819
7820 return error::kNoError;
7821}
7822
[email protected]2318d342011-07-11 22:27:427823error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
7824 uint32 immediate_data_size, const gles2::GetProgramInfoCHROMIUM& c) {
7825 GLuint program = static_cast<GLuint>(c.program);
7826 uint32 bucket_id = c.bucket_id;
7827 Bucket* bucket = CreateBucket(bucket_id);
7828 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
7829 ProgramManager::ProgramInfo* info = NULL;
[email protected]9a14ae612011-08-08 17:51:467830 info = GetProgramInfo(program);
7831 if (!info || !info->IsValid()) {
7832 return error::kNoError;
[email protected]2318d342011-07-11 22:27:427833 }
[email protected]5d4c6b22012-02-07 08:22:287834 info->GetProgramInfo(program_manager(), bucket);
[email protected]2318d342011-07-11 22:27:427835 return error::kNoError;
7836}
7837
[email protected]38d139d2011-07-14 00:38:437838error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
7839 switch (reset_status_) {
7840 case GL_NO_ERROR:
7841 // TODO(kbr): improve the precision of the error code in this case.
7842 // Consider delegating to context for error code if MakeCurrent fails.
7843 return error::kUnknown;
7844 case GL_GUILTY_CONTEXT_RESET_ARB:
7845 return error::kGuilty;
7846 case GL_INNOCENT_CONTEXT_RESET_ARB:
7847 return error::kInnocent;
7848 case GL_UNKNOWN_CONTEXT_RESET_ARB:
7849 return error::kUnknown;
7850 }
7851
7852 NOTREACHED();
7853 return error::kUnknown;
7854}
7855
7856bool GLES2DecoderImpl::WasContextLost() {
7857 if (context_->WasAllocatedUsingARBRobustness() && has_arb_robustness_) {
7858 GLenum status = glGetGraphicsResetStatusARB();
7859 if (status != GL_NO_ERROR) {
7860 // The graphics card was reset. Signal a lost context to the application.
7861 reset_status_ = status;
7862 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
7863 << " context lost via ARB_robustness. Reset status = 0x"
7864 << std::hex << status << std::dec;
7865 return true;
7866 }
7867 }
7868 return false;
7869}
7870
[email protected]882ba1e22012-03-08 19:02:537871bool GLES2DecoderImpl::GenQueriesEXTHelper(
7872 GLsizei n, const GLuint* client_ids) {
7873 for (GLsizei ii = 0; ii < n; ++ii) {
7874 if (query_manager_->GetQuery(client_ids[ii])) {
7875 return false;
7876 }
7877 }
[email protected]c45f1972012-03-14 07:27:367878 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
[email protected]882ba1e22012-03-08 19:02:537879 return true;
7880}
7881
7882void GLES2DecoderImpl::DeleteQueriesEXTHelper(
7883 GLsizei n, const GLuint* client_ids) {
7884 for (GLsizei ii = 0; ii < n; ++ii) {
7885 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
7886 if (query && !query->IsDeleted()) {
7887 if (query == current_query_) {
7888 current_query_ = NULL;
7889 }
[email protected]c45f1972012-03-14 07:27:367890 query->Destroy(true);
[email protected]882ba1e22012-03-08 19:02:537891 query_manager_->RemoveQuery(client_ids[ii]);
7892 }
7893 }
7894}
7895
[email protected]22e3f552012-03-13 01:54:197896bool GLES2DecoderImpl::ProcessPendingQueries() {
7897 if (query_manager_.get() == NULL) {
7898 return false;
7899 }
[email protected]c45f1972012-03-14 07:27:367900 if (!query_manager_->ProcessPendingQueries()) {
[email protected]22e3f552012-03-13 01:54:197901 current_decoder_error_ = error::kOutOfBounds;
7902 }
7903 return query_manager_->HavePendingQueries();
7904}
7905
[email protected]882ba1e22012-03-08 19:02:537906error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
7907 uint32 immediate_data_size, const gles2::BeginQueryEXT& c) {
7908 GLenum target = static_cast<GLenum>(c.target);
7909 GLuint client_id = static_cast<GLuint>(c.id);
7910 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
7911 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
7912
[email protected]c45f1972012-03-14 07:27:367913 switch (target) {
7914 case GL_COMMANDS_ISSUED_CHROMIUM:
7915 break;
7916 default:
7917 if (!feature_info_->feature_flags().occlusion_query_boolean) {
7918 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT: not enabled");
7919 return error::kNoError;
7920 }
7921 break;
[email protected]882ba1e22012-03-08 19:02:537922 }
7923
7924 if (current_query_) {
7925 SetGLError(
7926 GL_INVALID_OPERATION, "glBeginQueryEXT: query already in progress");
7927 return error::kNoError;
7928 }
7929
7930 if (client_id == 0) {
7931 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT: id is 0");
7932 return error::kNoError;
7933 }
7934
7935 QueryManager::Query* query = query_manager_->GetQuery(client_id);
7936 if (!query) {
[email protected]c45f1972012-03-14 07:27:367937 // TODO(gman): Decide if we need this check.
7938 //
[email protected]882ba1e22012-03-08 19:02:537939 // Checks id was made by glGenQueries
[email protected]c45f1972012-03-14 07:27:367940 //
7941 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
7942 // for all Query ids but from the POV of the command buffer service maybe
7943 // you don't.
7944 //
7945 // The client can enforce this. I don't think the service cares.
7946 //
7947 // IdAllocatorInterface* id_allocator =
7948 // group_->GetIdAllocator(id_namespaces::kQueries);
7949 // if (!id_allocator->InUse(client_id)) {
7950 // SetGLError(GL_INVALID_OPERATION,
7951 // "glBeginQueryEXT: id not made by glGenQueriesEXT");
7952 // return error::kNoError;
7953 // }
7954 query = query_manager_->CreateQuery(
7955 target, client_id, sync_shm_id, sync_shm_offset);
[email protected]882ba1e22012-03-08 19:02:537956 }
7957
[email protected]c45f1972012-03-14 07:27:367958 if (query->target() != target) {
[email protected]882ba1e22012-03-08 19:02:537959 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT: target does not match");
7960 return error::kNoError;
7961 } else if (query->shm_id() != sync_shm_id ||
7962 query->shm_offset() != sync_shm_offset) {
7963 DLOG(ERROR) << "Shared memory used by query not the same as before";
7964 return error::kInvalidArguments;
7965 }
7966
[email protected]c45f1972012-03-14 07:27:367967 if (!query_manager_->BeginQuery(query)) {
7968 return error::kOutOfBounds;
7969 }
[email protected]882ba1e22012-03-08 19:02:537970
[email protected]882ba1e22012-03-08 19:02:537971 current_query_ = query;
[email protected]882ba1e22012-03-08 19:02:537972 return error::kNoError;
7973}
7974
7975error::Error GLES2DecoderImpl::HandleEndQueryEXT(
7976 uint32 immediate_data_size, const gles2::EndQueryEXT& c) {
7977 GLenum target = static_cast<GLenum>(c.target);
7978 uint32 submit_count = static_cast<GLuint>(c.submit_count);
7979
7980 if (!current_query_) {
7981 SetGLError(GL_INVALID_OPERATION, "glEndQueryEXT: No active query");
7982 return error::kNoError;
7983 }
7984 if (current_query_->target() != target) {
7985 SetGLError(GL_INVALID_OPERATION,
7986 "glEndQueryEXT: target does not match active query");
7987 return error::kNoError;
7988 }
[email protected]882ba1e22012-03-08 19:02:537989
[email protected]c45f1972012-03-14 07:27:367990 if (!query_manager_->EndQuery(current_query_, submit_count)) {
7991 return error::kOutOfBounds;
7992 }
7993
7994 current_query_ = NULL;
[email protected]882ba1e22012-03-08 19:02:537995 return error::kNoError;
7996}
7997
[email protected]b0af4f52011-09-28 22:04:427998error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
7999 uint32 immediate_data_size,
8000 const gles2::CreateStreamTextureCHROMIUM& c) {
8001 if (!feature_info_->feature_flags().chromium_stream_texture) {
8002 SetGLError(GL_INVALID_OPERATION,
8003 "glOpenStreamTextureCHROMIUM: "
8004 "not supported.");
8005 return error::kNoError;
8006 }
8007
8008 uint32 client_id = c.client_id;
8009 typedef gles2::CreateStreamTextureCHROMIUM::Result Result;
8010 Result* result = GetSharedMemoryAs<Result*>(
8011 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8012
[email protected]e5081262012-01-05 23:09:038013 if (!result)
8014 return error::kOutOfBounds;
[email protected]b0af4f52011-09-28 22:04:428015 *result = GL_ZERO;
8016 TextureManager::TextureInfo* info =
8017 texture_manager()->GetTextureInfo(client_id);
8018 if (!info) {
8019 SetGLError(GL_INVALID_VALUE,
8020 "glCreateStreamTextureCHROMIUM: "
8021 "bad texture id.");
8022 return error::kNoError;
8023 }
8024
8025 if (info->IsStreamTexture()) {
8026 SetGLError(GL_INVALID_OPERATION,
8027 "glCreateStreamTextureCHROMIUM: "
8028 "is already a stream texture.");
8029 return error::kNoError;
8030 }
8031
8032 if (info->target() && info->target() != GL_TEXTURE_EXTERNAL_OES) {
8033 SetGLError(GL_INVALID_OPERATION,
8034 "glCreateStreamTextureCHROMIUM: "
8035 "is already bound to incompatible target.");
8036 return error::kNoError;
8037 }
8038
8039 if (!stream_texture_manager_)
8040 return error::kInvalidArguments;
8041
8042 GLuint object_id = stream_texture_manager_->CreateStreamTexture(
8043 info->service_id(), client_id);
8044
8045 if (object_id) {
8046 info->SetStreamTexture(true);
8047 } else {
8048 SetGLError(GL_OUT_OF_MEMORY,
8049 "glCreateStreamTextureCHROMIUM: "
8050 "failed to create platform texture.");
8051 }
8052
8053 *result = object_id;
8054 return error::kNoError;
8055}
8056
8057error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
8058 uint32 immediate_data_size,
8059 const gles2::DestroyStreamTextureCHROMIUM& c) {
8060 GLuint client_id = c.texture;
8061 TextureManager::TextureInfo* info =
8062 texture_manager()->GetTextureInfo(client_id);
8063 if (info && info->IsStreamTexture()) {
8064 if (!stream_texture_manager_)
8065 return error::kInvalidArguments;
8066
8067 stream_texture_manager_->DestroyStreamTexture(info->service_id());
8068 info->SetStreamTexture(false);
[email protected]80eb6b52012-01-19 00:14:418069 texture_manager()->SetInfoTarget(info, 0);
[email protected]b0af4f52011-09-28 22:04:428070 } else {
8071 SetGLError(GL_INVALID_VALUE,
8072 "glDestroyStreamTextureCHROMIUM: bad texture id.");
8073 }
8074
8075 return error::kNoError;
8076}
8077
[email protected]e51bdf32011-11-23 22:21:468078#if defined(OS_MACOSX)
8079void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
8080 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
8081 texture_id);
8082 if (it != texture_to_io_surface_map_.end()) {
8083 // Found a previous IOSurface bound to this texture; release it.
8084 CFTypeRef surface = it->second;
8085 CFRelease(surface);
8086 texture_to_io_surface_map_.erase(it);
8087 }
8088}
8089#endif
8090
8091void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
8092 GLenum target, GLsizei width, GLsizei height,
8093 GLuint io_surface_id, GLuint plane) {
8094#if defined(OS_MACOSX)
8095 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
8096 SetGLError(GL_INVALID_OPERATION,
8097 "glTexImageIOSurface2DCHROMIUM: only supported on desktop GL.");
8098 return;
8099 }
8100
8101 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
8102 if (!surface_support) {
8103 SetGLError(GL_INVALID_OPERATION,
8104 "glTexImageIOSurface2DCHROMIUM: only supported on 10.6.");
8105 return;
8106 }
8107
8108 if (target != GL_TEXTURE_RECTANGLE_ARB) {
8109 // This might be supported in the future, and if we could require
8110 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
8111 // could delete a lot of code. For now, perform strict validation so we
8112 // know what's going on.
8113 SetGLError(
8114 GL_INVALID_OPERATION,
8115 "glTexImageIOSurface2DCHROMIUM: requires TEXTURE_RECTANGLE_ARB target");
8116 return;
8117 }
8118
8119 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8120 if (!info) {
8121 SetGLError(GL_INVALID_OPERATION,
8122 "glTexImageIOSurface2DCHROMIUM: no rectangle texture bound");
8123 return;
8124 }
8125 if (info == texture_manager()->GetDefaultTextureInfo(target)) {
8126 // Maybe this is conceptually valid, but disallow it to avoid accidents.
8127 SetGLError(GL_INVALID_OPERATION,
8128 "glTexImageIOSurface2DCHROMIUM: can't bind default texture");
8129 return;
8130 }
8131
8132 // Look up the new IOSurface. Note that because of asynchrony
8133 // between processes this might fail; during live resizing the
8134 // plugin process might allocate and release an IOSurface before
8135 // this process gets a chance to look it up. Hold on to any old
8136 // IOSurface in this case.
8137 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
8138 if (!surface) {
8139 SetGLError(GL_INVALID_OPERATION,
8140 "glTexImageIOSurface2DCHROMIUM: no IOSurface with the given ID");
8141 return;
8142 }
8143
8144 // Release any IOSurface previously bound to this texture.
8145 ReleaseIOSurfaceForTexture(info->service_id());
8146
8147 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
8148 texture_to_io_surface_map_.insert(
8149 std::make_pair(info->service_id(), surface));
8150
8151 CGLContextObj context =
8152 static_cast<CGLContextObj>(context_->GetHandle());
8153
8154 CGLError err = surface_support->CGLTexImageIOSurface2D(
8155 context,
8156 target,
8157 GL_RGBA,
8158 width,
8159 height,
8160 GL_BGRA,
8161 GL_UNSIGNED_INT_8_8_8_8_REV,
8162 surface,
8163 plane);
8164
8165 if (err != kCGLNoError) {
8166 SetGLError(
8167 GL_INVALID_OPERATION,
8168 "glTexImageIOSurface2DCHROMIUM: error in CGLTexImageIOSurface2D");
8169 return;
8170 }
8171
8172 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:418173 info, target, 0, GL_RGBA, width, height, 1, 0,
[email protected]e51bdf32011-11-23 22:21:468174 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
8175
8176#else
8177 SetGLError(GL_INVALID_OPERATION,
8178 "glTexImageIOSurface2DCHROMIUM: not supported.");
8179#endif
8180}
8181
[email protected]97dc7cbe2011-12-06 17:26:178182static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
8183 switch (internalformat) {
8184 case GL_RGB565:
8185 return GL_RGB;
8186 case GL_RGBA4:
8187 return GL_RGBA;
8188 case GL_RGB5_A1:
8189 return GL_RGBA;
8190 case GL_RGB8_OES:
8191 return GL_RGB;
8192 case GL_RGBA8_OES:
8193 return GL_RGBA;
8194 case GL_LUMINANCE8_ALPHA8_EXT:
8195 return GL_LUMINANCE_ALPHA;
8196 case GL_LUMINANCE8_EXT:
8197 return GL_LUMINANCE;
8198 case GL_ALPHA8_EXT:
8199 return GL_ALPHA;
8200 case GL_RGBA32F_EXT:
8201 return GL_RGBA;
8202 case GL_RGB32F_EXT:
8203 return GL_RGB;
8204 case GL_ALPHA32F_EXT:
8205 return GL_ALPHA;
8206 case GL_LUMINANCE32F_EXT:
8207 return GL_LUMINANCE;
8208 case GL_LUMINANCE_ALPHA32F_EXT:
8209 return GL_LUMINANCE_ALPHA;
8210 case GL_RGBA16F_EXT:
8211 return GL_RGBA;
8212 case GL_RGB16F_EXT:
8213 return GL_RGB;
8214 case GL_ALPHA16F_EXT:
8215 return GL_ALPHA;
8216 case GL_LUMINANCE16F_EXT:
8217 return GL_LUMINANCE;
8218 case GL_LUMINANCE_ALPHA16F_EXT:
8219 return GL_LUMINANCE_ALPHA;
8220 case GL_BGRA8_EXT:
8221 return GL_BGRA_EXT;
8222 default:
8223 return GL_NONE;
8224 }
8225}
8226
8227static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
8228 switch (internalformat) {
8229 case GL_RGB565:
8230 return GL_UNSIGNED_SHORT_5_6_5;
8231 case GL_RGBA4:
8232 return GL_UNSIGNED_SHORT_4_4_4_4;
8233 case GL_RGB5_A1:
8234 return GL_UNSIGNED_SHORT_5_5_5_1;
8235 case GL_RGB8_OES:
8236 return GL_UNSIGNED_BYTE;
8237 case GL_RGBA8_OES:
8238 return GL_UNSIGNED_BYTE;
8239 case GL_LUMINANCE8_ALPHA8_EXT:
8240 return GL_UNSIGNED_BYTE;
8241 case GL_LUMINANCE8_EXT:
8242 return GL_UNSIGNED_BYTE;
8243 case GL_ALPHA8_EXT:
8244 return GL_UNSIGNED_BYTE;
8245 case GL_RGBA32F_EXT:
8246 return GL_FLOAT;
8247 case GL_RGB32F_EXT:
8248 return GL_FLOAT;
8249 case GL_ALPHA32F_EXT:
8250 return GL_FLOAT;
8251 case GL_LUMINANCE32F_EXT:
8252 return GL_FLOAT;
8253 case GL_LUMINANCE_ALPHA32F_EXT:
8254 return GL_FLOAT;
8255 case GL_RGBA16F_EXT:
8256 return GL_HALF_FLOAT_OES;
8257 case GL_RGB16F_EXT:
8258 return GL_HALF_FLOAT_OES;
8259 case GL_ALPHA16F_EXT:
8260 return GL_HALF_FLOAT_OES;
8261 case GL_LUMINANCE16F_EXT:
8262 return GL_HALF_FLOAT_OES;
8263 case GL_LUMINANCE_ALPHA16F_EXT:
8264 return GL_HALF_FLOAT_OES;
8265 case GL_BGRA8_EXT:
8266 return GL_UNSIGNED_BYTE;
8267 default:
8268 return GL_NONE;
8269 }
8270}
8271
8272void GLES2DecoderImpl::DoTexStorage2DEXT(
8273 GLenum target,
8274 GLint levels,
8275 GLenum internal_format,
8276 GLsizei width,
8277 GLsizei height) {
[email protected]80eb6b52012-01-19 00:14:418278 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
[email protected]97dc7cbe2011-12-06 17:26:178279 TextureManager::ComputeMipMapCount(width, height, 1) < levels) {
8280 SetGLError(GL_INVALID_VALUE, "glTexStorage2DEXT: dimensions out of range");
8281 return;
8282 }
8283 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8284 if (!info) {
8285 SetGLError(GL_INVALID_OPERATION,
8286 "glTexStorage2DEXT: unknown texture for target");
8287 return;
8288 }
8289 if (info->IsAttachedToFramebuffer()) {
8290 state_dirty_ = true;
8291 }
8292 if (info->IsImmutable()) {
8293 SetGLError(GL_INVALID_OPERATION,
8294 "glTexStorage2DEXT: texture is immutable");
8295 return;
8296 }
8297 CopyRealGLErrorsToWrapper();
[email protected]f0e6a34f2012-01-04 20:53:408298 glTexStorage2DEXT(target, levels, GetTexInternalFormat(internal_format),
8299 width, height);
[email protected]97dc7cbe2011-12-06 17:26:178300 GLenum error = PeekGLError();
8301 if (error == GL_NO_ERROR) {
8302 GLenum format = ExtractFormatFromStorageFormat(internal_format);
8303 GLenum type = ExtractTypeFromStorageFormat(internal_format);
[email protected]4502e6492011-12-14 19:39:158304 GLsizei level_width = width;
8305 GLsizei level_height = height;
8306 for (int ii = 0; ii < levels; ++ii) {
8307 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:418308 info, target, 0, format, level_width, level_height, 1, 0, format,
8309 type, false);
[email protected]4502e6492011-12-14 19:39:158310 level_width = std::max(1, level_width >> 1);
8311 level_height = std::max(1, level_height >> 1);
8312 }
[email protected]97dc7cbe2011-12-06 17:26:178313 info->SetImmutable(true);
8314 }
[email protected]97dc7cbe2011-12-06 17:26:178315}
[email protected]e51bdf32011-11-23 22:21:468316
[email protected]96449d2c2009-11-25 00:01:328317// Include the auto-generated part of this file. We split this because it means
8318// we can easily edit the non-auto generated parts right here in this file
8319// instead of having to edit some template or the code generator.
8320#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
8321
8322} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:258323} // namespace gpu