blob: 273df90dd028b1d976eceb2aebd1dc6dd97f0de0 [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]00eb49a2010-08-12 20:46:5715#include "base/at_exit.h"
[email protected]d353541f2012-05-03 22:45:4116#include "base/atomicops.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]0f8afe82012-05-14 23:43:0125#include "base/string_number_conversions.h"
[email protected]d37231fa2010-04-09 21:16:0226#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3227#define GLES2_GPU_SERVICE 1
28#include "gpu/command_buffer/common/gles2_cmd_format.h"
29#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1030#include "gpu/command_buffer/common/id_allocator.h"
[email protected]3916c97e2010-02-25 03:20:5031#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3232#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5033#include "gpu/command_buffer/service/context_group.h"
[email protected]915a59a12010-09-30 21:29:1134#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5835#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3236#include "gpu/command_buffer/service/gl_utils.h"
[email protected]43410e92012-04-20 17:06:2837#include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
[email protected]ba3176a2009-12-16 18:19:4638#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]e844ae22012-01-14 03:36:2639#include "gpu/command_buffer/service/gpu_switches.h"
[email protected]78b514b2012-05-01 21:50:5940#include "gpu/command_buffer/service/mailbox_manager.h"
[email protected]a93bb842010-02-16 23:03:4741#include "gpu/command_buffer/service/program_manager.h"
[email protected]882ba1e22012-03-08 19:02:5342#include "gpu/command_buffer/service/query_manager.h"
[email protected]a25fa872010-03-25 02:57:5843#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4744#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4545#include "gpu/command_buffer/service/shader_translator.h"
[email protected]87fb6ab2012-06-13 22:28:0446#include "gpu/command_buffer/service/shader_translator_cache.h"
[email protected]b0af4f52011-09-28 22:04:4247#include "gpu/command_buffer/service/stream_texture.h"
48#include "gpu/command_buffer/service/stream_texture_manager.h"
[email protected]78b514b2012-05-01 21:50:5949#include "gpu/command_buffer/service/texture_definition.h"
[email protected]a93bb842010-02-16 23:03:4750#include "gpu/command_buffer/service/texture_manager.h"
[email protected]d8ea9772011-07-11 18:11:4351#include "gpu/command_buffer/service/vertex_attrib_manager.h"
[email protected]c9e2cbbb2012-05-12 21:17:2752#include "ui/gl/gl_context.h"
53#include "ui/gl/gl_implementation.h"
54#include "ui/gl/gl_surface.h"
[email protected]e51bdf32011-11-23 22:21:4655#if defined(OS_MACOSX)
[email protected]d353541f2012-05-03 22:45:4156#include "ui/surface/io_surface_support_mac.h"
[email protected]e51bdf32011-11-23 22:21:4657#endif
[email protected]de17df392010-04-23 21:09:4158
[email protected]6217d392010-03-25 22:08:3559#if !defined(GL_DEPTH24_STENCIL8)
60#define GL_DEPTH24_STENCIL8 0x88F0
61#endif
62
[email protected]260ddc4e2012-06-28 00:01:5363#define TRACE_BACKBUFFER_MEMORY_TOTAL(decoder) \
64 TRACE_COUNTER_ID1( \
65 "GLES2DecoderImpl", "BackbufferMemory", decoder, \
66 decoder->GetBackbufferMemoryTotal())
67
[email protected]a7a27ace2009-12-12 00:11:2568namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3269namespace gles2 {
70
[email protected]f0d74742011-10-03 16:31:0471namespace {
72static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
73}
74
[email protected]6217d392010-03-25 22:08:3575class GLES2DecoderImpl;
76
[email protected]07f54fcc2009-12-22 02:46:3077// Check that certain assumptions the code makes are true. There are places in
78// the code where shared memory is passed direclty to GL. Example, glUniformiv,
79// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
80// a few others) are 32bits. If they are not 32bits the code will have to change
81// to call those GL functions with service side memory and then copy the results
82// to shared memory, converting the sizes.
83COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
84 GLint_not_same_size_as_uint32);
85COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
86 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3787COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
88 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3089
[email protected]43f28f832010-02-03 02:28:4890// TODO(kbr): the use of this anonymous namespace core dumps the
91// linker on Mac OS X 10.6 when the symbol ordering file is used
92// namespace {
[email protected]96449d2c2009-11-25 00:01:3293
94// Returns the address of the first byte after a struct.
95template <typename T>
96const void* AddressAfterStruct(const T& pod) {
97 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
98}
99
[email protected]07f54fcc2009-12-22 02:46:30100// Returns the address of the frst byte after the struct or NULL if size >
101// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:32102template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:30103RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
104 uint32 size,
105 uint32 immediate_data_size) {
106 return (size <= immediate_data_size) ?
107 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
108 NULL;
[email protected]96449d2c2009-11-25 00:01:32109}
110
[email protected]07f54fcc2009-12-22 02:46:30111// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:18112bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:32113 GLuint count,
114 size_t size,
[email protected]a76b0052010-03-05 00:33:18115 unsigned int elements_per_unit,
116 uint32* dst) {
117 uint32 value;
118 if (!SafeMultiplyUint32(count, size, &value)) {
119 return false;
120 }
121 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
122 return false;
123 }
124 *dst = value;
125 return true;
[email protected]96449d2c2009-11-25 00:01:32126}
127
128// A struct to hold info about each command.
129struct CommandInfo {
130 int arg_flags; // How to handle the arguments for this command
131 int arg_count; // How many arguments are expected for this command.
132};
133
134// A table of CommandInfo for all the commands.
135const CommandInfo g_command_info[] = {
136 #define GLES2_CMD_OP(name) { \
137 name::kArgFlags, \
138 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
139
140 GLES2_COMMAND_LIST(GLES2_CMD_OP)
141
142 #undef GLES2_CMD_OP
143};
144
[email protected]258a3313f2011-10-18 20:13:57145// Return true if a character belongs to the ASCII subset as defined in
146// GLSL ES 1.0 spec section 3.1.
147static bool CharacterIsValidForGLES(unsigned char c) {
148 // Printing characters are valid except " $ ` @ \ ' DEL.
149 if (c >= 32 && c <= 126 &&
150 c != '"' &&
151 c != '$' &&
152 c != '`' &&
153 c != '@' &&
154 c != '\\' &&
155 c != '\'') {
156 return true;
157 }
158 // Horizontal tab, line feed, vertical tab, form feed, carriage return
159 // are also valid.
160 if (c >= 9 && c <= 13) {
161 return true;
162 }
163
164 return false;
165}
166
167static bool StringIsValidForGLES(const char* str) {
168 for (; *str; ++str) {
169 if (!CharacterIsValidForGLES(*str)) {
170 return false;
171 }
172 }
173 return true;
174}
175
[email protected]f0e6a34f2012-01-04 20:53:40176static inline GLenum GetTexInternalFormat(GLenum internal_format) {
177 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
178 if (internal_format == GL_BGRA_EXT || internal_format == GL_BGRA8_EXT)
179 return GL_RGBA8;
180 }
181 return internal_format;
182}
183
[email protected]297ca1c2011-06-20 23:08:46184static void WrappedTexImage2D(
[email protected]473c01ccb2011-06-07 01:33:30185 GLenum target,
186 GLint level,
187 GLenum internal_format,
188 GLsizei width,
189 GLsizei height,
190 GLint border,
191 GLenum format,
192 GLenum type,
193 const void* pixels) {
[email protected]f0e6a34f2012-01-04 20:53:40194 GLenum gl_internal_format = GetTexInternalFormat(internal_format);
[email protected]473c01ccb2011-06-07 01:33:30195 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]f0e6a34f2012-01-04 20:53:40196 if (type == GL_FLOAT) {
[email protected]58b75f92012-03-20 21:15:43197 switch (format) {
198 case GL_RGBA:
199 gl_internal_format = GL_RGBA32F_ARB;
200 break;
201 case GL_RGB:
202 gl_internal_format = GL_RGB32F_ARB;
203 break;
204 case GL_LUMINANCE_ALPHA:
205 gl_internal_format = GL_LUMINANCE_ALPHA32F_ARB;
206 break;
207 case GL_LUMINANCE:
208 gl_internal_format = GL_LUMINANCE32F_ARB;
209 break;
210 case GL_ALPHA:
211 gl_internal_format = GL_ALPHA32F_ARB;
212 break;
213 default:
214 NOTREACHED();
215 break;
[email protected]473c01ccb2011-06-07 01:33:30216 }
217 } else if (type == GL_HALF_FLOAT_OES) {
[email protected]58b75f92012-03-20 21:15:43218 switch (format) {
219 case GL_RGBA:
220 gl_internal_format = GL_RGBA16F_ARB;
221 break;
222 case GL_RGB:
223 gl_internal_format = GL_RGB16F_ARB;
224 break;
225 case GL_LUMINANCE_ALPHA:
226 gl_internal_format = GL_LUMINANCE_ALPHA16F_ARB;
227 break;
228 case GL_LUMINANCE:
229 gl_internal_format = GL_LUMINANCE16F_ARB;
230 break;
231 case GL_ALPHA:
232 gl_internal_format = GL_ALPHA16F_ARB;
233 break;
234 default:
235 NOTREACHED();
236 break;
[email protected]473c01ccb2011-06-07 01:33:30237 }
238 }
239 }
240 glTexImage2D(
241 target, level, gl_internal_format, width, height, border, format, type,
242 pixels);
243}
244
[email protected]297ca1c2011-06-20 23:08:46245// Wrapper for glEnable/glDisable that doesn't suck.
246static void EnableDisable(GLenum pname, bool enable) {
247 if (enable) {
248 glEnable(pname);
249 } else {
250 glDisable(pname);
251 }
252}
253
[email protected]6217d392010-03-25 22:08:35254// This class prevents any GL errors that occur when it is in scope from
255// being reported to the client.
256class ScopedGLErrorSuppressor {
257 public:
258 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
259 ~ScopedGLErrorSuppressor();
260 private:
261 GLES2DecoderImpl* decoder_;
262 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
263};
264
265// Temporarily changes a decoder's bound 2D texture and restore it when this
266// object goes out of scope. Also temporarily switches to using active texture
267// unit zero in case the client has changed that to something invalid.
268class ScopedTexture2DBinder {
269 public:
270 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
271 ~ScopedTexture2DBinder();
272
273 private:
274 GLES2DecoderImpl* decoder_;
275 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
276};
277
278// Temporarily changes a decoder's bound render buffer and restore it when this
279// object goes out of scope.
280class ScopedRenderBufferBinder {
281 public:
282 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
283 ~ScopedRenderBufferBinder();
284
285 private:
286 GLES2DecoderImpl* decoder_;
287 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
288};
289
290// Temporarily changes a decoder's bound frame buffer and restore it when this
291// object goes out of scope.
292class ScopedFrameBufferBinder {
293 public:
294 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
295 ~ScopedFrameBufferBinder();
296
297 private:
298 GLES2DecoderImpl* decoder_;
299 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
300};
301
[email protected]34ff8b0c2010-10-01 20:06:02302// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52303// the multisampled offscreen render buffer if that buffer is multisampled, and,
[email protected]de26b3c2011-08-03 21:54:27304// if it is bound or enforce_internal_framebuffer is true. If internal is
305// true, the resolved framebuffer is not visible to the parent.
[email protected]34ff8b0c2010-10-01 20:06:02306class ScopedResolvedFrameBufferBinder {
307 public:
[email protected]e7e38032011-07-26 17:25:25308 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
[email protected]de26b3c2011-08-03 21:54:27309 bool enforce_internal_framebuffer,
310 bool internal);
[email protected]34ff8b0c2010-10-01 20:06:02311 ~ScopedResolvedFrameBufferBinder();
312
313 private:
314 GLES2DecoderImpl* decoder_;
315 bool resolve_and_bind_;
316 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
317};
318
[email protected]6217d392010-03-25 22:08:35319// Encapsulates an OpenGL texture.
320class Texture {
321 public:
322 explicit Texture(GLES2DecoderImpl* decoder);
323 ~Texture();
324
325 // Create a new render texture.
326 void Create();
327
328 // Set the initial size and format of a render texture or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02329 bool AllocateStorage(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35330
331 // Copy the contents of the currently bound frame buffer.
[email protected]3a4d0c52011-06-29 23:11:58332 void Copy(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35333
334 // Destroy the render texture. This must be explicitly called before
335 // destroying this object.
336 void Destroy();
337
[email protected]97872062010-11-03 19:07:05338 // Invalidate the texture. This can be used when a context is lost and it is
339 // not possible to make it current in order to free the resource.
340 void Invalidate();
341
[email protected]6217d392010-03-25 22:08:35342 GLuint id() const {
343 return id_;
344 }
345
[email protected]d37231fa2010-04-09 21:16:02346 gfx::Size size() const {
347 return size_;
348 }
349
[email protected]1078f912011-12-23 13:12:14350 size_t estimated_size() const {
351 return estimated_size_;
352 }
353
[email protected]6217d392010-03-25 22:08:35354 private:
355 GLES2DecoderImpl* decoder_;
356 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02357 gfx::Size size_;
[email protected]1078f912011-12-23 13:12:14358 size_t estimated_size_;
[email protected]6217d392010-03-25 22:08:35359 DISALLOW_COPY_AND_ASSIGN(Texture);
360};
361
362// Encapsulates an OpenGL render buffer of any format.
363class RenderBuffer {
364 public:
365 explicit RenderBuffer(GLES2DecoderImpl* decoder);
366 ~RenderBuffer();
367
368 // Create a new render buffer.
369 void Create();
370
371 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02372 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35373
374 // Destroy the render buffer. This must be explicitly called before destroying
375 // this object.
376 void Destroy();
377
[email protected]97872062010-11-03 19:07:05378 // Invalidate the render buffer. This can be used when a context is lost and
379 // it is not possible to make it current in order to free the resource.
380 void Invalidate();
381
[email protected]6217d392010-03-25 22:08:35382 GLuint id() const {
383 return id_;
384 }
385
[email protected]1078f912011-12-23 13:12:14386 size_t estimated_size() const {
387 return estimated_size_;
388 }
389
[email protected]6217d392010-03-25 22:08:35390 private:
391 GLES2DecoderImpl* decoder_;
392 GLuint id_;
[email protected]1078f912011-12-23 13:12:14393 size_t estimated_size_;
[email protected]6217d392010-03-25 22:08:35394 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
395};
396
397// Encapsulates an OpenGL frame buffer.
398class FrameBuffer {
399 public:
400 explicit FrameBuffer(GLES2DecoderImpl* decoder);
401 ~FrameBuffer();
402
403 // Create a new frame buffer.
404 void Create();
405
406 // Attach a color render buffer to a frame buffer.
407 void AttachRenderTexture(Texture* texture);
408
[email protected]b9363b22010-06-09 22:06:15409 // Attach a render buffer to a frame buffer. Note that this unbinds any
410 // currently bound frame buffer.
411 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35412
[email protected]6217d392010-03-25 22:08:35413 // Destroy the frame buffer. This must be explicitly called before destroying
414 // this object.
415 void Destroy();
416
[email protected]97872062010-11-03 19:07:05417 // Invalidate the frame buffer. This can be used when a context is lost and it
418 // is not possible to make it current in order to free the resource.
419 void Invalidate();
420
[email protected]6217d392010-03-25 22:08:35421 // See glCheckFramebufferStatusEXT.
422 GLenum CheckStatus();
423
424 GLuint id() const {
425 return id_;
426 }
427
428 private:
429 GLES2DecoderImpl* decoder_;
430 GLuint id_;
431 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
432};
[email protected]34ff8b0c2010-10-01 20:06:02433
[email protected]43f28f832010-02-03 02:28:48434// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32435
[email protected]ddb1e5a2010-12-13 20:10:45436bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
437 uint32* service_texture_id) {
438 return false;
439}
440
[email protected]a3ded6d2010-10-19 06:44:39441GLES2Decoder::GLES2Decoder()
[email protected]e844ae22012-01-14 03:36:26442 : debug_(false),
[email protected]b5d647c2012-02-10 01:41:32443 log_commands_(false),
444 log_synthesized_gl_errors_(true) {
[email protected]96449d2c2009-11-25 00:01:32445}
446
[email protected]3916c97e2010-02-25 03:20:50447GLES2Decoder::~GLES2Decoder() {
448}
449
[email protected]57edfdad2012-02-07 04:57:15450bool GLES2Decoder::testing_force_is_angle_;
451
452void GLES2Decoder::set_testing_force_is_angle(bool force) {
453 testing_force_is_angle_ = force;
454}
455
456bool GLES2Decoder::IsAngle() {
457#if defined(OS_WIN)
458 return testing_force_is_angle_ ||
459 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
460#else
461 return testing_force_is_angle_;
462#endif
463}
464
[email protected]f39f4b3f2010-05-12 17:04:08465// This class implements GLES2Decoder so we don't have to expose all the GLES2
466// cmd stuff to outside this class.
467class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
468 public GLES2Decoder {
469 public:
[email protected]0f8afe82012-05-14 23:43:01470 static const int kMaxLogMessages = 256;
[email protected]fa20ec82012-05-04 04:02:48471
[email protected]aa7666122011-09-02 19:45:52472 explicit GLES2DecoderImpl(ContextGroup* group);
[email protected]80eb6b52012-01-19 00:14:41473 ~GLES2DecoderImpl();
[email protected]f39f4b3f2010-05-12 17:04:08474
[email protected]96449d2c2009-11-25 00:01:32475 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14476 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50477 unsigned int arg_count,
478 const void* args);
[email protected]96449d2c2009-11-25 00:01:32479
480 // Overridden from AsyncAPIInterface.
481 virtual const char* GetCommandName(unsigned int command_id) const;
482
483 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38484 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
485 const scoped_refptr<gfx::GLContext>& context,
[email protected]069944672012-04-25 20:52:23486 bool offscreen,
[email protected]6217d392010-03-25 22:08:35487 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:29488 const DisallowedFeatures& disallowed_features,
[email protected]a3ded6d2010-10-19 06:44:39489 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:24490 const std::vector<int32>& attribs);
[email protected]63c9b052012-05-17 18:27:38491 virtual void Destroy(bool have_context);
492 virtual void SetSurface(
493 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
[email protected]3c644d82011-06-20 19:58:24494 virtual bool SetParent(GLES2Decoder* parent_decoder,
495 uint32 parent_texture_id);
[email protected]799b4b22011-08-22 17:09:59496 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]9a5afa432011-07-22 18:16:39497 void UpdateParentTextureInfo();
[email protected]eb54a562010-01-20 21:55:18498 virtual bool MakeCurrent();
[email protected]a96a6022011-11-04 00:58:12499 virtual void ReleaseCurrent();
[email protected]56ac89b2010-03-17 21:16:55500 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30501 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39502 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]882ba1e22012-03-08 19:02:53503 virtual QueryManager* GetQueryManager() { return query_manager_.get(); }
[email protected]22e3f552012-03-13 01:54:19504 virtual bool ProcessPendingQueries();
[email protected]43f28f832010-02-03 02:28:48505
[email protected]ad84a3a2012-06-08 21:42:43506 virtual void SetGLError(
507 GLenum error, const char* function_name, const char* msg);
[email protected]9d37f062011-11-22 01:24:52508 virtual void SetResizeCallback(
509 const base::Callback<void(gfx::Size)>& callback);
[email protected]22f320a2011-08-30 01:17:00510
[email protected]6b6e7ee2011-12-13 08:04:52511 virtual void SetMsgCallback(const MsgCallback& callback);
[email protected]22f320a2011-08-30 01:17:00512
[email protected]b0af4f52011-09-28 22:04:42513 virtual void SetStreamTextureManager(StreamTextureManager* manager);
[email protected]1318e922010-09-17 22:03:16514 virtual bool GetServiceTextureId(uint32 client_texture_id,
515 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48516
[email protected]efcdd2362012-07-09 21:07:00517 virtual uint32 GetGLError() OVERRIDE;
518
[email protected]8e3e0662010-08-23 18:46:30519 // Restores the current state to the user's settings.
520 void RestoreCurrentFramebufferBindings();
521 void RestoreCurrentRenderbufferBindings();
522 void RestoreCurrentTexture2DBindings();
523
[email protected]297ca1c2011-06-20 23:08:46524 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
525 void ApplyDirtyState();
526
[email protected]78b514b2012-05-01 21:50:59527 // Reapply the texture parameters to the given texture.
528 void BindAndApplyTextureParameters(TextureManager::TextureInfo* info);
529
[email protected]297ca1c2011-06-20 23:08:46530 // These check the state of the currently bound framebuffer or the
531 // backbuffer if no framebuffer is bound.
532 bool BoundFramebufferHasColorAttachmentWithAlpha();
533 bool BoundFramebufferHasDepthAttachment();
534 bool BoundFramebufferHasStencilAttachment();
535
[email protected]38d139d2011-07-14 00:38:43536 virtual error::ContextLostReason GetContextLostReason();
537
[email protected]96449d2c2009-11-25 00:01:32538 private:
[email protected]6217d392010-03-25 22:08:35539 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02540 friend class ScopedResolvedFrameBufferBinder;
[email protected]1078f912011-12-23 13:12:14541 friend class Texture;
[email protected]6217d392010-03-25 22:08:35542 friend class RenderBuffer;
543 friend class FrameBuffer;
544
[email protected]3916c97e2010-02-25 03:20:50545 // State associated with each texture unit.
546 struct TextureUnit {
547 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
548
549 // The last target that was bound to this texture unit.
550 GLenum bind_target;
551
552 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
553 TextureManager::TextureInfo::Ref bound_texture_2d;
554
555 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
556 // glBindTexture
557 TextureManager::TextureInfo::Ref bound_texture_cube_map;
[email protected]61eeb33f2011-07-26 15:30:31558
559 // texture currently bound to this unit's GL_TEXTURE_EXTERNAL_OES with
560 // glBindTexture
561 TextureManager::TextureInfo::Ref bound_texture_external_oes;
562
[email protected]e51bdf32011-11-23 22:21:46563 // texture currently bound to this unit's GL_TEXTURE_RECTANGLE_ARB with
564 // glBindTexture
565 TextureManager::TextureInfo::Ref bound_texture_rectangle_arb;
566
[email protected]61eeb33f2011-07-26 15:30:31567 TextureManager::TextureInfo::Ref GetInfoForSamplerType(GLenum type) {
568 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:46569 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
570 switch (type) {
571 case GL_SAMPLER_2D:
572 return bound_texture_2d;
573 case GL_SAMPLER_CUBE:
574 return bound_texture_cube_map;
575 case GL_SAMPLER_EXTERNAL_OES:
576 return bound_texture_external_oes;
577 case GL_SAMPLER_2D_RECT_ARB:
578 return bound_texture_rectangle_arb;
579 }
580
581 NOTREACHED();
582 return NULL;
[email protected]61eeb33f2011-07-26 15:30:31583 }
[email protected]a0b78dc2011-11-11 10:43:10584
585 void Unbind(TextureManager::TextureInfo* texture) {
586 if (bound_texture_2d == texture) {
587 bound_texture_2d = NULL;
588 }
589 if (bound_texture_cube_map == texture) {
590 bound_texture_cube_map = NULL;
591 }
592 if (bound_texture_external_oes == texture) {
593 bound_texture_external_oes = NULL;
594 }
595 }
[email protected]3916c97e2010-02-25 03:20:50596 };
597
[email protected]c2f8c8402010-12-06 18:07:24598 // Initialize or re-initialize the shader translator.
599 bool InitializeShaderTranslator();
600
[email protected]302ce6d2011-07-07 23:28:11601 void UpdateCapabilities();
602
[email protected]ae51d192010-04-27 00:48:03603 // Helpers for the glGen and glDelete functions.
604 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
605 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
606 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
607 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
608 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
609 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
610 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
611 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]882ba1e22012-03-08 19:02:53612 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
613 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47614
[email protected]3916c97e2010-02-25 03:20:50615 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50616 BufferManager* buffer_manager() {
617 return group_->buffer_manager();
618 }
619
[email protected]a25fa872010-03-25 02:57:58620 RenderbufferManager* renderbuffer_manager() {
621 return group_->renderbuffer_manager();
622 }
623
624 FramebufferManager* framebuffer_manager() {
625 return group_->framebuffer_manager();
626 }
627
[email protected]3916c97e2010-02-25 03:20:50628 ProgramManager* program_manager() {
629 return group_->program_manager();
630 }
631
632 ShaderManager* shader_manager() {
633 return group_->shader_manager();
634 }
635
636 TextureManager* texture_manager() {
637 return group_->texture_manager();
638 }
639
[email protected]78b514b2012-05-01 21:50:59640 MailboxManager* mailbox_manager() {
641 return group_->mailbox_manager();
642 }
643
[email protected]34ff8b0c2010-10-01 20:06:02644 bool IsOffscreenBufferMultisampled() const {
645 return offscreen_target_samples_ > 1;
646 }
647
[email protected]a93bb842010-02-16 23:03:47648 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03649 TextureManager::TextureInfo* CreateTextureInfo(
650 GLuint client_id, GLuint service_id) {
[email protected]80eb6b52012-01-19 00:14:41651 return texture_manager()->CreateTextureInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47652 }
653
654 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03655 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50656 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03657 texture_manager()->GetTextureInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10658 return info;
[email protected]a93bb842010-02-16 23:03:47659 }
660
661 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03662 void RemoveTextureInfo(GLuint client_id) {
[email protected]80eb6b52012-01-19 00:14:41663 texture_manager()->RemoveTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50664 }
[email protected]a93bb842010-02-16 23:03:47665
[email protected]d37231fa2010-04-09 21:16:02666 // Get the size (in pixels) of the currently bound frame buffer (either FBO
667 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30668 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02669
[email protected]9edc6b22010-12-23 02:00:26670 // Get the format of the currently bound frame buffer (either FBO or regular
671 // back buffer)
672 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46673 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26674
[email protected]a93bb842010-02-16 23:03:47675 // Wrapper for CompressedTexImage2D commands.
676 error::Error DoCompressedTexImage2D(
677 GLenum target,
678 GLint level,
679 GLenum internal_format,
680 GLsizei width,
681 GLsizei height,
682 GLint border,
683 GLsizei image_size,
684 const void* data);
685
[email protected]cadde4a2010-07-31 17:10:43686 // Wrapper for CompressedTexSubImage2D.
687 void DoCompressedTexSubImage2D(
688 GLenum target,
689 GLint level,
690 GLint xoffset,
691 GLint yoffset,
692 GLsizei width,
693 GLsizei height,
694 GLenum format,
695 GLsizei imageSize,
696 const void * data);
697
698 // Wrapper for CopyTexImage2D.
699 void DoCopyTexImage2D(
700 GLenum target,
701 GLint level,
702 GLenum internal_format,
703 GLint x,
704 GLint y,
705 GLsizei width,
706 GLsizei height,
707 GLint border);
708
709 // Wrapper for CopyTexSubImage2D.
710 void DoCopyTexSubImage2D(
711 GLenum target,
712 GLint level,
713 GLint xoffset,
714 GLint yoffset,
715 GLint x,
716 GLint y,
717 GLsizei width,
718 GLsizei height);
719
[email protected]a93bb842010-02-16 23:03:47720 // Wrapper for TexImage2D commands.
721 error::Error DoTexImage2D(
722 GLenum target,
723 GLint level,
724 GLenum internal_format,
725 GLsizei width,
726 GLsizei height,
727 GLint border,
728 GLenum format,
729 GLenum type,
730 const void* pixels,
731 uint32 pixels_size);
732
[email protected]cadde4a2010-07-31 17:10:43733 // Wrapper for TexSubImage2D.
734 void DoTexSubImage2D(
735 GLenum target,
736 GLint level,
737 GLint xoffset,
738 GLint yoffset,
739 GLsizei width,
740 GLsizei height,
741 GLenum format,
742 GLenum type,
743 const void * data);
744
[email protected]e51bdf32011-11-23 22:21:46745 // Wrapper for TexImageIOSurface2DCHROMIUM.
746 void DoTexImageIOSurface2DCHROMIUM(
747 GLenum target,
748 GLsizei width,
749 GLsizei height,
750 GLuint io_surface_id,
751 GLuint plane);
752
[email protected]43410e92012-04-20 17:06:28753 void DoCopyTextureCHROMIUM(
754 GLenum target,
755 GLuint source_id,
756 GLuint target_id,
[email protected]0a1e9ad2012-05-04 21:13:03757 GLint level,
758 GLenum internal_format);
[email protected]43410e92012-04-20 17:06:28759
[email protected]97dc7cbe2011-12-06 17:26:17760 // Wrapper for TexStorage2DEXT.
761 void DoTexStorage2DEXT(
762 GLenum target,
763 GLint levels,
764 GLenum internal_format,
765 GLsizei width,
766 GLsizei height);
767
[email protected]78b514b2012-05-01 21:50:59768 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
769 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
770
[email protected]a93bb842010-02-16 23:03:47771 // Creates a ProgramInfo for the given program.
[email protected]d685a682011-04-29 16:19:57772 ProgramManager::ProgramInfo* CreateProgramInfo(
773 GLuint client_id, GLuint service_id) {
774 return program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47775 }
776
[email protected]07f54fcc2009-12-22 02:46:30777 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03778 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14779 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46780 }
[email protected]07f54fcc2009-12-22 02:46:30781
[email protected]6b8cf1a2010-05-06 16:13:58782 // Gets the program info for the given program. If it's not a program
783 // generates a GL error. Returns NULL if not program.
784 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
785 GLuint client_id, const char* function_name) {
786 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
787 if (!info) {
788 if (GetShaderInfo(client_id)) {
[email protected]ad84a3a2012-06-08 21:42:43789 SetGLError(
790 GL_INVALID_OPERATION, function_name, "shader passed for program");
[email protected]6b8cf1a2010-05-06 16:13:58791 } else {
[email protected]ad84a3a2012-06-08 21:42:43792 SetGLError(GL_INVALID_VALUE, function_name, "unknown program");
[email protected]6b8cf1a2010-05-06 16:13:58793 }
794 }
795 return info;
796 }
797
798
[email protected]45bf5152010-02-12 00:11:31799 // Creates a ShaderInfo for the given shader.
[email protected]d685a682011-04-29 16:19:57800 ShaderManager::ShaderInfo* CreateShaderInfo(
801 GLuint client_id,
802 GLuint service_id,
803 GLenum shader_type) {
804 return shader_manager()->CreateShaderInfo(
805 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31806 }
807
808 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03809 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14810 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31811 }
812
[email protected]6b8cf1a2010-05-06 16:13:58813 // Gets the shader info for the given shader. If it's not a shader generates a
814 // GL error. Returns NULL if not shader.
815 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
816 GLuint client_id, const char* function_name) {
817 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
818 if (!info) {
819 if (GetProgramInfo(client_id)) {
820 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:43821 GL_INVALID_OPERATION, function_name, "program passed for shader");
[email protected]6b8cf1a2010-05-06 16:13:58822 } else {
[email protected]ad84a3a2012-06-08 21:42:43823 SetGLError(
824 GL_INVALID_VALUE, function_name, "unknown shader");
[email protected]6b8cf1a2010-05-06 16:13:58825 }
826 }
827 return info;
828 }
829
[email protected]a93bb842010-02-16 23:03:47830 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03831 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
832 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47833 }
834
[email protected]07f54fcc2009-12-22 02:46:30835 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03836 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
837 BufferManager::BufferInfo* info =
838 buffer_manager()->GetBufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10839 return info;
[email protected]1d32bc82010-01-13 22:06:46840 }
[email protected]07f54fcc2009-12-22 02:46:30841
[email protected]a93bb842010-02-16 23:03:47842 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
843 // on glDeleteBuffers so we can make sure the user does not try to render
844 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03845 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47846
[email protected]a25fa872010-03-25 02:57:58847 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03848 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
849 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58850 }
851
852 // Gets the framebuffer info for the given framebuffer.
853 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03854 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58855 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03856 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10857 return info;
[email protected]a25fa872010-03-25 02:57:58858 }
859
860 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03861 void RemoveFramebufferInfo(GLuint client_id) {
862 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58863 }
864
865 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03866 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
867 return renderbuffer_manager()->CreateRenderbufferInfo(
868 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58869 }
870
871 // Gets the renderbuffer info for the given renderbuffer.
872 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03873 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58874 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03875 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10876 return info;
[email protected]a25fa872010-03-25 02:57:58877 }
878
879 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03880 void RemoveRenderbufferInfo(GLuint client_id) {
881 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58882 }
883
[email protected]258a3313f2011-10-18 20:13:57884 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
[email protected]2be6abf32012-06-26 00:28:33885 void DoBindUniformLocationCHROMIUM(
886 GLuint client_id, GLint location, const char* name);
[email protected]258a3313f2011-10-18 20:13:57887
[email protected]558847a2010-03-24 07:02:54888 error::Error GetAttribLocationHelper(
889 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
890 const std::string& name_str);
891
892 error::Error GetUniformLocationHelper(
893 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
894 const std::string& name_str);
895
[email protected]3916c97e2010-02-25 03:20:50896 // Helper for glShaderSource.
897 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03898 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30899
[email protected]0d6bfdc2011-11-02 01:32:20900 // Clear any textures used by the current program.
901 bool ClearUnclearedTextures();
902
903 // Clear any uncleared level in texture.
904 // Returns false if there was a generated GL error.
905 bool ClearTexture(TextureManager::TextureInfo* info);
906
907 // Clears any uncleared attachments attached to the given frame buffer.
908 // Returns false if there was a generated GL error.
909 void ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:30910 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28911
[email protected]0d6bfdc2011-11-02 01:32:20912 // overridden from GLES2Decoder
913 virtual bool ClearLevel(
914 unsigned service_id,
915 unsigned bind_target,
916 unsigned target,
917 int level,
918 unsigned format,
919 unsigned type,
920 int width,
[email protected]4502e6492011-12-14 19:39:15921 int height,
922 bool is_texture_immutable);
[email protected]0d6bfdc2011-11-02 01:32:20923
[email protected]c007aa02010-09-02 22:22:40924 // Restore all GL state that affects clearing.
925 void RestoreClearState();
926
[email protected]3a2e7c7b2010-08-06 01:12:28927 // Remembers the state of some capabilities.
[email protected]297ca1c2011-06-20 23:08:46928 // Returns: true if glEnable/glDisable should actually be called.
929 bool SetCapabilityState(GLenum cap, bool enabled);
[email protected]3a2e7c7b2010-08-06 01:12:28930
[email protected]0d6bfdc2011-11-02 01:32:20931 // Check that the currently bound framebuffers are valid.
932 // Generates GL error if not.
933 bool CheckBoundFramebuffersValid(const char* func_name);
934
935 // Check if a framebuffer meets our requirements.
936 bool CheckFramebufferValid(
937 FramebufferManager::FramebufferInfo* framebuffer,
938 GLenum target,
939 const char* func_name);
[email protected]3a03a8f2011-03-19 00:51:27940
[email protected]939e7362010-05-13 20:49:10941 // Checks if the current program exists and is valid. If not generates the
942 // appropriate GL error. Returns true if the current program is in a usable
943 // state.
944 bool CheckCurrentProgram(const char* function_name);
945
946 // Checks if the current program exists and is valid and that location is not
947 // -1. If the current program is not valid generates the appropriate GL
948 // error. Returns true if the current program is in a usable state and
949 // location is not -1.
950 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
951
952 // Gets the type of a uniform for a location in the current program. Sets GL
953 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:36954 // program is valid and the location exists. Adjusts count so it
955 // does not overflow the uniform.
956 bool PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:12957 GLint fake_location, const char* function_name,
958 GLint* real_location, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:10959
[email protected]b177ae22011-11-01 03:29:11960 // Gets the service id for any simulated backbuffer fbo.
961 GLuint GetBackbufferServiceId();
962
[email protected]b273e432010-04-12 17:23:58963 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
964 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
965
[email protected]96449d2c2009-11-25 00:01:32966 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03967 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32968
969 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03970 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32971
[email protected]3916c97e2010-02-25 03:20:50972 // Wrapper for glActiveTexture
973 void DoActiveTexture(GLenum texture_unit);
974
[email protected]ae51d192010-04-27 00:48:03975 // Wrapper for glAttachShader
976 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
977
[email protected]96449d2c2009-11-25 00:01:32978 // Wrapper for glBindBuffer since we need to track the current targets.
979 void DoBindBuffer(GLenum target, GLuint buffer);
980
[email protected]86093972010-03-11 00:13:56981 // Wrapper for glBindFramebuffer since we need to track the current targets.
982 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
983
984 // Wrapper for glBindRenderbuffer since we need to track the current targets.
985 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
986
[email protected]a93bb842010-02-16 23:03:47987 // Wrapper for glBindTexture since we need to track the current targets.
988 void DoBindTexture(GLenum target, GLuint texture);
989
[email protected]8e3e0662010-08-23 18:46:30990 // Wrapper for glBlitFramebufferEXT.
991 void DoBlitFramebufferEXT(
992 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
993 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
994 GLbitfield mask, GLenum filter);
995
[email protected]36cef8ce2010-03-16 07:34:45996 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:11997 void DoBufferData(
998 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
999
[email protected]36cef8ce2010-03-16 07:34:451000 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:111001 void DoBufferSubData(
1002 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1003
[email protected]36cef8ce2010-03-16 07:34:451004 // Wrapper for glCheckFramebufferStatus
1005 GLenum DoCheckFramebufferStatus(GLenum target);
1006
[email protected]3a03a8f2011-03-19 00:51:271007 // Wrapper for glClear
[email protected]a7266a92012-06-28 02:11:081008 error::Error DoClear(GLbitfield mask);
[email protected]3a03a8f2011-03-19 00:51:271009
[email protected]3a2e7c7b2010-08-06 01:12:281010 // Wrappers for clear and mask settings functions.
1011 void DoClearColor(
1012 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
1013 void DoClearDepthf(GLclampf depth);
1014 void DoClearStencil(GLint s);
1015 void DoColorMask(
1016 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
1017 void DoDepthMask(GLboolean depth);
1018 void DoStencilMask(GLuint mask);
1019 void DoStencilMaskSeparate(GLenum face, GLuint mask);
1020
[email protected]45bf5152010-02-12 00:11:311021 // Wrapper for glCompileShader.
1022 void DoCompileShader(GLuint shader);
1023
[email protected]269200b12010-11-18 22:53:061024 // Helper for DeleteSharedIdsCHROMIUM commands.
1025 void DoDeleteSharedIdsCHROMIUM(
1026 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101027
[email protected]ae51d192010-04-27 00:48:031028 // Wrapper for glDetachShader
1029 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1030
[email protected]3a2e7c7b2010-08-06 01:12:281031 // Wrapper for glDisable
1032 void DoDisable(GLenum cap);
1033
[email protected]07f54fcc2009-12-22 02:46:301034 // Wrapper for glDisableVertexAttribArray.
1035 void DoDisableVertexAttribArray(GLuint index);
1036
[email protected]3a2e7c7b2010-08-06 01:12:281037 // Wrapper for glEnable
1038 void DoEnable(GLenum cap);
1039
[email protected]07f54fcc2009-12-22 02:46:301040 // Wrapper for glEnableVertexAttribArray.
1041 void DoEnableVertexAttribArray(GLuint index);
1042
[email protected]882ba1e22012-03-08 19:02:531043 // Wrapper for glFinish.
1044 void DoFinish();
1045
1046 // Wrapper for glFlush.
1047 void DoFlush();
1048
[email protected]36cef8ce2010-03-16 07:34:451049 // Wrapper for glFramebufferRenderbufffer.
1050 void DoFramebufferRenderbuffer(
1051 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1052 GLuint renderbuffer);
1053
1054 // Wrapper for glFramebufferTexture2D.
1055 void DoFramebufferTexture2D(
1056 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1057 GLint level);
1058
[email protected]a93bb842010-02-16 23:03:471059 // Wrapper for glGenerateMipmap
1060 void DoGenerateMipmap(GLenum target);
1061
[email protected]269200b12010-11-18 22:53:061062 // Helper for GenSharedIdsCHROMIUM commands.
1063 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:101064 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1065
[email protected]b273e432010-04-12 17:23:581066 // Wrapper for DoGetBooleanv.
1067 void DoGetBooleanv(GLenum pname, GLboolean* params);
1068
1069 // Wrapper for DoGetFloatv.
1070 void DoGetFloatv(GLenum pname, GLfloat* params);
1071
[email protected]36cef8ce2010-03-16 07:34:451072 // Wrapper for glGetFramebufferAttachmentParameteriv.
1073 void DoGetFramebufferAttachmentParameteriv(
1074 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1075
[email protected]a0c3e972010-04-21 00:49:131076 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581077 void DoGetIntegerv(GLenum pname, GLint* params);
1078
[email protected]29a9eb52010-04-13 09:04:231079 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:061080 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:231081 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1082
[email protected]a0c3e972010-04-21 00:49:131083 // Wrapper for glGetProgramiv.
1084 void DoGetProgramiv(
1085 GLuint program_id, GLenum pname, GLint* params);
1086
[email protected]36cef8ce2010-03-16 07:34:451087 // Wrapper for glRenderbufferParameteriv.
1088 void DoGetRenderbufferParameteriv(
1089 GLenum target, GLenum pname, GLint* params);
1090
[email protected]ddd968b82010-03-02 00:44:291091 // Wrapper for glGetShaderiv
1092 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1093
[email protected]b1122982010-05-17 23:04:241094 // Wrappers for glGetVertexAttrib.
1095 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1096 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1097
[email protected]1958e0e2010-04-22 05:17:151098 // Wrappers for glIsXXX functions.
[email protected]3dc69c42012-05-12 02:29:241099 bool DoIsEnabled(GLenum cap);
[email protected]1958e0e2010-04-22 05:17:151100 bool DoIsBuffer(GLuint client_id);
1101 bool DoIsFramebuffer(GLuint client_id);
1102 bool DoIsProgram(GLuint client_id);
1103 bool DoIsRenderbuffer(GLuint client_id);
1104 bool DoIsShader(GLuint client_id);
1105 bool DoIsTexture(GLuint client_id);
1106
[email protected]07f54fcc2009-12-22 02:46:301107 // Wrapper for glLinkProgram
1108 void DoLinkProgram(GLuint program);
1109
[email protected]269200b12010-11-18 22:53:061110 // Helper for RegisterSharedIdsCHROMIUM.
1111 void DoRegisterSharedIdsCHROMIUM(
1112 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101113
[email protected]36cef8ce2010-03-16 07:34:451114 // Wrapper for glRenderbufferStorage.
1115 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031116 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451117
[email protected]8e3e0662010-08-23 18:46:301118 // Wrapper for glRenderbufferStorageMultisampleEXT.
1119 void DoRenderbufferStorageMultisample(
1120 GLenum target, GLsizei samples, GLenum internalformat,
1121 GLsizei width, GLsizei height);
1122
[email protected]b273e432010-04-12 17:23:581123 // Wrapper for glReleaseShaderCompiler.
1124 void DoReleaseShaderCompiler() { }
1125
[email protected]3916c97e2010-02-25 03:20:501126 // Wrappers for glTexParameter functions.
1127 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1128 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1129 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1130 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1131
1132 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1133 // spec only these 2 functions can be used to set sampler uniforms.
[email protected]1b0a6752012-02-22 03:44:121134 void DoUniform1i(GLint fake_location, GLint v0);
1135 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1136 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1137 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1138 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101139
1140 // Wrappers for glUniformfv because some drivers don't correctly accept
1141 // bool uniforms.
[email protected]1b0a6752012-02-22 03:44:121142 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1143 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1144 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1145 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501146
[email protected]43c2f1f2011-03-25 18:35:361147 void DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:121148 GLint fake_location, GLsizei count, GLboolean transpose,
1149 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361150 void DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:121151 GLint fake_location, GLsizei count, GLboolean transpose,
1152 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361153 void DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:121154 GLint fake_location, GLsizei count, GLboolean transpose,
1155 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361156
[email protected]b1122982010-05-17 23:04:241157 // Wrappers for glVertexAttrib??
1158 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1159 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1160 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1161 void DoVertexAttrib4f(
1162 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1163 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1164 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1165 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1166 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1167
[email protected]43410e92012-04-20 17:06:281168 // Wrapper for glViewport
1169 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1170
[email protected]07f54fcc2009-12-22 02:46:301171 // Wrapper for glUseProgram
1172 void DoUseProgram(GLuint program);
1173
[email protected]ae51d192010-04-27 00:48:031174 // Wrapper for glValidateProgram.
1175 void DoValidateProgram(GLuint program_client_id);
1176
[email protected]4e8a5b122010-05-08 22:00:101177 // Gets the number of values that will be returned by glGetXXX. Returns
1178 // false if pname is unknown.
1179 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1180
[email protected]1002c2d2011-06-28 22:39:041181 // Gets the GLError and stores it in our wrapper. Effectively
1182 // this lets us peek at the error without losing it.
1183 GLenum PeekGLError();
1184
[email protected]07f54fcc2009-12-22 02:46:301185 // Copies the real GL errors to the wrapper. This is so we can
1186 // make sure there are no native GL errors before calling some GL function
1187 // so that on return we know any error generated was for that specific
1188 // command.
1189 void CopyRealGLErrorsToWrapper();
1190
[email protected]6217d392010-03-25 22:08:351191 // Clear all real GL errors. This is to prevent the client from seeing any
1192 // errors caused by GL calls that it was not responsible for issuing.
1193 void ClearRealGLErrors();
1194
[email protected]07f54fcc2009-12-22 02:46:301195 // Checks if the current program and vertex attributes are valid for drawing.
[email protected]ad84a3a2012-06-08 21:42:431196 bool IsDrawValid(
1197 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount);
[email protected]07f54fcc2009-12-22 02:46:301198
[email protected]c13e1da62011-09-09 21:48:301199 // Returns true if successful, simulated will be true if attrib0 was
1200 // simulated.
[email protected]c6aef902012-02-14 03:31:421201 bool SimulateAttrib0(
[email protected]ad84a3a2012-06-08 21:42:431202 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
[email protected]43410e92012-04-20 17:06:281203 void RestoreStateForAttrib(GLuint attrib);
[email protected]b1122982010-05-17 23:04:241204
[email protected]ef526492010-06-02 23:12:251205 // Returns true if textures were set.
1206 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501207 void RestoreStateForNonRenderableTextures();
1208
[email protected]8fbedc02010-11-18 18:43:401209 // Returns true if GL_FIXED attribs were simulated.
[email protected]c6aef902012-02-14 03:31:421210 bool SimulateFixedAttribs(
[email protected]ad84a3a2012-06-08 21:42:431211 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421212 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
[email protected]8fbedc02010-11-18 18:43:401213 void RestoreStateForSimulatedFixedAttribs();
1214
[email protected]c6aef902012-02-14 03:31:421215 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1216 // cases (primcount is 0 for non-instanced).
1217 error::Error DoDrawArrays(
[email protected]ad84a3a2012-06-08 21:42:431218 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421219 bool instanced, GLenum mode, GLint first, GLsizei count,
1220 GLsizei primcount);
1221 error::Error DoDrawElements(
[email protected]ad84a3a2012-06-08 21:42:431222 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421223 bool instanced, GLenum mode, GLsizei count, GLenum type,
1224 int32 offset, GLsizei primcount);
1225
[email protected]07f54fcc2009-12-22 02:46:301226 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501227 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301228 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501229 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1230 bound_array_buffer_ : bound_element_array_buffer_;
[email protected]a0b78dc2011-11-11 10:43:101231 return info;
[email protected]07f54fcc2009-12-22 02:46:301232 }
1233
[email protected]a93bb842010-02-16 23:03:471234 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501235 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1236 TextureUnit& unit = texture_units_[active_texture_unit_];
1237 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471238 switch (target) {
1239 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501240 info = unit.bound_texture_2d;
1241 break;
[email protected]a93bb842010-02-16 23:03:471242 case GL_TEXTURE_CUBE_MAP:
1243 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1244 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1245 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1246 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1247 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1248 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501249 info = unit.bound_texture_cube_map;
1250 break;
[email protected]61eeb33f2011-07-26 15:30:311251 case GL_TEXTURE_EXTERNAL_OES:
1252 info = unit.bound_texture_external_oes;
1253 break;
[email protected]e51bdf32011-11-23 22:21:461254 case GL_TEXTURE_RECTANGLE_ARB:
1255 info = unit.bound_texture_rectangle_arb;
1256 break;
[email protected]a93bb842010-02-16 23:03:471257 default:
1258 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501259 return NULL;
[email protected]a93bb842010-02-16 23:03:471260 }
[email protected]a0b78dc2011-11-11 10:43:101261 return info;
[email protected]a93bb842010-02-16 23:03:471262 }
1263
[email protected]61eeb33f2011-07-26 15:30:311264 GLenum GetBindTargetForSamplerType(GLenum type) {
1265 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:461266 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1267 switch (type) {
1268 case GL_SAMPLER_2D:
1269 return GL_TEXTURE_2D;
1270 case GL_SAMPLER_CUBE:
1271 return GL_TEXTURE_CUBE_MAP;
1272 case GL_SAMPLER_EXTERNAL_OES:
1273 return GL_TEXTURE_EXTERNAL_OES;
1274 case GL_SAMPLER_2D_RECT_ARB:
1275 return GL_TEXTURE_RECTANGLE_ARB;
1276 }
1277
1278 NOTREACHED();
1279 return 0;
[email protected]61eeb33f2011-07-26 15:30:311280 }
1281
[email protected]8e3e0662010-08-23 18:46:301282 // Gets the framebuffer info for a particular target.
1283 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1284 GLenum target) {
1285 FramebufferManager::FramebufferInfo* info = NULL;
1286 switch (target) {
1287 case GL_FRAMEBUFFER:
1288 case GL_DRAW_FRAMEBUFFER:
1289 info = bound_draw_framebuffer_;
1290 break;
1291 case GL_READ_FRAMEBUFFER:
1292 info = bound_read_framebuffer_;
1293 break;
1294 default:
1295 NOTREACHED();
1296 break;
1297 }
[email protected]a0b78dc2011-11-11 10:43:101298 return info;
[email protected]8e3e0662010-08-23 18:46:301299 }
1300
[email protected]0d6bfdc2011-11-02 01:32:201301 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfoForTarget(
1302 GLenum target) {
1303 RenderbufferManager::RenderbufferInfo* info = NULL;
1304 switch (target) {
1305 case GL_RENDERBUFFER:
1306 info = bound_renderbuffer_;
1307 break;
1308 default:
1309 NOTREACHED();
1310 break;
1311 }
[email protected]a0b78dc2011-11-11 10:43:101312 return info;
[email protected]0d6bfdc2011-11-02 01:32:201313 }
1314
[email protected]f7b85372010-02-03 01:11:371315 // Validates the program and location for a glGetUniform call and returns
1316 // a SizeResult setup to receive the result. Returns true if glGetUniform
1317 // should be called.
1318 bool GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:121319 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:371320 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:121321 error::Error* error, GLint* real_location, GLuint* service_id,
1322 void** result, GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371323
[email protected]1078f912011-12-23 13:12:141324 // Computes the estimated memory used for the backbuffer and passes it to
1325 // the tracing system.
[email protected]260ddc4e2012-06-28 00:01:531326 size_t GetBackbufferMemoryTotal();
[email protected]1078f912011-12-23 13:12:141327
[email protected]38d139d2011-07-14 00:38:431328 // Returns true if the context was just lost due to e.g. GL_ARB_robustness.
1329 bool WasContextLost();
1330
[email protected]e51bdf32011-11-23 22:21:461331#if defined(OS_MACOSX)
1332 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1333#endif
1334
[email protected]81375742012-06-08 00:04:001335 // Validates the combination of texture parameters. For example validates that
1336 // for a given format the specific type, level and targets are valid.
1337 // Synthesizes the correct GL error if invalid. Returns true if valid.
1338 bool ValidateTextureParameters(
1339 const char* function_name,
1340 GLenum target, GLenum format, GLenum type, GLint level);
1341
[email protected]ad84a3a2012-06-08 21:42:431342 bool ValidateCompressedTexDimensions(
1343 const char* function_name,
1344 GLint level, GLsizei width, GLsizei height, GLenum format);
1345 bool ValidateCompressedTexFuncData(
1346 const char* function_name,
1347 GLsizei width, GLsizei height, GLenum format, size_t size);
1348 bool ValidateCompressedTexSubDimensions(
1349 const char* function_name,
1350 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1351 GLsizei width, GLsizei height, GLenum format,
1352 TextureManager::TextureInfo* texture);
1353
[email protected]0f8afe82012-05-14 23:43:011354 void LogMessage(const std::string& msg);
1355 void RenderWarning(const std::string& msg);
1356 void PerformanceWarning(const std::string& msg);
1357
[email protected]a7266a92012-06-28 02:11:081358 bool ShouldDeferDraws() {
1359 return !offscreen_target_frame_buffer_.get() &&
1360 bound_draw_framebuffer_ == NULL &&
1361 surface_->DeferDraws();
1362 }
1363
[email protected]96449d2c2009-11-25 00:01:321364 // Generate a member function prototype for each command in an automated and
1365 // typesafe way.
1366 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141367 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191368 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321369 const gles2::name& args); \
1370
1371 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1372
1373 #undef GLES2_CMD_OP
1374
[email protected]2f2d7042010-04-14 21:45:581375 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381376 scoped_refptr<gfx::GLSurface> surface_;
1377 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021378
[email protected]a3ded6d2010-10-19 06:44:391379 // The ContextGroup for this decoder uses to track resources.
1380 ContextGroup::Ref group_;
1381
[email protected]6217d392010-03-25 22:08:351382 // A parent decoder can access this decoders saved offscreen frame buffer.
1383 // The parent pointer is reset if the parent is destroyed.
1384 base::WeakPtr<GLES2DecoderImpl> parent_;
1385
[email protected]34ff8b0c2010-10-01 20:06:021386 // Current width and height of the offscreen frame buffer.
1387 gfx::Size offscreen_size_;
1388
[email protected]96449d2c2009-11-25 00:01:321389 // Current GL error bits.
1390 uint32 error_bits_;
1391
[email protected]96449d2c2009-11-25 00:01:321392 // Util to help with GL.
1393 GLES2Util util_;
1394
1395 // pack alignment as last set by glPixelStorei
1396 GLint pack_alignment_;
1397
1398 // unpack alignment as last set by glPixelStorei
1399 GLint unpack_alignment_;
1400
[email protected]43410e92012-04-20 17:06:281401 // unpack flip y as last set by glPixelStorei
1402 bool unpack_flip_y_;
1403
[email protected]6c75c712012-06-19 15:43:171404 // unpack (un)premultiply alpha as last set by glPixelStorei
[email protected]43410e92012-04-20 17:06:281405 bool unpack_premultiply_alpha_;
[email protected]6c75c712012-06-19 15:43:171406 bool unpack_unpremultiply_alpha_;
[email protected]43410e92012-04-20 17:06:281407
[email protected]96449d2c2009-11-25 00:01:321408 // The currently bound array buffer. If this is 0 it is illegal to call
1409 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501410 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321411
1412 // The currently bound element array buffer. If this is 0 it is illegal
1413 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501414 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301415
[email protected]f39f4b3f2010-05-12 17:04:081416 // Class that manages vertex attribs.
[email protected]3757a372012-01-19 05:20:441417 scoped_ptr<VertexAttribManager> vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301418
[email protected]b1122982010-05-17 23:04:241419 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1420 GLuint attrib_0_buffer_id_;
1421
1422 // The value currently in attrib_0.
1423 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1424
[email protected]fc753442011-02-04 19:49:491425 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1426 bool attrib_0_buffer_matches_value_;
1427
[email protected]b1122982010-05-17 23:04:241428 // The size of attrib 0.
1429 GLsizei attrib_0_size_;
1430
[email protected]8fbedc02010-11-18 18:43:401431 // The buffer used to simulate GL_FIXED attribs.
1432 GLuint fixed_attrib_buffer_id_;
1433
1434 // The size of fiixed attrib buffer.
1435 GLsizei fixed_attrib_buffer_size_;
1436
[email protected]3916c97e2010-02-25 03:20:501437 // Current active texture by 0 - n index.
1438 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1439 // be 2.
1440 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301441
[email protected]3916c97e2010-02-25 03:20:501442 // Which textures are bound to texture units through glActiveTexture.
1443 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471444
[email protected]3a2e7c7b2010-08-06 01:12:281445 // state saved for clearing so we can clear render buffers and then
1446 // restore to these values.
1447 GLclampf clear_red_;
1448 GLclampf clear_green_;
1449 GLclampf clear_blue_;
1450 GLclampf clear_alpha_;
1451 GLboolean mask_red_;
1452 GLboolean mask_green_;
1453 GLboolean mask_blue_;
1454 GLboolean mask_alpha_;
1455 GLint clear_stencil_;
1456 GLuint mask_stencil_front_;
1457 GLuint mask_stencil_back_;
1458 GLclampf clear_depth_;
1459 GLboolean mask_depth_;
[email protected]0a1e9ad2012-05-04 21:13:031460 bool enable_blend_;
[email protected]43410e92012-04-20 17:06:281461 bool enable_cull_face_;
[email protected]3a2e7c7b2010-08-06 01:12:281462 bool enable_scissor_test_;
[email protected]297ca1c2011-06-20 23:08:461463 bool enable_depth_test_;
1464 bool enable_stencil_test_;
1465 bool state_dirty_;
[email protected]3a2e7c7b2010-08-06 01:12:281466
[email protected]1d32bc82010-01-13 22:06:461467 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501468 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301469
[email protected]8e3e0662010-08-23 18:46:301470 // The currently bound framebuffers
1471 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1472 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561473
1474 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081475 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561476
[email protected]b9363b22010-06-09 22:06:151477 // The offscreen frame buffer that the client renders to. With EGL, the
1478 // depth and stencil buffers are separate. With regular GL there is a single
1479 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1480 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351481 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1482 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021483 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151484 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1485 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021486 GLenum offscreen_target_color_format_;
1487 GLenum offscreen_target_depth_format_;
1488 GLenum offscreen_target_stencil_format_;
1489 GLsizei offscreen_target_samples_;
[email protected]8a61d872012-01-20 12:43:561490 GLboolean offscreen_target_buffer_preserved_;
[email protected]6217d392010-03-25 22:08:351491
[email protected]de26b3c2011-08-03 21:54:271492 // The copy that is saved when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021493 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351494 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]8a61d872012-01-20 12:43:561495 TextureManager::TextureInfo::Ref offscreen_saved_color_texture_info_;
[email protected]de26b3c2011-08-03 21:54:271496
1497 // The copy that is used as the destination for multi-sample resolves.
1498 scoped_ptr<FrameBuffer> offscreen_resolved_frame_buffer_;
1499 scoped_ptr<Texture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051500 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351501
[email protected]882ba1e22012-03-08 19:02:531502 scoped_ptr<QueryManager> query_manager_;
1503 QueryManager::Query::Ref current_query_;
1504
[email protected]9d37f062011-11-22 01:24:521505 base::Callback<void(gfx::Size)> resize_callback_;
[email protected]22f320a2011-08-30 01:17:001506
[email protected]6b6e7ee2011-12-13 08:04:521507 MsgCallback msg_callback_;
[email protected]43f28f832010-02-03 02:28:481508
[email protected]b0af4f52011-09-28 22:04:421509 StreamTextureManager* stream_texture_manager_;
1510
[email protected]32fe9aa2011-01-21 23:47:131511 // The format of the back buffer_
1512 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461513 bool back_buffer_has_depth_;
1514 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131515
[email protected]473c01ccb2011-06-07 01:33:301516 bool teximage2d_faster_than_texsubimage2d_;
1517 bool bufferdata_faster_than_buffersubdata_;
1518
[email protected]8eee29c2010-04-29 03:38:291519 // The last error message set.
1520 std::string last_error_;
1521
[email protected]0f8afe82012-05-14 23:43:011522 int log_message_count_;
[email protected]fa20ec82012-05-04 04:02:481523
[email protected]a3a93e7b2010-08-28 00:48:561524 // The current decoder error.
1525 error::Error current_decoder_error_;
1526
[email protected]b1d2dcb2010-05-17 19:24:181527 bool use_shader_translator_;
[email protected]87fb6ab2012-06-13 22:28:041528 scoped_refptr<ShaderTranslator> vertex_translator_;
1529 scoped_refptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181530
[email protected]e82fb792011-09-22 00:33:291531 DisallowedFeatures disallowed_features_;
[email protected]c410da802011-03-14 19:17:411532
[email protected]915a59a12010-09-30 21:29:111533 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051534 const Validators* validators_;
[email protected]80eb6b52012-01-19 00:14:411535 FeatureInfo::Ref feature_info_;
[email protected]9438b012010-06-15 22:55:051536
[email protected]b493ee622011-04-13 23:52:001537 // This indicates all the following texSubImage2D calls that are part of the
1538 // failed texImage2D call should be ignored.
1539 bool tex_image_2d_failed_;
1540
[email protected]65225772011-05-12 21:10:241541 int frame_number_;
1542
[email protected]38d139d2011-07-14 00:38:431543 bool has_arb_robustness_;
1544 GLenum reset_status_;
1545
[email protected]75c023c2011-08-22 23:54:511546 bool needs_mac_nvidia_driver_workaround_;
[email protected]a2a0fe762011-09-20 00:59:121547 bool needs_glsl_built_in_function_emulation_;
[email protected]75c023c2011-08-22 23:54:511548
[email protected]f0d74742011-10-03 16:31:041549 // These flags are used to override the state of the shared feature_info_
1550 // member. Because the same FeatureInfo instance may be shared among many
1551 // contexts, the assumptions on the availablity of extensions in WebGL
1552 // contexts may be broken. These flags override the shared state to preserve
1553 // WebGL semantics.
1554 bool force_webgl_glsl_validation_;
1555 bool derivatives_explicitly_enabled_;
1556
[email protected]062c38b2012-01-18 03:25:101557 bool compile_shader_always_succeeds_;
1558
[email protected]e51bdf32011-11-23 22:21:461559#if defined(OS_MACOSX)
1560 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1561 TextureToIOSurfaceMap texture_to_io_surface_map_;
1562#endif
1563
[email protected]c826d732012-02-09 04:40:261564 typedef std::vector<GLES2DecoderImpl*> ChildList;
1565 ChildList children_;
1566
[email protected]43410e92012-04-20 17:06:281567 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1568
1569 // Cached values of the currently assigned viewport dimensions.
1570 GLint viewport_x_, viewport_y_;
1571 GLsizei viewport_width_, viewport_height_;
1572 GLsizei viewport_max_width_, viewport_max_height_;
1573
[email protected]96449d2c2009-11-25 00:01:321574 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1575};
1576
[email protected]6217d392010-03-25 22:08:351577ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1578 : decoder_(decoder) {
1579 decoder_->CopyRealGLErrorsToWrapper();
1580}
1581
1582ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1583 decoder_->ClearRealGLErrors();
1584}
1585
1586ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1587 GLuint id)
1588 : decoder_(decoder) {
1589 ScopedGLErrorSuppressor suppressor(decoder_);
1590
1591 // TODO(apatrick): Check if there are any other states that need to be reset
1592 // before binding a new texture.
1593 glActiveTexture(GL_TEXTURE0);
1594 glBindTexture(GL_TEXTURE_2D, id);
1595}
1596
1597ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1598 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301599 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351600}
1601
1602ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1603 GLuint id)
1604 : decoder_(decoder) {
1605 ScopedGLErrorSuppressor suppressor(decoder_);
1606 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1607}
1608
1609ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1610 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301611 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351612}
1613
1614ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1615 GLuint id)
1616 : decoder_(decoder) {
1617 ScopedGLErrorSuppressor suppressor(decoder_);
1618 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1619}
1620
1621ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1622 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301623 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351624}
1625
[email protected]34ff8b0c2010-10-01 20:06:021626ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271627 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521628 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021629 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1630 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]c0701082011-04-20 00:34:521631 (!decoder_->bound_read_framebuffer_.get() ||
1632 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021633 if (!resolve_and_bind_)
1634 return;
1635
1636 ScopedGLErrorSuppressor suppressor(decoder_);
1637 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1638 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271639 GLuint targetid;
1640 if (internal) {
1641 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1642 decoder_->offscreen_resolved_frame_buffer_.reset(
1643 new FrameBuffer(decoder_));
1644 decoder_->offscreen_resolved_frame_buffer_->Create();
1645 decoder_->offscreen_resolved_color_texture_.reset(new Texture(decoder_));
1646 decoder_->offscreen_resolved_color_texture_->Create();
1647
1648 DCHECK(decoder_->offscreen_saved_color_format_);
1649 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1650 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_);
[email protected]de26b3c2011-08-03 21:54:271651 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1652 decoder_->offscreen_resolved_color_texture_.get());
1653 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1654 GL_FRAMEBUFFER_COMPLETE) {
1655 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1656 << "because offscreen resolved FBO was incomplete.";
1657 return;
1658 }
1659 }
1660 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1661 } else {
1662 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1663 }
1664 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021665 const int width = decoder_->offscreen_size_.width();
1666 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181667 glDisable(GL_SCISSOR_TEST);
[email protected]57edfdad2012-02-07 04:57:151668 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021669 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1670 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1671 } else {
1672 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1673 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1674 }
[email protected]de26b3c2011-08-03 21:54:271675 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021676}
1677
1678ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1679 if (!resolve_and_bind_)
1680 return;
1681
1682 ScopedGLErrorSuppressor suppressor(decoder_);
1683 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181684 if (decoder_->enable_scissor_test_) {
1685 glEnable(GL_SCISSOR_TEST);
1686 }
[email protected]34ff8b0c2010-10-01 20:06:021687}
1688
[email protected]6217d392010-03-25 22:08:351689Texture::Texture(GLES2DecoderImpl* decoder)
1690 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141691 id_(0),
1692 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351693}
1694
1695Texture::~Texture() {
1696 // This does not destroy the render texture because that would require that
1697 // the associated GL context was current. Just check that it was explicitly
1698 // destroyed.
1699 DCHECK_EQ(id_, 0u);
1700}
1701
1702void Texture::Create() {
1703 ScopedGLErrorSuppressor suppressor(decoder_);
1704 Destroy();
1705 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581706 ScopedTexture2DBinder binder(decoder_, id_);
1707 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1708 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1709 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1710 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]62788802011-10-03 17:57:161711
1712 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1713 // never called on an offscreen context, no data will ever be uploaded to the
1714 // saved offscreen color texture (it is deferred until to when SwapBuffers
1715 // is called). My idea is that some nvidia drivers might have a bug where
1716 // deleting a texture that has never been populated might cause a
1717 // crash.
1718 glTexImage2D(
1719 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
[email protected]1078f912011-12-23 13:12:141720 estimated_size_ = 16u * 16u * 4u;
[email protected]260ddc4e2012-06-28 00:01:531721 TRACE_BACKBUFFER_MEMORY_TOTAL(decoder_);
[email protected]6217d392010-03-25 22:08:351722}
1723
[email protected]34ff8b0c2010-10-01 20:06:021724bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351725 DCHECK_NE(id_, 0u);
1726 ScopedGLErrorSuppressor suppressor(decoder_);
1727 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]6217d392010-03-25 22:08:351728
[email protected]f0e6a34f2012-01-04 20:53:401729 WrappedTexImage2D(GL_TEXTURE_2D,
1730 0, // mip level
1731 format,
1732 size.width(),
1733 size.height(),
1734 0, // border
1735 format,
1736 GL_UNSIGNED_BYTE,
1737 NULL);
[email protected]6217d392010-03-25 22:08:351738
[email protected]d37231fa2010-04-09 21:16:021739 size_ = size;
1740
[email protected]1078f912011-12-23 13:12:141741 bool success = glGetError() == GL_NO_ERROR;
1742 if (success) {
1743 uint32 image_size = 0;
[email protected]3458a64a2012-04-10 17:39:341744 GLES2Util::ComputeImageDataSizes(
1745 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 4, &image_size,
1746 NULL, NULL);
[email protected]1078f912011-12-23 13:12:141747 estimated_size_ = image_size;
[email protected]260ddc4e2012-06-28 00:01:531748 TRACE_BACKBUFFER_MEMORY_TOTAL(decoder_);
[email protected]1078f912011-12-23 13:12:141749 }
1750 return success;
[email protected]6217d392010-03-25 22:08:351751}
1752
[email protected]3a4d0c52011-06-29 23:11:581753void Texture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351754 DCHECK_NE(id_, 0u);
1755 ScopedGLErrorSuppressor suppressor(decoder_);
1756 ScopedTexture2DBinder binder(decoder_, id_);
1757 glCopyTexImage2D(GL_TEXTURE_2D,
1758 0, // level
[email protected]3a4d0c52011-06-29 23:11:581759 format,
[email protected]6217d392010-03-25 22:08:351760 0, 0,
1761 size.width(),
1762 size.height(),
1763 0); // border
1764}
1765
1766void Texture::Destroy() {
1767 if (id_ != 0) {
1768 ScopedGLErrorSuppressor suppressor(decoder_);
1769 glDeleteTextures(1, &id_);
1770 id_ = 0;
[email protected]1078f912011-12-23 13:12:141771 estimated_size_ = 0;
[email protected]260ddc4e2012-06-28 00:01:531772 TRACE_BACKBUFFER_MEMORY_TOTAL(decoder_);
[email protected]6217d392010-03-25 22:08:351773 }
1774}
1775
[email protected]97872062010-11-03 19:07:051776void Texture::Invalidate() {
1777 id_ = 0;
1778}
1779
[email protected]6217d392010-03-25 22:08:351780RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1781 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141782 id_(0),
1783 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351784}
1785
1786RenderBuffer::~RenderBuffer() {
1787 // This does not destroy the render buffer because that would require that
1788 // the associated GL context was current. Just check that it was explicitly
1789 // destroyed.
1790 DCHECK_EQ(id_, 0u);
1791}
1792
1793void RenderBuffer::Create() {
1794 ScopedGLErrorSuppressor suppressor(decoder_);
1795 Destroy();
1796 glGenRenderbuffersEXT(1, &id_);
1797}
1798
[email protected]34ff8b0c2010-10-01 20:06:021799bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1800 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351801 ScopedGLErrorSuppressor suppressor(decoder_);
1802 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021803 if (samples <= 1) {
1804 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1805 format,
1806 size.width(),
1807 size.height());
1808 } else {
[email protected]57edfdad2012-02-07 04:57:151809 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021810 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1811 samples,
1812 format,
1813 size.width(),
1814 size.height());
1815 } else {
1816 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1817 samples,
1818 format,
1819 size.width(),
1820 size.height());
1821 }
1822 }
[email protected]1078f912011-12-23 13:12:141823 bool success = glGetError() == GL_NO_ERROR;
1824 if (success) {
1825 estimated_size_ = size.width() * size.height() * samples *
1826 GLES2Util::RenderbufferBytesPerPixel(format);
[email protected]260ddc4e2012-06-28 00:01:531827 TRACE_BACKBUFFER_MEMORY_TOTAL(decoder_);
[email protected]1078f912011-12-23 13:12:141828 }
1829 return success;
[email protected]6217d392010-03-25 22:08:351830}
1831
1832void RenderBuffer::Destroy() {
1833 if (id_ != 0) {
1834 ScopedGLErrorSuppressor suppressor(decoder_);
1835 glDeleteRenderbuffersEXT(1, &id_);
1836 id_ = 0;
[email protected]1078f912011-12-23 13:12:141837 estimated_size_ = 0;
[email protected]260ddc4e2012-06-28 00:01:531838 TRACE_BACKBUFFER_MEMORY_TOTAL(decoder_);
[email protected]6217d392010-03-25 22:08:351839 }
1840}
1841
[email protected]97872062010-11-03 19:07:051842void RenderBuffer::Invalidate() {
1843 id_ = 0;
1844}
1845
[email protected]6217d392010-03-25 22:08:351846FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1847 : decoder_(decoder),
1848 id_(0) {
1849}
1850
1851FrameBuffer::~FrameBuffer() {
1852 // This does not destroy the frame buffer because that would require that
1853 // the associated GL context was current. Just check that it was explicitly
1854 // destroyed.
1855 DCHECK_EQ(id_, 0u);
1856}
1857
1858void FrameBuffer::Create() {
1859 ScopedGLErrorSuppressor suppressor(decoder_);
1860 Destroy();
1861 glGenFramebuffersEXT(1, &id_);
1862}
1863
1864void FrameBuffer::AttachRenderTexture(Texture* texture) {
1865 DCHECK_NE(id_, 0u);
1866 ScopedGLErrorSuppressor suppressor(decoder_);
1867 ScopedFrameBufferBinder binder(decoder_, id_);
1868 GLuint attach_id = texture ? texture->id() : 0;
1869 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1870 GL_COLOR_ATTACHMENT0,
1871 GL_TEXTURE_2D,
1872 attach_id,
1873 0);
1874}
1875
[email protected]b9363b22010-06-09 22:06:151876void FrameBuffer::AttachRenderBuffer(GLenum target,
1877 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351878 DCHECK_NE(id_, 0u);
1879 ScopedGLErrorSuppressor suppressor(decoder_);
1880 ScopedFrameBufferBinder binder(decoder_, id_);
1881 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1882 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151883 target,
[email protected]6217d392010-03-25 22:08:351884 GL_RENDERBUFFER,
1885 attach_id);
1886}
1887
[email protected]6217d392010-03-25 22:08:351888void FrameBuffer::Destroy() {
1889 if (id_ != 0) {
1890 ScopedGLErrorSuppressor suppressor(decoder_);
1891 glDeleteFramebuffersEXT(1, &id_);
1892 id_ = 0;
1893 }
1894}
1895
[email protected]97872062010-11-03 19:07:051896void FrameBuffer::Invalidate() {
1897 id_ = 0;
1898}
1899
[email protected]6217d392010-03-25 22:08:351900GLenum FrameBuffer::CheckStatus() {
1901 DCHECK_NE(id_, 0u);
1902 ScopedGLErrorSuppressor suppressor(decoder_);
1903 ScopedFrameBufferBinder binder(decoder_, id_);
1904 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1905}
1906
[email protected]aa7666122011-09-02 19:45:521907GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1908 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321909}
1910
[email protected]aa7666122011-09-02 19:45:521911GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391912 : GLES2Decoder(),
[email protected]3b1ecc262011-08-03 22:49:571913 group_(group),
[email protected]96449d2c2009-11-25 00:01:321914 error_bits_(0),
[email protected]96449d2c2009-11-25 00:01:321915 pack_alignment_(4),
1916 unpack_alignment_(4),
[email protected]43410e92012-04-20 17:06:281917 unpack_flip_y_(false),
1918 unpack_premultiply_alpha_(false),
[email protected]6c75c712012-06-19 15:43:171919 unpack_unpremultiply_alpha_(false),
[email protected]b1122982010-05-17 23:04:241920 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491921 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241922 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401923 fixed_attrib_buffer_id_(0),
1924 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501925 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281926 clear_red_(0),
1927 clear_green_(0),
1928 clear_blue_(0),
1929 clear_alpha_(0),
1930 mask_red_(true),
1931 mask_green_(true),
1932 mask_blue_(true),
1933 mask_alpha_(true),
1934 clear_stencil_(0),
1935 mask_stencil_front_(-1),
1936 mask_stencil_back_(-1),
1937 clear_depth_(1.0f),
1938 mask_depth_(true),
[email protected]0a1e9ad2012-05-04 21:13:031939 enable_blend_(false),
[email protected]43410e92012-04-20 17:06:281940 enable_cull_face_(false),
[email protected]3a2e7c7b2010-08-06 01:12:281941 enable_scissor_test_(false),
[email protected]297ca1c2011-06-20 23:08:461942 enable_depth_test_(false),
1943 enable_stencil_test_(false),
1944 state_dirty_(true),
[email protected]34ff8b0c2010-10-01 20:06:021945 offscreen_target_color_format_(0),
1946 offscreen_target_depth_format_(0),
1947 offscreen_target_stencil_format_(0),
1948 offscreen_target_samples_(0),
[email protected]8a61d872012-01-20 12:43:561949 offscreen_target_buffer_preserved_(true),
[email protected]97872062010-11-03 19:07:051950 offscreen_saved_color_format_(0),
[email protected]b0af4f52011-09-28 22:04:421951 stream_texture_manager_(NULL),
[email protected]32fe9aa2011-01-21 23:47:131952 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:461953 back_buffer_has_depth_(false),
1954 back_buffer_has_stencil_(false),
[email protected]473c01ccb2011-06-07 01:33:301955 teximage2d_faster_than_texsubimage2d_(true),
1956 bufferdata_faster_than_buffersubdata_(true),
[email protected]0f8afe82012-05-14 23:43:011957 log_message_count_(0),
[email protected]a3a93e7b2010-08-28 00:48:561958 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051959 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111960 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001961 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241962 tex_image_2d_failed_(false),
[email protected]38d139d2011-07-14 00:38:431963 frame_number_(0),
1964 has_arb_robustness_(false),
[email protected]75c023c2011-08-22 23:54:511965 reset_status_(GL_NO_ERROR),
[email protected]a2a0fe762011-09-20 00:59:121966 needs_mac_nvidia_driver_workaround_(false),
[email protected]f0d74742011-10-03 16:31:041967 needs_glsl_built_in_function_emulation_(false),
1968 force_webgl_glsl_validation_(false),
[email protected]062c38b2012-01-18 03:25:101969 derivatives_explicitly_enabled_(false),
[email protected]43410e92012-04-20 17:06:281970 compile_shader_always_succeeds_(false),
[email protected]43410e92012-04-20 17:06:281971 viewport_x_(0),
1972 viewport_y_(0),
1973 viewport_width_(0),
1974 viewport_height_(0),
1975 viewport_max_width_(0),
1976 viewport_max_height_(0) {
[email protected]3b1ecc262011-08-03 22:49:571977 DCHECK(group);
1978
[email protected]b1122982010-05-17 23:04:241979 attrib_0_value_.v[0] = 0.0f;
1980 attrib_0_value_.v[1] = 0.0f;
1981 attrib_0_value_.v[2] = 0.0f;
1982 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151983
[email protected]c2f8c8402010-12-06 18:07:241984 // The shader translator is used for WebGL even when running on EGL
1985 // because additional restrictions are needed (like only enabling
1986 // GL_OES_standard_derivatives on demand). It is used for the unit
1987 // tests because
1988 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1989 // empty string to CompileShader and this is not a valid shader.
1990 // TODO(apatrick): fix this test.
1991 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:041992 !feature_info_->feature_flags().chromium_webglsl &&
1993 !force_webgl_glsl_validation_) ||
[email protected]39ba4f02012-03-26 01:16:001994 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
1995 CommandLine::ForCurrentProcess()->HasSwitch(
1996 switches::kDisableGLSLTranslator)) {
[email protected]b9363b22010-06-09 22:06:151997 use_shader_translator_ = false;
1998 }
[email protected]473c01ccb2011-06-07 01:33:301999
2000 // TODO(gman): Consider setting these based on GPU and/or driver.
2001 if (IsAngle()) {
2002 teximage2d_faster_than_texsubimage2d_ = false;
2003 bufferdata_faster_than_buffersubdata_ = false;
2004 }
[email protected]96449d2c2009-11-25 00:01:322005}
2006
[email protected]80eb6b52012-01-19 00:14:412007GLES2DecoderImpl::~GLES2DecoderImpl() {
2008}
2009
[email protected]c410da802011-03-14 19:17:412010bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:382011 const scoped_refptr<gfx::GLSurface>& surface,
2012 const scoped_refptr<gfx::GLContext>& context,
[email protected]069944672012-04-25 20:52:232013 bool offscreen,
[email protected]c410da802011-03-14 19:17:412014 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:292015 const DisallowedFeatures& disallowed_features,
[email protected]c410da802011-03-14 19:17:412016 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:242017 const std::vector<int32>& attribs) {
[email protected]3551cb202012-05-24 10:55:322018 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
[email protected]63c9b052012-05-17 18:27:382019 DCHECK(context->IsCurrent(surface.get()));
[email protected]66791e382010-07-14 20:48:302020 DCHECK(!context_.get());
2021
[email protected]e844ae22012-01-14 03:36:262022 if (CommandLine::ForCurrentProcess()->HasSwitch(
2023 switches::kEnableGPUDebugging)) {
2024 set_debug(true);
2025 }
2026
[email protected]39ba4f02012-03-26 01:16:002027 if (CommandLine::ForCurrentProcess()->HasSwitch(
2028 switches::kEnableGPUCommandLogging)) {
2029 set_log_commands(true);
2030 }
2031
[email protected]062c38b2012-01-18 03:25:102032 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2033 switches::kCompileShaderAlwaysSucceeds);
2034
[email protected]f62a5ab2011-05-23 20:34:152035
[email protected]63c9b052012-05-17 18:27:382036 // Take ownership of the context and surface. The surface can be replaced with
2037 // SetSurface.
[email protected]fbe20372011-06-01 01:46:382038 context_ = context;
[email protected]63c9b052012-05-17 18:27:382039 surface_ = surface;
[email protected]eb54a562010-01-20 21:55:182040
[email protected]e82fb792011-09-22 00:33:292041 if (!group_->Initialize(disallowed_features, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:222042 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:392043 << "failed to initialize.";
[email protected]1871a092011-10-10 21:46:422044 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]63c9b052012-05-17 18:27:382045 Destroy(true);
[email protected]ae1741092010-11-17 19:16:032046 return false;
[email protected]a3ded6d2010-10-19 06:44:392047 }
[email protected]b64c24952012-04-19 03:20:272048 CHECK_GL_ERROR();
[email protected]43410e92012-04-20 17:06:282049
[email protected]e82fb792011-09-22 00:33:292050 disallowed_features_ = disallowed_features;
[email protected]246a70452010-03-05 21:53:502051
[email protected]3757a372012-01-19 05:20:442052 vertex_attrib_manager_.reset(new VertexAttribManager());
2053 vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:322054
[email protected]d6ca4792012-05-14 19:24:132055 query_manager_.reset(new QueryManager(this, feature_info_));
[email protected]882ba1e22012-03-08 19:02:532056
[email protected]302ce6d2011-07-07 23:28:112057 util_.set_num_compressed_texture_formats(
2058 validators_->compressed_texture_format.GetValues().size());
2059
[email protected]1071e572011-02-09 20:00:122060 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2061 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2062 // OpenGL ES 2.0 does not have this issue.
2063 glEnableVertexAttribArray(0);
2064 }
[email protected]b1122982010-05-17 23:04:242065 glGenBuffersARB(1, &attrib_0_buffer_id_);
2066 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2067 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2068 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:402069 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:082070
[email protected]246a70452010-03-05 21:53:502071 texture_units_.reset(
2072 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:152073 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:492074 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:312075 // We want the last bind to be 2D.
2076 TextureManager::TextureInfo* info;
2077 if (feature_info_->feature_flags().oes_egl_image_external) {
2078 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_EXTERNAL_OES);
2079 texture_units_[tt].bound_texture_external_oes = info;
2080 glBindTexture(GL_TEXTURE_EXTERNAL_OES, info->service_id());
2081 }
[email protected]e51bdf32011-11-23 22:21:462082 if (feature_info_->feature_flags().arb_texture_rectangle) {
2083 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_RECTANGLE_ARB);
2084 texture_units_[tt].bound_texture_rectangle_arb = info;
2085 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, info->service_id());
2086 }
[email protected]61eeb33f2011-07-26 15:30:312087 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:492088 texture_units_[tt].bound_texture_cube_map = info;
2089 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
2090 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2091 texture_units_[tt].bound_texture_2d = info;
2092 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:152093 }
[email protected]00f893d2010-08-24 18:55:492094 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:502095 CHECK_GL_ERROR();
2096
[email protected]297ca1c2011-06-20 23:08:462097 ContextCreationAttribParser attrib_parser;
2098 if (!attrib_parser.Parse(attribs))
2099 return false;
[email protected]41c56362011-06-14 16:47:432100
[email protected]297ca1c2011-06-20 23:08:462101 // These are NOT if the back buffer has these proprorties. They are
2102 // if we want the command buffer to enforce them regardless of what
2103 // the real backbuffer is assuming the real back buffer gives us more than
2104 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2105 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2106 // can't do anything about that.
2107
2108 GLint v = 0;
2109 glGetIntegerv(GL_ALPHA_BITS, &v);
2110 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2111 // user requested RGB then RGB. If the user did not specify a preference than
2112 // use whatever we were given. Same for DEPTH and STENCIL.
2113 back_buffer_color_format_ =
2114 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2115 glGetIntegerv(GL_DEPTH_BITS, &v);
2116 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2117 glGetIntegerv(GL_STENCIL_BITS, &v);
2118 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2119
[email protected]069944672012-04-25 20:52:232120 if (offscreen) {
[email protected]34ff8b0c2010-10-01 20:06:022121 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:542122 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:022123 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
2124 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:432125 // max_sample_count must be initialized to a sane value. If
2126 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2127 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:022128 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2129 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2130 max_sample_count);
2131 } else {
2132 offscreen_target_samples_ = 1;
2133 }
[email protected]8a61d872012-01-20 12:43:562134 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
[email protected]34ff8b0c2010-10-01 20:06:022135
2136 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2137 const bool rgb8_supported =
2138 context_->HasExtension("GL_OES_rgb8_rgba8");
2139 // The only available default render buffer formats in GLES2 have very
2140 // little precision. Don't enable multisampling unless 8-bit render
2141 // buffer formats are available--instead fall back to 8-bit textures.
2142 if (rgb8_supported && offscreen_target_samples_ > 1) {
2143 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2144 GL_RGBA8 : GL_RGB8;
2145 } else {
2146 offscreen_target_samples_ = 1;
2147 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2148 GL_RGBA : GL_RGB;
2149 }
2150
2151 // ANGLE only supports packed depth/stencil formats, so use it if it is
2152 // available.
2153 const bool depth24_stencil8_supported =
2154 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272155 VLOG(1) << "GL_OES_packed_depth_stencil "
2156 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:002157 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2158 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022159 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2160 offscreen_target_stencil_format_ = 0;
2161 } else {
2162 // It may be the case that this depth/stencil combination is not
2163 // supported, but this will be checked later by CheckFramebufferStatus.
2164 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2165 GL_DEPTH_COMPONENT16 : 0;
2166 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2167 GL_STENCIL_INDEX8 : 0;
2168 }
2169 } else {
2170 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2171 GL_RGBA : GL_RGB;
2172
2173 // If depth is requested at all, use the packed depth stencil format if
2174 // it's available, as some desktop GL drivers don't support any non-packed
2175 // formats for depth attachments.
2176 const bool depth24_stencil8_supported =
2177 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272178 VLOG(1) << "GL_EXT_packed_depth_stencil "
2179 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:022180
[email protected]71ee3642010-10-14 18:08:002181 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2182 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022183 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2184 offscreen_target_stencil_format_ = 0;
2185 } else {
2186 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2187 GL_DEPTH_COMPONENT : 0;
2188 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2189 GL_STENCIL_INDEX : 0;
2190 }
2191 }
2192
[email protected]97872062010-11-03 19:07:052193 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2194 GL_RGBA : GL_RGB;
2195
[email protected]6217d392010-03-25 22:08:352196 // Create the target frame buffer. This is the one that the client renders
2197 // directly to.
2198 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
2199 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022200 // Due to GLES2 format limitations, either the color texture (for
2201 // non-multisampling) or the color render buffer (for multisampling) will be
2202 // attached to the offscreen frame buffer. The render buffer has more
2203 // limited formats available to it, but the texture can't do multisampling.
2204 if (IsOffscreenBufferMultisampled()) {
2205 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
2206 offscreen_target_color_render_buffer_->Create();
2207 } else {
2208 offscreen_target_color_texture_.reset(new Texture(this));
2209 offscreen_target_color_texture_->Create();
2210 }
2211 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152212 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022213 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152214 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:352215
2216 // Create the saved offscreen texture. The target frame buffer is copied
2217 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:022218 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
2219 offscreen_saved_frame_buffer_->Create();
2220 //
[email protected]6217d392010-03-25 22:08:352221 offscreen_saved_color_texture_.reset(new Texture(this));
2222 offscreen_saved_color_texture_->Create();
2223
[email protected]6217d392010-03-25 22:08:352224 // Allocate the render buffers at their initial size and check the status
2225 // of the frame buffers is okay.
[email protected]799b4b22011-08-22 17:09:592226 if (!ResizeOffscreenFrameBuffer(size)) {
[email protected]d0498742010-09-20 20:27:012227 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]63c9b052012-05-17 18:27:382228 Destroy(true);
[email protected]6217d392010-03-25 22:08:352229 return false;
2230 }
2231
2232 // Bind to the new default frame buffer (the offscreen target frame buffer).
2233 // This should now be associated with ID zero.
2234 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2235 }
2236
[email protected]295faf4b2012-01-25 23:31:412237 // Clear the backbuffer.
2238 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2239
[email protected]76a0ee102010-04-07 21:03:042240 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2241 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2242 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372243 // mailing list archives. It also implicitly enables the desktop GL
2244 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2245 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152246 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2247 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372248 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152249 }
[email protected]de17df392010-04-23 21:09:412250
[email protected]38d139d2011-07-14 00:38:432251 has_arb_robustness_ = context->HasExtension("GL_ARB_robustness");
2252
[email protected]84eb4252012-06-29 22:56:442253 if (!feature_info_->feature_flags().disable_workarounds) {
[email protected]75c023c2011-08-22 23:54:512254#if defined(OS_MACOSX)
[email protected]a2a0fe762011-09-20 00:59:122255 needs_mac_nvidia_driver_workaround_ =
[email protected]5c67c7032012-05-15 18:21:222256 feature_info_->feature_flags().is_nvidia;
[email protected]a2a0fe762011-09-20 00:59:122257 needs_glsl_built_in_function_emulation_ =
[email protected]5c67c7032012-05-15 18:21:222258 feature_info_->feature_flags().is_amd;
[email protected]75c023c2011-08-22 23:54:512259#endif
[email protected]a2a0fe762011-09-20 00:59:122260 }
[email protected]75c023c2011-08-22 23:54:512261
[email protected]c2f8c8402010-12-06 18:07:242262 if (!InitializeShaderTranslator()) {
2263 return false;
[email protected]de17df392010-04-23 21:09:412264 }
[email protected]76a0ee102010-04-07 21:03:042265
[email protected]5904806b2012-05-08 18:10:222266 viewport_width_ = size.width();
2267 viewport_height_ = size.height();
2268 glViewport(viewport_x_, viewport_y_, viewport_width_, viewport_height_);
[email protected]43410e92012-04-20 17:06:282269
[email protected]5904806b2012-05-08 18:10:222270 GLint viewport_params[4] = { 0 };
[email protected]43410e92012-04-20 17:06:282271 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2272 viewport_max_width_ = viewport_params[0];
[email protected]5904806b2012-05-08 18:10:222273 viewport_max_height_ = viewport_params[1];
[email protected]43410e92012-04-20 17:06:282274
[email protected]11f3e702012-06-19 19:00:012275 // Set all the default state because some GL drivers get it wrong.
2276 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2277 glLineWidth(1.0);
2278 EnableDisable(GL_BLEND, enable_blend_);
2279 glBlendColor(0.0f, 0.0, 0.0f, 0.0f);
2280 glBlendFunc(GL_ONE, GL_ZERO);
2281 glBlendEquation(GL_FUNC_ADD);
2282 glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO);
2283 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
2284 glColorMask(mask_red_, mask_green_, mask_blue_, mask_alpha_);
2285 EnableDisable(GL_CULL_FACE, enable_cull_face_);
2286 glCullFace(GL_BACK);
2287 glClearDepth(clear_depth_);
2288 glDepthFunc(GL_LESS);
2289 glDepthRange(0.0f, 1.0f);
2290 EnableDisable(GL_DEPTH_TEST, enable_depth_test_);
2291 glEnable(GL_DITHER);
2292 glFrontFace(GL_CCW);
2293 glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE);
2294 glLineWidth(1.0f);
2295 glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment_);
2296 glPolygonOffset(0.0f, 0.0f);
2297 glDisable(GL_POLYGON_OFFSET_FILL);
2298 glSampleCoverage(1.0, false);
2299 glScissor(viewport_x_, viewport_y_, viewport_width_, viewport_height_);
2300 EnableDisable(GL_SCISSOR_TEST, enable_scissor_test_);
2301 EnableDisable(GL_STENCIL_TEST, enable_stencil_test_);
2302 glClearStencil(clear_stencil_);
2303 glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFFU);
2304 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2305 glStencilMaskSeparate(GL_FRONT, mask_stencil_front_);
2306 glStencilMaskSeparate(GL_BACK, mask_stencil_back_);
2307 glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment_);
2308
2309 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2310 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2311 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2312 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2313
[email protected]6d9374e2012-07-17 03:31:242314 // AMD and Intel drivers on Mac OS apparently get gl_PointCoord
2315 // backward from the spec and this setting makes them work
2316 // correctly. rdar://problem/11883495
[email protected]dd289a5d62012-06-30 22:05:462317#if defined(OS_MACOSX)
2318 if (!feature_info_->feature_flags().disable_workarounds &&
[email protected]6d9374e2012-07-17 03:31:242319 (feature_info_->feature_flags().is_amd ||
2320 feature_info_->feature_flags().is_intel) &&
[email protected]dd289a5d62012-06-30 22:05:462321 gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL) {
2322 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2323 }
2324#endif
2325
[email protected]246a70452010-03-05 21:53:502326 return true;
[email protected]96449d2c2009-11-25 00:01:322327}
2328
[email protected]302ce6d2011-07-07 23:28:112329void GLES2DecoderImpl::UpdateCapabilities() {
2330 util_.set_num_compressed_texture_formats(
2331 validators_->compressed_texture_format.GetValues().size());
2332 util_.set_num_shader_binary_formats(
2333 validators_->shader_binary_format.GetValues().size());
2334}
2335
[email protected]c2f8c8402010-12-06 18:07:242336bool GLES2DecoderImpl::InitializeShaderTranslator() {
[email protected]a5d3dad2012-05-26 04:34:442337 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2338
[email protected]c2f8c8402010-12-06 18:07:242339 // Re-check the state of use_shader_translator_ each time this is called.
2340 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:042341 (feature_info_->feature_flags().chromium_webglsl ||
2342 force_webgl_glsl_validation_) &&
[email protected]c2f8c8402010-12-06 18:07:242343 !use_shader_translator_) {
2344 use_shader_translator_ = true;
2345 }
2346 if (!use_shader_translator_) {
2347 return true;
2348 }
2349 ShBuiltInResources resources;
2350 ShInitBuiltInResources(&resources);
2351 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2352 resources.MaxVertexUniformVectors =
2353 group_->max_vertex_uniform_vectors();
2354 resources.MaxVaryingVectors = group_->max_varying_vectors();
2355 resources.MaxVertexTextureImageUnits =
2356 group_->max_vertex_texture_image_units();
2357 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2358 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2359 resources.MaxFragmentUniformVectors =
2360 group_->max_fragment_uniform_vectors();
2361 resources.MaxDrawBuffers = 1;
[email protected]f0d74742011-10-03 16:31:042362
2363 if (force_webgl_glsl_validation_) {
2364 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2365 } else {
2366 resources.OES_standard_derivatives =
2367 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
[email protected]e51bdf32011-11-23 22:21:462368 resources.ARB_texture_rectangle =
2369 feature_info_->feature_flags().arb_texture_rectangle ? 1 : 0;
[email protected]f0d74742011-10-03 16:31:042370 }
2371
[email protected]f0d74742011-10-03 16:31:042372 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ||
2373 feature_info_->feature_flags().chromium_webglsl ?
2374 SH_WEBGL_SPEC : SH_GLES2_SPEC;
[email protected]a2a0fe762011-09-20 00:59:122375 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2376 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2377 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2378 ShaderTranslatorInterface::GlslBuiltInFunctionBehavior function_behavior =
2379 needs_glsl_built_in_function_emulation_ ?
2380 ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated :
2381 ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal;
[email protected]87fb6ab2012-06-13 22:28:042382
2383 ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
2384 vertex_translator_ = cache->GetTranslator(
2385 SH_VERTEX_SHADER, shader_spec, &resources,
2386 implementation_type, function_behavior);
2387 if (!vertex_translator_.get()) {
[email protected]c2f8c8402010-12-06 18:07:242388 LOG(ERROR) << "Could not initialize vertex shader translator.";
[email protected]63c9b052012-05-17 18:27:382389 Destroy(true);
[email protected]c2f8c8402010-12-06 18:07:242390 return false;
2391 }
[email protected]87fb6ab2012-06-13 22:28:042392
2393 fragment_translator_ = cache->GetTranslator(
2394 SH_FRAGMENT_SHADER, shader_spec, &resources,
2395 implementation_type, function_behavior);
2396 if (!fragment_translator_.get()) {
[email protected]c2f8c8402010-12-06 18:07:242397 LOG(ERROR) << "Could not initialize fragment shader translator.";
[email protected]63c9b052012-05-17 18:27:382398 Destroy(true);
[email protected]c2f8c8402010-12-06 18:07:242399 return false;
2400 }
2401 return true;
2402}
2403
[email protected]ae51d192010-04-27 00:48:032404bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472405 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032406 if (GetBufferInfo(client_ids[ii])) {
2407 return false;
2408 }
2409 }
2410 scoped_array<GLuint> service_ids(new GLuint[n]);
2411 glGenBuffersARB(n, service_ids.get());
2412 for (GLsizei ii = 0; ii < n; ++ii) {
2413 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2414 }
2415 return true;
2416}
2417
2418bool GLES2DecoderImpl::GenFramebuffersHelper(
2419 GLsizei n, const GLuint* client_ids) {
2420 for (GLsizei ii = 0; ii < n; ++ii) {
2421 if (GetFramebufferInfo(client_ids[ii])) {
2422 return false;
2423 }
2424 }
2425 scoped_array<GLuint> service_ids(new GLuint[n]);
2426 glGenFramebuffersEXT(n, service_ids.get());
2427 for (GLsizei ii = 0; ii < n; ++ii) {
2428 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2429 }
2430 return true;
2431}
2432
2433bool GLES2DecoderImpl::GenRenderbuffersHelper(
2434 GLsizei n, const GLuint* client_ids) {
2435 for (GLsizei ii = 0; ii < n; ++ii) {
2436 if (GetRenderbufferInfo(client_ids[ii])) {
2437 return false;
2438 }
2439 }
2440 scoped_array<GLuint> service_ids(new GLuint[n]);
2441 glGenRenderbuffersEXT(n, service_ids.get());
2442 for (GLsizei ii = 0; ii < n; ++ii) {
2443 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2444 }
2445 return true;
2446}
2447
2448bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2449 for (GLsizei ii = 0; ii < n; ++ii) {
2450 if (GetTextureInfo(client_ids[ii])) {
2451 return false;
2452 }
2453 }
2454 scoped_array<GLuint> service_ids(new GLuint[n]);
2455 glGenTextures(n, service_ids.get());
2456 for (GLsizei ii = 0; ii < n; ++ii) {
2457 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2458 }
2459 return true;
2460}
2461
2462void GLES2DecoderImpl::DeleteBuffersHelper(
2463 GLsizei n, const GLuint* client_ids) {
2464 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102465 BufferManager::BufferInfo* buffer = GetBufferInfo(client_ids[ii]);
2466 if (buffer && !buffer->IsDeleted()) {
[email protected]3757a372012-01-19 05:20:442467 vertex_attrib_manager_->Unbind(buffer);
[email protected]a0b78dc2011-11-11 10:43:102468 if (bound_array_buffer_ == buffer) {
2469 bound_array_buffer_ = NULL;
2470 }
2471 if (bound_element_array_buffer_ == buffer) {
2472 bound_element_array_buffer_ = NULL;
2473 }
[email protected]ae51d192010-04-27 00:48:032474 RemoveBufferInfo(client_ids[ii]);
2475 }
[email protected]a93bb842010-02-16 23:03:472476 }
[email protected]07f54fcc2009-12-22 02:46:302477}
2478
[email protected]ae51d192010-04-27 00:48:032479void GLES2DecoderImpl::DeleteFramebuffersHelper(
2480 GLsizei n, const GLuint* client_ids) {
[email protected]b177ae22011-11-01 03:29:112481 bool supports_seperate_framebuffer_binds =
2482 feature_info_->feature_flags().chromium_framebuffer_multisample;
2483
[email protected]a25fa872010-03-25 02:57:582484 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102485 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ae51d192010-04-27 00:48:032486 GetFramebufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102487 if (framebuffer && !framebuffer->IsDeleted()) {
2488 if (framebuffer == bound_draw_framebuffer_) {
[email protected]297ca1c2011-06-20 23:08:462489 bound_draw_framebuffer_ = NULL;
2490 state_dirty_ = true;
[email protected]b177ae22011-11-01 03:29:112491 GLenum target = supports_seperate_framebuffer_binds ?
2492 GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER;
2493 glBindFramebufferEXT(target, GetBackbufferServiceId());
2494 }
[email protected]a0b78dc2011-11-11 10:43:102495 if (framebuffer == bound_read_framebuffer_) {
[email protected]b177ae22011-11-01 03:29:112496 bound_read_framebuffer_ = NULL;
2497 GLenum target = supports_seperate_framebuffer_binds ?
2498 GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER;
2499 glBindFramebufferEXT(target, GetBackbufferServiceId());
[email protected]297ca1c2011-06-20 23:08:462500 }
[email protected]ae51d192010-04-27 00:48:032501 RemoveFramebufferInfo(client_ids[ii]);
2502 }
[email protected]a25fa872010-03-25 02:57:582503 }
[email protected]07f54fcc2009-12-22 02:46:302504}
2505
[email protected]ae51d192010-04-27 00:48:032506void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2507 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102508 bool supports_seperate_framebuffer_binds =
2509 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a25fa872010-03-25 02:57:582510 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102511 RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]ae51d192010-04-27 00:48:032512 GetRenderbufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102513 if (renderbuffer && !renderbuffer->IsDeleted()) {
2514 if (bound_renderbuffer_ == renderbuffer) {
2515 bound_renderbuffer_ = NULL;
2516 }
2517 // Unbind from current framebuffers.
2518 if (supports_seperate_framebuffer_binds) {
2519 if (bound_read_framebuffer_) {
2520 bound_read_framebuffer_->UnbindRenderbuffer(
2521 GL_READ_FRAMEBUFFER, renderbuffer);
2522 }
2523 if (bound_draw_framebuffer_) {
2524 bound_draw_framebuffer_->UnbindRenderbuffer(
2525 GL_DRAW_FRAMEBUFFER, renderbuffer);
2526 }
2527 } else {
2528 if (bound_draw_framebuffer_) {
2529 bound_draw_framebuffer_->UnbindRenderbuffer(
2530 GL_FRAMEBUFFER, renderbuffer);
2531 }
2532 }
[email protected]297ca1c2011-06-20 23:08:462533 state_dirty_ = true;
[email protected]ae51d192010-04-27 00:48:032534 RemoveRenderbufferInfo(client_ids[ii]);
2535 }
[email protected]a25fa872010-03-25 02:57:582536 }
[email protected]07f54fcc2009-12-22 02:46:302537}
2538
[email protected]ae51d192010-04-27 00:48:032539void GLES2DecoderImpl::DeleteTexturesHelper(
2540 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102541 bool supports_seperate_framebuffer_binds =
2542 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a93bb842010-02-16 23:03:472543 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102544 TextureManager::TextureInfo* texture = GetTextureInfo(client_ids[ii]);
2545 if (texture && !texture->IsDeleted()) {
2546 if (texture->IsAttachedToFramebuffer()) {
[email protected]297ca1c2011-06-20 23:08:462547 state_dirty_ = true;
2548 }
[email protected]a0b78dc2011-11-11 10:43:102549 // Unbind texture from texture units.
2550 for (size_t jj = 0; jj < group_->max_texture_units(); ++jj) {
2551 texture_units_[ii].Unbind(texture);
2552 }
2553 // Unbind from current framebuffers.
2554 if (supports_seperate_framebuffer_binds) {
2555 if (bound_read_framebuffer_) {
2556 bound_read_framebuffer_->UnbindTexture(GL_READ_FRAMEBUFFER, texture);
2557 }
2558 if (bound_draw_framebuffer_) {
2559 bound_draw_framebuffer_->UnbindTexture(GL_DRAW_FRAMEBUFFER, texture);
2560 }
2561 } else {
2562 if (bound_draw_framebuffer_) {
2563 bound_draw_framebuffer_->UnbindTexture(GL_FRAMEBUFFER, texture);
2564 }
2565 }
2566 GLuint service_id = texture->service_id();
2567 if (texture->IsStreamTexture() && stream_texture_manager_) {
[email protected]b0af4f52011-09-28 22:04:422568 stream_texture_manager_->DestroyStreamTexture(service_id);
2569 }
[email protected]e51bdf32011-11-23 22:21:462570#if defined(OS_MACOSX)
2571 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2572 ReleaseIOSurfaceForTexture(service_id);
2573 }
2574#endif
[email protected]ae51d192010-04-27 00:48:032575 RemoveTextureInfo(client_ids[ii]);
2576 }
[email protected]a93bb842010-02-16 23:03:472577 }
[email protected]07f54fcc2009-12-22 02:46:302578}
2579
[email protected]43f28f832010-02-03 02:28:482580// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322581
[email protected]eb54a562010-01-20 21:55:182582bool GLES2DecoderImpl::MakeCurrent() {
[email protected]63c9b052012-05-17 18:27:382583 if (!context_.get() || !context_->MakeCurrent(surface_.get()))
2584 return false;
2585
2586 if (WasContextLost()) {
[email protected]38d139d2011-07-14 00:38:432587 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
[email protected]63c9b052012-05-17 18:27:382588 return false;
[email protected]38d139d2011-07-14 00:38:432589 }
2590
[email protected]63c9b052012-05-17 18:27:382591 return true;
[email protected]eb54a562010-01-20 21:55:182592}
2593
[email protected]a96a6022011-11-04 00:58:122594void GLES2DecoderImpl::ReleaseCurrent() {
2595 if (context_.get())
2596 context_->ReleaseCurrent(surface_.get());
2597}
2598
[email protected]8e3e0662010-08-23 18:46:302599void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
[email protected]0d6bfdc2011-11-02 01:32:202600 RenderbufferManager::RenderbufferInfo* renderbuffer =
2601 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
[email protected]8e3e0662010-08-23 18:46:302602 glBindRenderbufferEXT(
[email protected]0d6bfdc2011-11-02 01:32:202603 GL_RENDERBUFFER, renderbuffer ? renderbuffer->service_id() : 0);
[email protected]8e3e0662010-08-23 18:46:302604}
2605
2606static void RebindCurrentFramebuffer(
2607 GLenum target,
2608 FramebufferManager::FramebufferInfo* info,
[email protected]a3783712012-01-20 22:18:242609 GLuint back_buffer_service_id) {
[email protected]8e3e0662010-08-23 18:46:302610 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462611
[email protected]a3783712012-01-20 22:18:242612 if (framebuffer_id == 0) {
2613 framebuffer_id = back_buffer_service_id;
[email protected]8e3e0662010-08-23 18:46:302614 }
[email protected]297ca1c2011-06-20 23:08:462615
[email protected]8e3e0662010-08-23 18:46:302616 glBindFramebufferEXT(target, framebuffer_id);
2617}
2618
2619void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]297ca1c2011-06-20 23:08:462620 state_dirty_ = true;
2621
[email protected]a3ded6d2010-10-19 06:44:392622 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302623 RebindCurrentFramebuffer(
2624 GL_FRAMEBUFFER,
2625 bound_draw_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242626 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302627 } else {
2628 RebindCurrentFramebuffer(
2629 GL_READ_FRAMEBUFFER_EXT,
2630 bound_read_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242631 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302632 RebindCurrentFramebuffer(
2633 GL_DRAW_FRAMEBUFFER_EXT,
2634 bound_draw_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242635 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302636 }
2637}
2638
2639void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2640 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2641 GLuint last_id;
2642 if (info.bound_texture_2d) {
2643 last_id = info.bound_texture_2d->service_id();
2644 } else {
2645 last_id = 0;
2646 }
2647
2648 glBindTexture(GL_TEXTURE_2D, last_id);
2649 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2650}
2651
[email protected]0d6bfdc2011-11-02 01:32:202652bool GLES2DecoderImpl::CheckFramebufferValid(
2653 FramebufferManager::FramebufferInfo* framebuffer,
2654 GLenum target, const char* func_name) {
[email protected]a0b78dc2011-11-11 10:43:102655 if (!framebuffer) {
[email protected]0d6bfdc2011-11-02 01:32:202656 return true;
2657 }
2658
[email protected]968351b2011-12-20 08:26:512659 if (framebuffer_manager()->IsComplete(framebuffer)) {
2660 return true;
2661 }
2662
[email protected]0d6bfdc2011-11-02 01:32:202663 GLenum completeness = framebuffer->IsPossiblyComplete();
2664 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
2665 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:432666 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
[email protected]3a03a8f2011-03-19 00:51:272667 return false;
2668 }
[email protected]0d6bfdc2011-11-02 01:32:202669
2670 // Are all the attachments cleared?
2671 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2672 texture_manager()->HaveUnclearedMips()) {
2673 if (!framebuffer->IsCleared()) {
2674 // Can we clear them?
2675 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2676 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:432677 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2678 "framebuffer incomplete (clear)");
[email protected]0d6bfdc2011-11-02 01:32:202679 return false;
2680 }
2681 ClearUnclearedAttachments(target, framebuffer);
2682 }
2683 }
2684
[email protected]968351b2011-12-20 08:26:512685 if (!framebuffer_manager()->IsComplete(framebuffer)) {
2686 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2687 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:432688 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2689 "framebuffer incomplete (check)");
[email protected]968351b2011-12-20 08:26:512690 return false;
2691 }
2692 framebuffer_manager()->MarkAsComplete(framebuffer);
2693 }
2694
[email protected]0d6bfdc2011-11-02 01:32:202695 // NOTE: At this point we don't know if the framebuffer is complete but
2696 // we DO know that everything that needs to be cleared has been cleared.
[email protected]3a03a8f2011-03-19 00:51:272697 return true;
2698}
2699
[email protected]0d6bfdc2011-11-02 01:32:202700bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
2701 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
2702 return CheckFramebufferValid(
2703 bound_draw_framebuffer_, GL_FRAMEBUFFER_EXT, func_name);
2704 }
2705 return CheckFramebufferValid(
2706 bound_draw_framebuffer_, GL_DRAW_FRAMEBUFFER_EXT, func_name) &&
2707 CheckFramebufferValid(
2708 bound_read_framebuffer_, GL_READ_FRAMEBUFFER_EXT, func_name);
2709}
2710
[email protected]8e3e0662010-08-23 18:46:302711gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
[email protected]0d6bfdc2011-11-02 01:32:202712 FramebufferManager::FramebufferInfo* framebuffer =
2713 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2714 if (framebuffer != NULL) {
[email protected]9edc6b22010-12-23 02:00:262715 const FramebufferManager::FramebufferInfo::Attachment* attachment =
[email protected]0d6bfdc2011-11-02 01:32:202716 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
[email protected]9edc6b22010-12-23 02:00:262717 if (attachment) {
2718 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502719 }
[email protected]9edc6b22010-12-23 02:00:262720 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022721 } else if (offscreen_target_frame_buffer_.get()) {
2722 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352723 } else {
[email protected]f62a5ab2011-05-23 20:34:152724 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022725 }
[email protected]246a70452010-03-05 21:53:502726}
2727
[email protected]9edc6b22010-12-23 02:00:262728GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202729 FramebufferManager::FramebufferInfo* framebuffer =
2730 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2731 if (framebuffer != NULL) {
2732 return framebuffer->GetColorAttachmentFormat();
[email protected]297ca1c2011-06-20 23:08:462733 } else if (offscreen_target_frame_buffer_.get()) {
2734 return offscreen_target_color_format_;
2735 } else {
2736 return back_buffer_color_format_;
2737 }
2738}
2739
2740GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202741 FramebufferManager::FramebufferInfo* framebuffer =
2742 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
2743 if (framebuffer != NULL) {
2744 return framebuffer->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262745 } else if (offscreen_target_frame_buffer_.get()) {
2746 return offscreen_target_color_format_;
2747 } else {
[email protected]32fe9aa2011-01-21 23:47:132748 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262749 }
2750}
2751
[email protected]9a5afa432011-07-22 18:16:392752void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]34ff8b0c2010-10-01 20:06:022753 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582754 // Update the info about the offscreen saved color texture in the parent.
2755 // The reference to the parent is a weak pointer and will become null if the
2756 // parent is later destroyed.
[email protected]262d7aa2010-12-03 22:07:292757 TextureManager* parent_texture_manager = parent_->texture_manager();
[email protected]262d7aa2010-12-03 22:07:292758 parent_texture_manager->SetLevelInfo(
[email protected]8a61d872012-01-20 12:43:562759 offscreen_saved_color_texture_info_,
[email protected]ef526492010-06-02 23:12:252760 GL_TEXTURE_2D,
2761 0, // level
2762 GL_RGBA,
[email protected]799b4b22011-08-22 17:09:592763 offscreen_size_.width(),
2764 offscreen_size_.height(),
[email protected]ef526492010-06-02 23:12:252765 1, // depth
2766 0, // border
2767 GL_RGBA,
[email protected]0d6bfdc2011-11-02 01:32:202768 GL_UNSIGNED_BYTE,
2769 true);
[email protected]262d7aa2010-12-03 22:07:292770 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562771 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042772 GL_TEXTURE_MAG_FILTER,
2773 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292774 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562775 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042776 GL_TEXTURE_MIN_FILTER,
2777 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292778 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562779 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042780 GL_TEXTURE_WRAP_S,
2781 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292782 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562783 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042784 GL_TEXTURE_WRAP_T,
2785 GL_CLAMP_TO_EDGE);
[email protected]8a61d872012-01-20 12:43:562786 } else {
2787 offscreen_saved_color_texture_info_ = NULL;
[email protected]0c8c9d22010-06-25 17:36:392788 }
[email protected]6217d392010-03-25 22:08:352789}
2790
[email protected]799b4b22011-08-22 17:09:592791void GLES2DecoderImpl::SetResizeCallback(
[email protected]9d37f062011-11-22 01:24:522792 const base::Callback<void(gfx::Size)>& callback) {
2793 resize_callback_ = callback;
[email protected]7ff86b92010-11-25 17:50:002794}
2795
[email protected]6b6e7ee2011-12-13 08:04:522796void GLES2DecoderImpl::SetMsgCallback(const MsgCallback& callback) {
2797 msg_callback_ = callback;
2798}
2799
[email protected]b0af4f52011-09-28 22:04:422800void GLES2DecoderImpl::SetStreamTextureManager(StreamTextureManager* manager) {
2801 stream_texture_manager_ = manager;
2802}
2803
[email protected]1318e922010-09-17 22:03:162804bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2805 uint32* service_texture_id) {
2806 TextureManager::TextureInfo* texture =
2807 texture_manager()->GetTextureInfo(client_texture_id);
2808 if (texture) {
2809 *service_texture_id = texture->service_id();
2810 return true;
2811 }
2812 return false;
2813}
2814
[email protected]63c9b052012-05-17 18:27:382815void GLES2DecoderImpl::Destroy(bool have_context) {
2816 DCHECK(!have_context || context_->IsCurrent(NULL));
[email protected]97872062010-11-03 19:07:052817
[email protected]c826d732012-02-09 04:40:262818 ChildList children = children_;
2819 for (ChildList::iterator it = children.begin(); it != children.end(); ++it)
2820 (*it)->SetParent(NULL, 0);
2821 DCHECK(children_.empty());
[email protected]3c644d82011-06-20 19:58:242822 SetParent(NULL, 0);
2823
[email protected]80eb6b52012-01-19 00:14:412824 // Unbind everything.
[email protected]3757a372012-01-19 05:20:442825 vertex_attrib_manager_.reset();
[email protected]80eb6b52012-01-19 00:14:412826 texture_units_.reset();
2827 bound_array_buffer_ = NULL;
2828 bound_element_array_buffer_ = NULL;
[email protected]882ba1e22012-03-08 19:02:532829 current_query_ = NULL;
[email protected]80eb6b52012-01-19 00:14:412830 current_program_ = NULL;
2831 bound_read_framebuffer_ = NULL;
2832 bound_draw_framebuffer_ = NULL;
2833 bound_renderbuffer_ = NULL;
2834
[email protected]eadc96792010-10-27 19:39:392835 if (have_context) {
[email protected]c322e882012-05-23 18:06:182836 if (copy_texture_CHROMIUM_.get()) {
2837 copy_texture_CHROMIUM_->Destroy();
2838 copy_texture_CHROMIUM_.reset();
2839 }
[email protected]43410e92012-04-20 17:06:282840
[email protected]ca488e12010-12-13 20:06:142841 if (current_program_) {
2842 program_manager()->UnuseProgram(shader_manager(), current_program_);
2843 current_program_ = NULL;
2844 }
2845
[email protected]b1122982010-05-17 23:04:242846 if (attrib_0_buffer_id_) {
2847 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2848 }
[email protected]8fbedc02010-11-18 18:43:402849 if (fixed_attrib_buffer_id_) {
2850 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2851 }
[email protected]b1122982010-05-17 23:04:242852
[email protected]97872062010-11-03 19:07:052853 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542854 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052855 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542856 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052857 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022858 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052859 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152860 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052861 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152862 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052863 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022864 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052865 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542866 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:272867 if (offscreen_resolved_frame_buffer_.get())
2868 offscreen_resolved_frame_buffer_->Destroy();
2869 if (offscreen_resolved_color_texture_.get())
2870 offscreen_resolved_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052871 } else {
2872 if (offscreen_target_frame_buffer_.get())
2873 offscreen_target_frame_buffer_->Invalidate();
2874 if (offscreen_target_color_texture_.get())
2875 offscreen_target_color_texture_->Invalidate();
2876 if (offscreen_target_color_render_buffer_.get())
2877 offscreen_target_color_render_buffer_->Invalidate();
2878 if (offscreen_target_depth_render_buffer_.get())
2879 offscreen_target_depth_render_buffer_->Invalidate();
2880 if (offscreen_target_stencil_render_buffer_.get())
2881 offscreen_target_stencil_render_buffer_->Invalidate();
2882 if (offscreen_saved_frame_buffer_.get())
2883 offscreen_saved_frame_buffer_->Invalidate();
2884 if (offscreen_saved_color_texture_.get())
2885 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:272886 if (offscreen_resolved_frame_buffer_.get())
2887 offscreen_resolved_frame_buffer_->Invalidate();
2888 if (offscreen_resolved_color_texture_.get())
2889 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022890 }
[email protected]43410e92012-04-20 17:06:282891 copy_texture_CHROMIUM_.reset();
[email protected]97872062010-11-03 19:07:052892
[email protected]882ba1e22012-03-08 19:02:532893 if (query_manager_.get()) {
2894 query_manager_->Destroy(have_context);
2895 query_manager_.reset();
2896 }
2897
[email protected]1871a092011-10-10 21:46:422898 if (group_) {
2899 group_->Destroy(have_context);
2900 group_ = NULL;
2901 }
[email protected]3ae019382011-10-05 19:42:412902
[email protected]fe871662011-06-16 20:43:052903 if (context_.get()) {
2904 context_->ReleaseCurrent(NULL);
[email protected]79311e82011-09-20 00:40:502905 context_ = NULL;
[email protected]fe871662011-06-16 20:43:052906 }
[email protected]0fc35742011-04-13 17:57:542907
[email protected]97872062010-11-03 19:07:052908 offscreen_target_frame_buffer_.reset();
2909 offscreen_target_color_texture_.reset();
2910 offscreen_target_color_render_buffer_.reset();
2911 offscreen_target_depth_render_buffer_.reset();
2912 offscreen_target_stencil_render_buffer_.reset();
2913 offscreen_saved_frame_buffer_.reset();
2914 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:272915 offscreen_resolved_frame_buffer_.reset();
2916 offscreen_resolved_color_texture_.reset();
[email protected]e51bdf32011-11-23 22:21:462917
2918#if defined(OS_MACOSX)
2919 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
2920 it != texture_to_io_surface_map_.end(); ++it) {
2921 CFRelease(it->second);
2922 }
2923 texture_to_io_surface_map_.clear();
2924#endif
[email protected]96449d2c2009-11-25 00:01:322925}
2926
[email protected]63c9b052012-05-17 18:27:382927void GLES2DecoderImpl::SetSurface(
2928 const scoped_refptr<gfx::GLSurface>& surface) {
2929 DCHECK(context_->IsCurrent(NULL));
2930 DCHECK(surface_.get());
2931 surface_ = surface;
2932 RestoreCurrentFramebufferBindings();
2933}
2934
[email protected]3c644d82011-06-20 19:58:242935bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
2936 uint32 new_parent_texture_id) {
[email protected]9a5afa432011-07-22 18:16:392937 if (!offscreen_saved_color_texture_.get())
2938 return false;
2939
[email protected]3c644d82011-06-20 19:58:242940 // Remove the saved frame buffer mapping from the parent decoder. The
2941 // parent pointer is a weak pointer so it will be null if the parent has
2942 // already been destroyed.
2943 if (parent_) {
[email protected]c826d732012-02-09 04:40:262944 ChildList::iterator it = std::find(
2945 parent_->children_.begin(),
2946 parent_->children_.end(),
2947 this);
2948 DCHECK(it != parent_->children_.end());
2949 parent_->children_.erase(it);
[email protected]3c644d82011-06-20 19:58:242950 // First check the texture has been mapped into the parent. This might not
2951 // be the case if initialization failed midway through.
2952 GLuint service_id = offscreen_saved_color_texture_->id();
2953 GLuint client_id = 0;
2954 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
[email protected]80eb6b52012-01-19 00:14:412955 parent_->texture_manager()->RemoveTextureInfo(client_id);
[email protected]3c644d82011-06-20 19:58:242956 }
2957 }
2958
2959 GLES2DecoderImpl* new_parent_impl = static_cast<GLES2DecoderImpl*>(
2960 new_parent);
2961 if (new_parent_impl) {
[email protected]c826d732012-02-09 04:40:262962#ifndef NDEBUG
2963 ChildList::iterator it = std::find(
2964 new_parent_impl->children_.begin(),
2965 new_parent_impl->children_.end(),
2966 this);
2967 DCHECK(it == new_parent_impl->children_.end());
2968#endif
2969 new_parent_impl->children_.push_back(this);
[email protected]3c644d82011-06-20 19:58:242970 // Map the ID of the saved offscreen texture into the parent so that
2971 // it can reference it.
2972 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]98687862011-07-11 23:31:302973
2974 // Replace texture info when ID is already in use by parent.
2975 if (new_parent_impl->texture_manager()->GetTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412976 new_parent_texture_id))
[email protected]98687862011-07-11 23:31:302977 new_parent_impl->texture_manager()->RemoveTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412978 new_parent_texture_id);
[email protected]98687862011-07-11 23:31:302979
[email protected]8a61d872012-01-20 12:43:562980 offscreen_saved_color_texture_info_ =
[email protected]5f4f2a732011-07-30 00:47:552981 new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id);
[email protected]8a61d872012-01-20 12:43:562982 offscreen_saved_color_texture_info_->SetNotOwned();
2983 new_parent_impl->texture_manager()->
2984 SetInfoTarget(offscreen_saved_color_texture_info_, GL_TEXTURE_2D);
[email protected]3c644d82011-06-20 19:58:242985
2986 parent_ = new_parent_impl->AsWeakPtr();
[email protected]9a5afa432011-07-22 18:16:392987
2988 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:242989 } else {
2990 parent_.reset();
[email protected]8a61d872012-01-20 12:43:562991 offscreen_saved_color_texture_info_ = NULL;
[email protected]3c644d82011-06-20 19:58:242992 }
2993
2994 return true;
2995}
2996
[email protected]260ddc4e2012-06-28 00:01:532997size_t GLES2DecoderImpl::GetBackbufferMemoryTotal() {
[email protected]1078f912011-12-23 13:12:142998 size_t total = 0;
2999 if (offscreen_target_frame_buffer_.get()) {
3000 if (offscreen_target_color_texture_.get()) {
3001 total += offscreen_target_color_texture_->estimated_size();
3002 }
3003 if (offscreen_target_color_render_buffer_.get()) {
3004 total += offscreen_target_color_render_buffer_->estimated_size();
3005 }
3006 if (offscreen_target_depth_render_buffer_.get()) {
3007 total += offscreen_target_depth_render_buffer_->estimated_size();
3008 }
3009 if (offscreen_target_stencil_render_buffer_.get()) {
3010 total += offscreen_target_stencil_render_buffer_->estimated_size();
3011 }
3012 if (offscreen_saved_color_texture_.get()) {
3013 total += offscreen_saved_color_texture_->estimated_size();
3014 }
3015 if (offscreen_resolved_color_texture_.get()) {
3016 total += offscreen_resolved_color_texture_->estimated_size();
3017 }
3018 } else {
3019 gfx::Size size = surface_->GetSize();
3020 total += size.width() * size.height() *
3021 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_);
3022 }
[email protected]260ddc4e2012-06-28 00:01:533023 return total;
[email protected]1078f912011-12-23 13:12:143024}
3025
[email protected]799b4b22011-08-22 17:09:593026bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3027 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3028 if (!is_offscreen) {
3029 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3030 << " with an onscreen framebuffer.";
3031 return false;
3032 }
3033
3034 if (offscreen_size_ == size)
3035 return true;
3036
3037 offscreen_size_ = size;
3038 int w = offscreen_size_.width();
3039 int h = offscreen_size_.height();
3040 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3041 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3042 << "to allocate storage due to excessive dimensions.";
3043 return false;
3044 }
3045
3046 // Reallocate the offscreen target buffers.
3047 DCHECK(offscreen_target_color_format_);
3048 if (IsOffscreenBufferMultisampled()) {
3049 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3050 offscreen_size_, offscreen_target_color_format_,
3051 offscreen_target_samples_)) {
3052 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3053 << "to allocate storage for offscreen target color buffer.";
3054 return false;
3055 }
3056 } else {
3057 if (!offscreen_target_color_texture_->AllocateStorage(
3058 offscreen_size_, offscreen_target_color_format_)) {
3059 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3060 << "to allocate storage for offscreen target color texture.";
3061 return false;
3062 }
3063 }
3064 if (offscreen_target_depth_format_ &&
3065 !offscreen_target_depth_render_buffer_->AllocateStorage(
3066 offscreen_size_, offscreen_target_depth_format_,
3067 offscreen_target_samples_)) {
3068 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3069 << "to allocate storage for offscreen target depth buffer.";
3070 return false;
3071 }
3072 if (offscreen_target_stencil_format_ &&
3073 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3074 offscreen_size_, offscreen_target_stencil_format_,
3075 offscreen_target_samples_)) {
3076 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3077 << "to allocate storage for offscreen target stencil buffer.";
3078 return false;
3079 }
[email protected]260ddc4e2012-06-28 00:01:533080 TRACE_BACKBUFFER_MEMORY_TOTAL(this);
[email protected]799b4b22011-08-22 17:09:593081
3082 // Attach the offscreen target buffers to the target frame buffer.
3083 if (IsOffscreenBufferMultisampled()) {
3084 offscreen_target_frame_buffer_->AttachRenderBuffer(
3085 GL_COLOR_ATTACHMENT0,
3086 offscreen_target_color_render_buffer_.get());
3087 } else {
3088 offscreen_target_frame_buffer_->AttachRenderTexture(
3089 offscreen_target_color_texture_.get());
3090 }
3091 if (offscreen_target_depth_format_) {
3092 offscreen_target_frame_buffer_->AttachRenderBuffer(
3093 GL_DEPTH_ATTACHMENT,
3094 offscreen_target_depth_render_buffer_.get());
3095 }
3096 const bool packed_depth_stencil =
3097 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3098 if (packed_depth_stencil) {
3099 offscreen_target_frame_buffer_->AttachRenderBuffer(
3100 GL_STENCIL_ATTACHMENT,
3101 offscreen_target_depth_render_buffer_.get());
3102 } else if (offscreen_target_stencil_format_) {
3103 offscreen_target_frame_buffer_->AttachRenderBuffer(
3104 GL_STENCIL_ATTACHMENT,
3105 offscreen_target_stencil_render_buffer_.get());
3106 }
3107
3108 if (offscreen_target_frame_buffer_->CheckStatus() !=
3109 GL_FRAMEBUFFER_COMPLETE) {
3110 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3111 << "because offscreen FBO was incomplete.";
3112 return false;
3113 }
3114
3115 // Clear the target frame buffer.
3116 {
3117 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3118 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3119 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3120 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3121 glClearStencil(0);
3122 glStencilMaskSeparate(GL_FRONT, -1);
3123 glStencilMaskSeparate(GL_BACK, -1);
3124 glClearDepth(0);
3125 glDepthMask(GL_TRUE);
3126 glDisable(GL_SCISSOR_TEST);
3127 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3128 RestoreClearState();
3129 }
[email protected]d85ef76d2011-09-08 22:21:433130
3131 // Destroy the offscreen resolved framebuffers.
3132 if (offscreen_resolved_frame_buffer_.get())
3133 offscreen_resolved_frame_buffer_->Destroy();
3134 if (offscreen_resolved_color_texture_.get())
3135 offscreen_resolved_color_texture_->Destroy();
3136 offscreen_resolved_color_texture_.reset();
3137 offscreen_resolved_frame_buffer_.reset();
3138
[email protected]799b4b22011-08-22 17:09:593139 return true;
[email protected]6217d392010-03-25 22:08:353140}
3141
[email protected]799b4b22011-08-22 17:09:593142error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3143 uint32 immediate_data_size, const gles2::ResizeCHROMIUM& c) {
3144 GLuint width = static_cast<GLuint>(c.width);
3145 GLuint height = static_cast<GLuint>(c.height);
3146 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
[email protected]a0d989162011-11-22 13:15:073147#if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3148 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
[email protected]7ff86b92010-11-25 17:50:003149 // Make sure that we are done drawing to the back buffer before resizing.
3150 glFinish();
3151#endif
[email protected]799b4b22011-08-22 17:09:593152 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3153 if (is_offscreen) {
[email protected]7794d512012-04-17 20:36:493154 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3155 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3156 << "ResizeOffscreenFrameBuffer failed.";
[email protected]799b4b22011-08-22 17:09:593157 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:493158 }
[email protected]7ff86b92010-11-25 17:50:003159 }
[email protected]799b4b22011-08-22 17:09:593160
[email protected]9d37f062011-11-22 01:24:523161 if (!resize_callback_.is_null()) {
3162 resize_callback_.Run(gfx::Size(width, height));
[email protected]c777de52011-09-09 23:08:563163 DCHECK(context_->IsCurrent(surface_.get()));
[email protected]7794d512012-04-17 20:36:493164 if (!context_->IsCurrent(surface_.get())) {
3165 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3166 << "current after resize callback.";
[email protected]658f7562011-09-09 05:24:053167 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:493168 }
[email protected]658f7562011-09-09 05:24:053169 }
[email protected]799b4b22011-08-22 17:09:593170
[email protected]260ddc4e2012-06-28 00:01:533171 TRACE_BACKBUFFER_MEMORY_TOTAL(this);
[email protected]1078f912011-12-23 13:12:143172
[email protected]799b4b22011-08-22 17:09:593173 return error::kNoError;
[email protected]43ecf372010-11-16 19:19:393174}
3175
[email protected]96449d2c2009-11-25 00:01:323176const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3177 if (command_id > kStartPoint && command_id < kNumCommands) {
3178 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3179 }
3180 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3181}
3182
3183// Decode command with its arguments, and call the corresponding GL function.
3184// Note: args is a pointer to the command buffer. As such, it could be changed
3185// by a (malicious) client at any time, so if validation has to happen, it
3186// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:143187error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:323188 unsigned int command,
3189 unsigned int arg_count,
3190 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:143191 error::Error result = error::kNoError;
[email protected]e844ae22012-01-14 03:36:263192 if (log_commands()) {
[email protected]39ba4f02012-03-26 01:16:003193 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3194 // LOG(INFO), tried VLOG(1), no luck.
3195 LOG(ERROR) << "[" << this << "]" << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193196 }
[email protected]96449d2c2009-11-25 00:01:323197 unsigned int command_index = command - kStartPoint - 1;
3198 if (command_index < arraysize(g_command_info)) {
3199 const CommandInfo& info = g_command_info[command_index];
3200 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3201 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3202 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:193203 uint32 immediate_data_size =
3204 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:323205 switch (command) {
3206 #define GLES2_CMD_OP(name) \
3207 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:193208 result = Handle ## name( \
3209 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:323210 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:193211 break; \
[email protected]96449d2c2009-11-25 00:01:323212
3213 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:323214 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:383215 }
3216 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:303217 GLenum error;
3218 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]39ba4f02012-03-26 01:16:003219 LOG(ERROR) << "[" << this << "] "
3220 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3221 << GetCommandName(command);
[email protected]ad84a3a2012-06-08 21:42:433222 SetGLError(error, "DoCommand", "GL error from driver");
[email protected]b9849abf2009-11-25 19:13:193223 }
[email protected]96449d2c2009-11-25 00:01:323224 }
3225 } else {
[email protected]f7a64ee2010-02-01 22:24:143226 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:323227 }
[email protected]b9849abf2009-11-25 19:13:193228 } else {
3229 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:323230 }
[email protected]a3a93e7b2010-08-28 00:48:563231 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3232 result = current_decoder_error_;
3233 current_decoder_error_ = error::kNoError;
3234 }
[email protected]b9849abf2009-11-25 19:13:193235 return result;
[email protected]96449d2c2009-11-25 00:01:323236}
3237
[email protected]ae51d192010-04-27 00:48:033238void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
3239 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:503240}
3241
[email protected]ae51d192010-04-27 00:48:033242bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3243 if (GetProgramInfo(client_id)) {
3244 return false;
3245 }
[email protected]96449d2c2009-11-25 00:01:323246 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:033247 if (service_id != 0) {
3248 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:323249 }
[email protected]ae51d192010-04-27 00:48:033250 return true;
[email protected]96449d2c2009-11-25 00:01:323251}
3252
[email protected]ae51d192010-04-27 00:48:033253bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3254 if (GetShaderInfo(client_id)) {
3255 return false;
[email protected]96449d2c2009-11-25 00:01:323256 }
[email protected]ae51d192010-04-27 00:48:033257 GLuint service_id = glCreateShader(type);
3258 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:383259 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:033260 }
3261 return true;
[email protected]96449d2c2009-11-25 00:01:323262}
3263
[email protected]882ba1e22012-03-08 19:02:533264void GLES2DecoderImpl::DoFinish() {
3265 glFinish();
[email protected]22e3f552012-03-13 01:54:193266 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533267}
3268
3269void GLES2DecoderImpl::DoFlush() {
3270 glFlush();
[email protected]22e3f552012-03-13 01:54:193271 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533272}
3273
[email protected]3916c97e2010-02-25 03:20:503274void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:453275 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]660858b2011-07-13 23:16:143276 if (texture_index >= group_->max_texture_units()) {
[email protected]ad84a3a2012-06-08 21:42:433277 SetGLError(
3278 GL_INVALID_ENUM, "glActiveTexture", "texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:503279 return;
3280 }
[email protected]36cef8ce2010-03-16 07:34:453281 active_texture_unit_ = texture_index;
3282 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:503283}
3284
[email protected]051b1372010-04-12 02:42:083285void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:503286 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083287 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033288 if (client_id != 0) {
3289 info = GetBufferInfo(client_id);
3290 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353291 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153292 LOG(ERROR) << "glBindBuffer: id not generated by glGenBuffers";
3293 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353294 return;
3295 }
3296
[email protected]ae51d192010-04-27 00:48:033297 // It's a new id so make a buffer info for it.
3298 glGenBuffersARB(1, &service_id);
3299 CreateBufferInfo(client_id, service_id);
3300 info = GetBufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573301 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103302 group_->GetIdAllocator(id_namespaces::kBuffers);
3303 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033304 }
[email protected]051b1372010-04-12 02:42:083305 }
[email protected]ae51d192010-04-27 00:48:033306 if (info) {
[email protected]4e8a5b122010-05-08 22:00:103307 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:293308 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:433309 "glBindBuffer", "buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:473310 return;
3311 }
[email protected]ae51d192010-04-27 00:48:033312 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:473313 }
[email protected]96449d2c2009-11-25 00:01:323314 switch (target) {
3315 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503316 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323317 break;
3318 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503319 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323320 break;
3321 default:
[email protected]a93bb842010-02-16 23:03:473322 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:323323 break;
3324 }
[email protected]051b1372010-04-12 02:42:083325 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:323326}
3327
[email protected]297ca1c2011-06-20 23:08:463328bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
3329 return (GLES2Util::GetChannelsForFormat(
3330 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3331}
3332
3333bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203334 FramebufferManager::FramebufferInfo* framebuffer =
3335 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3336 if (framebuffer) {
3337 return framebuffer->HasDepthAttachment();
[email protected]297ca1c2011-06-20 23:08:463338 }
3339 if (offscreen_target_frame_buffer_.get()) {
3340 return offscreen_target_depth_format_ != 0;
3341 }
3342 return back_buffer_has_depth_;
3343}
3344
3345bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203346 FramebufferManager::FramebufferInfo* framebuffer =
3347 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3348 if (framebuffer) {
3349 return framebuffer->HasStencilAttachment();
[email protected]297ca1c2011-06-20 23:08:463350 }
3351 if (offscreen_target_frame_buffer_.get()) {
3352 return offscreen_target_stencil_format_ != 0 ||
3353 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3354 }
3355 return back_buffer_has_stencil_;
3356}
3357
3358void GLES2DecoderImpl::ApplyDirtyState() {
3359 if (state_dirty_) {
3360 glColorMask(
3361 mask_red_, mask_green_, mask_blue_,
3362 mask_alpha_ && BoundFramebufferHasColorAttachmentWithAlpha());
3363 bool have_depth = BoundFramebufferHasDepthAttachment();
3364 glDepthMask(mask_depth_ && have_depth);
3365 EnableDisable(GL_DEPTH_TEST, enable_depth_test_ && have_depth);
3366 bool have_stencil = BoundFramebufferHasStencilAttachment();
3367 glStencilMaskSeparate(GL_FRONT, have_stencil ? mask_stencil_front_ : 0);
3368 glStencilMaskSeparate(GL_BACK, have_stencil ? mask_stencil_back_ : 0);
3369 EnableDisable(GL_STENCIL_TEST, enable_stencil_test_ && have_stencil);
[email protected]43410e92012-04-20 17:06:283370 EnableDisable(GL_CULL_FACE, enable_cull_face_);
3371 EnableDisable(GL_SCISSOR_TEST, enable_scissor_test_);
[email protected]0a1e9ad2012-05-04 21:13:033372 EnableDisable(GL_BLEND, enable_blend_);
[email protected]297ca1c2011-06-20 23:08:463373 state_dirty_ = false;
3374 }
3375}
3376
[email protected]78b514b2012-05-01 21:50:593377void GLES2DecoderImpl::BindAndApplyTextureParameters(
3378 TextureManager::TextureInfo* info) {
3379 glBindTexture(info->target(), info->service_id());
3380 glTexParameteri(info->target(), GL_TEXTURE_MIN_FILTER, info->min_filter());
3381 glTexParameteri(info->target(), GL_TEXTURE_MAG_FILTER, info->mag_filter());
3382 glTexParameteri(info->target(), GL_TEXTURE_WRAP_S, info->wrap_s());
3383 glTexParameteri(info->target(), GL_TEXTURE_WRAP_T, info->wrap_t());
3384}
3385
[email protected]b177ae22011-11-01 03:29:113386GLuint GLES2DecoderImpl::GetBackbufferServiceId() {
3387 return (offscreen_target_frame_buffer_.get()) ?
3388 offscreen_target_frame_buffer_->id() :
3389 surface_->GetBackingFrameBufferObject();
3390}
3391
[email protected]051b1372010-04-12 02:42:083392void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3393 FramebufferManager::FramebufferInfo* info = NULL;
3394 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033395 if (client_id != 0) {
3396 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083397 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353398 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153399 LOG(ERROR)
3400 << "glBindFramebuffer: id not generated by glGenFramebuffers";
3401 current_decoder_error_ = error::kGenericError;
3402 return;
[email protected]bf5a8d132011-08-16 08:39:353403 }
3404
[email protected]ae51d192010-04-27 00:48:033405 // It's a new id so make a framebuffer info for it.
3406 glGenFramebuffersEXT(1, &service_id);
3407 CreateFramebufferInfo(client_id, service_id);
3408 info = GetFramebufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573409 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103410 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3411 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033412 } else {
3413 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083414 }
[email protected]06c8b082011-01-05 18:00:363415 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083416 }
[email protected]8e3e0662010-08-23 18:46:303417
3418 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
3419 bound_draw_framebuffer_ = info;
3420 }
3421 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
3422 bound_read_framebuffer_ = info;
3423 }
[email protected]6217d392010-03-25 22:08:353424
[email protected]297ca1c2011-06-20 23:08:463425 state_dirty_ = true;
3426
[email protected]b177ae22011-11-01 03:29:113427 // If we are rendering to the backbuffer get the FBO id for any simulated
3428 // backbuffer.
3429 if (info == NULL) {
3430 service_id = GetBackbufferServiceId();
[email protected]297ca1c2011-06-20 23:08:463431 }
[email protected]6217d392010-03-25 22:08:353432
[email protected]051b1372010-04-12 02:42:083433 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563434}
3435
[email protected]051b1372010-04-12 02:42:083436void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
3437 RenderbufferManager::RenderbufferInfo* info = NULL;
3438 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033439 if (client_id != 0) {
3440 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083441 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353442 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153443 LOG(ERROR)
3444 << "glBindRenderbuffer: id not generated by glGenRenderbuffers";
3445 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353446 return;
3447 }
3448
[email protected]ae51d192010-04-27 00:48:033449 // It's a new id so make a renderbuffer info for it.
3450 glGenRenderbuffersEXT(1, &service_id);
3451 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:103452 info = GetRenderbufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573453 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103454 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3455 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033456 } else {
3457 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083458 }
[email protected]06c8b082011-01-05 18:00:363459 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083460 }
3461 bound_renderbuffer_ = info;
3462 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563463}
3464
[email protected]051b1372010-04-12 02:42:083465void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033466 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083467 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033468 if (client_id != 0) {
3469 info = GetTextureInfo(client_id);
3470 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353471 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153472 LOG(ERROR) << "glBindTexture: id not generated by glGenTextures";
3473 current_decoder_error_ = error::kGenericError;
3474 return;
[email protected]bf5a8d132011-08-16 08:39:353475 }
3476
[email protected]ae51d192010-04-27 00:48:033477 // It's a new id so make a texture info for it.
3478 glGenTextures(1, &service_id);
[email protected]80eb6b52012-01-19 00:14:413479 DCHECK_NE(0u, service_id);
[email protected]ae51d192010-04-27 00:48:033480 CreateTextureInfo(client_id, service_id);
3481 info = GetTextureInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573482 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103483 group_->GetIdAllocator(id_namespaces::kTextures);
3484 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033485 }
3486 } else {
3487 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:083488 }
[email protected]ae51d192010-04-27 00:48:033489
[email protected]1958e0e2010-04-22 05:17:153490 // Check the texture exists
3491 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:033492 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:293493 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:433494 "glBindTexture", "texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:153495 return;
3496 }
[email protected]b0af4f52011-09-28 22:04:423497 if (info->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
3498 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:433499 "glBindTexture", "illegal target for stream texture.");
[email protected]b0af4f52011-09-28 22:04:423500 return;
3501 }
[email protected]1958e0e2010-04-22 05:17:153502 if (info->target() == 0) {
[email protected]80eb6b52012-01-19 00:14:413503 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:473504 }
[email protected]ae51d192010-04-27 00:48:033505 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:503506 TextureUnit& unit = texture_units_[active_texture_unit_];
3507 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:473508 switch (target) {
3509 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:503510 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:473511 break;
3512 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:503513 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:473514 break;
[email protected]61eeb33f2011-07-26 15:30:313515 case GL_TEXTURE_EXTERNAL_OES:
3516 unit.bound_texture_external_oes = info;
[email protected]b0af4f52011-09-28 22:04:423517 if (info->IsStreamTexture()) {
3518 DCHECK(stream_texture_manager_);
3519 StreamTexture* stream_tex =
3520 stream_texture_manager_->LookupStreamTexture(info->service_id());
3521 if (stream_tex)
3522 stream_tex->Update();
3523 }
[email protected]61eeb33f2011-07-26 15:30:313524 break;
[email protected]e51bdf32011-11-23 22:21:463525 case GL_TEXTURE_RECTANGLE_ARB:
3526 unit.bound_texture_rectangle_arb = info;
3527 break;
[email protected]a93bb842010-02-16 23:03:473528 default:
3529 NOTREACHED(); // Validation should prevent us getting here.
3530 break;
3531 }
3532}
3533
[email protected]07f54fcc2009-12-22 02:46:303534void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443535 if (vertex_attrib_manager_->Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:123536 if (index != 0 ||
3537 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:243538 glDisableVertexAttribArray(index);
3539 }
[email protected]07f54fcc2009-12-22 02:46:303540 } else {
[email protected]8eee29c2010-04-29 03:38:293541 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:433542 "glDisableVertexAttribArray", "index out of range");
[email protected]07f54fcc2009-12-22 02:46:303543 }
3544}
3545
3546void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443547 if (vertex_attrib_manager_->Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:303548 glEnableVertexAttribArray(index);
3549 } else {
[email protected]8eee29c2010-04-29 03:38:293550 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:433551 "glEnableVertexAttribArray", "index out of range");
[email protected]07f54fcc2009-12-22 02:46:303552 }
3553}
3554
[email protected]a93bb842010-02-16 23:03:473555void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:503556 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]97dc7cbe2011-12-06 17:26:173557 if (!info ||
[email protected]38c0a972012-05-12 00:48:023558 !texture_manager()->CanGenerateMipmaps(info)) {
[email protected]8eee29c2010-04-29 03:38:293559 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:433560 "glGenerateMipmaps", "Can not generate mips");
[email protected]a93bb842010-02-16 23:03:473561 return;
3562 }
[email protected]38c0a972012-05-12 00:48:023563
[email protected]7687479c2012-05-14 23:54:043564 if (!texture_manager()->ClearTextureLevel(this, info, target, 0)) {
[email protected]ad84a3a2012-06-08 21:42:433565 SetGLError(GL_OUT_OF_MEMORY, "glGenerateMipmaps", "dimensions too big");
[email protected]7687479c2012-05-14 23:54:043566 return;
3567 }
3568
[email protected]38c0a972012-05-12 00:48:023569 CopyRealGLErrorsToWrapper();
[email protected]59f3ca02011-03-26 22:24:193570 // Workaround for Mac driver bug. In the large scheme of things setting
3571 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
[email protected]a8bad262011-10-21 18:28:563572 // hit so there's probably no need to make this conditional. The bug appears
3573 // to be that if the filtering mode is set to something that doesn't require
3574 // mipmaps for rendering, or is never set to something other than the default,
3575 // then glGenerateMipmap misbehaves.
[email protected]84eb4252012-06-29 22:56:443576 if (!feature_info_->feature_flags().disable_workarounds) {
[email protected]c892a4e12012-05-08 18:20:193577 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3578 }
[email protected]a93bb842010-02-16 23:03:473579 glGenerateMipmapEXT(target);
[email protected]84eb4252012-06-29 22:56:443580 if (!feature_info_->feature_flags().disable_workarounds) {
[email protected]c892a4e12012-05-08 18:20:193581 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
3582 }
[email protected]38c0a972012-05-12 00:48:023583 GLenum error = PeekGLError();
3584 if (error == GL_NO_ERROR) {
3585 texture_manager()->MarkMipmapsGenerated(info);
3586 }
[email protected]a93bb842010-02-16 23:03:473587}
3588
[email protected]b273e432010-04-12 17:23:583589bool GLES2DecoderImpl::GetHelper(
3590 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:583591 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:153592 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
3593 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:433594 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
3595 *num_written = 1;
3596 if (params) {
3597 *params = GL_RGBA; // We don't support other formats.
3598 }
3599 return true;
3600 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3601 *num_written = 1;
3602 if (params) {
3603 *params = GL_UNSIGNED_BYTE; // We don't support other types.
3604 }
3605 return true;
3606 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
3607 *num_written = 1;
3608 if (params) {
3609 *params = group_->max_fragment_uniform_vectors();
3610 }
3611 return true;
3612 case GL_MAX_VARYING_VECTORS:
3613 *num_written = 1;
3614 if (params) {
3615 *params = group_->max_varying_vectors();
3616 }
3617 return true;
3618 case GL_MAX_VERTEX_UNIFORM_VECTORS:
3619 *num_written = 1;
3620 if (params) {
3621 *params = group_->max_vertex_uniform_vectors();
3622 }
3623 return true;
[email protected]4e8a5b122010-05-08 22:00:103624 }
[email protected]5cb735d2011-10-13 01:37:233625 }
3626 switch (pname) {
[email protected]5094b0f2010-11-09 19:45:243627 case GL_MAX_VIEWPORT_DIMS:
3628 if (offscreen_target_frame_buffer_.get()) {
3629 *num_written = 2;
3630 if (params) {
3631 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3632 params[1] = renderbuffer_manager()->max_renderbuffer_size();
3633 }
3634 return true;
3635 }
[email protected]5cb735d2011-10-13 01:37:233636 return false;
[email protected]84afefa2011-10-19 21:45:533637 case GL_MAX_SAMPLES:
3638 *num_written = 1;
3639 if (params) {
3640 params[0] = renderbuffer_manager()->max_samples();
3641 }
3642 return true;
3643 case GL_MAX_RENDERBUFFER_SIZE:
3644 *num_written = 1;
3645 if (params) {
3646 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3647 }
3648 return true;
[email protected]5cb735d2011-10-13 01:37:233649 case GL_MAX_TEXTURE_SIZE:
3650 *num_written = 1;
3651 if (params) {
3652 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
3653 }
3654 return true;
3655 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
3656 *num_written = 1;
3657 if (params) {
3658 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
3659 }
3660 return true;
[email protected]297ca1c2011-06-20 23:08:463661 case GL_COLOR_WRITEMASK:
3662 *num_written = 4;
3663 if (params) {
3664 params[0] = mask_red_;
3665 params[1] = mask_green_;
3666 params[2] = mask_blue_;
3667 params[3] = mask_alpha_;
3668 }
3669 return true;
3670 case GL_DEPTH_WRITEMASK:
3671 *num_written = 1;
3672 if (params) {
3673 params[0] = mask_depth_;
3674 }
3675 return true;
3676 case GL_STENCIL_BACK_WRITEMASK:
3677 *num_written = 1;
3678 if (params) {
3679 params[0] = mask_stencil_back_;
3680 }
3681 return true;
3682 case GL_STENCIL_WRITEMASK:
3683 *num_written = 1;
3684 if (params) {
3685 params[0] = mask_stencil_front_;
3686 }
3687 return true;
3688 case GL_DEPTH_TEST:
3689 *num_written = 1;
3690 if (params) {
3691 params[0] = enable_depth_test_;
3692 }
3693 return true;
3694 case GL_STENCIL_TEST:
3695 *num_written = 1;
3696 if (params) {
3697 params[0] = enable_stencil_test_;
3698 }
3699 return true;
3700 case GL_ALPHA_BITS:
3701 *num_written = 1;
3702 if (params) {
3703 GLint v = 0;
3704 glGetIntegerv(GL_ALPHA_BITS, &v);
3705 params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0;
3706 }
3707 return true;
3708 case GL_DEPTH_BITS:
3709 *num_written = 1;
3710 if (params) {
3711 GLint v = 0;
3712 glGetIntegerv(GL_DEPTH_BITS, &v);
3713 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
3714 }
3715 return true;
3716 case GL_STENCIL_BITS:
3717 *num_written = 1;
3718 if (params) {
3719 GLint v = 0;
3720 glGetIntegerv(GL_STENCIL_BITS, &v);
3721 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
3722 }
3723 return true;
[email protected]656dcaad2010-05-07 17:18:373724 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113725 *num_written = validators_->compressed_texture_format.GetValues().size();
3726 if (params) {
3727 for (GLint ii = 0; ii < *num_written; ++ii) {
3728 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
3729 }
3730 }
[email protected]656dcaad2010-05-07 17:18:373731 return true;
[email protected]b273e432010-04-12 17:23:583732 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
3733 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103734 if (params) {
[email protected]302ce6d2011-07-07 23:28:113735 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103736 }
[email protected]b273e432010-04-12 17:23:583737 return true;
3738 case GL_NUM_SHADER_BINARY_FORMATS:
3739 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103740 if (params) {
[email protected]302ce6d2011-07-07 23:28:113741 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103742 }
[email protected]b273e432010-04-12 17:23:583743 return true;
3744 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113745 *num_written = validators_->shader_binary_format.GetValues().size();
3746 if (params) {
3747 for (GLint ii = 0; ii < *num_written; ++ii) {
3748 params[ii] = validators_->shader_binary_format.GetValues()[ii];
3749 }
3750 }
3751 return true;
[email protected]b273e432010-04-12 17:23:583752 case GL_SHADER_COMPILER:
3753 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103754 if (params) {
3755 *params = GL_TRUE;
3756 }
[email protected]b273e432010-04-12 17:23:583757 return true;
[email protected]6b8cf1a2010-05-06 16:13:583758 case GL_ARRAY_BUFFER_BINDING:
3759 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103760 if (params) {
3761 if (bound_array_buffer_) {
3762 GLuint client_id = 0;
3763 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
3764 &client_id);
3765 *params = client_id;
3766 } else {
3767 *params = 0;
3768 }
[email protected]6b8cf1a2010-05-06 16:13:583769 }
3770 return true;
3771 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3772 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103773 if (params) {
3774 if (bound_element_array_buffer_) {
3775 GLuint client_id = 0;
3776 buffer_manager()->GetClientId(
3777 bound_element_array_buffer_->service_id(),
3778 &client_id);
3779 *params = client_id;
3780 } else {
3781 *params = 0;
3782 }
[email protected]6b8cf1a2010-05-06 16:13:583783 }
3784 return true;
3785 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:303786 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:583787 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103788 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203789 FramebufferManager::FramebufferInfo* framebuffer =
3790 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3791 if (framebuffer) {
[email protected]4e8a5b122010-05-08 22:00:103792 GLuint client_id = 0;
3793 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203794 framebuffer->service_id(), &client_id);
[email protected]8e3e0662010-08-23 18:46:303795 *params = client_id;
3796 } else {
3797 *params = 0;
3798 }
3799 }
3800 return true;
3801 case GL_READ_FRAMEBUFFER_BINDING:
3802 *num_written = 1;
3803 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203804 FramebufferManager::FramebufferInfo* framebuffer =
3805 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
3806 if (framebuffer) {
[email protected]8e3e0662010-08-23 18:46:303807 GLuint client_id = 0;
3808 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203809 framebuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103810 *params = client_id;
3811 } else {
3812 *params = 0;
3813 }
[email protected]6b8cf1a2010-05-06 16:13:583814 }
3815 return true;
3816 case GL_RENDERBUFFER_BINDING:
3817 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103818 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203819 RenderbufferManager::RenderbufferInfo* renderbuffer =
3820 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
3821 if (renderbuffer) {
[email protected]4e8a5b122010-05-08 22:00:103822 GLuint client_id = 0;
3823 renderbuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203824 renderbuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103825 *params = client_id;
3826 } else {
3827 *params = 0;
3828 }
[email protected]6b8cf1a2010-05-06 16:13:583829 }
3830 return true;
3831 case GL_CURRENT_PROGRAM:
3832 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103833 if (params) {
3834 if (current_program_) {
3835 GLuint client_id = 0;
3836 program_manager()->GetClientId(
3837 current_program_->service_id(), &client_id);
3838 *params = client_id;
3839 } else {
3840 *params = 0;
3841 }
[email protected]6b8cf1a2010-05-06 16:13:583842 }
3843 return true;
[email protected]4e8a5b122010-05-08 22:00:103844 case GL_TEXTURE_BINDING_2D:
3845 *num_written = 1;
3846 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583847 TextureUnit& unit = texture_units_[active_texture_unit_];
3848 if (unit.bound_texture_2d) {
3849 GLuint client_id = 0;
3850 texture_manager()->GetClientId(
3851 unit.bound_texture_2d->service_id(), &client_id);
3852 *params = client_id;
3853 } else {
3854 *params = 0;
3855 }
[email protected]6b8cf1a2010-05-06 16:13:583856 }
[email protected]4e8a5b122010-05-08 22:00:103857 return true;
3858 case GL_TEXTURE_BINDING_CUBE_MAP:
3859 *num_written = 1;
3860 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583861 TextureUnit& unit = texture_units_[active_texture_unit_];
3862 if (unit.bound_texture_cube_map) {
3863 GLuint client_id = 0;
3864 texture_manager()->GetClientId(
3865 unit.bound_texture_cube_map->service_id(), &client_id);
3866 *params = client_id;
3867 } else {
3868 *params = 0;
3869 }
[email protected]6b8cf1a2010-05-06 16:13:583870 }
[email protected]4e8a5b122010-05-08 22:00:103871 return true;
[email protected]61eeb33f2011-07-26 15:30:313872 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3873 *num_written = 1;
3874 if (params) {
3875 TextureUnit& unit = texture_units_[active_texture_unit_];
3876 if (unit.bound_texture_external_oes) {
3877 GLuint client_id = 0;
3878 texture_manager()->GetClientId(
3879 unit.bound_texture_external_oes->service_id(), &client_id);
3880 *params = client_id;
3881 } else {
3882 *params = 0;
3883 }
3884 }
3885 return true;
[email protected]e51bdf32011-11-23 22:21:463886 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
3887 *num_written = 1;
3888 if (params) {
3889 TextureUnit& unit = texture_units_[active_texture_unit_];
3890 if (unit.bound_texture_rectangle_arb) {
3891 GLuint client_id = 0;
3892 texture_manager()->GetClientId(
3893 unit.bound_texture_rectangle_arb->service_id(), &client_id);
3894 *params = client_id;
3895 } else {
3896 *params = 0;
3897 }
3898 }
3899 return true;
[email protected]6c75c712012-06-19 15:43:173900 case GL_UNPACK_FLIP_Y_CHROMIUM:
3901 *num_written = 1;
3902 if (params) {
3903 params[0] = unpack_flip_y_;
3904 }
3905 return true;
3906 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
3907 *num_written = 1;
3908 if (params) {
3909 params[0] = unpack_premultiply_alpha_;
3910 }
3911 return true;
3912 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
3913 *num_written = 1;
3914 if (params) {
3915 params[0] = unpack_unpremultiply_alpha_;
3916 }
3917 return true;
[email protected]b273e432010-04-12 17:23:583918 default:
[email protected]4e8a5b122010-05-08 22:00:103919 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533920 return false;
[email protected]b273e432010-04-12 17:23:583921 }
3922}
3923
[email protected]4e8a5b122010-05-08 22:00:103924bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3925 GLenum pname, GLsizei* num_values) {
3926 return GetHelper(pname, NULL, num_values);
3927}
3928
[email protected]b273e432010-04-12 17:23:583929void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3930 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103931 GLsizei num_written = 0;
3932 if (GetHelper(pname, NULL, &num_written)) {
3933 scoped_array<GLint> values(new GLint[num_written]);
3934 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583935 for (GLsizei ii = 0; ii < num_written; ++ii) {
3936 params[ii] = static_cast<GLboolean>(values[ii]);
3937 }
3938 } else {
3939 glGetBooleanv(pname, params);
3940 }
3941}
3942
3943void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3944 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103945 GLsizei num_written = 0;
3946 if (GetHelper(pname, NULL, &num_written)) {
3947 scoped_array<GLint> values(new GLint[num_written]);
3948 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583949 for (GLsizei ii = 0; ii < num_written; ++ii) {
3950 params[ii] = static_cast<GLfloat>(values[ii]);
3951 }
3952 } else {
3953 glGetFloatv(pname, params);
3954 }
3955}
3956
3957void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3958 DCHECK(params);
3959 GLsizei num_written;
3960 if (!GetHelper(pname, params, &num_written)) {
3961 glGetIntegerv(pname, params);
3962 }
3963}
3964
[email protected]a0c3e972010-04-21 00:49:133965void GLES2DecoderImpl::DoGetProgramiv(
3966 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583967 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3968 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133969 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133970 return;
3971 }
3972 info->GetProgramiv(pname, params);
3973}
3974
[email protected]258a3313f2011-10-18 20:13:573975void GLES2DecoderImpl::DoBindAttribLocation(
3976 GLuint program, GLuint index, const char* name) {
3977 if (!StringIsValidForGLES(name)) {
[email protected]ad84a3a2012-06-08 21:42:433978 SetGLError(GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:573979 return;
3980 }
[email protected]68dcb1f2012-04-07 00:14:563981 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
[email protected]ad84a3a2012-06-08 21:42:433982 SetGLError(GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
[email protected]68dcb1f2012-04-07 00:14:563983 return;
3984 }
3985 if (index >= group_->max_vertex_attribs()) {
[email protected]ad84a3a2012-06-08 21:42:433986 SetGLError(GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
[email protected]68dcb1f2012-04-07 00:14:563987 return;
3988 }
[email protected]6b8cf1a2010-05-06 16:13:583989 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3990 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033991 if (!info) {
[email protected]258a3313f2011-10-18 20:13:573992 return;
[email protected]558847a2010-03-24 07:02:543993 }
[email protected]c3e4c4e2012-03-02 19:23:243994 info->SetAttribLocationBinding(name, static_cast<GLint>(index));
[email protected]258a3313f2011-10-18 20:13:573995 glBindAttribLocation(info->service_id(), index, name);
3996}
3997
3998error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3999 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
4000 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:544001 GLuint index = static_cast<GLuint>(c.index);
4002 uint32 name_size = c.data_size;
4003 const char* name = GetSharedMemoryAs<const char*>(
4004 c.name_shm_id, c.name_shm_offset, name_size);
4005 if (name == NULL) {
4006 return error::kOutOfBounds;
4007 }
4008 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:574009 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:544010 return error::kNoError;
4011}
4012
4013error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
4014 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:584015 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:544016 GLuint index = static_cast<GLuint>(c.index);
4017 uint32 name_size = c.data_size;
4018 const char* name = GetImmediateDataAs<const char*>(
4019 c, name_size, immediate_data_size);
4020 if (name == NULL) {
4021 return error::kOutOfBounds;
4022 }
4023 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:574024 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:544025 return error::kNoError;
4026}
4027
4028error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
4029 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:584030 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:544031 GLuint index = static_cast<GLuint>(c.index);
4032 Bucket* bucket = GetBucket(c.name_bucket_id);
4033 if (!bucket || bucket->size() == 0) {
4034 return error::kInvalidArguments;
4035 }
4036 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:184037 if (!bucket->GetAsString(&name_str)) {
4038 return error::kInvalidArguments;
4039 }
[email protected]258a3313f2011-10-18 20:13:574040 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:544041 return error::kNoError;
4042}
4043
[email protected]2be6abf32012-06-26 00:28:334044void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
4045 GLuint program, GLint location, const char* name) {
4046 if (!StringIsValidForGLES(name)) {
4047 SetGLError(GL_INVALID_VALUE,
4048 "glBindUniformLocationCHROMIUM", "Invalid character");
4049 return;
4050 }
4051 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
4052 SetGLError(GL_INVALID_OPERATION,
4053 "glBindUniformLocationCHROMIUM", "reserved prefix");
4054 return;
4055 }
4056 if (location < 0 || static_cast<uint32>(location) >=
4057 (group_->max_fragment_uniform_vectors() +
4058 group_->max_vertex_uniform_vectors()) * 4) {
4059 SetGLError(GL_INVALID_VALUE,
4060 "glBindUniformLocationCHROMIUM", "location out of range");
4061 return;
4062 }
4063 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4064 program, "glBindUniformLocationCHROMIUM");
4065 if (!info) {
4066 return;
4067 }
4068 if (!info->SetUniformLocationBinding(name, location)) {
4069 SetGLError(GL_INVALID_VALUE,
4070 "glBindUniformLocationCHROMIUM", "location out of range");
4071 }
4072}
4073
4074error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUM(
4075 uint32 immediate_data_size, const gles2::BindUniformLocationCHROMIUM& c) {
4076 GLuint program = static_cast<GLuint>(c.program);
4077 GLint location = static_cast<GLint>(c.location);
4078 uint32 name_size = c.data_size;
4079 const char* name = GetSharedMemoryAs<const char*>(
4080 c.name_shm_id, c.name_shm_offset, name_size);
4081 if (name == NULL) {
4082 return error::kOutOfBounds;
4083 }
4084 String name_str(name, name_size);
4085 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4086 return error::kNoError;
4087}
4088
4089error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMImmediate(
4090 uint32 immediate_data_size,
4091 const gles2::BindUniformLocationCHROMIUMImmediate& c) {
4092 GLuint program = static_cast<GLuint>(c.program);
4093 GLint location = static_cast<GLint>(c.location);
4094 uint32 name_size = c.data_size;
4095 const char* name = GetImmediateDataAs<const char*>(
4096 c, name_size, immediate_data_size);
4097 if (name == NULL) {
4098 return error::kOutOfBounds;
4099 }
4100 String name_str(name, name_size);
4101 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4102 return error::kNoError;
4103}
4104
4105error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4106 uint32 immediate_data_size,
4107 const gles2::BindUniformLocationCHROMIUMBucket& c) {
4108 GLuint program = static_cast<GLuint>(c.program);
4109 GLint location = static_cast<GLint>(c.location);
4110 Bucket* bucket = GetBucket(c.name_bucket_id);
4111 if (!bucket || bucket->size() == 0) {
4112 return error::kInvalidArguments;
4113 }
4114 std::string name_str;
4115 if (!bucket->GetAsString(&name_str)) {
4116 return error::kInvalidArguments;
4117 }
4118 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4119 return error::kNoError;
4120}
4121
[email protected]f7a64ee2010-02-01 22:24:144122error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:464123 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:034124 GLuint client_id = c.shader;
4125 if (client_id) {
4126 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
4127 if (info) {
[email protected]ca488e12010-12-13 20:06:144128 if (!info->IsDeleted()) {
4129 glDeleteShader(info->service_id());
4130 shader_manager()->MarkAsDeleted(info);
4131 }
[email protected]ae51d192010-04-27 00:48:034132 } else {
[email protected]ad84a3a2012-06-08 21:42:434133 SetGLError(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
[email protected]ae51d192010-04-27 00:48:034134 }
[email protected]96449d2c2009-11-25 00:01:324135 }
[email protected]f7a64ee2010-02-01 22:24:144136 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324137}
4138
[email protected]f7a64ee2010-02-01 22:24:144139error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:464140 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:034141 GLuint client_id = c.program;
4142 if (client_id) {
4143 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
4144 if (info) {
[email protected]ca488e12010-12-13 20:06:144145 if (!info->IsDeleted()) {
[email protected]ca488e12010-12-13 20:06:144146 program_manager()->MarkAsDeleted(shader_manager(), info);
4147 }
[email protected]ae51d192010-04-27 00:48:034148 } else {
[email protected]ad84a3a2012-06-08 21:42:434149 SetGLError(GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
[email protected]ae51d192010-04-27 00:48:034150 }
[email protected]96449d2c2009-11-25 00:01:324151 }
[email protected]f7a64ee2010-02-01 22:24:144152 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324153}
4154
[email protected]269200b12010-11-18 22:53:064155void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104156 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574157 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104158 for (GLsizei ii = 0; ii < n; ++ii) {
4159 id_allocator->FreeID(ids[ii]);
4160 }
4161}
4162
[email protected]269200b12010-11-18 22:53:064163error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
4164 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104165 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4166 GLsizei n = static_cast<GLsizei>(c.n);
4167 uint32 data_size;
4168 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4169 return error::kOutOfBounds;
4170 }
4171 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4172 c.ids_shm_id, c.ids_shm_offset, data_size);
4173 if (n < 0) {
[email protected]ad84a3a2012-06-08 21:42:434174 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104175 return error::kNoError;
4176 }
4177 if (ids == NULL) {
4178 return error::kOutOfBounds;
4179 }
[email protected]269200b12010-11-18 22:53:064180 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:104181 return error::kNoError;
4182}
4183
[email protected]269200b12010-11-18 22:53:064184void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104185 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574186 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104187 if (id_offset == 0) {
4188 for (GLsizei ii = 0; ii < n; ++ii) {
4189 ids[ii] = id_allocator->AllocateID();
4190 }
4191 } else {
4192 for (GLsizei ii = 0; ii < n; ++ii) {
4193 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4194 id_offset = ids[ii] + 1;
4195 }
4196 }
4197}
4198
[email protected]269200b12010-11-18 22:53:064199error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4200 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104201 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4202 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4203 GLsizei n = static_cast<GLsizei>(c.n);
4204 uint32 data_size;
4205 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4206 return error::kOutOfBounds;
4207 }
4208 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4209 c.ids_shm_id, c.ids_shm_offset, data_size);
4210 if (n < 0) {
[email protected]ad84a3a2012-06-08 21:42:434211 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104212 return error::kNoError;
4213 }
4214 if (ids == NULL) {
4215 return error::kOutOfBounds;
4216 }
[email protected]269200b12010-11-18 22:53:064217 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:104218 return error::kNoError;
4219}
4220
[email protected]269200b12010-11-18 22:53:064221void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104222 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574223 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104224 for (GLsizei ii = 0; ii < n; ++ii) {
4225 if (!id_allocator->MarkAsUsed(ids[ii])) {
4226 for (GLsizei jj = 0; jj < ii; ++jj) {
4227 id_allocator->FreeID(ids[jj]);
4228 }
4229 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:434230 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4231 "attempt to register id that already exists");
[email protected]066849e32010-05-03 19:14:104232 return;
4233 }
4234 }
4235}
4236
[email protected]269200b12010-11-18 22:53:064237error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4238 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104239 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4240 GLsizei n = static_cast<GLsizei>(c.n);
4241 uint32 data_size;
4242 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4243 return error::kOutOfBounds;
4244 }
4245 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4246 c.ids_shm_id, c.ids_shm_offset, data_size);
4247 if (n < 0) {
[email protected]ad84a3a2012-06-08 21:42:434248 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104249 return error::kNoError;
4250 }
4251 if (ids == NULL) {
4252 return error::kOutOfBounds;
4253 }
[email protected]269200b12010-11-18 22:53:064254 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:104255 return error::kNoError;
4256}
4257
[email protected]a7266a92012-06-28 02:11:084258error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
4259 if (ShouldDeferDraws())
4260 return error::kDeferCommandUntilLater;
[email protected]0d6bfdc2011-11-02 01:32:204261 if (CheckBoundFramebuffersValid("glClear")) {
[email protected]529c6672012-01-04 02:18:264262 UNSHIPPED_TRACE_EVENT_INSTANT2("test_gpu", "DoClear", "red", clear_red_,
4263 "green", clear_green_);
[email protected]297ca1c2011-06-20 23:08:464264 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:274265 glClear(mask);
4266 }
[email protected]a7266a92012-06-28 02:11:084267 return error::kNoError;
4268}
4269
4270error::Error GLES2DecoderImpl::HandleClear(
4271 uint32 immediate_data_size, const gles2::Clear& c) {
4272 GLbitfield mask = static_cast<GLbitfield>(c.mask);
4273 return DoClear(mask);
[email protected]3a03a8f2011-03-19 00:51:274274}
4275
[email protected]36cef8ce2010-03-16 07:34:454276void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4277 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:034278 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:304279 FramebufferManager::FramebufferInfo* framebuffer_info =
4280 GetFramebufferInfoForTarget(target);
4281 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294282 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434283 "glFramebufferRenderbuffer", "no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454284 return;
4285 }
[email protected]ae51d192010-04-27 00:48:034286 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:284287 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:034288 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:284289 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:034290 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294291 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434292 "glFramebufferRenderbuffer", "unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:034293 return;
4294 }
4295 service_id = info->service_id();
4296 }
[email protected]9edc6b22010-12-23 02:00:264297 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034298 glFramebufferRenderbufferEXT(
4299 target, attachment, renderbuffertarget, service_id);
[email protected]1002c2d2011-06-28 22:39:044300 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264301 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:304302 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]3a2e7c7b2010-08-06 01:12:284303 }
[email protected]297ca1c2011-06-20 23:08:464304 if (framebuffer_info == bound_draw_framebuffer_) {
4305 state_dirty_ = true;
4306 }
[email protected]3a2e7c7b2010-08-06 01:12:284307}
4308
[email protected]297ca1c2011-06-20 23:08:464309bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
[email protected]3a2e7c7b2010-08-06 01:12:284310 switch (cap) {
[email protected]0a1e9ad2012-05-04 21:13:034311 case GL_BLEND:
4312 enable_blend_ = enabled;
4313 return true;
[email protected]43410e92012-04-20 17:06:284314 case GL_CULL_FACE:
4315 enable_cull_face_ = enabled;
4316 return true;
[email protected]3a2e7c7b2010-08-06 01:12:284317 case GL_SCISSOR_TEST:
4318 enable_scissor_test_ = enabled;
[email protected]297ca1c2011-06-20 23:08:464319 return true;
4320 case GL_DEPTH_TEST: {
4321 if (enable_depth_test_ != enabled) {
4322 enable_depth_test_ = enabled;
4323 state_dirty_ = true;
4324 }
4325 return false;
4326 }
4327 case GL_STENCIL_TEST:
4328 if (enable_stencil_test_ != enabled) {
4329 enable_stencil_test_ = enabled;
4330 state_dirty_ = true;
4331 }
4332 return false;
[email protected]3a2e7c7b2010-08-06 01:12:284333 default:
[email protected]297ca1c2011-06-20 23:08:464334 return true;
[email protected]3a2e7c7b2010-08-06 01:12:284335 }
4336}
4337
4338void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464339 if (SetCapabilityState(cap, false)) {
4340 glDisable(cap);
4341 }
[email protected]3a2e7c7b2010-08-06 01:12:284342}
4343
4344void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464345 if (SetCapabilityState(cap, true)) {
4346 glEnable(cap);
4347 }
[email protected]3a2e7c7b2010-08-06 01:12:284348}
4349
[email protected]3dc69c42012-05-12 02:29:244350bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
4351 switch (cap) {
4352 case GL_BLEND:
4353 return enable_blend_;
4354 case GL_CULL_FACE:
4355 return enable_cull_face_;
4356 case GL_SCISSOR_TEST:
4357 return enable_scissor_test_;
4358 case GL_DEPTH_TEST:
4359 return enable_depth_test_;
4360 case GL_STENCIL_TEST:
4361 return enable_stencil_test_;
4362 default:
4363 return glIsEnabled(cap) != 0;
4364 }
4365}
4366
[email protected]3a2e7c7b2010-08-06 01:12:284367void GLES2DecoderImpl::DoClearColor(
4368 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
4369 clear_red_ = red;
4370 clear_green_ = green;
4371 clear_blue_ = blue;
4372 clear_alpha_ = alpha;
4373 glClearColor(red, green, blue, alpha);
4374}
4375
4376void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
4377 clear_depth_ = depth;
4378 glClearDepth(depth);
4379}
4380
4381void GLES2DecoderImpl::DoClearStencil(GLint s) {
4382 clear_stencil_ = s;
4383 glClearStencil(s);
4384}
4385
4386void GLES2DecoderImpl::DoColorMask(
4387 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
4388 mask_red_ = red;
4389 mask_green_ = green;
4390 mask_blue_ = blue;
4391 mask_alpha_ = alpha;
[email protected]297ca1c2011-06-20 23:08:464392 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284393}
4394
4395void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
4396 mask_depth_ = depth;
[email protected]297ca1c2011-06-20 23:08:464397 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284398}
4399
4400void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
4401 mask_stencil_front_ = mask;
4402 mask_stencil_back_ = mask;
[email protected]297ca1c2011-06-20 23:08:464403 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284404}
4405
4406void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
[email protected]297ca1c2011-06-20 23:08:464407 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284408 mask_stencil_front_ = mask;
[email protected]297ca1c2011-06-20 23:08:464409 }
4410 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284411 mask_stencil_back_ = mask;
4412 }
[email protected]297ca1c2011-06-20 23:08:464413 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284414}
4415
[email protected]0d6bfdc2011-11-02 01:32:204416// Assumes framebuffer is complete.
4417void GLES2DecoderImpl::ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:304418 GLenum target, FramebufferManager::FramebufferInfo* info) {
4419 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204420 // bind this to the DRAW point, clear then bind back to READ
4421 // TODO(gman): I don't think there is any guarantee that an FBO that
4422 // is complete on the READ attachment will be complete as a DRAW
4423 // attachment.
4424 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
4425 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, info->service_id());
[email protected]8e3e0662010-08-23 18:46:304426 }
[email protected]3a2e7c7b2010-08-06 01:12:284427 GLbitfield clear_bits = 0;
4428 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:464429 glClearColor(
[email protected]0d6bfdc2011-11-02 01:32:204430 0.0f, 0.0f, 0.0f,
[email protected]297ca1c2011-06-20 23:08:464431 (GLES2Util::GetChannelsForFormat(
[email protected]0d6bfdc2011-11-02 01:32:204432 info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f : 1.0f);
[email protected]3a2e7c7b2010-08-06 01:12:284433 glColorMask(true, true, true, true);
4434 clear_bits |= GL_COLOR_BUFFER_BIT;
4435 }
4436
4437 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4438 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4439 glClearStencil(0);
4440 glStencilMask(-1);
4441 clear_bits |= GL_STENCIL_BUFFER_BIT;
4442 }
4443
4444 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4445 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4446 glClearDepth(1.0f);
4447 glDepthMask(true);
4448 clear_bits |= GL_DEPTH_BUFFER_BIT;
4449 }
4450
4451 glDisable(GL_SCISSOR_TEST);
4452 glClear(clear_bits);
4453
[email protected]968351b2011-12-20 08:26:514454 framebuffer_manager()->MarkAttachmentsAsCleared(
4455 info, renderbuffer_manager(), texture_manager());
[email protected]3a2e7c7b2010-08-06 01:12:284456
[email protected]c007aa02010-09-02 22:22:404457 RestoreClearState();
4458
4459 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204460 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, info->service_id());
[email protected]87d1a3fe2011-12-01 04:25:484461 FramebufferManager::FramebufferInfo* framebuffer =
4462 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4463 GLuint service_id =
4464 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
4465 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
[email protected]c007aa02010-09-02 22:22:404466 }
4467}
4468
4469void GLES2DecoderImpl::RestoreClearState() {
[email protected]297ca1c2011-06-20 23:08:464470 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284471 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
[email protected]3a2e7c7b2010-08-06 01:12:284472 glClearStencil(clear_stencil_);
[email protected]3a2e7c7b2010-08-06 01:12:284473 glClearDepth(clear_depth_);
[email protected]3a2e7c7b2010-08-06 01:12:284474 if (enable_scissor_test_) {
4475 glEnable(GL_SCISSOR_TEST);
4476 }
[email protected]36cef8ce2010-03-16 07:34:454477}
4478
4479GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]0d6bfdc2011-11-02 01:32:204480 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]8e3e0662010-08-23 18:46:304481 GetFramebufferInfoForTarget(target);
[email protected]0d6bfdc2011-11-02 01:32:204482 if (!framebuffer) {
[email protected]36cef8ce2010-03-16 07:34:454483 return GL_FRAMEBUFFER_COMPLETE;
4484 }
[email protected]0d6bfdc2011-11-02 01:32:204485 GLenum completeness = framebuffer->IsPossiblyComplete();
4486 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4487 return completeness;
4488 }
[email protected]36cef8ce2010-03-16 07:34:454489 return glCheckFramebufferStatusEXT(target);
4490}
4491
4492void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:034493 GLenum target, GLenum attachment, GLenum textarget,
4494 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:304495 FramebufferManager::FramebufferInfo* framebuffer_info =
4496 GetFramebufferInfoForTarget(target);
4497 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294498 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434499 "glFramebufferTexture2D", "no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:454500 return;
4501 }
[email protected]ae51d192010-04-27 00:48:034502 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:284503 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:034504 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:284505 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:034506 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294507 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434508 "glFramebufferTexture2D", "unknown texture");
[email protected]ae51d192010-04-27 00:48:034509 return;
4510 }
4511 service_id = info->service_id();
4512 }
[email protected]0d6bfdc2011-11-02 01:32:204513
[email protected]80eb6b52012-01-19 00:14:414514 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
[email protected]0d6bfdc2011-11-02 01:32:204515 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:434516 "glFramebufferTexture2D", "level out of range");
[email protected]0d6bfdc2011-11-02 01:32:204517 return;
4518 }
4519
[email protected]9edc6b22010-12-23 02:00:264520 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034521 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]1002c2d2011-06-28 22:39:044522 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264523 if (error == GL_NO_ERROR) {
4524 framebuffer_info->AttachTexture(attachment, info, textarget, level);
[email protected]3a2e7c7b2010-08-06 01:12:284525 }
[email protected]297ca1c2011-06-20 23:08:464526 if (framebuffer_info == bound_draw_framebuffer_) {
4527 state_dirty_ = true;
4528 }
[email protected]36cef8ce2010-03-16 07:34:454529}
4530
4531void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4532 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:304533 FramebufferManager::FramebufferInfo* framebuffer_info =
4534 GetFramebufferInfoForTarget(target);
4535 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294536 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434537 "glFramebufferAttachmentParameteriv", "no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454538 return;
4539 }
4540 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:574541 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4542 GLint type = 0;
4543 GLuint client_id = 0;
4544 glGetFramebufferAttachmentParameterivEXT(
4545 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
4546 switch (type) {
4547 case GL_RENDERBUFFER: {
4548 renderbuffer_manager()->GetClientId(*params, &client_id);
4549 break;
4550 }
4551 case GL_TEXTURE: {
4552 texture_manager()->GetClientId(*params, &client_id);
4553 break;
4554 }
4555 default:
4556 break;
4557 }
4558 *params = client_id;
4559 }
[email protected]36cef8ce2010-03-16 07:34:454560}
4561
4562void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4563 GLenum target, GLenum pname, GLint* params) {
[email protected]0d6bfdc2011-11-02 01:32:204564 RenderbufferManager::RenderbufferInfo* renderbuffer =
4565 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4566 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294567 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434568 "glGetRenderbufferParameteriv", "no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454569 return;
4570 }
[email protected]3a03a8f2011-03-19 00:51:274571 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:434572 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4573 *params = renderbuffer->internal_format();
4574 break;
4575 case GL_RENDERBUFFER_WIDTH:
4576 *params = renderbuffer->width();
4577 break;
4578 case GL_RENDERBUFFER_HEIGHT:
4579 *params = renderbuffer->height();
4580 break;
4581 default:
4582 glGetRenderbufferParameterivEXT(target, pname, params);
4583 break;
[email protected]b71f52c2010-06-18 22:20:204584 }
[email protected]36cef8ce2010-03-16 07:34:454585}
4586
[email protected]8e3e0662010-08-23 18:46:304587void GLES2DecoderImpl::DoBlitFramebufferEXT(
4588 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
4589 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
4590 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:394591 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304592 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434593 "glBlitFramebufferEXT", "function not available");
[email protected]8e3e0662010-08-23 18:46:304594 }
[email protected]5094b0f2010-11-09 19:45:244595 if (IsAngle()) {
4596 glBlitFramebufferANGLE(
4597 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4598 } else {
4599 glBlitFramebufferEXT(
4600 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4601 }
[email protected]529c6672012-01-04 02:18:264602 UNSHIPPED_TRACE_EVENT_INSTANT1("test_gpu", "DoBlit", "width", srcX1 - srcX0);
[email protected]8e3e0662010-08-23 18:46:304603}
4604
4605void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
4606 GLenum target, GLsizei samples, GLenum internalformat,
4607 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:394608 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304609 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434610 "glRenderbufferStorageMultisampleEXT", "function not available");
[email protected]8e3e0662010-08-23 18:46:304611 return;
4612 }
[email protected]8e3e0662010-08-23 18:46:304613
[email protected]0d6bfdc2011-11-02 01:32:204614 RenderbufferManager::RenderbufferInfo* renderbuffer =
4615 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4616 if (!renderbuffer) {
4617 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434618 "glGetRenderbufferStorageMultisample", "no renderbuffer bound");
[email protected]0d6bfdc2011-11-02 01:32:204619 return;
4620 }
4621
[email protected]84afefa2011-10-19 21:45:534622 if (samples > renderbuffer_manager()->max_samples()) {
4623 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:434624 "glGetRenderbufferStorageMultisample", "samples too large");
[email protected]84afefa2011-10-19 21:45:534625 return;
4626 }
4627
4628 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4629 height > renderbuffer_manager()->max_renderbuffer_size()) {
4630 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:434631 "glGetRenderbufferStorageMultisample", "size too large");
[email protected]84afefa2011-10-19 21:45:534632 return;
4633 }
4634
[email protected]9edc6b22010-12-23 02:00:264635 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:304636 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264637 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:304638 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264639 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:304640 break;
4641 case GL_RGBA4:
4642 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264643 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:304644 break;
4645 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264646 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:304647 break;
4648 }
4649 }
4650
[email protected]9edc6b22010-12-23 02:00:264651 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:084652 if (IsAngle()) {
4653 glRenderbufferStorageMultisampleANGLE(
4654 target, samples, impl_format, width, height);
4655 } else {
4656 glRenderbufferStorageMultisampleEXT(
4657 target, samples, impl_format, width, height);
4658 }
[email protected]1002c2d2011-06-28 22:39:044659 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264660 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514661 // TODO(gman): If renderbuffers tracked which framebuffers they were
4662 // attached to we could just mark those framebuffers as not complete.
4663 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204664 renderbuffer_manager()->SetInfo(
4665 renderbuffer, samples, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264666 }
[email protected]8e3e0662010-08-23 18:46:304667}
4668
[email protected]36cef8ce2010-03-16 07:34:454669void GLES2DecoderImpl::DoRenderbufferStorage(
4670 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]0d6bfdc2011-11-02 01:32:204671 RenderbufferManager::RenderbufferInfo* renderbuffer =
4672 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4673 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294674 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434675 "glGetRenderbufferStorage", "no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454676 return;
4677 }
[email protected]876f6fee2010-08-02 23:10:324678
[email protected]84afefa2011-10-19 21:45:534679 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4680 height > renderbuffer_manager()->max_renderbuffer_size()) {
4681 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:434682 "glGetRenderbufferStorage", "size too large");
[email protected]84afefa2011-10-19 21:45:534683 return;
4684 }
4685
[email protected]9edc6b22010-12-23 02:00:264686 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:324687 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264688 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:324689 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264690 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:324691 break;
4692 case GL_RGBA4:
4693 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264694 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:324695 break;
4696 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264697 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:324698 break;
4699 }
[email protected]b71f52c2010-06-18 22:20:204700 }
[email protected]876f6fee2010-08-02 23:10:324701
[email protected]9edc6b22010-12-23 02:00:264702 CopyRealGLErrorsToWrapper();
4703 glRenderbufferStorageEXT(target, impl_format, width, height);
[email protected]1002c2d2011-06-28 22:39:044704 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264705 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514706 // TODO(gman): If tetxures tracked which framebuffers they were attached to
4707 // we could just mark those framebuffers as not complete.
4708 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204709 renderbuffer_manager()->SetInfo(
4710 renderbuffer, 0, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264711 }
[email protected]36cef8ce2010-03-16 07:34:454712}
4713
[email protected]07f54fcc2009-12-22 02:46:304714void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]43ed3a72012-05-30 22:55:384715 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]6b8cf1a2010-05-06 16:13:584716 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4717 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:474718 if (!info) {
[email protected]a93bb842010-02-16 23:03:474719 return;
4720 }
[email protected]05afda12011-01-20 00:17:344721
[email protected]7f1a51c322012-07-19 18:52:024722 if (info->Link()) {
[email protected]2df73892012-04-28 01:09:544723 if (info == current_program_.get()) {
4724 program_manager()->ClearUniforms(info);
4725 }
4726 }
[email protected]07f54fcc2009-12-22 02:46:304727};
4728
[email protected]3916c97e2010-02-25 03:20:504729void GLES2DecoderImpl::DoTexParameterf(
4730 GLenum target, GLenum pname, GLfloat param) {
4731 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:304732 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:434733 SetGLError(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:244734 return;
[email protected]07f54fcc2009-12-22 02:46:304735 }
[email protected]cbb22e42011-05-12 23:36:244736
4737 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414738 info, pname, static_cast<GLint>(param))) {
[email protected]ad84a3a2012-06-08 21:42:434739 SetGLError(GL_INVALID_ENUM, "glTexParameterf", "param GL_INVALID_ENUM");
[email protected]cbb22e42011-05-12 23:36:244740 return;
4741 }
4742 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:304743}
4744
[email protected]3916c97e2010-02-25 03:20:504745void GLES2DecoderImpl::DoTexParameteri(
4746 GLenum target, GLenum pname, GLint param) {
4747 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4748 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:434749 SetGLError(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:244750 return;
[email protected]3916c97e2010-02-25 03:20:504751 }
[email protected]cbb22e42011-05-12 23:36:244752
[email protected]80eb6b52012-01-19 00:14:414753 if (!texture_manager()->SetParameter(info, pname, param)) {
[email protected]ad84a3a2012-06-08 21:42:434754 SetGLError(GL_INVALID_ENUM, "glTexParameteri", "param GL_INVALID_ENUM");
[email protected]cbb22e42011-05-12 23:36:244755 return;
4756 }
4757 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:504758}
4759
4760void GLES2DecoderImpl::DoTexParameterfv(
4761 GLenum target, GLenum pname, const GLfloat* params) {
4762 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4763 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:434764 SetGLError(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:244765 return;
[email protected]3916c97e2010-02-25 03:20:504766 }
[email protected]cbb22e42011-05-12 23:36:244767
4768 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414769 info, pname, static_cast<GLint>(params[0]))) {
[email protected]ad84a3a2012-06-08 21:42:434770 SetGLError(GL_INVALID_ENUM, "glTexParameterfv", "param GL_INVALID_ENUM");
[email protected]cbb22e42011-05-12 23:36:244771 return;
4772 }
4773 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504774}
4775
4776void GLES2DecoderImpl::DoTexParameteriv(
4777 GLenum target, GLenum pname, const GLint* params) {
4778 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4779 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:434780 SetGLError(GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:244781 return;
[email protected]3916c97e2010-02-25 03:20:504782 }
[email protected]cbb22e42011-05-12 23:36:244783
[email protected]80eb6b52012-01-19 00:14:414784 if (!texture_manager()->SetParameter(info, pname, *params)) {
[email protected]ad84a3a2012-06-08 21:42:434785 SetGLError(GL_INVALID_ENUM, "glTexParameteriv", "param GL_INVALID_ENUM");
[email protected]cbb22e42011-05-12 23:36:244786 return;
4787 }
4788 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504789}
4790
[email protected]939e7362010-05-13 20:49:104791bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:144792 if (!current_program_) {
[email protected]ad84a3a2012-06-08 21:42:434793 // The program does not exist.
4794 SetGLError(GL_INVALID_OPERATION, function_name, "no program in use");
4795 return false;
[email protected]939e7362010-05-13 20:49:104796 }
[email protected]ca488e12010-12-13 20:06:144797 if (!current_program_->InUse()) {
[email protected]ad84a3a2012-06-08 21:42:434798 SetGLError(GL_INVALID_OPERATION, function_name, "program not linked");
[email protected]939e7362010-05-13 20:49:104799 return false;
4800 }
4801 return true;
4802}
4803
4804bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
4805 GLint location, const char* function_name) {
4806 if (!CheckCurrentProgram(function_name)) {
4807 return false;
4808 }
4809 return location != -1;
4810}
4811
[email protected]43c2f1f2011-03-25 18:35:364812bool GLES2DecoderImpl::PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124813 GLint fake_location, const char* function_name,
4814 GLint* real_location, GLenum* type, GLsizei* count) {
[email protected]43c2f1f2011-03-25 18:35:364815 DCHECK(type);
4816 DCHECK(count);
[email protected]1b0a6752012-02-22 03:44:124817 DCHECK(real_location);
4818 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
[email protected]939e7362010-05-13 20:49:104819 return false;
4820 }
[email protected]43c2f1f2011-03-25 18:35:364821 GLint array_index = -1;
4822 const ProgramManager::ProgramInfo::UniformInfo* info =
[email protected]1b0a6752012-02-22 03:44:124823 current_program_->GetUniformInfoByFakeLocation(
4824 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:364825 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:434826 SetGLError(GL_INVALID_OPERATION, function_name, "unknown location");
[email protected]939e7362010-05-13 20:49:104827 return false;
4828 }
[email protected]43c2f1f2011-03-25 18:35:364829 if (*count > 1 && !info->is_array) {
4830 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:434831 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
[email protected]43c2f1f2011-03-25 18:35:364832 return false;
4833 }
4834 *count = std::min(info->size - array_index, *count);
4835 if (*count <= 0) {
4836 return false;
4837 }
4838 *type = info->type;
[email protected]939e7362010-05-13 20:49:104839 return true;
4840}
4841
[email protected]1b0a6752012-02-22 03:44:124842void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
4843 GLenum type = 0;
4844 GLsizei count = 1;
4845 GLint real_location = -1;
4846 if (!PrepForSetUniformByLocation(
4847 fake_location, "glUniform1iv", &real_location, &type, &count)) {
[email protected]3916c97e2010-02-25 03:20:504848 return;
4849 }
[email protected]d20a6512012-05-02 20:17:464850 if (!current_program_->SetSamplers(
4851 group_->max_texture_units(), fake_location, 1, &v0)) {
[email protected]ad84a3a2012-06-08 21:42:434852 SetGLError(GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
[email protected]d20a6512012-05-02 20:17:464853 return;
4854 }
[email protected]1b0a6752012-02-22 03:44:124855 glUniform1i(real_location, v0);
[email protected]3916c97e2010-02-25 03:20:504856}
4857
4858void GLES2DecoderImpl::DoUniform1iv(
[email protected]1b0a6752012-02-22 03:44:124859 GLint fake_location, GLsizei count, const GLint *value) {
[email protected]43c2f1f2011-03-25 18:35:364860 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124861 GLint real_location = -1;
4862 if (!PrepForSetUniformByLocation(
4863 fake_location, "glUniform1iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364864 return;
4865 }
[email protected]74727112012-06-13 21:18:084866 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
4867 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]d20a6512012-05-02 20:17:464868 if (!current_program_->SetSamplers(
4869 group_->max_texture_units(), fake_location, count, value)) {
[email protected]ad84a3a2012-06-08 21:42:434870 SetGLError(GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
[email protected]d20a6512012-05-02 20:17:464871 return;
4872 }
[email protected]43c2f1f2011-03-25 18:35:364873 }
[email protected]1b0a6752012-02-22 03:44:124874 glUniform1iv(real_location, count, value);
[email protected]3916c97e2010-02-25 03:20:504875}
4876
[email protected]939e7362010-05-13 20:49:104877void GLES2DecoderImpl::DoUniform1fv(
[email protected]1b0a6752012-02-22 03:44:124878 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364879 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124880 GLint real_location = -1;
4881 if (!PrepForSetUniformByLocation(
4882 fake_location, "glUniform1fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104883 return;
4884 }
4885 if (type == GL_BOOL) {
4886 scoped_array<GLint> temp(new GLint[count]);
4887 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:534888 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104889 }
[email protected]1b0a6752012-02-22 03:44:124890 DoUniform1iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104891 } else {
[email protected]1b0a6752012-02-22 03:44:124892 glUniform1fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104893 }
4894}
4895
4896void GLES2DecoderImpl::DoUniform2fv(
[email protected]1b0a6752012-02-22 03:44:124897 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364898 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124899 GLint real_location = -1;
4900 if (!PrepForSetUniformByLocation(
4901 fake_location, "glUniform2fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104902 return;
4903 }
4904 if (type == GL_BOOL_VEC2) {
4905 GLsizei num_values = count * 2;
4906 scoped_array<GLint> temp(new GLint[num_values]);
4907 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534908 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104909 }
[email protected]1b0a6752012-02-22 03:44:124910 glUniform2iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104911 } else {
[email protected]1b0a6752012-02-22 03:44:124912 glUniform2fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104913 }
4914}
4915
4916void GLES2DecoderImpl::DoUniform3fv(
[email protected]1b0a6752012-02-22 03:44:124917 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364918 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124919 GLint real_location = -1;
4920 if (!PrepForSetUniformByLocation(
4921 fake_location, "glUniform3fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104922 return;
4923 }
4924 if (type == GL_BOOL_VEC3) {
4925 GLsizei num_values = count * 3;
4926 scoped_array<GLint> temp(new GLint[num_values]);
4927 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534928 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104929 }
[email protected]1b0a6752012-02-22 03:44:124930 glUniform3iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104931 } else {
[email protected]1b0a6752012-02-22 03:44:124932 glUniform3fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104933 }
4934}
4935
4936void GLES2DecoderImpl::DoUniform4fv(
[email protected]1b0a6752012-02-22 03:44:124937 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364938 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124939 GLint real_location = -1;
4940 if (!PrepForSetUniformByLocation(
4941 fake_location, "glUniform4fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104942 return;
4943 }
4944 if (type == GL_BOOL_VEC4) {
4945 GLsizei num_values = count * 4;
4946 scoped_array<GLint> temp(new GLint[num_values]);
4947 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534948 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104949 }
[email protected]1b0a6752012-02-22 03:44:124950 glUniform4iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104951 } else {
[email protected]1b0a6752012-02-22 03:44:124952 glUniform4fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104953 }
4954}
4955
[email protected]43c2f1f2011-03-25 18:35:364956void GLES2DecoderImpl::DoUniform2iv(
[email protected]1b0a6752012-02-22 03:44:124957 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364958 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124959 GLint real_location = -1;
4960 if (!PrepForSetUniformByLocation(
4961 fake_location, "glUniform2iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364962 return;
4963 }
[email protected]1b0a6752012-02-22 03:44:124964 glUniform2iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364965}
4966
4967void GLES2DecoderImpl::DoUniform3iv(
[email protected]1b0a6752012-02-22 03:44:124968 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364969 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124970 GLint real_location = -1;
4971 if (!PrepForSetUniformByLocation(
4972 fake_location, "glUniform3iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364973 return;
4974 }
[email protected]1b0a6752012-02-22 03:44:124975 glUniform3iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364976}
4977
4978void GLES2DecoderImpl::DoUniform4iv(
[email protected]1b0a6752012-02-22 03:44:124979 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364980 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124981 GLint real_location = -1;
4982 if (!PrepForSetUniformByLocation(
4983 fake_location, "glUniform4iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364984 return;
4985 }
[email protected]1b0a6752012-02-22 03:44:124986 glUniform4iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364987}
4988
4989void GLES2DecoderImpl::DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:124990 GLint fake_location, GLsizei count, GLboolean transpose,
4991 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364992 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124993 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364994 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124995 fake_location, "glUniformMatrix2fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364996 return;
4997 }
[email protected]1b0a6752012-02-22 03:44:124998 glUniformMatrix2fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364999}
5000
5001void GLES2DecoderImpl::DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:125002 GLint fake_location, GLsizei count, GLboolean transpose,
5003 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365004 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125005 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:365006 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:125007 fake_location, "glUniformMatrix3fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365008 return;
5009 }
[email protected]1b0a6752012-02-22 03:44:125010 glUniformMatrix3fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:365011}
5012
5013void GLES2DecoderImpl::DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:125014 GLint fake_location, GLsizei count, GLboolean transpose,
5015 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365016 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125017 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:365018 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:125019 fake_location, "glUniformMatrix4fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365020 return;
5021 }
[email protected]1b0a6752012-02-22 03:44:125022 glUniformMatrix4fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:365023}
5024
[email protected]3916c97e2010-02-25 03:20:505025void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:035026 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:505027 ProgramManager::ProgramInfo* info = NULL;
5028 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:585029 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:505030 if (!info) {
[email protected]ae51d192010-04-27 00:48:035031 return;
5032 }
5033 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:505034 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]ad84a3a2012-06-08 21:42:435035 SetGLError(GL_INVALID_OPERATION, "glUseProgram", "program not linked");
[email protected]3916c97e2010-02-25 03:20:505036 return;
5037 }
[email protected]ae51d192010-04-27 00:48:035038 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:505039 }
[email protected]ca488e12010-12-13 20:06:145040 if (current_program_) {
5041 program_manager()->UnuseProgram(shader_manager(), current_program_);
5042 }
[email protected]3916c97e2010-02-25 03:20:505043 current_program_ = info;
[email protected]2df73892012-04-28 01:09:545044 glUseProgram(service_id);
[email protected]ca488e12010-12-13 20:06:145045 if (current_program_) {
5046 program_manager()->UseProgram(current_program_);
5047 }
[email protected]3916c97e2010-02-25 03:20:505048}
5049
[email protected]efcdd2362012-07-09 21:07:005050uint32 GLES2DecoderImpl::GetGLError() {
[email protected]96449d2c2009-11-25 00:01:325051 // Check the GL error first, then our wrapped error.
5052 GLenum error = glGetError();
5053 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:375054 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:325055 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:295056 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:325057 break;
5058 }
5059 }
5060 }
5061
5062 if (error != GL_NO_ERROR) {
5063 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:295064 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:325065 }
5066 return error;
5067}
5068
[email protected]1002c2d2011-06-28 22:39:045069GLenum GLES2DecoderImpl::PeekGLError() {
5070 GLenum error = glGetError();
5071 if (error != GL_NO_ERROR) {
[email protected]ad84a3a2012-06-08 21:42:435072 SetGLError(error, "", "");
[email protected]1002c2d2011-06-28 22:39:045073 }
5074 return error;
5075}
5076
[email protected]ad84a3a2012-06-08 21:42:435077void GLES2DecoderImpl::SetGLError(
5078 GLenum error, const char* function_name, const char* msg) {
[email protected]8eee29c2010-04-29 03:38:295079 if (msg) {
5080 last_error_ = msg;
[email protected]0f8afe82012-05-14 23:43:015081 LogMessage(std::string("GL ERROR :") +
[email protected]ad84a3a2012-06-08 21:42:435082 GLES2Util::GetStringEnum(error) + " : " +
5083 function_name + ": " + msg);
[email protected]8eee29c2010-04-29 03:38:295084 }
[email protected]ddd968b82010-03-02 00:44:295085 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:325086}
5087
[email protected]0f8afe82012-05-14 23:43:015088void GLES2DecoderImpl::LogMessage(const std::string& msg) {
5089 if (log_message_count_ < kMaxLogMessages ||
5090 CommandLine::ForCurrentProcess()->HasSwitch(
5091 switches::kDisableGLErrorLimit)) {
5092 ++log_message_count_;
5093 // LOG this unless logging is turned off as any chromium code that
5094 // generates these errors probably has a bug.
5095 if (log_synthesized_gl_errors()) {
[email protected]3f00df92012-06-19 00:44:585096 LOG(ERROR) << msg;
[email protected]0f8afe82012-05-14 23:43:015097 }
5098 if (!msg_callback_.is_null()) {
5099 msg_callback_.Run(0, msg);
5100 }
5101 } else {
5102 if (log_message_count_ == kMaxLogMessages) {
5103 ++log_message_count_;
5104 LOG(ERROR)
5105 << "Too many GL errors, not reporting any more for this context."
5106 << " use --disable-gl-error-limit to see all errors.";
5107 }
5108 }
5109}
5110
5111void GLES2DecoderImpl::RenderWarning(const std::string& msg) {
5112 LogMessage(std::string("RENDER WARNING: ") + msg);
5113}
5114
5115void GLES2DecoderImpl::PerformanceWarning(const std::string& msg) {
5116 LogMessage(std::string("PERFORMANCE WARNING: ") + msg);
5117}
5118
[email protected]07f54fcc2009-12-22 02:46:305119void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
5120 GLenum error;
5121 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]ad84a3a2012-06-08 21:42:435122 SetGLError(error, "", NULL);
[email protected]07f54fcc2009-12-22 02:46:305123 }
5124}
5125
[email protected]6217d392010-03-25 22:08:355126void GLES2DecoderImpl::ClearRealGLErrors() {
5127 GLenum error;
5128 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]3ed14d112011-12-13 22:05:515129 if (error != GL_OUT_OF_MEMORY) {
5130 // GL_OUT_OF_MEMORY can legally happen on lost device.
5131 NOTREACHED() << "GL error " << error << " was unhandled.";
5132 }
[email protected]6217d392010-03-25 22:08:355133 }
5134}
5135
[email protected]ef526492010-06-02 23:12:255136bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:505137 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:255138 // Only check if there are some unrenderable textures.
5139 if (!texture_manager()->HaveUnrenderableTextures()) {
5140 return false;
5141 }
5142 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:505143 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
5144 current_program_->sampler_indices();
5145 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5146 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
5147 current_program_->GetUniformInfo(sampler_indices[ii]);
5148 DCHECK(uniform_info);
5149 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5150 GLuint texture_unit_index = uniform_info->texture_units[jj];
5151 if (texture_unit_index < group_->max_texture_units()) {
5152 TextureUnit& texture_unit = texture_units_[texture_unit_index];
5153 TextureManager::TextureInfo* texture_info =
[email protected]61eeb33f2011-07-26 15:30:315154 texture_unit.GetInfoForSamplerType(uniform_info->type);
[email protected]80eb6b52012-01-19 00:14:415155 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]ef526492010-06-02 23:12:255156 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:505157 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5158 glBindTexture(
[email protected]61eeb33f2011-07-26 15:30:315159 GetBindTargetForSamplerType(uniform_info->type),
[email protected]00f893d2010-08-24 18:55:495160 texture_manager()->black_texture_id(uniform_info->type));
[email protected]0f8afe82012-05-14 23:43:015161 RenderWarning(
5162 std::string("texture bound to texture unit ") +
5163 base::IntToString(texture_unit_index) +
5164 " is not renderable. It maybe non-power-of-2 and have "
5165 " incompatible texture filtering or is not "
5166 "'texture complete'");
[email protected]3916c97e2010-02-25 03:20:505167 }
5168 }
5169 // else: should this be an error?
5170 }
5171 }
[email protected]ef526492010-06-02 23:12:255172 return textures_set;
[email protected]3916c97e2010-02-25 03:20:505173}
5174
5175void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
5176 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:505177 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
5178 current_program_->sampler_indices();
5179 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5180 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
5181 current_program_->GetUniformInfo(sampler_indices[ii]);
5182 DCHECK(uniform_info);
5183 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5184 GLuint texture_unit_index = uniform_info->texture_units[jj];
5185 if (texture_unit_index < group_->max_texture_units()) {
5186 TextureUnit& texture_unit = texture_units_[texture_unit_index];
5187 TextureManager::TextureInfo* texture_info =
5188 uniform_info->type == GL_SAMPLER_2D ?
5189 texture_unit.bound_texture_2d :
5190 texture_unit.bound_texture_cube_map;
[email protected]80eb6b52012-01-19 00:14:415191 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]3916c97e2010-02-25 03:20:505192 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5193 // Get the texture info that was previously bound here.
5194 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
5195 texture_unit.bound_texture_2d :
5196 texture_unit.bound_texture_cube_map;
5197 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:035198 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:505199 }
5200 }
5201 }
5202 }
5203 // Set the active texture back to whatever the user had it as.
5204 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:305205}
5206
[email protected]0d6bfdc2011-11-02 01:32:205207bool GLES2DecoderImpl::ClearUnclearedTextures() {
5208 // Only check if there are some uncleared textures.
5209 if (!texture_manager()->HaveUnsafeTextures()) {
5210 return true;
5211 }
5212
5213 // 1: Check all textures we are about to render with.
5214 if (current_program_) {
5215 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
5216 current_program_->sampler_indices();
5217 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5218 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
5219 current_program_->GetUniformInfo(sampler_indices[ii]);
5220 DCHECK(uniform_info);
5221 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5222 GLuint texture_unit_index = uniform_info->texture_units[jj];
5223 if (texture_unit_index < group_->max_texture_units()) {
5224 TextureUnit& texture_unit = texture_units_[texture_unit_index];
5225 TextureManager::TextureInfo* texture_info =
5226 texture_unit.GetInfoForSamplerType(uniform_info->type);
5227 if (texture_info && !texture_info->SafeToRenderFrom()) {
5228 if (!texture_manager()->ClearRenderableLevels(this, texture_info)) {
5229 return false;
5230 }
5231 }
5232 }
5233 }
5234 }
5235 }
5236 return true;
5237}
5238
[email protected]c6aef902012-02-14 03:31:425239bool GLES2DecoderImpl::IsDrawValid(
[email protected]ad84a3a2012-06-08 21:42:435240 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount) {
[email protected]689fa1c52010-06-09 18:35:035241 // NOTE: We specifically do not check current_program->IsValid() because
5242 // it could never be invalid since glUseProgram would have failed. While
5243 // glLinkProgram could later mark the program as invalid the previous
5244 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:145245 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:505246 // The program does not exist.
5247 // But GL says no ERROR.
[email protected]0f8afe82012-05-14 23:43:015248 RenderWarning("Drawing with no current shader program.");
[email protected]3916c97e2010-02-25 03:20:505249 return false;
5250 }
[email protected]c6aef902012-02-14 03:31:425251
5252 // true if any enabled, used divisor is zero
5253 bool divisor0 = false;
[email protected]f39f4b3f2010-05-12 17:04:085254 // Validate all attribs currently enabled. If they are used by the current
5255 // program then check that they have enough elements to handle the draw call.
5256 // If they are not used by the current program check that they have a buffer
5257 // assigned.
5258 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:445259 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]f39f4b3f2010-05-12 17:04:085260 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:405261 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:085262 const VertexAttribManager::VertexAttribInfo* info = *it;
5263 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5264 current_program_->GetAttribInfoByLocation(info->index());
5265 if (attrib_info) {
[email protected]c6aef902012-02-14 03:31:425266 divisor0 |= (info->divisor() == 0);
5267 GLuint count = info->MaxVertexAccessed(primcount, max_vertex_accessed);
[email protected]f39f4b3f2010-05-12 17:04:085268 // This attrib is used in the current program.
[email protected]c6aef902012-02-14 03:31:425269 if (!info->CanAccess(count)) {
[email protected]0f8afe82012-05-14 23:43:015270 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:435271 GL_INVALID_OPERATION, function_name,
[email protected]0f8afe82012-05-14 23:43:015272 (std::string(
[email protected]ad84a3a2012-06-08 21:42:435273 "attempt to access out of range vertices in attribute ") +
5274 base::IntToString(info->index())).c_str());
[email protected]f39f4b3f2010-05-12 17:04:085275 return false;
5276 }
5277 } else {
5278 // This attrib is not used in the current program.
[email protected]a0b78dc2011-11-11 10:43:105279 if (!info->buffer()) {
[email protected]f39f4b3f2010-05-12 17:04:085280 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:435281 GL_INVALID_OPERATION, function_name,
[email protected]0f8afe82012-05-14 23:43:015282 (std::string(
[email protected]ad84a3a2012-06-08 21:42:435283 "attempt to render with no buffer attached to "
[email protected]0f8afe82012-05-14 23:43:015284 "enabled attribute ") +
5285 base::IntToString(info->index())).c_str());
[email protected]f39f4b3f2010-05-12 17:04:085286 return false;
5287 }
[email protected]1d32bc82010-01-13 22:06:465288 }
[email protected]07f54fcc2009-12-22 02:46:305289 }
[email protected]c6aef902012-02-14 03:31:425290
5291 if (primcount && !divisor0) {
5292 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:435293 GL_INVALID_OPERATION, function_name,
5294 "attempt instanced render with all attributes having "
[email protected]c6aef902012-02-14 03:31:425295 "non-zero divisors");
5296 return false;
5297 }
5298
[email protected]3916c97e2010-02-25 03:20:505299 return true;
[email protected]b1122982010-05-17 23:04:245300}
5301
[email protected]c13e1da62011-09-09 21:48:305302bool GLES2DecoderImpl::SimulateAttrib0(
[email protected]ad84a3a2012-06-08 21:42:435303 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
[email protected]c13e1da62011-09-09 21:48:305304 DCHECK(simulated);
5305 *simulated = false;
5306
[email protected]876f6fee2010-08-02 23:10:325307 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
[email protected]c13e1da62011-09-09 21:48:305308 return true;
[email protected]876f6fee2010-08-02 23:10:325309
[email protected]b1122982010-05-17 23:04:245310 const VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445311 vertex_attrib_manager_->GetVertexAttribInfo(0);
[email protected]b1122982010-05-17 23:04:245312 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:495313 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
5314 if (info->enabled() && attrib_0_used) {
[email protected]c13e1da62011-09-09 21:48:305315 return true;
[email protected]b1122982010-05-17 23:04:245316 }
5317
[email protected]b1122982010-05-17 23:04:245318 // Make a buffer with a single repeated vec4 value enough to
5319 // simulate the constant value that is supposed to be here.
5320 // This is required to emulate GLES2 on GL.
[email protected]c13e1da62011-09-09 21:48:305321 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
5322
5323 GLuint num_vertices = max_vertex_accessed + 1;
5324 GLuint size_needed = 0;
5325
5326 if (num_vertices == 0 ||
5327 !SafeMultiply(num_vertices, static_cast<GLuint>(sizeof(Vec4)),
5328 &size_needed) ||
5329 size_needed > 0x7FFFFFFFU) {
[email protected]ad84a3a2012-06-08 21:42:435330 SetGLError(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c13e1da62011-09-09 21:48:305331 return false;
5332 }
5333
[email protected]0f8afe82012-05-14 23:43:015334 PerformanceWarning(
5335 "Attribute 0 is disabled. This has signficant performance penalty");
5336
[email protected]c13e1da62011-09-09 21:48:305337 CopyRealGLErrorsToWrapper();
5338 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
5339
[email protected]8f0b86c2f2012-04-10 05:48:285340 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
5341 if (new_buffer) {
[email protected]fc753442011-02-04 19:49:495342 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305343 GLenum error = glGetError();
5344 if (error != GL_NO_ERROR) {
[email protected]ad84a3a2012-06-08 21:42:435345 SetGLError(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c13e1da62011-09-09 21:48:305346 return false;
5347 }
[email protected]fc753442011-02-04 19:49:495348 }
[email protected]8f0b86c2f2012-04-10 05:48:285349 if (new_buffer ||
5350 (attrib_0_used &&
5351 (!attrib_0_buffer_matches_value_ ||
5352 (info->value().v[0] != attrib_0_value_.v[0] ||
5353 info->value().v[1] != attrib_0_value_.v[1] ||
5354 info->value().v[2] != attrib_0_value_.v[2] ||
5355 info->value().v[3] != attrib_0_value_.v[3])))) {
[email protected]fc753442011-02-04 19:49:495356 std::vector<Vec4> temp(num_vertices, info->value());
5357 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
5358 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:245359 attrib_0_value_ = info->value();
5360 attrib_0_size_ = size_needed;
5361 }
5362
5363 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5364
[email protected]c6aef902012-02-14 03:31:425365 if (info->divisor())
5366 glVertexAttribDivisorANGLE(0, 0);
5367
[email protected]c13e1da62011-09-09 21:48:305368 *simulated = true;
[email protected]b1122982010-05-17 23:04:245369 return true;
[email protected]b1122982010-05-17 23:04:245370}
5371
[email protected]43410e92012-04-20 17:06:285372void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib) {
[email protected]b1122982010-05-17 23:04:245373 const VertexAttribManager::VertexAttribInfo* info =
[email protected]43410e92012-04-20 17:06:285374 vertex_attrib_manager_->GetVertexAttribInfo(attrib);
[email protected]b1122982010-05-17 23:04:245375 const void* ptr = reinterpret_cast<const void*>(info->offset());
5376 BufferManager::BufferInfo* buffer_info = info->buffer();
5377 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
5378 glVertexAttribPointer(
[email protected]43410e92012-04-20 17:06:285379 attrib, info->size(), info->type(), info->normalized(), info->gl_stride(),
[email protected]b1122982010-05-17 23:04:245380 ptr);
[email protected]c6aef902012-02-14 03:31:425381 if (info->divisor())
[email protected]43410e92012-04-20 17:06:285382 glVertexAttribDivisorANGLE(attrib, info->divisor());
[email protected]b1122982010-05-17 23:04:245383 glBindBuffer(GL_ARRAY_BUFFER,
5384 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
[email protected]43410e92012-04-20 17:06:285385
[email protected]265f8992012-07-20 01:03:145386 // Never touch vertex attribute 0's state (in particular, never
5387 // disable it) when running on desktop GL because it will never be
5388 // re-enabled.
5389 if (attrib != 0 ||
5390 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
5391 if (info->enabled()) {
5392 glEnableVertexAttribArray(attrib);
5393 } else {
5394 glDisableVertexAttribArray(attrib);
5395 }
[email protected]43410e92012-04-20 17:06:285396 }
[email protected]b1122982010-05-17 23:04:245397}
[email protected]07f54fcc2009-12-22 02:46:305398
[email protected]8fbedc02010-11-18 18:43:405399bool GLES2DecoderImpl::SimulateFixedAttribs(
[email protected]ad84a3a2012-06-08 21:42:435400 const char* function_name,
[email protected]c6aef902012-02-14 03:31:425401 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
[email protected]8fbedc02010-11-18 18:43:405402 DCHECK(simulated);
5403 *simulated = false;
5404 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
5405 return true;
5406
[email protected]3757a372012-01-19 05:20:445407 if (!vertex_attrib_manager_->HaveFixedAttribs()) {
[email protected]8fbedc02010-11-18 18:43:405408 return true;
5409 }
5410
[email protected]0f8afe82012-05-14 23:43:015411 PerformanceWarning(
5412 "GL_FIXED attributes have a signficant performance penalty");
5413
[email protected]8fbedc02010-11-18 18:43:405414 // NOTE: we could be smart and try to check if a buffer is used
5415 // twice in 2 different attribs, find the overlapping parts and therefore
5416 // duplicate the minimum amount of data but this whole code path is not meant
5417 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
5418 // tests so we just add to the buffer attrib used.
5419
[email protected]c13e1da62011-09-09 21:48:305420 GLuint elements_needed = 0;
[email protected]8fbedc02010-11-18 18:43:405421 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:445422 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]8fbedc02010-11-18 18:43:405423 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5424 infos.begin(); it != infos.end(); ++it) {
5425 const VertexAttribManager::VertexAttribInfo* info = *it;
5426 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5427 current_program_->GetAttribInfoByLocation(info->index());
[email protected]c6aef902012-02-14 03:31:425428 GLuint max_accessed = info->MaxVertexAccessed(primcount,
5429 max_vertex_accessed);
5430 GLuint num_vertices = max_accessed + 1;
5431 if (num_vertices == 0) {
[email protected]ad84a3a2012-06-08 21:42:435432 SetGLError(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c6aef902012-02-14 03:31:425433 return false;
5434 }
[email protected]8fbedc02010-11-18 18:43:405435 if (attrib_info &&
[email protected]c6aef902012-02-14 03:31:425436 info->CanAccess(max_accessed) &&
[email protected]8fbedc02010-11-18 18:43:405437 info->type() == GL_FIXED) {
[email protected]c13e1da62011-09-09 21:48:305438 GLuint elements_used = 0;
5439 if (!SafeMultiply(num_vertices,
5440 static_cast<GLuint>(info->size()), &elements_used) ||
[email protected]8fbedc02010-11-18 18:43:405441 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
[email protected]ad84a3a2012-06-08 21:42:435442 SetGLError(
5443 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]8fbedc02010-11-18 18:43:405444 return false;
5445 }
5446 }
5447 }
5448
[email protected]c13e1da62011-09-09 21:48:305449 const GLuint kSizeOfFloat = sizeof(float); // NOLINT
5450 GLuint size_needed = 0;
5451 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed) ||
5452 size_needed > 0x7FFFFFFFU) {
[email protected]ad84a3a2012-06-08 21:42:435453 SetGLError(GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]8fbedc02010-11-18 18:43:405454 return false;
5455 }
5456
[email protected]c13e1da62011-09-09 21:48:305457 CopyRealGLErrorsToWrapper();
[email protected]8fbedc02010-11-18 18:43:405458
5459 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
[email protected]c13e1da62011-09-09 21:48:305460 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
[email protected]8fbedc02010-11-18 18:43:405461 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305462 GLenum error = glGetError();
5463 if (error != GL_NO_ERROR) {
[email protected]ad84a3a2012-06-08 21:42:435464 SetGLError(
5465 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]c13e1da62011-09-09 21:48:305466 return false;
5467 }
[email protected]8fbedc02010-11-18 18:43:405468 }
5469
5470 // Copy the elements and convert to float
5471 GLintptr offset = 0;
5472 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5473 infos.begin(); it != infos.end(); ++it) {
5474 const VertexAttribManager::VertexAttribInfo* info = *it;
5475 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5476 current_program_->GetAttribInfoByLocation(info->index());
[email protected]c6aef902012-02-14 03:31:425477 GLuint max_accessed = info->MaxVertexAccessed(primcount,
5478 max_vertex_accessed);
5479 GLuint num_vertices = max_accessed + 1;
5480 if (num_vertices == 0) {
[email protected]ad84a3a2012-06-08 21:42:435481 SetGLError(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c6aef902012-02-14 03:31:425482 return false;
5483 }
[email protected]8fbedc02010-11-18 18:43:405484 if (attrib_info &&
[email protected]c6aef902012-02-14 03:31:425485 info->CanAccess(max_accessed) &&
[email protected]8fbedc02010-11-18 18:43:405486 info->type() == GL_FIXED) {
5487 int num_elements = info->size() * kSizeOfFloat;
5488 int size = num_elements * num_vertices;
5489 scoped_array<float> data(new float[size]);
5490 const int32* src = reinterpret_cast<const int32 *>(
5491 info->buffer()->GetRange(info->offset(), size));
5492 const int32* end = src + num_elements;
5493 float* dst = data.get();
5494 while (src != end) {
5495 *dst++ = static_cast<float>(*src++) / 65536.0f;
5496 }
5497 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
5498 glVertexAttribPointer(
5499 info->index(), info->size(), GL_FLOAT, false, 0,
5500 reinterpret_cast<GLvoid*>(offset));
5501 offset += size;
5502 }
5503 }
5504 *simulated = true;
5505 return true;
5506}
5507
5508void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
5509 // There's no need to call glVertexAttribPointer because we shadow all the
5510 // settings and passing GL_FIXED to it will not work.
5511 glBindBuffer(GL_ARRAY_BUFFER,
5512 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
5513}
5514
[email protected]ad84a3a2012-06-08 21:42:435515error::Error GLES2DecoderImpl::DoDrawArrays(
5516 const char* function_name,
5517 bool instanced,
5518 GLenum mode,
5519 GLint first,
5520 GLsizei count,
5521 GLsizei primcount) {
[email protected]a7266a92012-06-28 02:11:085522 if (ShouldDeferDraws())
5523 return error::kDeferCommandUntilLater;
[email protected]38d139d2011-07-14 00:38:435524 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]ad84a3a2012-06-08 21:42:435525 SetGLError(GL_INVALID_ENUM, function_name, "mode GL_INVALID_ENUM");
[email protected]38d139d2011-07-14 00:38:435526 return error::kNoError;
5527 }
5528 if (count < 0) {
[email protected]ad84a3a2012-06-08 21:42:435529 SetGLError(GL_INVALID_VALUE, function_name, "count < 0");
[email protected]38d139d2011-07-14 00:38:435530 return error::kNoError;
5531 }
[email protected]c6aef902012-02-14 03:31:425532 if (primcount < 0) {
[email protected]ad84a3a2012-06-08 21:42:435533 SetGLError(GL_INVALID_VALUE, function_name, "primcount < 0");
[email protected]c6aef902012-02-14 03:31:425534 return error::kNoError;
5535 }
[email protected]ad84a3a2012-06-08 21:42:435536 if (!CheckBoundFramebuffersValid(function_name)) {
[email protected]38d139d2011-07-14 00:38:435537 return error::kNoError;
5538 }
5539 // We have to check this here because the prototype for glDrawArrays
5540 // is GLint not GLsizei.
5541 if (first < 0) {
[email protected]ad84a3a2012-06-08 21:42:435542 SetGLError(GL_INVALID_VALUE, function_name, "first < 0");
[email protected]38d139d2011-07-14 00:38:435543 return error::kNoError;
5544 }
5545
[email protected]c6aef902012-02-14 03:31:425546 if (count == 0 || (instanced && primcount == 0)) {
[email protected]0f8afe82012-05-14 23:43:015547 RenderWarning("Render count or primcount is 0.");
[email protected]38d139d2011-07-14 00:38:435548 return error::kNoError;
5549 }
5550
5551 GLuint max_vertex_accessed = first + count - 1;
[email protected]ad84a3a2012-06-08 21:42:435552 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:205553 if (!ClearUnclearedTextures()) {
[email protected]ad84a3a2012-06-08 21:42:435554 SetGLError(GL_INVALID_VALUE, function_name, "out of memory");
[email protected]0d6bfdc2011-11-02 01:32:205555 return error::kNoError;
5556 }
[email protected]c13e1da62011-09-09 21:48:305557 bool simulated_attrib_0 = false;
[email protected]ad84a3a2012-06-08 21:42:435558 if (!SimulateAttrib0(
5559 function_name, max_vertex_accessed, &simulated_attrib_0)) {
[email protected]c13e1da62011-09-09 21:48:305560 return error::kNoError;
5561 }
[email protected]38d139d2011-07-14 00:38:435562 bool simulated_fixed_attribs = false;
[email protected]ad84a3a2012-06-08 21:42:435563 if (SimulateFixedAttribs(
5564 function_name, max_vertex_accessed, &simulated_fixed_attribs,
5565 primcount)) {
[email protected]38d139d2011-07-14 00:38:435566 bool textures_set = SetBlackTextureForNonRenderableTextures();
5567 ApplyDirtyState();
[email protected]c6aef902012-02-14 03:31:425568 if (!instanced) {
5569 glDrawArrays(mode, first, count);
5570 } else {
5571 glDrawArraysInstancedANGLE(mode, first, count, primcount);
5572 }
[email protected]22e3f552012-03-13 01:54:195573 ProcessPendingQueries();
[email protected]38d139d2011-07-14 00:38:435574 if (textures_set) {
5575 RestoreStateForNonRenderableTextures();
5576 }
5577 if (simulated_fixed_attribs) {
5578 RestoreStateForSimulatedFixedAttribs();
5579 }
5580 }
5581 if (simulated_attrib_0) {
[email protected]43410e92012-04-20 17:06:285582 RestoreStateForAttrib(0);
[email protected]38d139d2011-07-14 00:38:435583 }
5584 if (WasContextLost()) {
5585 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawArrays.";
5586 return error::kLostContext;
5587 }
5588 }
5589 return error::kNoError;
5590}
5591
[email protected]c6aef902012-02-14 03:31:425592error::Error GLES2DecoderImpl::HandleDrawArrays(
5593 uint32 immediate_data_size, const gles2::DrawArrays& c) {
[email protected]ad84a3a2012-06-08 21:42:435594 return DoDrawArrays("glDrawArrays",
5595 false,
[email protected]c6aef902012-02-14 03:31:425596 static_cast<GLenum>(c.mode),
5597 static_cast<GLint>(c.first),
5598 static_cast<GLsizei>(c.count),
5599 0);
5600}
5601
5602error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
5603 uint32 immediate_data_size, const gles2::DrawArraysInstancedANGLE& c) {
5604 if (!feature_info_->feature_flags().angle_instanced_arrays) {
5605 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435606 "glDrawArraysInstancedANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:425607 return error::kNoError;
5608 }
[email protected]ad84a3a2012-06-08 21:42:435609 return DoDrawArrays("glDrawArraysIntancedANGLE",
5610 true,
[email protected]c6aef902012-02-14 03:31:425611 static_cast<GLenum>(c.mode),
5612 static_cast<GLint>(c.first),
5613 static_cast<GLsizei>(c.count),
5614 static_cast<GLsizei>(c.primcount));
5615}
5616
[email protected]ad84a3a2012-06-08 21:42:435617error::Error GLES2DecoderImpl::DoDrawElements(
5618 const char* function_name,
5619 bool instanced,
5620 GLenum mode,
5621 GLsizei count,
5622 GLenum type,
5623 int32 offset,
5624 GLsizei primcount) {
[email protected]a7266a92012-06-28 02:11:085625 if (ShouldDeferDraws())
5626 return error::kDeferCommandUntilLater;
[email protected]a0b78dc2011-11-11 10:43:105627 if (!bound_element_array_buffer_) {
[email protected]8eee29c2010-04-29 03:38:295628 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435629 function_name, "No element array buffer bound");
[email protected]8eee29c2010-04-29 03:38:295630 return error::kNoError;
5631 }
5632
[email protected]8eee29c2010-04-29 03:38:295633 if (count < 0) {
[email protected]ad84a3a2012-06-08 21:42:435634 SetGLError(GL_INVALID_VALUE, function_name, "count < 0");
[email protected]8eee29c2010-04-29 03:38:295635 return error::kNoError;
5636 }
5637 if (offset < 0) {
[email protected]ad84a3a2012-06-08 21:42:435638 SetGLError(GL_INVALID_VALUE, function_name, "offset < 0");
[email protected]8eee29c2010-04-29 03:38:295639 return error::kNoError;
5640 }
[email protected]9438b012010-06-15 22:55:055641 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]ad84a3a2012-06-08 21:42:435642 SetGLError(GL_INVALID_ENUM, function_name, "mode GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:295643 return error::kNoError;
5644 }
[email protected]9438b012010-06-15 22:55:055645 if (!validators_->index_type.IsValid(type)) {
[email protected]ad84a3a2012-06-08 21:42:435646 SetGLError(GL_INVALID_ENUM, function_name, "type GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:295647 return error::kNoError;
5648 }
[email protected]c6aef902012-02-14 03:31:425649 if (primcount < 0) {
[email protected]ad84a3a2012-06-08 21:42:435650 SetGLError(GL_INVALID_VALUE, function_name, "primcount < 0");
[email protected]c6aef902012-02-14 03:31:425651 return error::kNoError;
5652 }
[email protected]8eee29c2010-04-29 03:38:295653
[email protected]ad84a3a2012-06-08 21:42:435654 if (!CheckBoundFramebuffersValid(function_name)) {
[email protected]3a03a8f2011-03-19 00:51:275655 return error::kNoError;
5656 }
5657
[email protected]c6aef902012-02-14 03:31:425658 if (count == 0 || (instanced && primcount == 0)) {
[email protected]6c788fb72010-08-26 02:16:315659 return error::kNoError;
5660 }
5661
[email protected]8eee29c2010-04-29 03:38:295662 GLuint max_vertex_accessed;
5663 if (!bound_element_array_buffer_->GetMaxValueForRange(
5664 offset, count, type, &max_vertex_accessed)) {
5665 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435666 function_name, "range out of bounds for buffer");
[email protected]8eee29c2010-04-29 03:38:295667 return error::kNoError;
5668 }
5669
[email protected]ad84a3a2012-06-08 21:42:435670 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:205671 if (!ClearUnclearedTextures()) {
[email protected]ad84a3a2012-06-08 21:42:435672 SetGLError(GL_INVALID_VALUE, function_name, "out of memory");
[email protected]0d6bfdc2011-11-02 01:32:205673 return error::kNoError;
5674 }
[email protected]c13e1da62011-09-09 21:48:305675 bool simulated_attrib_0 = false;
[email protected]ad84a3a2012-06-08 21:42:435676 if (!SimulateAttrib0(
5677 function_name, max_vertex_accessed, &simulated_attrib_0)) {
[email protected]c13e1da62011-09-09 21:48:305678 return error::kNoError;
5679 }
[email protected]8fbedc02010-11-18 18:43:405680 bool simulated_fixed_attribs = false;
[email protected]ad84a3a2012-06-08 21:42:435681 if (SimulateFixedAttribs(
5682 function_name, max_vertex_accessed, &simulated_fixed_attribs,
5683 primcount)) {
[email protected]8fbedc02010-11-18 18:43:405684 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:465685 ApplyDirtyState();
[email protected]8fbedc02010-11-18 18:43:405686 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
[email protected]c6aef902012-02-14 03:31:425687 if (!instanced) {
5688 glDrawElements(mode, count, type, indices);
5689 } else {
5690 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
5691 }
[email protected]22e3f552012-03-13 01:54:195692 ProcessPendingQueries();
[email protected]8fbedc02010-11-18 18:43:405693 if (textures_set) {
5694 RestoreStateForNonRenderableTextures();
5695 }
5696 if (simulated_fixed_attribs) {
5697 RestoreStateForSimulatedFixedAttribs();
5698 }
[email protected]ba3176a2009-12-16 18:19:465699 }
[email protected]b1122982010-05-17 23:04:245700 if (simulated_attrib_0) {
[email protected]43410e92012-04-20 17:06:285701 RestoreStateForAttrib(0);
[email protected]b1122982010-05-17 23:04:245702 }
[email protected]38d139d2011-07-14 00:38:435703 if (WasContextLost()) {
5704 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawElements.";
5705 return error::kLostContext;
5706 }
[email protected]96449d2c2009-11-25 00:01:325707 }
[email protected]f7a64ee2010-02-01 22:24:145708 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325709}
5710
[email protected]c6aef902012-02-14 03:31:425711error::Error GLES2DecoderImpl::HandleDrawElements(
5712 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]ad84a3a2012-06-08 21:42:435713 return DoDrawElements("glDrawElements",
5714 false,
[email protected]c6aef902012-02-14 03:31:425715 static_cast<GLenum>(c.mode),
5716 static_cast<GLsizei>(c.count),
5717 static_cast<GLenum>(c.type),
5718 static_cast<int32>(c.index_offset),
5719 0);
5720}
5721
5722error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
5723 uint32 immediate_data_size, const gles2::DrawElementsInstancedANGLE& c) {
5724 if (!feature_info_->feature_flags().angle_instanced_arrays) {
5725 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435726 "glDrawElementsInstancedANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:425727 return error::kNoError;
5728 }
[email protected]ad84a3a2012-06-08 21:42:435729 return DoDrawElements("glDrawElementsInstancedANGLE",
5730 true,
[email protected]c6aef902012-02-14 03:31:425731 static_cast<GLenum>(c.mode),
5732 static_cast<GLsizei>(c.count),
5733 static_cast<GLenum>(c.type),
5734 static_cast<int32>(c.index_offset),
5735 static_cast<GLsizei>(c.primcount));
5736}
5737
[email protected]269200b12010-11-18 22:53:065738GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:235739 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
5740 GLuint max_vertex_accessed = 0;
5741 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:295742 if (!info) {
[email protected]ae51d192010-04-27 00:48:035743 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:295744 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:435745 "GetMaxValueInBufferCHROMIUM", "unknown buffer");
[email protected]29a9eb52010-04-13 09:04:235746 } else {
5747 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:035748 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:065749 SetGLError(
5750 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435751 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:235752 }
5753 }
5754 return max_vertex_accessed;
5755}
5756
[email protected]96449d2c2009-11-25 00:01:325757// Calls glShaderSource for the various versions of the ShaderSource command.
5758// Assumes that data / data_size points to a piece of memory that is in range
5759// of whatever context it came from (shared memory, immediate memory, bucket
5760// memory.)
[email protected]45bf5152010-02-12 00:11:315761error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035762 GLuint client_id, const char* data, uint32 data_size) {
[email protected]258a3313f2011-10-18 20:13:575763 std::string str(data, data + data_size);
[email protected]6b8cf1a2010-05-06 16:13:585764 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5765 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:315766 if (!info) {
[email protected]45bf5152010-02-12 00:11:315767 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325768 }
[email protected]45bf5152010-02-12 00:11:315769 // Note: We don't actually call glShaderSource here. We wait until
5770 // the call to glCompileShader.
[email protected]258a3313f2011-10-18 20:13:575771 info->UpdateSource(str.c_str());
[email protected]f7a64ee2010-02-01 22:24:145772 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325773}
5774
[email protected]f7a64ee2010-02-01 22:24:145775error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:195776 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:325777 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315778 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:325779 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:465780 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145781 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325782 }
[email protected]ae51d192010-04-27 00:48:035783 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:325784}
5785
[email protected]f7a64ee2010-02-01 22:24:145786error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:195787 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:325788 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315789 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:305790 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465791 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145792 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325793 }
[email protected]ae51d192010-04-27 00:48:035794 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:315795}
5796
[email protected]558847a2010-03-24 07:02:545797error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
5798 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:545799 Bucket* bucket = GetBucket(c.data_bucket_id);
5800 if (!bucket || bucket->size() == 0) {
5801 return error::kInvalidArguments;
5802 }
5803 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035804 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:545805 bucket->size() - 1);
5806}
5807
[email protected]ae51d192010-04-27 00:48:035808void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]43ed3a72012-05-30 22:55:385809 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]6b8cf1a2010-05-06 16:13:585810 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5811 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:315812 if (!info) {
[email protected]45bf5152010-02-12 00:11:315813 return;
5814 }
[email protected]7f1a51c322012-07-19 18:52:025815 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
5816 // glShaderSource and then glCompileShader.
5817 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:345818 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:185819 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:345820 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:455821 vertex_translator_.get() : fragment_translator_.get();
[email protected]7f1a51c322012-07-19 18:52:025822
5823 if (!translator->Translate(shader_src)) {
5824 info->SetStatus(false, translator->info_log(), NULL);
5825 return;
5826 }
5827 shader_src = translator->translated_shader();
5828 if (!feature_info_->feature_flags().angle_translated_shader_source)
5829 info->UpdateTranslatedSource(shader_src);
[email protected]de17df392010-04-23 21:09:415830 }
[email protected]de17df392010-04-23 21:09:415831
[email protected]7f1a51c322012-07-19 18:52:025832 glShaderSource(info->service_id(), 1, &shader_src, NULL);
5833 glCompileShader(info->service_id());
5834 if (feature_info_->feature_flags().angle_translated_shader_source) {
5835 GLint max_len = 0;
5836 glGetShaderiv(info->service_id(),
5837 GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
5838 &max_len);
5839 scoped_array<char> temp(new char[max_len]);
5840 GLint len = 0;
5841 glGetTranslatedShaderSourceANGLE(
5842 info->service_id(), max_len, &len, temp.get());
5843 DCHECK(max_len == 0 || len < max_len);
5844 DCHECK(len == 0 || temp[len] == '\0');
5845 info->UpdateTranslatedSource(temp.get());
5846 }
5847
5848 GLint status = GL_FALSE;
5849 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
5850 if (status) {
5851 info->SetStatus(true, "", translator);
5852 } else {
5853 // We cannot reach here if we are using the shader translator.
5854 // All invalid shaders must be rejected by the translator.
5855 // All translated shaders must compile.
5856 LOG_IF(ERROR, use_shader_translator_)
5857 << "Shader translator allowed/produced an invalid shader.";
5858 GLint max_len = 0;
5859 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
5860 scoped_array<char> temp(new char[max_len]);
5861 GLint len = 0;
5862 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
5863 DCHECK(max_len == 0 || len < max_len);
5864 DCHECK(len == 0 || temp[len] == '\0');
5865 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
5866 }
[email protected]45bf5152010-02-12 00:11:315867};
5868
[email protected]ddd968b82010-03-02 00:44:295869void GLES2DecoderImpl::DoGetShaderiv(
5870 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:585871 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5872 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:295873 if (!info) {
[email protected]ddd968b82010-03-02 00:44:295874 return;
5875 }
[email protected]8f1ccdac2010-05-19 21:01:485876 switch (pname) {
5877 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525878 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:485879 return;
5880 case GL_COMPILE_STATUS:
[email protected]062c38b2012-01-18 03:25:105881 *params = compile_shader_always_succeeds_ ? true : info->IsValid();
[email protected]e5186162010-06-14 18:54:415882 return;
[email protected]8f1ccdac2010-05-19 21:01:485883 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525884 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:415885 return;
[email protected]d6a53e42011-10-05 00:09:365886 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5887 *params = info->translated_source() ?
5888 info->translated_source()->size() + 1 : 0;
5889 return;
[email protected]8f1ccdac2010-05-19 21:01:485890 default:
5891 break;
[email protected]ddd968b82010-03-02 00:44:295892 }
[email protected]8f1ccdac2010-05-19 21:01:485893 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:295894}
5895
[email protected]ae51d192010-04-27 00:48:035896error::Error GLES2DecoderImpl::HandleGetShaderSource(
5897 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
5898 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:035899 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5900 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:585901 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5902 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:525903 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:295904 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:295905 return error::kNoError;
5906 }
[email protected]df6cf1ad2011-01-29 01:20:525907 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:035908 return error::kNoError;
5909}
5910
[email protected]d6a53e42011-10-05 00:09:365911error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
5912 uint32 immediate_data_size,
5913 const gles2::GetTranslatedShaderSourceANGLE& c) {
5914 GLuint shader = c.shader;
5915
5916 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5917 Bucket* bucket = CreateBucket(bucket_id);
5918 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5919 shader, "glTranslatedGetShaderSourceANGLE");
5920 if (!info) {
5921 bucket->SetSize(0);
5922 return error::kNoError;
5923 }
5924
5925 bucket->SetFromString(info->translated_source() ?
5926 info->translated_source()->c_str() : NULL);
5927 return error::kNoError;
5928}
5929
[email protected]ae51d192010-04-27 00:48:035930error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
5931 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
5932 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:585933 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5934 Bucket* bucket = CreateBucket(bucket_id);
5935 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5936 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525937 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465938 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035939 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:315940 }
[email protected]df6cf1ad2011-01-29 01:20:525941 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035942 return error::kNoError;
5943}
5944
5945error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
5946 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
5947 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:585948 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5949 Bucket* bucket = CreateBucket(bucket_id);
5950 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5951 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525952 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465953 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035954 return error::kNoError;
5955 }
[email protected]df6cf1ad2011-01-29 01:20:525956 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035957 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325958}
5959
[email protected]1958e0e2010-04-22 05:17:155960bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105961 const BufferManager::BufferInfo* buffer = GetBufferInfo(client_id);
5962 return buffer && buffer->IsValid() && !buffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155963}
5964
5965bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105966 const FramebufferManager::FramebufferInfo* framebuffer =
[email protected]06c8b082011-01-05 18:00:365967 GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105968 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155969}
5970
5971bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365972 // IsProgram is true for programs as soon as they are created, until they are
5973 // deleted and no longer in use.
[email protected]a0b78dc2011-11-11 10:43:105974 const ProgramManager::ProgramInfo* program = GetProgramInfo(client_id);
5975 return program != NULL && !program->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155976}
5977
5978bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105979 const RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]06c8b082011-01-05 18:00:365980 GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105981 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155982}
5983
5984bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365985 // IsShader is true for shaders as soon as they are created, until they
5986 // are deleted and not attached to any programs.
[email protected]a0b78dc2011-11-11 10:43:105987 const ShaderManager::ShaderInfo* shader = GetShaderInfo(client_id);
5988 return shader != NULL && !shader->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155989}
5990
5991bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105992 const TextureManager::TextureInfo* texture = GetTextureInfo(client_id);
5993 return texture && texture->IsValid() && !texture->IsDeleted();
[email protected]ae51d192010-04-27 00:48:035994}
5995
5996void GLES2DecoderImpl::DoAttachShader(
5997 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585998 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5999 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:036000 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:036001 return;
[email protected]1958e0e2010-04-22 05:17:156002 }
[email protected]6b8cf1a2010-05-06 16:13:586003 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
6004 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:036005 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:036006 return;
6007 }
[email protected]ca488e12010-12-13 20:06:146008 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:316009 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436010 "glAttachShader", "can not attach more than"
[email protected]fb96c8e2010-08-12 04:10:316011 " one shader of the same type.");
6012 return;
6013 }
[email protected]ae51d192010-04-27 00:48:036014 glAttachShader(program_info->service_id(), shader_info->service_id());
6015}
6016
6017void GLES2DecoderImpl::DoDetachShader(
6018 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:586019 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
6020 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:036021 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:036022 return;
6023 }
[email protected]6b8cf1a2010-05-06 16:13:586024 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
6025 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:036026 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:036027 return;
6028 }
[email protected]9a0ccd42011-03-16 23:58:226029 if (!program_info->DetachShader(shader_manager(), shader_info)) {
6030 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436031 "glDetachShader", "shader not attached to program");
[email protected]9a0ccd42011-03-16 23:58:226032 return;
6033 }
[email protected]ae51d192010-04-27 00:48:036034 glDetachShader(program_info->service_id(), shader_info->service_id());
6035}
6036
6037void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:586038 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6039 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:036040 if (!info) {
[email protected]ae51d192010-04-27 00:48:036041 return;
6042 }
[email protected]d685a682011-04-29 16:19:576043 info->Validate();
[email protected]1958e0e2010-04-22 05:17:156044}
6045
[email protected]b1122982010-05-17 23:04:246046void GLES2DecoderImpl::DoGetVertexAttribfv(
6047 GLuint index, GLenum pname, GLfloat* params) {
6048 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:446049 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246050 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436051 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
[email protected]b1122982010-05-17 23:04:246052 return;
6053 }
6054 switch (pname) {
6055 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
6056 BufferManager::BufferInfo* buffer = info->buffer();
6057 if (buffer && !buffer->IsDeleted()) {
6058 GLuint client_id;
6059 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
6060 *params = static_cast<GLfloat>(client_id);
6061 }
6062 break;
6063 }
6064 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
6065 *params = static_cast<GLfloat>(info->enabled());
6066 break;
6067 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
6068 *params = static_cast<GLfloat>(info->size());
6069 break;
6070 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
6071 *params = static_cast<GLfloat>(info->gl_stride());
6072 break;
6073 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
6074 *params = static_cast<GLfloat>(info->type());
6075 break;
6076 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
6077 *params = static_cast<GLfloat>(info->normalized());
6078 break;
6079 case GL_CURRENT_VERTEX_ATTRIB:
6080 params[0] = info->value().v[0];
6081 params[1] = info->value().v[1];
6082 params[2] = info->value().v[2];
6083 params[3] = info->value().v[3];
6084 break;
[email protected]c6aef902012-02-14 03:31:426085 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
6086 *params = static_cast<GLfloat>(info->divisor());
6087 break;
[email protected]b1122982010-05-17 23:04:246088 default:
6089 NOTREACHED();
6090 break;
6091 }
6092}
6093
6094void GLES2DecoderImpl::DoGetVertexAttribiv(
6095 GLuint index, GLenum pname, GLint* params) {
6096 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:446097 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246098 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436099 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
[email protected]b1122982010-05-17 23:04:246100 return;
6101 }
6102 switch (pname) {
6103 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
6104 BufferManager::BufferInfo* buffer = info->buffer();
6105 if (buffer && !buffer->IsDeleted()) {
6106 GLuint client_id;
6107 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
6108 *params = client_id;
6109 }
6110 break;
6111 }
6112 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
6113 *params = info->enabled();
6114 break;
6115 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
6116 *params = info->size();
6117 break;
6118 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
6119 *params = info->gl_stride();
6120 break;
6121 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
6122 *params = info->type();
6123 break;
6124 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
6125 *params = static_cast<GLint>(info->normalized());
6126 break;
[email protected]c6aef902012-02-14 03:31:426127 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
6128 *params = info->divisor();
6129 break;
[email protected]b1122982010-05-17 23:04:246130 case GL_CURRENT_VERTEX_ATTRIB:
6131 params[0] = static_cast<GLint>(info->value().v[0]);
6132 params[1] = static_cast<GLint>(info->value().v[1]);
6133 params[2] = static_cast<GLint>(info->value().v[2]);
6134 params[3] = static_cast<GLint>(info->value().v[3]);
6135 break;
6136 default:
6137 NOTREACHED();
6138 break;
6139 }
6140}
6141
6142void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
6143 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:446144 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246145 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436146 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f", "index out of range");
[email protected]b1122982010-05-17 23:04:246147 return;
6148 }
6149 VertexAttribManager::VertexAttribInfo::Vec4 value;
6150 value.v[0] = v0;
6151 value.v[1] = 0.0f;
6152 value.v[2] = 0.0f;
6153 value.v[3] = 1.0f;
6154 info->set_value(value);
6155 glVertexAttrib1f(index, v0);
6156}
6157
6158void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
6159 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:446160 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246161 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436162 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f", "index out of range");
[email protected]b1122982010-05-17 23:04:246163 return;
6164 }
6165 VertexAttribManager::VertexAttribInfo::Vec4 value;
6166 value.v[0] = v0;
6167 value.v[1] = v1;
6168 value.v[2] = 0.0f;
6169 value.v[3] = 1.0f;
6170 info->set_value(value);
6171 glVertexAttrib2f(index, v0, v1);
6172}
6173
6174void GLES2DecoderImpl::DoVertexAttrib3f(
6175 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
6176 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:446177 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246178 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436179 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f", "index out of range");
[email protected]b1122982010-05-17 23:04:246180 return;
6181 }
6182 VertexAttribManager::VertexAttribInfo::Vec4 value;
6183 value.v[0] = v0;
6184 value.v[1] = v1;
6185 value.v[2] = v2;
6186 value.v[3] = 1.0f;
6187 info->set_value(value);
6188 glVertexAttrib3f(index, v0, v1, v2);
6189}
6190
6191void GLES2DecoderImpl::DoVertexAttrib4f(
6192 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
6193 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:446194 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246195 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436196 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f", "index out of range");
[email protected]b1122982010-05-17 23:04:246197 return;
6198 }
6199 VertexAttribManager::VertexAttribInfo::Vec4 value;
6200 value.v[0] = v0;
6201 value.v[1] = v1;
6202 value.v[2] = v2;
6203 value.v[3] = v3;
6204 info->set_value(value);
6205 glVertexAttrib4f(index, v0, v1, v2, v3);
6206}
6207
6208void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
6209 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:446210 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246211 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436212 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv", "index out of range");
[email protected]b1122982010-05-17 23:04:246213 return;
6214 }
6215 VertexAttribManager::VertexAttribInfo::Vec4 value;
6216 value.v[0] = v[0];
6217 value.v[1] = 0.0f;
6218 value.v[2] = 0.0f;
6219 value.v[3] = 1.0f;
6220 info->set_value(value);
6221 glVertexAttrib1fv(index, v);
6222}
6223
6224void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
6225 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:446226 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246227 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436228 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv", "index out of range");
[email protected]b1122982010-05-17 23:04:246229 return;
6230 }
6231 VertexAttribManager::VertexAttribInfo::Vec4 value;
6232 value.v[0] = v[0];
6233 value.v[1] = v[1];
6234 value.v[2] = 0.0f;
6235 value.v[3] = 1.0f;
6236 info->set_value(value);
6237 glVertexAttrib2fv(index, v);
6238}
6239
6240void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
6241 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:446242 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246243 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436244 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv", "index out of range");
[email protected]b1122982010-05-17 23:04:246245 return;
6246 }
6247 VertexAttribManager::VertexAttribInfo::Vec4 value;
6248 value.v[0] = v[0];
6249 value.v[1] = v[1];
6250 value.v[2] = v[2];
6251 value.v[3] = 1.0f;
6252 info->set_value(value);
6253 glVertexAttrib3fv(index, v);
6254}
6255
6256void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
6257 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:446258 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246259 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436260 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv", "index out of range");
[email protected]b1122982010-05-17 23:04:246261 return;
6262 }
6263 VertexAttribManager::VertexAttribInfo::Vec4 value;
6264 value.v[0] = v[0];
6265 value.v[1] = v[1];
6266 value.v[2] = v[2];
6267 value.v[3] = v[3];
6268 info->set_value(value);
6269 glVertexAttrib4fv(index, v);
6270}
6271
[email protected]f7a64ee2010-02-01 22:24:146272error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:196273 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:296274 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
6275 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436276 "glVertexAttribPointer", "no array buffer bound");
[email protected]8eee29c2010-04-29 03:38:296277 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326278 }
[email protected]8eee29c2010-04-29 03:38:296279
6280 GLuint indx = c.indx;
6281 GLint size = c.size;
6282 GLenum type = c.type;
6283 GLboolean normalized = c.normalized;
6284 GLsizei stride = c.stride;
6285 GLsizei offset = c.offset;
6286 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:056287 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:296288 SetGLError(GL_INVALID_ENUM,
[email protected]ad84a3a2012-06-08 21:42:436289 "glVertexAttribPointer", "type GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:296290 return error::kNoError;
6291 }
[email protected]9438b012010-06-15 22:55:056292 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:316293 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436294 "glVertexAttribPointer", "size GL_INVALID_VALUE");
[email protected]8eee29c2010-04-29 03:38:296295 return error::kNoError;
6296 }
6297 if (indx >= group_->max_vertex_attribs()) {
[email protected]ad84a3a2012-06-08 21:42:436298 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
[email protected]8eee29c2010-04-29 03:38:296299 return error::kNoError;
6300 }
6301 if (stride < 0) {
6302 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436303 "glVertexAttribPointer", "stride < 0");
[email protected]8eee29c2010-04-29 03:38:296304 return error::kNoError;
6305 }
6306 if (stride > 255) {
6307 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436308 "glVertexAttribPointer", "stride > 255");
[email protected]8eee29c2010-04-29 03:38:296309 return error::kNoError;
6310 }
6311 if (offset < 0) {
6312 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436313 "glVertexAttribPointer", "offset < 0");
[email protected]8eee29c2010-04-29 03:38:296314 return error::kNoError;
6315 }
6316 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:316317 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:296318 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:316319 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436320 "glVertexAttribPointer", "offset not valid for type");
[email protected]ff81c192011-01-07 23:04:316321 return error::kNoError;
6322 }
6323 if (stride % component_size > 0) {
6324 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436325 "glVertexAttribPointer", "stride not valid for type");
[email protected]8eee29c2010-04-29 03:38:296326 return error::kNoError;
6327 }
[email protected]3757a372012-01-19 05:20:446328 vertex_attrib_manager_->SetAttribInfo(
[email protected]8fbedc02010-11-18 18:43:406329 indx,
[email protected]8eee29c2010-04-29 03:38:296330 bound_array_buffer_,
6331 size,
6332 type,
[email protected]b1122982010-05-17 23:04:246333 normalized,
6334 stride,
6335 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:296336 offset);
[email protected]8fbedc02010-11-18 18:43:406337 if (type != GL_FIXED) {
6338 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
6339 }
[email protected]f7a64ee2010-02-01 22:24:146340 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326341}
6342
[email protected]43410e92012-04-20 17:06:286343void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
6344 GLsizei height) {
6345 viewport_x_ = x;
6346 viewport_y_ = y;
6347 viewport_width_ = std::min(width, viewport_max_width_);
6348 viewport_height_ = std::min(height, viewport_max_height_);
6349 glViewport(x, y, width, height);
6350}
6351
[email protected]c6aef902012-02-14 03:31:426352error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
6353 uint32 immediate_data_size, const gles2::VertexAttribDivisorANGLE& c) {
6354 if (!feature_info_->feature_flags().angle_instanced_arrays) {
6355 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436356 "glVertexAttribDivisorANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:426357 }
6358 GLuint index = c.index;
6359 GLuint divisor = c.divisor;
6360 if (index >= group_->max_vertex_attribs()) {
6361 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436362 "glVertexAttribDivisorANGLE", "index out of range");
[email protected]c6aef902012-02-14 03:31:426363 return error::kNoError;
6364 }
6365
6366 vertex_attrib_manager_->SetDivisor(
6367 index,
6368 divisor);
6369 glVertexAttribDivisorANGLE(index, divisor);
6370 return error::kNoError;
6371}
6372
[email protected]f7a64ee2010-02-01 22:24:146373error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:196374 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:316375 GLint x = c.x;
6376 GLint y = c.y;
6377 GLsizei width = c.width;
6378 GLsizei height = c.height;
6379 GLenum format = c.format;
6380 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:566381 if (width < 0 || height < 0) {
[email protected]ad84a3a2012-06-08 21:42:436382 SetGLError(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
[email protected]57f223832010-03-19 01:57:566383 return error::kNoError;
6384 }
[email protected]a51788e2010-02-24 21:54:256385 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:186386 uint32 pixels_size;
[email protected]3458a64a2012-04-10 17:39:346387 if (!GLES2Util::ComputeImageDataSizes(
6388 width, height, format, type, pack_alignment_, &pixels_size, NULL, NULL)) {
[email protected]a76b0052010-03-05 00:33:186389 return error::kOutOfBounds;
6390 }
[email protected]612d2f82009-12-08 20:49:316391 void* pixels = GetSharedMemoryAs<void*>(
6392 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:256393 Result* result = GetSharedMemoryAs<Result*>(
6394 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6395 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:146396 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466397 }
[email protected]a51788e2010-02-24 21:54:256398
[email protected]9438b012010-06-15 22:55:056399 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]ad84a3a2012-06-08 21:42:436400 SetGLError(GL_INVALID_ENUM, "glReadPixels", "format GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:296401 return error::kNoError;
6402 }
[email protected]9438b012010-06-15 22:55:056403 if (!validators_->pixel_type.IsValid(type)) {
[email protected]ad84a3a2012-06-08 21:42:436404 SetGLError(GL_INVALID_ENUM, "glReadPixels", "type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:126405 return error::kNoError;
6406 }
[email protected]57f223832010-03-19 01:57:566407 if (width == 0 || height == 0) {
6408 return error::kNoError;
6409 }
6410
[email protected]57f223832010-03-19 01:57:566411 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:306412 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:566413
6414 GLint max_x;
6415 GLint max_y;
6416 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]ad84a3a2012-06-08 21:42:436417 SetGLError(GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:146418 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:316419 }
[email protected]57f223832010-03-19 01:57:566420
[email protected]0d6bfdc2011-11-02 01:32:206421 if (!CheckBoundFramebuffersValid("glReadPixels")) {
6422 return error::kNoError;
6423 }
6424
[email protected]a0b78dc2011-11-11 10:43:106425 CopyRealGLErrorsToWrapper();
6426
6427 ScopedResolvedFrameBufferBinder binder(this, false, true);
6428
[email protected]d37231fa2010-04-09 21:16:026429 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:566430 // The user requested an out of range area. Get the results 1 line
6431 // at a time.
6432 uint32 temp_size;
[email protected]3458a64a2012-04-10 17:39:346433 uint32 unpadded_row_size;
6434 uint32 padded_row_size;
6435 if (!GLES2Util::ComputeImageDataSizes(
6436 width, 2, format, type, pack_alignment_, &temp_size,
6437 &unpadded_row_size, &padded_row_size)) {
[email protected]ad84a3a2012-06-08 21:42:436438 SetGLError(GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]57f223832010-03-19 01:57:566439 return error::kNoError;
6440 }
6441
6442 GLint dest_x_offset = std::max(-x, 0);
6443 uint32 dest_row_offset;
[email protected]3458a64a2012-04-10 17:39:346444 if (!GLES2Util::ComputeImageDataSizes(
6445 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset, NULL,
6446 NULL)) {
[email protected]ad84a3a2012-06-08 21:42:436447 SetGLError(GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]57f223832010-03-19 01:57:566448 return error::kNoError;
6449 }
6450
6451 // Copy each row into the larger dest rect.
6452 int8* dst = static_cast<int8*>(pixels);
6453 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:026454 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:566455 GLint read_width = read_end_x - read_x;
6456 for (GLint yy = 0; yy < height; ++yy) {
6457 GLint ry = y + yy;
6458
6459 // Clear the row.
6460 memset(dst, 0, unpadded_row_size);
6461
6462 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:026463 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:566464 glReadPixels(
6465 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
6466 }
6467 dst += padded_row_size;
6468 }
6469 } else {
6470 glReadPixels(x, y, width, height, format, type, pixels);
6471 }
[email protected]1002c2d2011-06-28 22:39:046472 GLenum error = PeekGLError();
[email protected]a51788e2010-02-24 21:54:256473 if (error == GL_NO_ERROR) {
6474 *result = true;
[email protected]4848b9f82011-03-10 18:37:566475
6476 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6477 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
[email protected]84eb4252012-06-29 22:56:446478 if ((channels_exist & 0x0008) == 0 &&
6479 !feature_info_->feature_flags().disable_workarounds) {
[email protected]4848b9f82011-03-10 18:37:566480 // Set the alpha to 255 because some drivers are buggy in this regard.
6481 uint32 temp_size;
[email protected]3458a64a2012-04-10 17:39:346482
6483 uint32 unpadded_row_size;
6484 uint32 padded_row_size;
6485 if (!GLES2Util::ComputeImageDataSizes(
6486 width, 2, format, type, pack_alignment_, &temp_size,
6487 &unpadded_row_size, &padded_row_size)) {
[email protected]ad84a3a2012-06-08 21:42:436488 SetGLError(GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]4848b9f82011-03-10 18:37:566489 return error::kNoError;
6490 }
6491 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
6492 // of this implementation.
6493 if (type != GL_UNSIGNED_BYTE) {
[email protected]ad84a3a2012-06-08 21:42:436494 SetGLError(
6495 GL_INVALID_OPERATION, "glReadPixels",
6496 "unsupported readPixel format");
[email protected]4848b9f82011-03-10 18:37:566497 return error::kNoError;
6498 }
6499 switch (format) {
6500 case GL_RGBA:
[email protected]297ca1c2011-06-20 23:08:466501 case GL_BGRA_EXT:
[email protected]4848b9f82011-03-10 18:37:566502 case GL_ALPHA: {
6503 int offset = (format == GL_ALPHA) ? 0 : 3;
6504 int step = (format == GL_ALPHA) ? 1 : 4;
6505 uint8* dst = static_cast<uint8*>(pixels) + offset;
6506 for (GLint yy = 0; yy < height; ++yy) {
6507 uint8* end = dst + unpadded_row_size;
6508 for (uint8* d = dst; d < end; d += step) {
6509 *d = 255;
6510 }
6511 dst += padded_row_size;
6512 }
6513 break;
6514 }
6515 default:
6516 break;
6517 }
6518 }
[email protected]a51788e2010-02-24 21:54:256519 }
[email protected]4848b9f82011-03-10 18:37:566520
[email protected]f7a64ee2010-02-01 22:24:146521 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326522}
6523
[email protected]f7a64ee2010-02-01 22:24:146524error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:196525 uint32 immediate_data_size, const gles2::PixelStorei& c) {
6526 GLenum pname = c.pname;
6527 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:056528 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]ad84a3a2012-06-08 21:42:436529 SetGLError(GL_INVALID_ENUM, "glPixelStorei", "pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:126530 return error::kNoError;
6531 }
[email protected]222471d2011-11-30 18:06:396532 switch (pname) {
6533 case GL_PACK_ALIGNMENT:
6534 case GL_UNPACK_ALIGNMENT:
6535 if (!validators_->pixel_store_alignment.IsValid(param)) {
6536 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436537 "glPixelStore", "param GL_INVALID_VALUE");
[email protected]222471d2011-11-30 18:06:396538 return error::kNoError;
6539 }
[email protected]164d6d52012-05-05 00:55:036540 break;
[email protected]0a1e9ad2012-05-04 21:13:036541 case GL_UNPACK_FLIP_Y_CHROMIUM:
6542 unpack_flip_y_ = (param != 0);
6543 return error::kNoError;
6544 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
6545 unpack_premultiply_alpha_ = (param != 0);
6546 return error::kNoError;
[email protected]6c75c712012-06-19 15:43:176547 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
6548 unpack_unpremultiply_alpha_ = (param != 0);
6549 return error::kNoError;
[email protected]222471d2011-11-30 18:06:396550 default:
6551 break;
[email protected]b9849abf2009-11-25 19:13:196552 }
6553 glPixelStorei(pname, param);
6554 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:436555 case GL_PACK_ALIGNMENT:
6556 pack_alignment_ = param;
6557 break;
6558 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
6559 break;
6560 case GL_UNPACK_ALIGNMENT:
6561 unpack_alignment_ = param;
6562 break;
6563 default:
6564 // Validation should have prevented us from getting here.
6565 NOTREACHED();
6566 break;
[email protected]b9849abf2009-11-25 19:13:196567 }
[email protected]f7a64ee2010-02-01 22:24:146568 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196569}
6570
[email protected]1c75a3702011-11-11 14:15:286571error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
6572 uint32 immediate_data_size, const gles2::PostSubBufferCHROMIUM& c) {
[email protected]43ed3a72012-05-30 22:55:386573 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
[email protected]6f5fac9d12012-06-26 21:02:456574 if (!surface_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
[email protected]1c75a3702011-11-11 14:15:286575 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436576 "glPostSubBufferCHROMIUM", "command not supported by surface");
[email protected]1c75a3702011-11-11 14:15:286577 return error::kNoError;
6578 }
[email protected]7794d512012-04-17 20:36:496579 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
[email protected]1c75a3702011-11-11 14:15:286580 return error::kNoError;
[email protected]7794d512012-04-17 20:36:496581 } else {
6582 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
[email protected]1c75a3702011-11-11 14:15:286583 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:496584 }
[email protected]1c75a3702011-11-11 14:15:286585}
6586
[email protected]558847a2010-03-24 07:02:546587error::Error GLES2DecoderImpl::GetAttribLocationHelper(
6588 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6589 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576590 if (!StringIsValidForGLES(name_str.c_str())) {
[email protected]ad84a3a2012-06-08 21:42:436591 SetGLError(GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:576592 return error::kNoError;
6593 }
[email protected]6b8cf1a2010-05-06 16:13:586594 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6595 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:036596 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146597 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196598 }
[email protected]ae51d192010-04-27 00:48:036599 if (!info->IsValid()) {
[email protected]ad84a3a2012-06-08 21:42:436600 SetGLError(
6601 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
[email protected]0bfd9882010-02-05 23:02:256602 return error::kNoError;
6603 }
[email protected]b9849abf2009-11-25 19:13:196604 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546605 location_shm_id, location_shm_offset, sizeof(GLint));
6606 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146607 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196608 }
[email protected]558847a2010-03-24 07:02:546609 // Require the client to init this incase the context is lost and we are no
6610 // longer executing commands.
6611 if (*location != -1) {
6612 return error::kGenericError;
6613 }
[email protected]0bfd9882010-02-05 23:02:256614 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:146615 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196616}
6617
[email protected]558847a2010-03-24 07:02:546618error::Error GLES2DecoderImpl::HandleGetAttribLocation(
6619 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
6620 uint32 name_size = c.data_size;
6621 const char* name = GetSharedMemoryAs<const char*>(
6622 c.name_shm_id, c.name_shm_offset, name_size);
6623 if (!name) {
6624 return error::kOutOfBounds;
6625 }
6626 String name_str(name, name_size);
6627 return GetAttribLocationHelper(
6628 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6629}
6630
[email protected]f7a64ee2010-02-01 22:24:146631error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196632 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:546633 uint32 name_size = c.data_size;
6634 const char* name = GetImmediateDataAs<const char*>(
6635 c, name_size, immediate_data_size);
6636 if (!name) {
6637 return error::kOutOfBounds;
6638 }
6639 String name_str(name, name_size);
6640 return GetAttribLocationHelper(
6641 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6642}
6643
6644error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
6645 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
6646 Bucket* bucket = GetBucket(c.name_bucket_id);
6647 if (!bucket) {
6648 return error::kInvalidArguments;
6649 }
6650 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186651 if (!bucket->GetAsString(&name_str)) {
6652 return error::kInvalidArguments;
6653 }
[email protected]558847a2010-03-24 07:02:546654 return GetAttribLocationHelper(
6655 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6656}
6657
6658error::Error GLES2DecoderImpl::GetUniformLocationHelper(
6659 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6660 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576661 if (!StringIsValidForGLES(name_str.c_str())) {
[email protected]ad84a3a2012-06-08 21:42:436662 SetGLError(GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:576663 return error::kNoError;
6664 }
[email protected]6b8cf1a2010-05-06 16:13:586665 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6666 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:036667 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146668 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196669 }
[email protected]ae51d192010-04-27 00:48:036670 if (!info->IsValid()) {
[email protected]ad84a3a2012-06-08 21:42:436671 SetGLError(
6672 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
[email protected]0bfd9882010-02-05 23:02:256673 return error::kNoError;
6674 }
[email protected]b9849abf2009-11-25 19:13:196675 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546676 location_shm_id, location_shm_offset, sizeof(GLint));
6677 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146678 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196679 }
[email protected]558847a2010-03-24 07:02:546680 // Require the client to init this incase the context is lost an we are no
6681 // longer executing commands.
6682 if (*location != -1) {
6683 return error::kGenericError;
6684 }
[email protected]2be6abf32012-06-26 00:28:336685 *location = info->GetUniformFakeLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:146686 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196687}
6688
[email protected]f7a64ee2010-02-01 22:24:146689error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:196690 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:196691 uint32 name_size = c.data_size;
6692 const char* name = GetSharedMemoryAs<const char*>(
6693 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:546694 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146695 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196696 }
6697 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546698 return GetUniformLocationHelper(
6699 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196700}
6701
[email protected]f7a64ee2010-02-01 22:24:146702error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196703 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:196704 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:306705 const char* name = GetImmediateDataAs<const char*>(
6706 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:546707 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146708 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196709 }
6710 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546711 return GetUniformLocationHelper(
6712 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6713}
6714
6715error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
6716 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
6717 Bucket* bucket = GetBucket(c.name_bucket_id);
6718 if (!bucket) {
6719 return error::kInvalidArguments;
6720 }
6721 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186722 if (!bucket->GetAsString(&name_str)) {
6723 return error::kInvalidArguments;
6724 }
[email protected]558847a2010-03-24 07:02:546725 return GetUniformLocationHelper(
6726 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196727}
6728
[email protected]ddd968b82010-03-02 00:44:296729error::Error GLES2DecoderImpl::HandleGetString(
6730 uint32 immediate_data_size, const gles2::GetString& c) {
6731 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:056732 if (!validators_->string_type.IsValid(name)) {
[email protected]ad84a3a2012-06-08 21:42:436733 SetGLError(GL_INVALID_ENUM, "glGetString", "name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:296734 return error::kNoError;
6735 }
[email protected]1958e0e2010-04-22 05:17:156736 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
6737 const char* str = NULL;
[email protected]f0d74742011-10-03 16:31:046738 std::string extensions;
[email protected]1958e0e2010-04-22 05:17:156739 switch (name) {
6740 case GL_VERSION:
6741 str = "OpenGL ES 2.0 Chromium";
6742 break;
6743 case GL_SHADING_LANGUAGE_VERSION:
6744 str = "OpenGL ES GLSL ES 1.0 Chromium";
6745 break;
[email protected]32939602012-05-09 06:25:166746 case GL_RENDERER:
6747 str = "Chromium";
6748 break;
6749 case GL_VENDOR:
6750 str = "Chromium";
6751 break;
[email protected]1958e0e2010-04-22 05:17:156752 case GL_EXTENSIONS:
[email protected]f0d74742011-10-03 16:31:046753 {
6754 // For WebGL contexts, strip out the OES derivatives extension if it has
6755 // not been enabled.
6756 if (force_webgl_glsl_validation_ &&
6757 !derivatives_explicitly_enabled_) {
6758 extensions = feature_info_->extensions();
6759 size_t offset = extensions.find(kOESDerivativeExtension);
6760 if (std::string::npos != offset) {
6761 extensions.replace(offset,
6762 offset + arraysize(kOESDerivativeExtension),
6763 std::string());
6764 }
[email protected]f0d74742011-10-03 16:31:046765 } else {
[email protected]6f5fac9d12012-06-26 21:02:456766 extensions = feature_info_->extensions().c_str();
[email protected]f0d74742011-10-03 16:31:046767 }
[email protected]6f5fac9d12012-06-26 21:02:456768 std::string surface_extensions = surface_->GetExtensions();
6769 if (!surface_extensions.empty())
6770 extensions += " " + surface_extensions;
6771 str = extensions.c_str();
[email protected]f0d74742011-10-03 16:31:046772 }
[email protected]1958e0e2010-04-22 05:17:156773 break;
6774 default:
6775 str = gl_str;
6776 break;
6777 }
[email protected]ddd968b82010-03-02 00:44:296778 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:156779 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:296780 return error::kNoError;
6781}
6782
[email protected]0c86dbf2010-03-05 08:14:116783void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:156784 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:056785 if (!validators_->buffer_target.IsValid(target)) {
[email protected]ad84a3a2012-06-08 21:42:436786 SetGLError(GL_INVALID_ENUM, "glBufferData", "target GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:296787 return;
6788 }
[email protected]9438b012010-06-15 22:55:056789 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]ad84a3a2012-06-08 21:42:436790 SetGLError(GL_INVALID_ENUM, "glBufferData", "usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:116791 return;
[email protected]3b6ec202010-03-05 05:16:236792 }
6793 if (size < 0) {
[email protected]ad84a3a2012-06-08 21:42:436794 SetGLError(GL_INVALID_VALUE, "glBufferData", "size < 0");
[email protected]037896bd2010-04-21 19:07:286795 return;
[email protected]3b6ec202010-03-05 05:16:236796 }
6797 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
6798 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436799 SetGLError(GL_INVALID_VALUE, "glBufferData", "unknown buffer");
[email protected]037896bd2010-04-21 19:07:286800 return;
[email protected]3b6ec202010-03-05 05:16:236801 }
6802 // Clear the buffer to 0 if no initial data was passed in.
6803 scoped_array<int8> zero;
6804 if (!data) {
6805 zero.reset(new int8[size]);
6806 memset(zero.get(), 0, size);
6807 data = zero.get();
6808 }
[email protected]473c01ccb2011-06-07 01:33:306809
6810 if (!bufferdata_faster_than_buffersubdata_ &&
6811 size == info->size() && usage == info->usage()) {
6812 glBufferSubData(target, 0, size, data);
6813 info->SetRange(0, size, data);
6814 return;
6815 }
6816
[email protected]3b6ec202010-03-05 05:16:236817 CopyRealGLErrorsToWrapper();
6818 glBufferData(target, size, data, usage);
[email protected]1002c2d2011-06-28 22:39:046819 GLenum error = PeekGLError();
6820 if (error == GL_NO_ERROR) {
[email protected]473c01ccb2011-06-07 01:33:306821 buffer_manager()->SetInfo(info, size, usage);
[email protected]0c86dbf2010-03-05 08:14:116822 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:236823 }
[email protected]0c86dbf2010-03-05 08:14:116824}
6825
6826error::Error GLES2DecoderImpl::HandleBufferData(
6827 uint32 immediate_data_size, const gles2::BufferData& c) {
6828 GLenum target = static_cast<GLenum>(c.target);
6829 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
6830 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6831 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6832 GLenum usage = static_cast<GLenum>(c.usage);
6833 const void* data = NULL;
6834 if (data_shm_id != 0 || data_shm_offset != 0) {
6835 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
6836 if (!data) {
6837 return error::kOutOfBounds;
6838 }
6839 }
6840 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:146841 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196842}
6843
[email protected]f7a64ee2010-02-01 22:24:146844error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:196845 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
6846 GLenum target = static_cast<GLenum>(c.target);
6847 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:306848 const void* data = GetImmediateDataAs<const void*>(
6849 c, size, immediate_data_size);
6850 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146851 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:306852 }
[email protected]b9849abf2009-11-25 19:13:196853 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:116854 DoBufferData(target, size, data, usage);
6855 return error::kNoError;
6856}
6857
6858void GLES2DecoderImpl::DoBufferSubData(
6859 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:506860 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476861 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436862 SetGLError(GL_INVALID_VALUE, "glBufferSubData", "unknown buffer");
[email protected]037896bd2010-04-21 19:07:286863 return;
[email protected]a93bb842010-02-16 23:03:476864 }
[email protected]0c86dbf2010-03-05 08:14:116865 if (!info->SetRange(offset, size, data)) {
[email protected]ad84a3a2012-06-08 21:42:436866 SetGLError(GL_INVALID_VALUE, "glBufferSubData", "out of range");
[email protected]473c01ccb2011-06-07 01:33:306867 return;
[email protected]07f54fcc2009-12-22 02:46:306868 }
[email protected]473c01ccb2011-06-07 01:33:306869 if (bufferdata_faster_than_buffersubdata_ &&
6870 offset == 0 && size == info->size()) {
6871 glBufferData(target, size, data, info->usage());
6872 return;
6873 }
6874 glBufferSubData(target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:196875}
6876
[email protected]0d6bfdc2011-11-02 01:32:206877bool GLES2DecoderImpl::ClearLevel(
6878 unsigned service_id,
6879 unsigned bind_target,
6880 unsigned target,
6881 int level,
6882 unsigned format,
6883 unsigned type,
6884 int width,
[email protected]4502e6492011-12-14 19:39:156885 int height,
6886 bool is_texture_immutable) {
[email protected]81375742012-06-08 00:04:006887 uint32 channels = GLES2Util::GetChannelsForFormat(format);
6888 if (IsAngle() && (channels & GLES2Util::kDepth) != 0) {
6889 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
6890 // on depth formats.
6891 GLuint fb = 0;
6892 glGenFramebuffersEXT(1, &fb);
6893 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
6894
6895 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
6896 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
6897 GL_DEPTH_ATTACHMENT;
6898
6899 glFramebufferTexture2DEXT(
6900 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
6901 // ANGLE promises a depth only attachment ok.
6902 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
6903 GL_FRAMEBUFFER_COMPLETE) {
6904 return false;
6905 }
6906 glClearStencil(0);
6907 glStencilMask(-1);
6908 glClearDepth(1.0f);
6909 glDepthMask(true);
6910 glDisable(GL_SCISSOR_TEST);
6911 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
6912
6913 RestoreClearState();
6914
6915 glDeleteFramebuffersEXT(1, &fb);
6916 FramebufferManager::FramebufferInfo* framebuffer =
6917 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
6918 GLuint fb_service_id =
6919 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
6920 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
6921 return true;
6922 }
6923
[email protected]45d15a62012-04-18 14:33:176924 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
6925
6926 uint32 size;
6927 uint32 padded_row_size;
[email protected]3458a64a2012-04-10 17:39:346928 if (!GLES2Util::ComputeImageDataSizes(
[email protected]45d15a62012-04-18 14:33:176929 width, height, format, type, unpack_alignment_, &size,
6930 NULL, &padded_row_size)) {
[email protected]0d6bfdc2011-11-02 01:32:206931 return false;
6932 }
[email protected]45d15a62012-04-18 14:33:176933
[email protected]a5d3dad2012-05-26 04:34:446934 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
6935
[email protected]45d15a62012-04-18 14:33:176936 int tile_height;
6937
6938 if (size > kMaxZeroSize) {
6939 if (kMaxZeroSize < padded_row_size) {
6940 // That'd be an awfully large texture.
6941 return false;
6942 }
6943 // We should never have a large total size with a zero row size.
6944 DCHECK_GT(padded_row_size, 0U);
6945 tile_height = kMaxZeroSize / padded_row_size;
6946 if (!GLES2Util::ComputeImageDataSizes(
6947 width, tile_height, format, type, unpack_alignment_, &size, NULL,
6948 NULL)) {
6949 return false;
6950 }
[email protected]4502e6492011-12-14 19:39:156951 } else {
[email protected]45d15a62012-04-18 14:33:176952 tile_height = height;
6953 }
6954
6955 // Assumes the size has already been checked.
6956 scoped_array<char> zero(new char[size]);
6957 memset(zero.get(), 0, size);
6958 glBindTexture(bind_target, service_id);
6959
6960 GLint y = 0;
6961 while (y < height) {
6962 GLint h = y + tile_height > height ? height - y : tile_height;
6963 if (is_texture_immutable || h != height) {
6964 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
6965 } else {
6966 WrappedTexImage2D(
6967 target, level, format, width, h, 0, format, type, zero.get());
6968 }
6969 y += tile_height;
[email protected]4502e6492011-12-14 19:39:156970 }
[email protected]0d6bfdc2011-11-02 01:32:206971 TextureManager::TextureInfo* info = GetTextureInfoForTarget(bind_target);
6972 glBindTexture(bind_target, info ? info->service_id() : 0);
6973 return true;
6974}
6975
[email protected]ad84a3a2012-06-08 21:42:436976namespace {
6977
6978const int kS3TCBlockWidth = 4;
6979const int kS3TCBlockHeight = 4;
6980const int kS3TCDXT1BlockSize = 8;
6981const int kS3TCDXT3AndDXT5BlockSize = 16;
6982
6983bool IsValidDXTSize(GLint level, GLsizei size) {
[email protected]10b56de2012-07-14 02:09:516984 return (size == 1) ||
6985 (size == 2) || !(size % kS3TCBlockWidth);
[email protected]ad84a3a2012-06-08 21:42:436986}
6987
6988} // anonymous namespace.
6989
6990bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
6991 const char* function_name,
6992 GLsizei width, GLsizei height, GLenum format, size_t size) {
6993 unsigned int bytes_required = 0;
6994
6995 switch (format) {
6996 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
6997 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: {
6998 int num_blocks_across =
6999 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7000 int num_blocks_down =
7001 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7002 int num_blocks = num_blocks_across * num_blocks_down;
7003 bytes_required = num_blocks * kS3TCDXT1BlockSize;
7004 break;
7005 }
7006 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7007 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7008 int num_blocks_across =
7009 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7010 int num_blocks_down =
7011 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7012 int num_blocks = num_blocks_across * num_blocks_down;
7013 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
7014 break;
7015 }
7016 default:
7017 SetGLError(GL_INVALID_ENUM, function_name, "invalid format");
7018 return false;
7019 }
7020
7021 if (size != bytes_required) {
7022 SetGLError(
7023 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
7024 return false;
7025 }
7026
7027 return true;
7028}
7029
7030bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7031 const char* function_name,
7032 GLint level, GLsizei width, GLsizei height, GLenum format) {
7033 switch (format) {
7034 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7035 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7036 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7037 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7038 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
7039 SetGLError(
7040 GL_INVALID_OPERATION, function_name,
7041 "width or height invalid for level");
7042 return false;
7043 }
7044 return true;
7045 }
7046 default:
7047 return false;
7048 }
7049}
7050
7051bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
7052 const char* function_name,
7053 GLenum target, GLint level, GLint xoffset, GLint yoffset,
7054 GLsizei width, GLsizei height, GLenum format,
7055 TextureManager::TextureInfo* texture) {
7056 if (xoffset < 0 || yoffset < 0) {
7057 SetGLError(
7058 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
7059 return false;
7060 }
7061
7062 switch (format) {
7063 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7064 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7065 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7066 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7067 const int kBlockWidth = 4;
7068 const int kBlockHeight = 4;
7069 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
7070 SetGLError(
7071 GL_INVALID_OPERATION, function_name,
7072 "xoffset or yoffset not multiple of 4");
7073 return false;
7074 }
7075 GLsizei tex_width = 0;
7076 GLsizei tex_height = 0;
7077 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
7078 width - xoffset > tex_width ||
7079 height - yoffset > tex_height) {
7080 SetGLError(
7081 GL_INVALID_OPERATION, function_name, "dimensions out of range");
7082 return false;
7083 }
7084 return ValidateCompressedTexDimensions(
7085 function_name, level, width, height, format);
7086 }
7087 default:
7088 return false;
7089 }
7090}
7091
[email protected]a93bb842010-02-16 23:03:477092error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
7093 GLenum target,
7094 GLint level,
7095 GLenum internal_format,
7096 GLsizei width,
7097 GLsizei height,
7098 GLint border,
7099 GLsizei image_size,
7100 const void* data) {
[email protected]a93bb842010-02-16 23:03:477101 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:057102 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:297103 SetGLError(GL_INVALID_ENUM,
[email protected]ad84a3a2012-06-08 21:42:437104 "glCompressedTexImage2D", "target GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:297105 return error::kNoError;
7106 }
[email protected]9438b012010-06-15 22:55:057107 if (!validators_->compressed_texture_format.IsValid(
7108 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:297109 SetGLError(GL_INVALID_ENUM,
[email protected]ad84a3a2012-06-08 21:42:437110 "glCompressedTexImage2D", "internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:477111 return error::kNoError;
7112 }
[email protected]80eb6b52012-01-19 00:14:417113 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:477114 border != 0) {
[email protected]8eee29c2010-04-29 03:38:297115 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:437116 "glCompressedTexImage2D", "dimensions out of range");
[email protected]a93bb842010-02-16 23:03:477117 return error::kNoError;
7118 }
[email protected]3916c97e2010-02-25 03:20:507119 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:477120 if (!info) {
[email protected]8eee29c2010-04-29 03:38:297121 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:437122 "glCompressedTexImage2D", "unknown texture target");
[email protected]a93bb842010-02-16 23:03:477123 return error::kNoError;
7124 }
[email protected]97dc7cbe2011-12-06 17:26:177125 if (info->IsImmutable()) {
7126 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437127 "glCompressedTexImage2D", "texture is immutable");
7128 return error::kNoError;
7129 }
7130
7131 if (!ValidateCompressedTexDimensions(
7132 "glCompressedTexImage2D", level, width, height, internal_format) ||
7133 !ValidateCompressedTexFuncData(
7134 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
[email protected]97dc7cbe2011-12-06 17:26:177135 return error::kNoError;
7136 }
[email protected]968351b2011-12-20 08:26:517137
7138 if (info->IsAttachedToFramebuffer()) {
7139 state_dirty_ = true;
7140 // TODO(gman): If textures tracked which framebuffers they were attached to
7141 // we could just mark those framebuffers as not complete.
7142 framebuffer_manager()->IncFramebufferStateChangeCount();
7143 }
7144
[email protected]a93bb842010-02-16 23:03:477145 scoped_array<int8> zero;
7146 if (!data) {
7147 zero.reset(new int8[image_size]);
7148 memset(zero.get(), 0, image_size);
7149 data = zero.get();
7150 }
[email protected]cadde4a2010-07-31 17:10:437151 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:477152 glCompressedTexImage2D(
7153 target, level, internal_format, width, height, border, image_size, data);
[email protected]1002c2d2011-06-28 22:39:047154 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:437155 if (error == GL_NO_ERROR) {
7156 texture_manager()->SetLevelInfo(
[email protected]0d6bfdc2011-11-02 01:32:207157 info, target, level, internal_format, width, height, 1, border, 0, 0,
7158 true);
[email protected]cadde4a2010-07-31 17:10:437159 }
[email protected]a93bb842010-02-16 23:03:477160 return error::kNoError;
7161}
7162
[email protected]f7a64ee2010-02-01 22:24:147163error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:197164 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
7165 GLenum target = static_cast<GLenum>(c.target);
7166 GLint level = static_cast<GLint>(c.level);
7167 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7168 GLsizei width = static_cast<GLsizei>(c.width);
7169 GLsizei height = static_cast<GLsizei>(c.height);
7170 GLint border = static_cast<GLint>(c.border);
7171 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
7172 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7173 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7174 const void* data = NULL;
7175 if (data_shm_id != 0 || data_shm_offset != 0) {
7176 data = GetSharedMemoryAs<const void*>(
7177 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:467178 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:147179 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197180 }
7181 }
[email protected]a93bb842010-02-16 23:03:477182 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:197183 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:197184}
7185
[email protected]f7a64ee2010-02-01 22:24:147186error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:197187 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
7188 GLenum target = static_cast<GLenum>(c.target);
7189 GLint level = static_cast<GLint>(c.level);
7190 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7191 GLsizei width = static_cast<GLsizei>(c.width);
7192 GLsizei height = static_cast<GLsizei>(c.height);
7193 GLint border = static_cast<GLint>(c.border);
7194 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:307195 const void* data = GetImmediateDataAs<const void*>(
7196 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:467197 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:147198 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:467199 }
[email protected]a93bb842010-02-16 23:03:477200 return DoCompressedTexImage2D(
7201 target, level, internal_format, width, height, border, image_size, data);
7202}
7203
[email protected]b6140d02010-05-17 14:47:167204error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
7205 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
7206 GLenum target = static_cast<GLenum>(c.target);
7207 GLint level = static_cast<GLint>(c.level);
7208 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7209 GLsizei width = static_cast<GLsizei>(c.width);
7210 GLsizei height = static_cast<GLsizei>(c.height);
7211 GLint border = static_cast<GLint>(c.border);
7212 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287213 if (!bucket) {
7214 return error::kInvalidArguments;
7215 }
7216 uint32 data_size = bucket->size();
7217 GLsizei imageSize = data_size;
7218 const void* data = bucket->GetData(0, data_size);
7219 if (!data) {
7220 return error::kInvalidArguments;
7221 }
[email protected]b6140d02010-05-17 14:47:167222 return DoCompressedTexImage2D(
7223 target, level, internal_format, width, height, border,
[email protected]12f93d82011-10-17 21:16:287224 imageSize, data);
[email protected]b6140d02010-05-17 14:47:167225}
7226
7227error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
7228 uint32 immediate_data_size,
7229 const gles2::CompressedTexSubImage2DBucket& c) {
7230 GLenum target = static_cast<GLenum>(c.target);
7231 GLint level = static_cast<GLint>(c.level);
7232 GLint xoffset = static_cast<GLint>(c.xoffset);
7233 GLint yoffset = static_cast<GLint>(c.yoffset);
7234 GLsizei width = static_cast<GLsizei>(c.width);
7235 GLsizei height = static_cast<GLsizei>(c.height);
7236 GLenum format = static_cast<GLenum>(c.format);
7237 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287238 if (!bucket) {
7239 return error::kInvalidArguments;
7240 }
[email protected]b6140d02010-05-17 14:47:167241 uint32 data_size = bucket->size();
7242 GLsizei imageSize = data_size;
7243 const void* data = bucket->GetData(0, data_size);
[email protected]12f93d82011-10-17 21:16:287244 if (!data) {
7245 return error::kInvalidArguments;
7246 }
[email protected]9438b012010-06-15 22:55:057247 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:167248 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:437249 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target GL_INVALID_ENUM");
[email protected]b6140d02010-05-17 14:47:167250 return error::kNoError;
7251 }
[email protected]9438b012010-06-15 22:55:057252 if (!validators_->compressed_texture_format.IsValid(format)) {
7253 SetGLError(GL_INVALID_ENUM,
[email protected]ad84a3a2012-06-08 21:42:437254 "glCompressedTexSubImage2D", "format GL_INVALID_ENUM");
[email protected]9438b012010-06-15 22:55:057255 return error::kNoError;
7256 }
[email protected]b6140d02010-05-17 14:47:167257 if (width < 0) {
[email protected]ad84a3a2012-06-08 21:42:437258 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
[email protected]b6140d02010-05-17 14:47:167259 return error::kNoError;
7260 }
7261 if (height < 0) {
[email protected]ad84a3a2012-06-08 21:42:437262 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
[email protected]b6140d02010-05-17 14:47:167263 return error::kNoError;
7264 }
7265 if (imageSize < 0) {
[email protected]ad84a3a2012-06-08 21:42:437266 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
[email protected]b6140d02010-05-17 14:47:167267 return error::kNoError;
7268 }
[email protected]cadde4a2010-07-31 17:10:437269 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:167270 target, level, xoffset, yoffset, width, height, format, imageSize, data);
7271 return error::kNoError;
7272}
7273
[email protected]81375742012-06-08 00:04:007274bool GLES2DecoderImpl::ValidateTextureParameters(
7275 const char* function_name,
7276 GLenum target, GLenum format, GLenum type, GLint level) {
7277 if (!feature_info_->GetTextureFormatValidator(format).IsValid(type)) {
[email protected]ad84a3a2012-06-08 21:42:437278 SetGLError(GL_INVALID_OPERATION, function_name,
7279 (std::string("invalid type ") +
[email protected]81375742012-06-08 00:04:007280 GLES2Util::GetStringEnum(type) + " for format " +
7281 GLES2Util::GetStringEnum(format)).c_str());
7282 return false;
7283 }
7284
7285 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7286 if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) {
[email protected]ad84a3a2012-06-08 21:42:437287 SetGLError(GL_INVALID_OPERATION, function_name,
7288 (std::string("invalid type ") +
[email protected]81375742012-06-08 00:04:007289 GLES2Util::GetStringEnum(type) + " for format " +
7290 GLES2Util::GetStringEnum(format)).c_str());
7291 return false;
7292 }
7293 return true;
7294}
7295
[email protected]a93bb842010-02-16 23:03:477296error::Error GLES2DecoderImpl::DoTexImage2D(
7297 GLenum target,
7298 GLint level,
7299 GLenum internal_format,
7300 GLsizei width,
7301 GLsizei height,
7302 GLint border,
7303 GLenum format,
7304 GLenum type,
7305 const void* pixels,
7306 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:057307 if (!validators_->texture_target.IsValid(target)) {
[email protected]ad84a3a2012-06-08 21:42:437308 SetGLError(GL_INVALID_ENUM, "glTexImage2D", "target GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:297309 return error::kNoError;
7310 }
[email protected]9438b012010-06-15 22:55:057311 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:297312 SetGLError(GL_INVALID_ENUM,
[email protected]ad84a3a2012-06-08 21:42:437313 "glTexImage2D", "internal_format GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:297314 return error::kNoError;
7315 }
[email protected]9438b012010-06-15 22:55:057316 if (!validators_->texture_format.IsValid(format)) {
[email protected]ad84a3a2012-06-08 21:42:437317 SetGLError(GL_INVALID_ENUM, "glTexImage2D", "format GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:297318 return error::kNoError;
7319 }
[email protected]9438b012010-06-15 22:55:057320 if (!validators_->pixel_type.IsValid(type)) {
[email protected]ad84a3a2012-06-08 21:42:437321 SetGLError(GL_INVALID_ENUM, "glTexImage2D", "type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:147322 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197323 }
[email protected]7b92c412010-07-20 17:48:257324 if (format != internal_format) {
[email protected]ad84a3a2012-06-08 21:42:437325 SetGLError(GL_INVALID_OPERATION,
7326 "glTexImage2D", "format != internalFormat");
[email protected]7b92c412010-07-20 17:48:257327 return error::kNoError;
7328 }
[email protected]81375742012-06-08 00:04:007329 if (!ValidateTextureParameters("glTexImage2D", target, format, type, level)) {
7330 return error::kNoError;
7331 }
[email protected]80eb6b52012-01-19 00:14:417332 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:477333 border != 0) {
[email protected]ad84a3a2012-06-08 21:42:437334 SetGLError(GL_INVALID_VALUE, "glTexImage2D", "dimensions out of range");
[email protected]a93bb842010-02-16 23:03:477335 return error::kNoError;
7336 }
[email protected]81375742012-06-08 00:04:007337 if ((GLES2Util::GetChannelsForFormat(format) &
7338 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && pixels) {
7339 SetGLError(
7340 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437341 "glTexImage2D", "can not supply data for depth or stencil textures");
[email protected]81375742012-06-08 00:04:007342 return error::kNoError;
7343 }
[email protected]3916c97e2010-02-25 03:20:507344 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:477345 if (!info) {
[email protected]8eee29c2010-04-29 03:38:297346 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437347 "glTexImage2D", "unknown texture for target");
[email protected]a93bb842010-02-16 23:03:477348 return error::kNoError;
7349 }
[email protected]0226c112011-07-22 03:25:077350
[email protected]97dc7cbe2011-12-06 17:26:177351 if (info->IsImmutable()) {
7352 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437353 "glTexImage2D", "texture is immutable");
[email protected]97dc7cbe2011-12-06 17:26:177354 return error::kNoError;
7355 }
7356
[email protected]0226c112011-07-22 03:25:077357 GLsizei tex_width = 0;
7358 GLsizei tex_height = 0;
7359 GLenum tex_type = 0;
7360 GLenum tex_format = 0;
7361 bool level_is_same =
7362 info->GetLevelSize(target, level, &tex_width, &tex_height) &&
7363 info->GetLevelType(target, level, &tex_type, &tex_format) &&
7364 width == tex_width && height == tex_height &&
7365 type == tex_type && format == tex_format;
7366
7367 if (level_is_same && !pixels) {
[email protected]1bed6222011-12-21 11:21:397368 // Just set the level info but mark the texture as uncleared.
7369 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:417370 info,
[email protected]1bed6222011-12-21 11:21:397371 target, level, internal_format, width, height, 1, border, format, type,
7372 false);
[email protected]ea72ed222011-08-17 18:58:437373 tex_image_2d_failed_ = false;
[email protected]0226c112011-07-22 03:25:077374 return error::kNoError;
7375 }
7376
[email protected]297ca1c2011-06-20 23:08:467377 if (info->IsAttachedToFramebuffer()) {
7378 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:517379 // TODO(gman): If textures tracked which framebuffers they were attached to
7380 // we could just mark those framebuffers as not complete.
7381 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:467382 }
7383
[email protected]1bed6222011-12-21 11:21:397384 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same && pixels) {
[email protected]0226c112011-07-22 03:25:077385 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
[email protected]57edfdad2012-02-07 04:57:157386 texture_manager()->SetLevelCleared(info, target, level);
[email protected]0226c112011-07-22 03:25:077387 tex_image_2d_failed_ = false;
7388 return error::kNoError;
[email protected]7488d962010-07-16 02:41:587389 }
[email protected]876f6fee2010-08-02 23:10:327390
[email protected]cadde4a2010-07-31 17:10:437391 CopyRealGLErrorsToWrapper();
[email protected]473c01ccb2011-06-07 01:33:307392 WrappedTexImage2D(
7393 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:477394 pixels);
[email protected]1002c2d2011-06-28 22:39:047395 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:437396 if (error == GL_NO_ERROR) {
[email protected]0d6bfdc2011-11-02 01:32:207397 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:417398 info,
[email protected]0d6bfdc2011-11-02 01:32:207399 target, level, internal_format, width, height, 1, border, format, type,
7400 pixels != NULL);
[email protected]b493ee622011-04-13 23:52:007401 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:437402 }
[email protected]f7a64ee2010-02-01 22:24:147403 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197404}
7405
[email protected]f7a64ee2010-02-01 22:24:147406error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:197407 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]43ed3a72012-05-30 22:55:387408 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:007409 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:197410 GLenum target = static_cast<GLenum>(c.target);
7411 GLint level = static_cast<GLint>(c.level);
7412 GLint internal_format = static_cast<GLint>(c.internalformat);
7413 GLsizei width = static_cast<GLsizei>(c.width);
7414 GLsizei height = static_cast<GLsizei>(c.height);
7415 GLint border = static_cast<GLint>(c.border);
7416 GLenum format = static_cast<GLenum>(c.format);
7417 GLenum type = static_cast<GLenum>(c.type);
7418 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
7419 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:187420 uint32 pixels_size;
[email protected]3458a64a2012-04-10 17:39:347421 if (!GLES2Util::ComputeImageDataSizes(
7422 width, height, format, type, unpack_alignment_, &pixels_size, NULL,
7423 NULL)) {
[email protected]a76b0052010-03-05 00:33:187424 return error::kOutOfBounds;
7425 }
[email protected]b9849abf2009-11-25 19:13:197426 const void* pixels = NULL;
7427 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
7428 pixels = GetSharedMemoryAs<const void*>(
7429 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:467430 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:147431 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197432 }
7433 }
[email protected]a93bb842010-02-16 23:03:477434 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:197435 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:477436 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:197437}
7438
[email protected]f7a64ee2010-02-01 22:24:147439error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:197440 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
7441 GLenum target = static_cast<GLenum>(c.target);
7442 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:467443 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:197444 GLsizei width = static_cast<GLsizei>(c.width);
7445 GLsizei height = static_cast<GLsizei>(c.height);
7446 GLint border = static_cast<GLint>(c.border);
7447 GLenum format = static_cast<GLenum>(c.format);
7448 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:187449 uint32 size;
[email protected]3458a64a2012-04-10 17:39:347450 if (!GLES2Util::ComputeImageDataSizes(
7451 width, height, format, type, unpack_alignment_, &size, NULL, NULL)) {
[email protected]a76b0052010-03-05 00:33:187452 return error::kOutOfBounds;
7453 }
[email protected]07f54fcc2009-12-22 02:46:307454 const void* pixels = GetImmediateDataAs<const void*>(
7455 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:467456 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:147457 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:467458 }
[email protected]a93bb842010-02-16 23:03:477459 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:467460 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:477461 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:147462 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327463}
7464
[email protected]cadde4a2010-07-31 17:10:437465void GLES2DecoderImpl::DoCompressedTexSubImage2D(
7466 GLenum target,
7467 GLint level,
7468 GLint xoffset,
7469 GLint yoffset,
7470 GLsizei width,
7471 GLsizei height,
7472 GLenum format,
7473 GLsizei image_size,
7474 const void * data) {
7475 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7476 if (!info) {
7477 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437478 "glCompressedTexSubImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:437479 return;
7480 }
7481 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:527482 GLenum internal_format = 0;
7483 if (!info->GetLevelType(target, level, &type, &internal_format)) {
7484 SetGLError(
7485 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437486 "glCompressedTexSubImage2D", "level does not exist.");
[email protected]df6cf1ad2011-01-29 01:20:527487 return;
7488 }
7489 if (internal_format != format) {
7490 SetGLError(
7491 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437492 "glCompressedTexSubImage2D", "format does not match internal format.");
[email protected]df6cf1ad2011-01-29 01:20:527493 return;
7494 }
7495 if (!info->ValidForTexture(
7496 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:437497 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:437498 "glCompressedTexSubImage2D", "bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:437499 return;
7500 }
[email protected]ad84a3a2012-06-08 21:42:437501
7502 if (!ValidateCompressedTexFuncData(
7503 "glCompressedTexSubImage2D", width, height, format, image_size) ||
7504 !ValidateCompressedTexSubDimensions(
7505 "glCompressedTexSubImage2D",
7506 target, level, xoffset, yoffset, width, height, format, info)) {
7507 return;
7508 }
7509
7510
[email protected]0d6bfdc2011-11-02 01:32:207511 // Note: There is no need to deal with texture cleared tracking here
7512 // because the validation above means you can only get here if the level
7513 // is already a matching compressed format and in that case
7514 // CompressedTexImage2D already cleared the texture.
[email protected]cadde4a2010-07-31 17:10:437515 glCompressedTexSubImage2D(
7516 target, level, xoffset, yoffset, width, height, format, image_size, data);
7517}
7518
[email protected]6e288612010-12-21 20:45:037519static void Clip(
7520 GLint start, GLint range, GLint sourceRange,
7521 GLint* out_start, GLint* out_range) {
7522 DCHECK(out_start);
7523 DCHECK(out_range);
7524 if (start < 0) {
7525 range += start;
7526 start = 0;
7527 }
7528 GLint end = start + range;
7529 if (end > sourceRange) {
7530 range -= end - sourceRange;
7531 }
7532 *out_start = start;
7533 *out_range = range;
7534}
7535
[email protected]cadde4a2010-07-31 17:10:437536void GLES2DecoderImpl::DoCopyTexImage2D(
[email protected]a5d3dad2012-05-26 04:34:447537 GLenum target,
7538 GLint level,
7539 GLenum internal_format,
7540 GLint x,
7541 GLint y,
7542 GLsizei width,
7543 GLsizei height,
7544 GLint border) {
[email protected]cadde4a2010-07-31 17:10:437545 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7546 if (!info) {
7547 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437548 "glCopyTexImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:437549 return;
7550 }
[email protected]97dc7cbe2011-12-06 17:26:177551 if (info->IsImmutable()) {
7552 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437553 "glCopyTexImage2D", "texture is immutable");
[email protected]97dc7cbe2011-12-06 17:26:177554 }
[email protected]80eb6b52012-01-19 00:14:417555 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:187556 border != 0) {
[email protected]ad84a3a2012-06-08 21:42:437557 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
[email protected]f5719fb2010-08-04 18:27:187558 return;
7559 }
[email protected]81375742012-06-08 00:04:007560 if (!ValidateTextureParameters(
7561 "glCopyTexImage2D", target, internal_format, GL_UNSIGNED_BYTE, level)) {
7562 return;
7563 }
[email protected]f5719fb2010-08-04 18:27:187564
[email protected]9edc6b22010-12-23 02:00:267565 // Check we have compatible formats.
7566 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7567 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7568 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
7569
7570 if ((channels_needed & channels_exist) != channels_needed) {
[email protected]ad84a3a2012-06-08 21:42:437571 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
[email protected]9edc6b22010-12-23 02:00:267572 return;
7573 }
7574
[email protected]81375742012-06-08 00:04:007575 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
7576 SetGLError(
7577 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437578 "glCopyImage2D", "can not be used with depth or stencil textures");
[email protected]81375742012-06-08 00:04:007579 return;
7580 }
7581
[email protected]a0b78dc2011-11-11 10:43:107582 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
7583 return;
7584 }
7585
[email protected]cadde4a2010-07-31 17:10:437586 CopyRealGLErrorsToWrapper();
[email protected]de26b3c2011-08-03 21:54:277587 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:037588 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:267589
[email protected]297ca1c2011-06-20 23:08:467590 if (info->IsAttachedToFramebuffer()) {
7591 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:517592 // TODO(gman): If textures tracked which framebuffers they were attached to
7593 // we could just mark those framebuffers as not complete.
7594 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:467595 }
7596
[email protected]9edc6b22010-12-23 02:00:267597 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:037598 GLint copyX = 0;
7599 GLint copyY = 0;
7600 GLint copyWidth = 0;
7601 GLint copyHeight = 0;
7602 Clip(x, width, size.width(), &copyX, &copyWidth);
7603 Clip(y, height, size.height(), &copyY, &copyHeight);
7604
7605 if (copyX != x ||
7606 copyY != y ||
7607 copyWidth != width ||
7608 copyHeight != height) {
7609 // some part was clipped so clear the texture.
[email protected]0d6bfdc2011-11-02 01:32:207610 if (!ClearLevel(
7611 info->service_id(), info->target(),
[email protected]4502e6492011-12-14 19:39:157612 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
7613 info->IsImmutable())) {
[email protected]ad84a3a2012-06-08 21:42:437614 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
[email protected]6e288612010-12-21 20:45:037615 return;
7616 }
[email protected]6e288612010-12-21 20:45:037617 if (copyHeight > 0 && copyWidth > 0) {
7618 GLint dx = copyX - x;
7619 GLint dy = copyY - y;
7620 GLint destX = dx;
7621 GLint destY = dy;
7622 glCopyTexSubImage2D(target, level,
7623 destX, destY, copyX, copyY,
7624 copyWidth, copyHeight);
7625 }
7626 } else {
7627 glCopyTexImage2D(target, level, internal_format,
7628 copyX, copyY, copyWidth, copyHeight, border);
7629 }
[email protected]1002c2d2011-06-28 22:39:047630 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:437631 if (error == GL_NO_ERROR) {
7632 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:417633 info, target, level, internal_format, width, height, 1,
[email protected]0d6bfdc2011-11-02 01:32:207634 border, internal_format, GL_UNSIGNED_BYTE, true);
[email protected]cadde4a2010-07-31 17:10:437635 }
7636}
7637
7638void GLES2DecoderImpl::DoCopyTexSubImage2D(
[email protected]a5d3dad2012-05-26 04:34:447639 GLenum target,
7640 GLint level,
7641 GLint xoffset,
7642 GLint yoffset,
7643 GLint x,
7644 GLint y,
7645 GLsizei width,
7646 GLsizei height) {
[email protected]cadde4a2010-07-31 17:10:437647 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7648 if (!info) {
7649 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437650 "glCopyTexSubImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:437651 return;
7652 }
7653 GLenum type = 0;
7654 GLenum format = 0;
7655 if (!info->GetLevelType(target, level, &type, &format) ||
7656 !info->ValidForTexture(
7657 target, level, xoffset, yoffset, width, height, format, type)) {
7658 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:437659 "glCopyTexSubImage2D", "bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:437660 return;
7661 }
[email protected]9edc6b22010-12-23 02:00:267662
7663 // Check we have compatible formats.
7664 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7665 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7666 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
7667
7668 if ((channels_needed & channels_exist) != channels_needed) {
7669 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:437670 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
[email protected]9edc6b22010-12-23 02:00:267671 return;
7672 }
7673
[email protected]81375742012-06-08 00:04:007674 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
7675 SetGLError(
7676 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437677 "glCopySubImage2D", "can not be used with depth or stencil textures");
[email protected]81375742012-06-08 00:04:007678 return;
7679 }
7680
[email protected]a0b78dc2011-11-11 10:43:107681 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
7682 return;
7683 }
7684
[email protected]de26b3c2011-08-03 21:54:277685 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:037686 gfx::Size size = GetBoundReadFrameBufferSize();
7687 GLint copyX = 0;
7688 GLint copyY = 0;
7689 GLint copyWidth = 0;
7690 GLint copyHeight = 0;
7691 Clip(x, width, size.width(), &copyX, &copyWidth);
7692 Clip(y, height, size.height(), &copyY, &copyHeight);
[email protected]0d6bfdc2011-11-02 01:32:207693
7694 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
[email protected]ad84a3a2012-06-08 21:42:437695 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
[email protected]0d6bfdc2011-11-02 01:32:207696 return;
7697 }
7698
[email protected]6e288612010-12-21 20:45:037699 if (copyX != x ||
7700 copyY != y ||
7701 copyWidth != width ||
7702 copyHeight != height) {
[email protected]0d6bfdc2011-11-02 01:32:207703 // some part was clipped so clear the sub rect.
[email protected]6e288612010-12-21 20:45:037704 uint32 pixels_size = 0;
[email protected]3458a64a2012-04-10 17:39:347705 if (!GLES2Util::ComputeImageDataSizes(
7706 width, height, format, type, unpack_alignment_, &pixels_size, NULL,
7707 NULL)) {
[email protected]ad84a3a2012-06-08 21:42:437708 SetGLError(
7709 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
[email protected]6e288612010-12-21 20:45:037710 return;
7711 }
7712 scoped_array<char> zero(new char[pixels_size]);
7713 memset(zero.get(), 0, pixels_size);
7714 glTexSubImage2D(
7715 target, level, xoffset, yoffset, width, height,
7716 format, type, zero.get());
7717 }
[email protected]0d6bfdc2011-11-02 01:32:207718
[email protected]6e288612010-12-21 20:45:037719 if (copyHeight > 0 && copyWidth > 0) {
7720 GLint dx = copyX - x;
7721 GLint dy = copyY - y;
7722 GLint destX = xoffset + dx;
7723 GLint destY = yoffset + dy;
7724 glCopyTexSubImage2D(target, level,
7725 destX, destY, copyX, copyY,
7726 copyWidth, copyHeight);
7727 }
[email protected]cadde4a2010-07-31 17:10:437728}
7729
7730void GLES2DecoderImpl::DoTexSubImage2D(
7731 GLenum target,
7732 GLint level,
7733 GLint xoffset,
7734 GLint yoffset,
7735 GLsizei width,
7736 GLsizei height,
7737 GLenum format,
7738 GLenum type,
7739 const void * data) {
7740 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7741 if (!info) {
7742 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437743 "glTexSubImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:437744 return;
7745 }
[email protected]df6cf1ad2011-01-29 01:20:527746 GLenum current_type = 0;
7747 GLenum internal_format = 0;
7748 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
7749 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:437750 GL_INVALID_OPERATION, "glTexSubImage2D", "level does not exist.");
[email protected]df6cf1ad2011-01-29 01:20:527751 return;
7752 }
7753 if (format != internal_format) {
7754 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437755 "glTexSubImage2D", "format does not match internal format.");
[email protected]df6cf1ad2011-01-29 01:20:527756 return;
7757 }
7758 if (type != current_type) {
7759 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437760 "glTexSubImage2D", "type does not match type of texture.");
[email protected]df6cf1ad2011-01-29 01:20:527761 return;
7762 }
7763
[email protected]cadde4a2010-07-31 17:10:437764 if (!info->ValidForTexture(
7765 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]ad84a3a2012-06-08 21:42:437766 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:437767 return;
7768 }
[email protected]473c01ccb2011-06-07 01:33:307769
[email protected]81375742012-06-08 00:04:007770 if ((GLES2Util::GetChannelsForFormat(format) &
7771 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
7772 SetGLError(
7773 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437774 "glTexSubImage2D", "can not supply data for depth or stencil textures");
[email protected]81375742012-06-08 00:04:007775 return;
7776 }
7777
[email protected]4502e6492011-12-14 19:39:157778 GLsizei tex_width = 0;
7779 GLsizei tex_height = 0;
7780 bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height);
7781 DCHECK(ok);
7782 if (xoffset != 0 || yoffset != 0 ||
7783 width != tex_width || height != tex_height) {
7784 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
[email protected]ad84a3a2012-06-08 21:42:437785 SetGLError(GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
[email protected]473c01ccb2011-06-07 01:33:307786 return;
7787 }
[email protected]4502e6492011-12-14 19:39:157788 glTexSubImage2D(
7789 target, level, xoffset, yoffset, width, height, format, type, data);
[email protected]0d6bfdc2011-11-02 01:32:207790 return;
7791 }
[email protected]4502e6492011-12-14 19:39:157792
7793 if (teximage2d_faster_than_texsubimage2d_ && !info->IsImmutable()) {
7794 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
7795 // same as internal_foramt. If that changes we'll need to look them up.
7796 WrappedTexImage2D(
7797 target, level, format, width, height, 0, format, type, data);
7798 } else {
7799 glTexSubImage2D(
7800 target, level, xoffset, yoffset, width, height, format, type, data);
7801 }
7802 texture_manager()->SetLevelCleared(info, target, level);
[email protected]cadde4a2010-07-31 17:10:437803}
7804
[email protected]b493ee622011-04-13 23:52:007805error::Error GLES2DecoderImpl::HandleTexSubImage2D(
7806 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]43ed3a72012-05-30 22:55:387807 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:007808 GLboolean internal = static_cast<GLboolean>(c.internal);
7809 if (internal == GL_TRUE && tex_image_2d_failed_)
7810 return error::kNoError;
7811
7812 GLenum target = static_cast<GLenum>(c.target);
7813 GLint level = static_cast<GLint>(c.level);
7814 GLint xoffset = static_cast<GLint>(c.xoffset);
7815 GLint yoffset = static_cast<GLint>(c.yoffset);
7816 GLsizei width = static_cast<GLsizei>(c.width);
7817 GLsizei height = static_cast<GLsizei>(c.height);
7818 GLenum format = static_cast<GLenum>(c.format);
7819 GLenum type = static_cast<GLenum>(c.type);
7820 uint32 data_size;
[email protected]3458a64a2012-04-10 17:39:347821 if (!GLES2Util::ComputeImageDataSizes(
7822 width, height, format, type, unpack_alignment_, &data_size, NULL, NULL)) {
[email protected]b493ee622011-04-13 23:52:007823 return error::kOutOfBounds;
7824 }
7825 const void* pixels = GetSharedMemoryAs<const void*>(
7826 c.pixels_shm_id, c.pixels_shm_offset, data_size);
7827 if (!validators_->texture_target.IsValid(target)) {
[email protected]ad84a3a2012-06-08 21:42:437828 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D", "target GL_INVALID_ENUM");
[email protected]b493ee622011-04-13 23:52:007829 return error::kNoError;
7830 }
7831 if (width < 0) {
[email protected]ad84a3a2012-06-08 21:42:437832 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "width < 0");
[email protected]b493ee622011-04-13 23:52:007833 return error::kNoError;
7834 }
7835 if (height < 0) {
[email protected]ad84a3a2012-06-08 21:42:437836 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "height < 0");
[email protected]b493ee622011-04-13 23:52:007837 return error::kNoError;
7838 }
7839 if (!validators_->texture_format.IsValid(format)) {
[email protected]ad84a3a2012-06-08 21:42:437840 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D", "format GL_INVALID_ENUM");
[email protected]b493ee622011-04-13 23:52:007841 return error::kNoError;
7842 }
7843 if (!validators_->pixel_type.IsValid(type)) {
[email protected]ad84a3a2012-06-08 21:42:437844 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D", "type GL_INVALID_ENUM");
[email protected]b493ee622011-04-13 23:52:007845 return error::kNoError;
7846 }
7847 if (pixels == NULL) {
7848 return error::kOutOfBounds;
7849 }
7850 DoTexSubImage2D(
7851 target, level, xoffset, yoffset, width, height, format, type, pixels);
7852 return error::kNoError;
7853}
7854
7855error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
7856 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
7857 GLboolean internal = static_cast<GLboolean>(c.internal);
7858 if (internal == GL_TRUE && tex_image_2d_failed_)
7859 return error::kNoError;
7860
7861 GLenum target = static_cast<GLenum>(c.target);
7862 GLint level = static_cast<GLint>(c.level);
7863 GLint xoffset = static_cast<GLint>(c.xoffset);
7864 GLint yoffset = static_cast<GLint>(c.yoffset);
7865 GLsizei width = static_cast<GLsizei>(c.width);
7866 GLsizei height = static_cast<GLsizei>(c.height);
7867 GLenum format = static_cast<GLenum>(c.format);
7868 GLenum type = static_cast<GLenum>(c.type);
7869 uint32 data_size;
[email protected]3458a64a2012-04-10 17:39:347870 if (!GLES2Util::ComputeImageDataSizes(
7871 width, height, format, type, unpack_alignment_, &data_size, NULL, NULL)) {
[email protected]b493ee622011-04-13 23:52:007872 return error::kOutOfBounds;
7873 }
7874 const void* pixels = GetImmediateDataAs<const void*>(
7875 c, data_size, immediate_data_size);
7876 if (!validators_->texture_target.IsValid(target)) {
[email protected]ad84a3a2012-06-08 21:42:437877 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D", "target GL_INVALID_ENUM");
[email protected]b493ee622011-04-13 23:52:007878 return error::kNoError;
7879 }
7880 if (width < 0) {
[email protected]ad84a3a2012-06-08 21:42:437881 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "width < 0");
[email protected]b493ee622011-04-13 23:52:007882 return error::kNoError;
7883 }
7884 if (height < 0) {
[email protected]ad84a3a2012-06-08 21:42:437885 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "height < 0");
[email protected]b493ee622011-04-13 23:52:007886 return error::kNoError;
7887 }
7888 if (!validators_->texture_format.IsValid(format)) {
[email protected]ad84a3a2012-06-08 21:42:437889 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D", "format GL_INVALID_ENUM");
[email protected]b493ee622011-04-13 23:52:007890 return error::kNoError;
7891 }
7892 if (!validators_->pixel_type.IsValid(type)) {
[email protected]ad84a3a2012-06-08 21:42:437893 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D", "type GL_INVALID_ENUM");
[email protected]b493ee622011-04-13 23:52:007894 return error::kNoError;
7895 }
7896 if (pixels == NULL) {
7897 return error::kOutOfBounds;
7898 }
7899 DoTexSubImage2D(
7900 target, level, xoffset, yoffset, width, height, format, type, pixels);
7901 return error::kNoError;
7902}
7903
[email protected]f7a64ee2010-02-01 22:24:147904error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:197905 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:367906 GLuint index = static_cast<GLuint>(c.index);
7907 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:257908 typedef gles2::GetVertexAttribPointerv::Result Result;
7909 Result* result = GetSharedMemoryAs<Result*>(
7910 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:367911 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:147912 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:367913 }
[email protected]07d0cc82010-02-17 04:51:407914 // Check that the client initialized the result.
7915 if (result->size != 0) {
7916 return error::kInvalidArguments;
7917 }
[email protected]9438b012010-06-15 22:55:057918 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:297919 SetGLError(GL_INVALID_ENUM,
[email protected]ad84a3a2012-06-08 21:42:437920 "glGetVertexAttribPointerv", "pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:147921 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367922 }
[email protected]3916c97e2010-02-25 03:20:507923 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:297924 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:437925 "glGetVertexAttribPointerv", "index out of range.");
[email protected]f7a64ee2010-02-01 22:24:147926 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367927 }
[email protected]0bfd9882010-02-05 23:02:257928 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:087929 *result->GetData() =
[email protected]3757a372012-01-19 05:20:447930 vertex_attrib_manager_->GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:147931 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327932}
7933
[email protected]f7b85372010-02-03 01:11:377934bool GLES2DecoderImpl::GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127935 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:377936 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:127937 error::Error* error, GLint* real_location,
7938 GLuint* service_id, void** result_pointer, GLenum* result_type) {
[email protected]939e7362010-05-13 20:49:107939 DCHECK(error);
7940 DCHECK(service_id);
7941 DCHECK(result_pointer);
7942 DCHECK(result_type);
[email protected]1b0a6752012-02-22 03:44:127943 DCHECK(real_location);
[email protected]f7b85372010-02-03 01:11:377944 *error = error::kNoError;
7945 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:257946 SizedResult<GLint>* result;
7947 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7948 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
7949 if (!result) {
[email protected]f7b85372010-02-03 01:11:377950 *error = error::kOutOfBounds;
7951 return false;
7952 }
[email protected]0bfd9882010-02-05 23:02:257953 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:377954 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:257955 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:587956 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7957 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:377958 if (!info) {
[email protected]ae51d192010-04-27 00:48:037959 return false;
7960 }
7961 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:377962 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]ad84a3a2012-06-08 21:42:437963 SetGLError(GL_INVALID_OPERATION, "glGetUniform", "program not linked");
[email protected]f7b85372010-02-03 01:11:377964 return false;
7965 }
[email protected]ae51d192010-04-27 00:48:037966 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:367967 GLint array_index = -1;
7968 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
[email protected]1b0a6752012-02-22 03:44:127969 info->GetUniformInfoByFakeLocation(
7970 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:367971 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:377972 // No such location.
[email protected]ad84a3a2012-06-08 21:42:437973 SetGLError(GL_INVALID_OPERATION, "glGetUniform", "unknown location");
[email protected]f7b85372010-02-03 01:11:377974 return false;
7975 }
[email protected]43c2f1f2011-03-25 18:35:367976 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:507977 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:377978 if (size == 0) {
[email protected]ad84a3a2012-06-08 21:42:437979 SetGLError(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
[email protected]f7b85372010-02-03 01:11:377980 return false;
7981 }
[email protected]0bfd9882010-02-05 23:02:257982 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7983 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
7984 if (!result) {
[email protected]f7b85372010-02-03 01:11:377985 *error = error::kOutOfBounds;
7986 return false;
7987 }
[email protected]0bfd9882010-02-05 23:02:257988 result->size = size;
[email protected]939e7362010-05-13 20:49:107989 *result_type = type;
[email protected]f7b85372010-02-03 01:11:377990 return true;
7991}
7992
[email protected]f7a64ee2010-02-01 22:24:147993error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:197994 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:377995 GLuint program = c.program;
[email protected]2be6abf32012-06-26 00:28:337996 GLint fake_location = c.location;
[email protected]f7b85372010-02-03 01:11:377997 GLuint service_id;
[email protected]939e7362010-05-13 20:49:107998 GLenum result_type;
[email protected]1b0a6752012-02-22 03:44:127999 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:378000 Error error;
[email protected]0bfd9882010-02-05 23:02:258001 void* result;
[email protected]f7b85372010-02-03 01:11:378002 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:128003 program, fake_location, c.params_shm_id, c.params_shm_offset,
8004 &error, &real_location, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:258005 glGetUniformiv(
[email protected]1b0a6752012-02-22 03:44:128006 service_id, real_location,
[email protected]0bfd9882010-02-05 23:02:258007 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:378008 }
8009 return error;
[email protected]96449d2c2009-11-25 00:01:328010}
8011
[email protected]f7a64ee2010-02-01 22:24:148012error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:198013 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:378014 GLuint program = c.program;
[email protected]2be6abf32012-06-26 00:28:338015 GLint fake_location = c.location;
[email protected]f7b85372010-02-03 01:11:378016 GLuint service_id;
[email protected]1b0a6752012-02-22 03:44:128017 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:378018 Error error;
[email protected]0bfd9882010-02-05 23:02:258019 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:108020 Result* result;
8021 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:378022 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:128023 program, fake_location, c.params_shm_id, c.params_shm_offset,
8024 &error, &real_location, &service_id,
8025 reinterpret_cast<void**>(&result), &result_type)) {
[email protected]939e7362010-05-13 20:49:108026 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
8027 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
8028 GLsizei num_values = result->GetNumResults();
8029 scoped_array<GLint> temp(new GLint[num_values]);
[email protected]1b0a6752012-02-22 03:44:128030 glGetUniformiv(service_id, real_location, temp.get());
[email protected]939e7362010-05-13 20:49:108031 GLfloat* dst = result->GetData();
8032 for (GLsizei ii = 0; ii < num_values; ++ii) {
8033 dst[ii] = (temp[ii] != 0);
8034 }
8035 } else {
[email protected]1b0a6752012-02-22 03:44:128036 glGetUniformfv(service_id, real_location, result->GetData());
[email protected]939e7362010-05-13 20:49:108037 }
[email protected]f7b85372010-02-03 01:11:378038 }
8039 return error;
[email protected]96449d2c2009-11-25 00:01:328040}
8041
[email protected]f7a64ee2010-02-01 22:24:148042error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:198043 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:258044 GLenum shader_type = static_cast<GLenum>(c.shadertype);
8045 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
8046 typedef gles2::GetShaderPrecisionFormat::Result Result;
8047 Result* result = GetSharedMemoryAs<Result*>(
8048 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8049 if (!result) {
8050 return error::kOutOfBounds;
8051 }
[email protected]07d0cc82010-02-17 04:51:408052 // Check that the client initialized the result.
8053 if (result->success != 0) {
8054 return error::kInvalidArguments;
8055 }
[email protected]9438b012010-06-15 22:55:058056 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:298057 SetGLError(GL_INVALID_ENUM,
[email protected]ad84a3a2012-06-08 21:42:438058 "glGetShaderPrecisionFormat", "shader_type GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:298059 return error::kNoError;
8060 }
[email protected]9438b012010-06-15 22:55:058061 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:298062 SetGLError(GL_INVALID_ENUM,
[email protected]ad84a3a2012-06-08 21:42:438063 "glGetShaderPrecisionFormat", "precision_type GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:298064 return error::kNoError;
8065 }
8066
8067 result->success = 1; // true
8068 switch (precision_type) {
8069 case GL_LOW_INT:
8070 case GL_MEDIUM_INT:
8071 case GL_HIGH_INT:
[email protected]0a34b582012-04-09 22:42:568072 // These values are for a 32-bit twos-complement integer format.
8073 result->min_range = 31;
8074 result->max_range = 30;
[email protected]8eee29c2010-04-29 03:38:298075 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:108076 break;
[email protected]8eee29c2010-04-29 03:38:298077 case GL_LOW_FLOAT:
8078 case GL_MEDIUM_FLOAT:
8079 case GL_HIGH_FLOAT:
[email protected]0a34b582012-04-09 22:42:568080 // These values are for an IEEE single-precision floating-point format.
8081 result->min_range = 127;
8082 result->max_range = 127;
8083 result->precision = 23;
[email protected]8eee29c2010-04-29 03:38:298084 break;
8085 default:
8086 NOTREACHED();
8087 break;
[email protected]0bfd9882010-02-05 23:02:258088 }
[email protected]f7a64ee2010-02-01 22:24:148089 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328090}
8091
[email protected]f7a64ee2010-02-01 22:24:148092error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:198093 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:258094 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:588095 GLuint program = static_cast<GLuint>(c.program);
8096 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
8097 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:038098 if (!info) {
[email protected]0bfd9882010-02-05 23:02:258099 return error::kNoError;
8100 }
8101 typedef gles2::GetAttachedShaders::Result Result;
8102 uint32 max_count = Result::ComputeMaxResults(result_size);
8103 Result* result = GetSharedMemoryAs<Result*>(
8104 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
8105 if (!result) {
8106 return error::kOutOfBounds;
8107 }
[email protected]07d0cc82010-02-17 04:51:408108 // Check that the client initialized the result.
8109 if (result->size != 0) {
8110 return error::kInvalidArguments;
8111 }
[email protected]0bfd9882010-02-05 23:02:258112 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:038113 glGetAttachedShaders(
8114 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:258115 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:038116 if (!shader_manager()->GetClientId(result->GetData()[ii],
8117 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:258118 NOTREACHED();
8119 return error::kGenericError;
8120 }
8121 }
8122 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:148123 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328124}
8125
[email protected]f7a64ee2010-02-01 22:24:148126error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:198127 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:258128 GLuint program = c.program;
8129 GLuint index = c.index;
8130 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:258131 typedef gles2::GetActiveUniform::Result Result;
8132 Result* result = GetSharedMemoryAs<Result*>(
8133 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8134 if (!result) {
8135 return error::kOutOfBounds;
8136 }
[email protected]07d0cc82010-02-17 04:51:408137 // Check that the client initialized the result.
8138 if (result->success != 0) {
8139 return error::kInvalidArguments;
8140 }
[email protected]6b8cf1a2010-05-06 16:13:588141 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
8142 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:038143 if (!info) {
[email protected]0bfd9882010-02-05 23:02:258144 return error::kNoError;
8145 }
8146 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
8147 info->GetUniformInfo(index);
8148 if (!uniform_info) {
[email protected]ad84a3a2012-06-08 21:42:438149 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
[email protected]0bfd9882010-02-05 23:02:258150 return error::kNoError;
8151 }
8152 result->success = 1; // true.
8153 result->size = uniform_info->size;
8154 result->type = uniform_info->type;
8155 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:298156 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:148157 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328158}
8159
[email protected]f7a64ee2010-02-01 22:24:148160error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:198161 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:258162 GLuint program = c.program;
8163 GLuint index = c.index;
8164 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:258165 typedef gles2::GetActiveAttrib::Result Result;
8166 Result* result = GetSharedMemoryAs<Result*>(
8167 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8168 if (!result) {
8169 return error::kOutOfBounds;
8170 }
[email protected]07d0cc82010-02-17 04:51:408171 // Check that the client initialized the result.
8172 if (result->success != 0) {
8173 return error::kInvalidArguments;
8174 }
[email protected]6b8cf1a2010-05-06 16:13:588175 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
8176 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:038177 if (!info) {
[email protected]0bfd9882010-02-05 23:02:258178 return error::kNoError;
8179 }
8180 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
8181 info->GetAttribInfo(index);
8182 if (!attrib_info) {
[email protected]ad84a3a2012-06-08 21:42:438183 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
[email protected]0bfd9882010-02-05 23:02:258184 return error::kNoError;
8185 }
8186 result->success = 1; // true.
8187 result->size = attrib_info->size;
8188 result->type = attrib_info->type;
8189 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:298190 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:148191 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328192}
8193
[email protected]b273e432010-04-12 17:23:588194error::Error GLES2DecoderImpl::HandleShaderBinary(
8195 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
8196#if 1 // No binary shader support.
[email protected]ad84a3a2012-06-08 21:42:438197 SetGLError(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
[email protected]b273e432010-04-12 17:23:588198 return error::kNoError;
8199#else
8200 GLsizei n = static_cast<GLsizei>(c.n);
8201 if (n < 0) {
[email protected]ad84a3a2012-06-08 21:42:438202 SetGLError(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
[email protected]b273e432010-04-12 17:23:588203 return error::kNoError;
8204 }
8205 GLsizei length = static_cast<GLsizei>(c.length);
8206 if (length < 0) {
[email protected]ad84a3a2012-06-08 21:42:438207 SetGLError(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
[email protected]b273e432010-04-12 17:23:588208 return error::kNoError;
8209 }
8210 uint32 data_size;
8211 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
8212 return error::kOutOfBounds;
8213 }
8214 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
8215 c.shaders_shm_id, c.shaders_shm_offset, data_size);
8216 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
8217 const void* binary = GetSharedMemoryAs<const void*>(
8218 c.binary_shm_id, c.binary_shm_offset, length);
8219 if (shaders == NULL || binary == NULL) {
8220 return error::kOutOfBounds;
8221 }
8222 scoped_array<GLuint> service_ids(new GLuint[n]);
8223 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:038224 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
8225 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:438226 SetGLError(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
[email protected]b273e432010-04-12 17:23:588227 return error::kNoError;
8228 }
[email protected]ae51d192010-04-27 00:48:038229 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:588230 }
8231 // TODO(gman): call glShaderBinary
8232 return error::kNoError;
8233#endif
8234}
8235
[email protected]6217d392010-03-25 22:08:358236error::Error GLES2DecoderImpl::HandleSwapBuffers(
8237 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:498238 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
[email protected]a7266a92012-06-28 02:11:088239 if (!is_offscreen && surface_->DeferSwapBuffers()) {
8240 return error::kDeferCommandUntilLater;
8241 }
8242
[email protected]64ace852011-05-19 21:49:498243 int this_frame_number = frame_number_++;
[email protected]64ace852011-05-19 21:49:498244 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
8245 "offscreen", is_offscreen,
8246 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:358247 // If offscreen then don't actually SwapBuffers to the display. Just copy
8248 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:498249 if (is_offscreen) {
[email protected]1fb8c482011-08-31 01:01:538250 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
8251 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
8252 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
8253 // fix this.
8254 if (needs_mac_nvidia_driver_workaround_) {
8255 offscreen_saved_frame_buffer_->Create();
8256 glFinish();
8257 }
8258
8259 // Allocate the offscreen saved color texture.
8260 DCHECK(offscreen_saved_color_format_);
8261 offscreen_saved_color_texture_->AllocateStorage(
8262 offscreen_size_, offscreen_saved_color_format_);
[email protected]260ddc4e2012-06-28 00:01:538263 TRACE_BACKBUFFER_MEMORY_TOTAL(this);
[email protected]1fb8c482011-08-31 01:01:538264
8265 offscreen_saved_frame_buffer_->AttachRenderTexture(
8266 offscreen_saved_color_texture_.get());
8267 if (offscreen_saved_frame_buffer_->CheckStatus() !=
8268 GL_FRAMEBUFFER_COMPLETE) {
8269 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
8270 << "because offscreen saved FBO was incomplete.";
8271 return error::kLostContext;
8272 }
8273
[email protected]1fb8c482011-08-31 01:01:538274 // Clear the offscreen color texture.
8275 // TODO(piman): Is this still necessary?
8276 {
8277 ScopedFrameBufferBinder binder(this,
8278 offscreen_saved_frame_buffer_->id());
8279 glClearColor(0, 0, 0, 0);
8280 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
8281 glDisable(GL_SCISSOR_TEST);
8282 glClear(GL_COLOR_BUFFER_BIT);
8283 RestoreClearState();
8284 }
8285
8286 UpdateParentTextureInfo();
8287 }
8288
[email protected]6217d392010-03-25 22:08:358289 ScopedGLErrorSuppressor suppressor(this);
8290
[email protected]34ff8b0c2010-10-01 20:06:028291 if (IsOffscreenBufferMultisampled()) {
[email protected]51411e32012-01-19 20:21:138292 // For multisampled buffers, resolve the frame buffer.
[email protected]de26b3c2011-08-03 21:54:278293 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]89d6ed02011-04-20 00:23:238294 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:488295 } else {
[email protected]069944672012-04-25 20:52:238296 ScopedFrameBufferBinder binder(this,
8297 offscreen_target_frame_buffer_->id());
[email protected]51411e32012-01-19 20:21:138298
[email protected]069944672012-04-25 20:52:238299 if (offscreen_target_buffer_preserved_) {
8300 // Copy the target frame buffer to the saved offscreen texture.
8301 offscreen_saved_color_texture_->Copy(
8302 offscreen_saved_color_texture_->size(),
8303 offscreen_saved_color_format_);
8304 } else {
8305 // Flip the textures in the parent context via the texture manager.
8306 if (!!offscreen_saved_color_texture_info_.get())
8307 offscreen_saved_color_texture_info_->
8308 SetServiceId(offscreen_target_color_texture_->id());
[email protected]8a61d872012-01-20 12:43:568309
[email protected]069944672012-04-25 20:52:238310 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
8311 offscreen_target_frame_buffer_->AttachRenderTexture(
8312 offscreen_target_color_texture_.get());
[email protected]b86b14982010-10-11 18:45:488313 }
[email protected]069944672012-04-25 20:52:238314
8315 // Ensure the side effects of the copy are visible to the parent
8316 // context. There is no need to do this for ANGLE because it uses a
8317 // single D3D device for all contexts.
8318 if (!IsAngle())
8319 glFlush();
[email protected]89d6ed02011-04-20 00:23:238320 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:398321 }
[email protected]6217d392010-03-25 22:08:358322 } else {
[email protected]64ace852011-05-19 21:49:498323 TRACE_EVENT1("gpu", "GLContext::SwapBuffers", "frame", this_frame_number);
[email protected]f62a5ab2011-05-23 20:34:158324 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:018325 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:028326 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:018327 }
[email protected]6217d392010-03-25 22:08:358328 }
8329
[email protected]89d6ed02011-04-20 00:23:238330 return error::kNoError;
[email protected]6217d392010-03-25 22:08:358331}
8332
[email protected]d4239852011-08-12 04:51:228333error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
8334 uint32 immediate_data_size, const gles2::EnableFeatureCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:188335 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:288336 if (!bucket || bucket->size() == 0) {
8337 return error::kInvalidArguments;
8338 }
[email protected]d4239852011-08-12 04:51:228339 typedef gles2::EnableFeatureCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:188340 Result* result = GetSharedMemoryAs<Result*>(
8341 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8342 if (!result) {
8343 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:108344 }
[email protected]b1d2dcb2010-05-17 19:24:188345 // Check that the client initialized the result.
8346 if (*result != 0) {
8347 return error::kInvalidArguments;
8348 }
8349 std::string feature_str;
8350 if (!bucket->GetAsString(&feature_str)) {
8351 return error::kInvalidArguments;
8352 }
8353
8354 // TODO(gman): make this some kind of table to function pointer thingy.
[email protected]d4239852011-08-12 04:51:228355 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
[email protected]b1d2dcb2010-05-17 19:24:188356 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]d4239852011-08-12 04:51:228357 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
[email protected]8fbedc02010-11-18 18:43:408358 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
8359 // TODO(gman): decide how to remove the need for this const_cast.
8360 // I could make validators_ non const but that seems bad as this is the only
8361 // place it is needed. I could make some special friend class of validators
8362 // just to allow this to set them. That seems silly. I could refactor this
8363 // code to use the extension mechanism or the initialization attributes to
8364 // turn this feature on. Given that the only real point of this is to make
8365 // the conformance tests pass and given that there is lots of real work that
8366 // needs to be done it seems like refactoring for one to one of those
8367 // methods is a very low priority.
8368 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]f0d74742011-10-03 16:31:048369 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
8370 force_webgl_glsl_validation_ = true;
8371 InitializeShaderTranslator();
[email protected]b1d2dcb2010-05-17 19:24:188372 } else {
8373 return error::kNoError;
8374 }
8375
8376 *result = 1; // true.
8377 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:108378}
8379
[email protected]c2f8c8402010-12-06 18:07:248380error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
8381 uint32 immediate_data_size,
8382 const gles2::GetRequestableExtensionsCHROMIUM& c) {
8383 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]80eb6b52012-01-19 00:14:418384 FeatureInfo::Ref info(new FeatureInfo());
[email protected]e82fb792011-09-22 00:33:298385 info->Initialize(disallowed_features_, NULL);
[email protected]c2f8c8402010-12-06 18:07:248386 bucket->SetFromString(info->extensions().c_str());
8387 return error::kNoError;
8388}
8389
8390error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
8391 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
8392 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:288393 if (!bucket || bucket->size() == 0) {
8394 return error::kInvalidArguments;
8395 }
[email protected]c2f8c8402010-12-06 18:07:248396 std::string feature_str;
8397 if (!bucket->GetAsString(&feature_str)) {
8398 return error::kInvalidArguments;
8399 }
8400
8401 bool std_derivatives_enabled =
8402 feature_info_->feature_flags().oes_standard_derivatives;
8403 bool webglsl_enabled =
8404 feature_info_->feature_flags().chromium_webglsl;
8405
8406 feature_info_->AddFeatures(feature_str.c_str());
8407
[email protected]f0d74742011-10-03 16:31:048408 bool initialization_required = false;
8409 if (force_webgl_glsl_validation_ && !derivatives_explicitly_enabled_) {
8410 size_t derivatives_offset = feature_str.find(kOESDerivativeExtension);
8411 if (std::string::npos != derivatives_offset) {
8412 derivatives_explicitly_enabled_ = true;
8413 initialization_required = true;
8414 }
8415 }
8416
[email protected]c2f8c8402010-12-06 18:07:248417 // If we just enabled a feature which affects the shader translator,
8418 // we may need to re-initialize it.
8419 if (std_derivatives_enabled !=
8420 feature_info_->feature_flags().oes_standard_derivatives ||
8421 webglsl_enabled !=
[email protected]f0d74742011-10-03 16:31:048422 feature_info_->feature_flags().chromium_webglsl ||
8423 initialization_required) {
[email protected]c2f8c8402010-12-06 18:07:248424 InitializeShaderTranslator();
8425 }
8426
[email protected]302ce6d2011-07-07 23:28:118427 UpdateCapabilities();
8428
[email protected]c2f8c8402010-12-06 18:07:248429 return error::kNoError;
8430}
8431
[email protected]372e0412011-06-28 16:08:568432error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
8433 uint32 immediate_data_size, const gles2::GetMultipleIntegervCHROMIUM& c) {
8434 GLuint count = c.count;
8435 uint32 pnames_size;
8436 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
8437 return error::kOutOfBounds;
8438 }
8439 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
8440 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
8441 if (pnames == NULL) {
8442 return error::kOutOfBounds;
8443 }
8444
8445 // We have to copy them since we use them twice so the client
8446 // can't change them between the time we validate them and the time we use
8447 // them.
8448 scoped_array<GLenum> enums(new GLenum[count]);
8449 memcpy(enums.get(), pnames, pnames_size);
8450
8451 // Count up the space needed for the result.
8452 uint32 num_results = 0;
8453 for (GLuint ii = 0; ii < count; ++ii) {
8454 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
8455 if (num == 0) {
8456 SetGLError(GL_INVALID_ENUM,
[email protected]ad84a3a2012-06-08 21:42:438457 "glGetMulitpleCHROMIUM", "pname GL_INVALID_ENUM");
[email protected]372e0412011-06-28 16:08:568458 return error::kNoError;
8459 }
8460 // Num will never be more than 4.
8461 DCHECK_LE(num, 4u);
8462 if (!SafeAdd(num_results, num, &num_results)) {
8463 return error::kOutOfBounds;
8464 }
8465 }
8466
8467 uint32 result_size = 0;
8468 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
8469 return error::kOutOfBounds;
8470 }
8471
8472 if (result_size != static_cast<uint32>(c.size)) {
8473 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438474 "glGetMulitpleCHROMIUM", "bad size GL_INVALID_VALUE");
[email protected]372e0412011-06-28 16:08:568475 return error::kNoError;
8476 }
8477
8478 GLint* results = GetSharedMemoryAs<GLint*>(
8479 c.results_shm_id, c.results_shm_offset, result_size);
8480 if (results == NULL) {
8481 return error::kOutOfBounds;
8482 }
8483
8484 // Check the results have been cleared in case the context was lost.
8485 for (uint32 ii = 0; ii < num_results; ++ii) {
8486 if (results[ii]) {
8487 return error::kInvalidArguments;
8488 }
8489 }
8490
8491 // Get each result.
8492 GLint* start = results;
8493 for (GLuint ii = 0; ii < count; ++ii) {
8494 GLsizei num_written = 0;
8495 if (!GetHelper(enums[ii], results, &num_written)) {
8496 glGetIntegerv(enums[ii], results);
8497 }
8498 results += num_written;
8499 }
8500
8501 // Just to verify. Should this be a DCHECK?
8502 if (static_cast<uint32>(results - start) != num_results) {
8503 return error::kOutOfBounds;
8504 }
8505
8506 return error::kNoError;
8507}
8508
[email protected]2318d342011-07-11 22:27:428509error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
8510 uint32 immediate_data_size, const gles2::GetProgramInfoCHROMIUM& c) {
8511 GLuint program = static_cast<GLuint>(c.program);
8512 uint32 bucket_id = c.bucket_id;
8513 Bucket* bucket = CreateBucket(bucket_id);
8514 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
8515 ProgramManager::ProgramInfo* info = NULL;
[email protected]9a14ae612011-08-08 17:51:468516 info = GetProgramInfo(program);
8517 if (!info || !info->IsValid()) {
8518 return error::kNoError;
[email protected]2318d342011-07-11 22:27:428519 }
[email protected]5d4c6b22012-02-07 08:22:288520 info->GetProgramInfo(program_manager(), bucket);
[email protected]2318d342011-07-11 22:27:428521 return error::kNoError;
8522}
8523
[email protected]38d139d2011-07-14 00:38:438524error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
8525 switch (reset_status_) {
[email protected]ad84a3a2012-06-08 21:42:438526 case GL_NO_ERROR:
8527 // TODO(kbr): improve the precision of the error code in this case.
8528 // Consider delegating to context for error code if MakeCurrent fails.
8529 return error::kUnknown;
8530 case GL_GUILTY_CONTEXT_RESET_ARB:
8531 return error::kGuilty;
8532 case GL_INNOCENT_CONTEXT_RESET_ARB:
8533 return error::kInnocent;
8534 case GL_UNKNOWN_CONTEXT_RESET_ARB:
8535 return error::kUnknown;
[email protected]38d139d2011-07-14 00:38:438536 }
8537
8538 NOTREACHED();
8539 return error::kUnknown;
8540}
8541
8542bool GLES2DecoderImpl::WasContextLost() {
8543 if (context_->WasAllocatedUsingARBRobustness() && has_arb_robustness_) {
8544 GLenum status = glGetGraphicsResetStatusARB();
8545 if (status != GL_NO_ERROR) {
8546 // The graphics card was reset. Signal a lost context to the application.
8547 reset_status_ = status;
8548 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
8549 << " context lost via ARB_robustness. Reset status = 0x"
8550 << std::hex << status << std::dec;
8551 return true;
8552 }
8553 }
8554 return false;
8555}
8556
[email protected]882ba1e22012-03-08 19:02:538557bool GLES2DecoderImpl::GenQueriesEXTHelper(
8558 GLsizei n, const GLuint* client_ids) {
8559 for (GLsizei ii = 0; ii < n; ++ii) {
8560 if (query_manager_->GetQuery(client_ids[ii])) {
8561 return false;
8562 }
8563 }
[email protected]c45f1972012-03-14 07:27:368564 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
[email protected]882ba1e22012-03-08 19:02:538565 return true;
8566}
8567
8568void GLES2DecoderImpl::DeleteQueriesEXTHelper(
8569 GLsizei n, const GLuint* client_ids) {
8570 for (GLsizei ii = 0; ii < n; ++ii) {
8571 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
8572 if (query && !query->IsDeleted()) {
8573 if (query == current_query_) {
8574 current_query_ = NULL;
8575 }
[email protected]c45f1972012-03-14 07:27:368576 query->Destroy(true);
[email protected]882ba1e22012-03-08 19:02:538577 query_manager_->RemoveQuery(client_ids[ii]);
8578 }
8579 }
8580}
8581
[email protected]22e3f552012-03-13 01:54:198582bool GLES2DecoderImpl::ProcessPendingQueries() {
8583 if (query_manager_.get() == NULL) {
8584 return false;
8585 }
[email protected]c45f1972012-03-14 07:27:368586 if (!query_manager_->ProcessPendingQueries()) {
[email protected]22e3f552012-03-13 01:54:198587 current_decoder_error_ = error::kOutOfBounds;
8588 }
8589 return query_manager_->HavePendingQueries();
8590}
8591
[email protected]882ba1e22012-03-08 19:02:538592error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
8593 uint32 immediate_data_size, const gles2::BeginQueryEXT& c) {
8594 GLenum target = static_cast<GLenum>(c.target);
8595 GLuint client_id = static_cast<GLuint>(c.id);
8596 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
8597 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
8598
[email protected]c45f1972012-03-14 07:27:368599 switch (target) {
8600 case GL_COMMANDS_ISSUED_CHROMIUM:
8601 break;
8602 default:
8603 if (!feature_info_->feature_flags().occlusion_query_boolean) {
[email protected]ad84a3a2012-06-08 21:42:438604 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT", "not enabled");
[email protected]c45f1972012-03-14 07:27:368605 return error::kNoError;
8606 }
8607 break;
[email protected]882ba1e22012-03-08 19:02:538608 }
8609
8610 if (current_query_) {
8611 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:438612 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
[email protected]882ba1e22012-03-08 19:02:538613 return error::kNoError;
8614 }
8615
8616 if (client_id == 0) {
[email protected]ad84a3a2012-06-08 21:42:438617 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
[email protected]882ba1e22012-03-08 19:02:538618 return error::kNoError;
8619 }
8620
8621 QueryManager::Query* query = query_manager_->GetQuery(client_id);
8622 if (!query) {
[email protected]c45f1972012-03-14 07:27:368623 // TODO(gman): Decide if we need this check.
8624 //
[email protected]882ba1e22012-03-08 19:02:538625 // Checks id was made by glGenQueries
[email protected]c45f1972012-03-14 07:27:368626 //
8627 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
8628 // for all Query ids but from the POV of the command buffer service maybe
8629 // you don't.
8630 //
8631 // The client can enforce this. I don't think the service cares.
8632 //
8633 // IdAllocatorInterface* id_allocator =
8634 // group_->GetIdAllocator(id_namespaces::kQueries);
8635 // if (!id_allocator->InUse(client_id)) {
8636 // SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438637 // "glBeginQueryEXT", "id not made by glGenQueriesEXT");
[email protected]c45f1972012-03-14 07:27:368638 // return error::kNoError;
8639 // }
8640 query = query_manager_->CreateQuery(
8641 target, client_id, sync_shm_id, sync_shm_offset);
[email protected]882ba1e22012-03-08 19:02:538642 }
8643
[email protected]c45f1972012-03-14 07:27:368644 if (query->target() != target) {
[email protected]ad84a3a2012-06-08 21:42:438645 SetGLError(
8646 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
[email protected]882ba1e22012-03-08 19:02:538647 return error::kNoError;
8648 } else if (query->shm_id() != sync_shm_id ||
8649 query->shm_offset() != sync_shm_offset) {
8650 DLOG(ERROR) << "Shared memory used by query not the same as before";
8651 return error::kInvalidArguments;
8652 }
8653
[email protected]c45f1972012-03-14 07:27:368654 if (!query_manager_->BeginQuery(query)) {
8655 return error::kOutOfBounds;
8656 }
[email protected]882ba1e22012-03-08 19:02:538657
[email protected]882ba1e22012-03-08 19:02:538658 current_query_ = query;
[email protected]882ba1e22012-03-08 19:02:538659 return error::kNoError;
8660}
8661
8662error::Error GLES2DecoderImpl::HandleEndQueryEXT(
8663 uint32 immediate_data_size, const gles2::EndQueryEXT& c) {
8664 GLenum target = static_cast<GLenum>(c.target);
8665 uint32 submit_count = static_cast<GLuint>(c.submit_count);
8666
8667 if (!current_query_) {
[email protected]ad84a3a2012-06-08 21:42:438668 SetGLError(GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
[email protected]882ba1e22012-03-08 19:02:538669 return error::kNoError;
8670 }
8671 if (current_query_->target() != target) {
8672 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438673 "glEndQueryEXT", "target does not match active query");
[email protected]882ba1e22012-03-08 19:02:538674 return error::kNoError;
8675 }
[email protected]882ba1e22012-03-08 19:02:538676
[email protected]c45f1972012-03-14 07:27:368677 if (!query_manager_->EndQuery(current_query_, submit_count)) {
8678 return error::kOutOfBounds;
8679 }
8680
8681 current_query_ = NULL;
[email protected]882ba1e22012-03-08 19:02:538682 return error::kNoError;
8683}
8684
[email protected]b0af4f52011-09-28 22:04:428685error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
8686 uint32 immediate_data_size,
8687 const gles2::CreateStreamTextureCHROMIUM& c) {
8688 if (!feature_info_->feature_flags().chromium_stream_texture) {
8689 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438690 "glOpenStreamTextureCHROMIUM", ""
[email protected]b0af4f52011-09-28 22:04:428691 "not supported.");
8692 return error::kNoError;
8693 }
8694
8695 uint32 client_id = c.client_id;
8696 typedef gles2::CreateStreamTextureCHROMIUM::Result Result;
8697 Result* result = GetSharedMemoryAs<Result*>(
8698 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8699
[email protected]e5081262012-01-05 23:09:038700 if (!result)
8701 return error::kOutOfBounds;
[email protected]b0af4f52011-09-28 22:04:428702 *result = GL_ZERO;
8703 TextureManager::TextureInfo* info =
8704 texture_manager()->GetTextureInfo(client_id);
8705 if (!info) {
8706 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438707 "glCreateStreamTextureCHROMIUM", ""
[email protected]b0af4f52011-09-28 22:04:428708 "bad texture id.");
8709 return error::kNoError;
8710 }
8711
8712 if (info->IsStreamTexture()) {
8713 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438714 "glCreateStreamTextureCHROMIUM", ""
[email protected]b0af4f52011-09-28 22:04:428715 "is already a stream texture.");
8716 return error::kNoError;
8717 }
8718
8719 if (info->target() && info->target() != GL_TEXTURE_EXTERNAL_OES) {
8720 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438721 "glCreateStreamTextureCHROMIUM", ""
[email protected]b0af4f52011-09-28 22:04:428722 "is already bound to incompatible target.");
8723 return error::kNoError;
8724 }
8725
8726 if (!stream_texture_manager_)
8727 return error::kInvalidArguments;
8728
8729 GLuint object_id = stream_texture_manager_->CreateStreamTexture(
8730 info->service_id(), client_id);
8731
8732 if (object_id) {
8733 info->SetStreamTexture(true);
8734 } else {
8735 SetGLError(GL_OUT_OF_MEMORY,
[email protected]ad84a3a2012-06-08 21:42:438736 "glCreateStreamTextureCHROMIUM", ""
[email protected]b0af4f52011-09-28 22:04:428737 "failed to create platform texture.");
8738 }
8739
8740 *result = object_id;
8741 return error::kNoError;
8742}
8743
8744error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
8745 uint32 immediate_data_size,
8746 const gles2::DestroyStreamTextureCHROMIUM& c) {
8747 GLuint client_id = c.texture;
8748 TextureManager::TextureInfo* info =
8749 texture_manager()->GetTextureInfo(client_id);
8750 if (info && info->IsStreamTexture()) {
8751 if (!stream_texture_manager_)
8752 return error::kInvalidArguments;
8753
8754 stream_texture_manager_->DestroyStreamTexture(info->service_id());
8755 info->SetStreamTexture(false);
[email protected]80eb6b52012-01-19 00:14:418756 texture_manager()->SetInfoTarget(info, 0);
[email protected]b0af4f52011-09-28 22:04:428757 } else {
8758 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438759 "glDestroyStreamTextureCHROMIUM", "bad texture id.");
[email protected]b0af4f52011-09-28 22:04:428760 }
8761
8762 return error::kNoError;
8763}
8764
[email protected]e51bdf32011-11-23 22:21:468765#if defined(OS_MACOSX)
8766void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
8767 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
8768 texture_id);
8769 if (it != texture_to_io_surface_map_.end()) {
8770 // Found a previous IOSurface bound to this texture; release it.
8771 CFTypeRef surface = it->second;
8772 CFRelease(surface);
8773 texture_to_io_surface_map_.erase(it);
8774 }
8775}
8776#endif
8777
8778void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
8779 GLenum target, GLsizei width, GLsizei height,
8780 GLuint io_surface_id, GLuint plane) {
8781#if defined(OS_MACOSX)
8782 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
[email protected]ad84a3a2012-06-08 21:42:438783 SetGLError(
8784 GL_INVALID_OPERATION,
8785 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
[email protected]e51bdf32011-11-23 22:21:468786 return;
8787 }
8788
8789 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
8790 if (!surface_support) {
8791 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438792 "glTexImageIOSurface2DCHROMIUM", "only supported on 10.6.");
[email protected]e51bdf32011-11-23 22:21:468793 return;
8794 }
8795
8796 if (target != GL_TEXTURE_RECTANGLE_ARB) {
8797 // This might be supported in the future, and if we could require
8798 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
8799 // could delete a lot of code. For now, perform strict validation so we
8800 // know what's going on.
8801 SetGLError(
8802 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438803 "glTexImageIOSurface2DCHROMIUM",
8804 "requires TEXTURE_RECTANGLE_ARB target");
[email protected]e51bdf32011-11-23 22:21:468805 return;
8806 }
8807
8808 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8809 if (!info) {
8810 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438811 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
[email protected]e51bdf32011-11-23 22:21:468812 return;
8813 }
8814 if (info == texture_manager()->GetDefaultTextureInfo(target)) {
8815 // Maybe this is conceptually valid, but disallow it to avoid accidents.
8816 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438817 "glTexImageIOSurface2DCHROMIUM", "can't bind default texture");
[email protected]e51bdf32011-11-23 22:21:468818 return;
8819 }
8820
8821 // Look up the new IOSurface. Note that because of asynchrony
8822 // between processes this might fail; during live resizing the
8823 // plugin process might allocate and release an IOSurface before
8824 // this process gets a chance to look it up. Hold on to any old
8825 // IOSurface in this case.
8826 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
8827 if (!surface) {
[email protected]ad84a3a2012-06-08 21:42:438828 SetGLError(
8829 GL_INVALID_OPERATION,
8830 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
[email protected]e51bdf32011-11-23 22:21:468831 return;
8832 }
8833
8834 // Release any IOSurface previously bound to this texture.
8835 ReleaseIOSurfaceForTexture(info->service_id());
8836
8837 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
8838 texture_to_io_surface_map_.insert(
8839 std::make_pair(info->service_id(), surface));
8840
8841 CGLContextObj context =
8842 static_cast<CGLContextObj>(context_->GetHandle());
8843
8844 CGLError err = surface_support->CGLTexImageIOSurface2D(
8845 context,
8846 target,
8847 GL_RGBA,
8848 width,
8849 height,
8850 GL_BGRA,
8851 GL_UNSIGNED_INT_8_8_8_8_REV,
8852 surface,
8853 plane);
8854
8855 if (err != kCGLNoError) {
8856 SetGLError(
8857 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438858 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
[email protected]e51bdf32011-11-23 22:21:468859 return;
8860 }
8861
8862 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:418863 info, target, 0, GL_RGBA, width, height, 1, 0,
[email protected]e51bdf32011-11-23 22:21:468864 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
8865
8866#else
8867 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438868 "glTexImageIOSurface2DCHROMIUM", "not supported.");
[email protected]e51bdf32011-11-23 22:21:468869#endif
8870}
8871
[email protected]97dc7cbe2011-12-06 17:26:178872static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
8873 switch (internalformat) {
8874 case GL_RGB565:
8875 return GL_RGB;
8876 case GL_RGBA4:
8877 return GL_RGBA;
8878 case GL_RGB5_A1:
8879 return GL_RGBA;
8880 case GL_RGB8_OES:
8881 return GL_RGB;
8882 case GL_RGBA8_OES:
8883 return GL_RGBA;
8884 case GL_LUMINANCE8_ALPHA8_EXT:
8885 return GL_LUMINANCE_ALPHA;
8886 case GL_LUMINANCE8_EXT:
8887 return GL_LUMINANCE;
8888 case GL_ALPHA8_EXT:
8889 return GL_ALPHA;
8890 case GL_RGBA32F_EXT:
8891 return GL_RGBA;
8892 case GL_RGB32F_EXT:
8893 return GL_RGB;
8894 case GL_ALPHA32F_EXT:
8895 return GL_ALPHA;
8896 case GL_LUMINANCE32F_EXT:
8897 return GL_LUMINANCE;
8898 case GL_LUMINANCE_ALPHA32F_EXT:
8899 return GL_LUMINANCE_ALPHA;
8900 case GL_RGBA16F_EXT:
8901 return GL_RGBA;
8902 case GL_RGB16F_EXT:
8903 return GL_RGB;
8904 case GL_ALPHA16F_EXT:
8905 return GL_ALPHA;
8906 case GL_LUMINANCE16F_EXT:
8907 return GL_LUMINANCE;
8908 case GL_LUMINANCE_ALPHA16F_EXT:
8909 return GL_LUMINANCE_ALPHA;
8910 case GL_BGRA8_EXT:
8911 return GL_BGRA_EXT;
8912 default:
8913 return GL_NONE;
8914 }
8915}
8916
[email protected]43410e92012-04-20 17:06:288917void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
[email protected]0a1e9ad2012-05-04 21:13:038918 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
8919 GLenum internal_format) {
[email protected]43410e92012-04-20 17:06:288920 TextureManager::TextureInfo* dest_info = GetTextureInfo(dest_id);
8921 TextureManager::TextureInfo* source_info = GetTextureInfo(source_id);
8922
8923 if (!source_info || !dest_info) {
[email protected]ad84a3a2012-06-08 21:42:438924 SetGLError(GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
[email protected]43410e92012-04-20 17:06:288925 return;
8926 }
8927
8928 if (GL_TEXTURE_2D != target) {
8929 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438930 "glCopyTextureCHROMIUM", "invalid texture target");
[email protected]43410e92012-04-20 17:06:288931 return;
8932 }
8933
[email protected]0a1e9ad2012-05-04 21:13:038934 if (dest_info->target() != GL_TEXTURE_2D ||
8935 source_info->target() != GL_TEXTURE_2D) {
8936 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438937 "glCopyTextureCHROMIUM", "invalid texture target binding");
[email protected]0a1e9ad2012-05-04 21:13:038938 return;
8939 }
8940
[email protected]43410e92012-04-20 17:06:288941 int source_width, source_height, dest_width, dest_height;
8942 if (!source_info->GetLevelSize(GL_TEXTURE_2D, 0, &source_width,
8943 &source_height)) {
8944 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438945 "glCopyTextureChromium", "source texture has no level 0");
[email protected]43410e92012-04-20 17:06:288946 return;
8947 }
8948
[email protected]43410e92012-04-20 17:06:288949 // Check that this type of texture is allowed.
8950 if (!texture_manager()->ValidForTarget(GL_TEXTURE_2D, level, source_width,
8951 source_height, 1)) {
8952 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438953 "glCopyTextureCHROMIUM", "Bad dimensions");
[email protected]43410e92012-04-20 17:06:288954 return;
8955 }
8956
[email protected]cf6b8f62012-05-25 21:43:378957 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
8958 // needed because it takes 10s of milliseconds to initialize.
8959 if (!copy_texture_CHROMIUM_.get()) {
8960 CopyRealGLErrorsToWrapper();
8961 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
8962 copy_texture_CHROMIUM_->Initialize();
8963 RestoreCurrentFramebufferBindings();
8964 if (PeekGLError() != GL_NO_ERROR)
8965 return;
8966 }
8967
[email protected]0a1e9ad2012-05-04 21:13:038968 GLenum dest_type;
8969 GLenum dest_internal_format;
8970 bool dest_level_defined = dest_info->GetLevelSize(GL_TEXTURE_2D, level,
8971 &dest_width,
8972 &dest_height);
[email protected]43410e92012-04-20 17:06:288973
[email protected]0a1e9ad2012-05-04 21:13:038974 if (dest_level_defined) {
8975 dest_info->GetLevelType(GL_TEXTURE_2D, level, &dest_type,
8976 &dest_internal_format);
8977 } else {
8978 GLenum source_internal_format;
8979 source_info->GetLevelType(GL_TEXTURE_2D, 0, &dest_type,
8980 &source_internal_format);
8981 }
8982
8983 // Resize the destination texture to the dimensions of the source texture.
8984 if (!dest_level_defined || dest_width != source_width ||
8985 dest_height != source_height ||
8986 dest_internal_format != internal_format) {
[email protected]43410e92012-04-20 17:06:288987 // Ensure that the glTexImage2D succeeds.
8988 CopyRealGLErrorsToWrapper();
[email protected]0a1e9ad2012-05-04 21:13:038989 glBindTexture(GL_TEXTURE_2D, dest_info->service_id());
[email protected]43410e92012-04-20 17:06:288990 WrappedTexImage2D(
8991 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
[email protected]0a1e9ad2012-05-04 21:13:038992 0, internal_format, dest_type, NULL);
[email protected]43410e92012-04-20 17:06:288993 GLenum error = PeekGLError();
[email protected]0a1e9ad2012-05-04 21:13:038994 if (error != GL_NO_ERROR) {
8995 RestoreCurrentTexture2DBindings();
[email protected]43410e92012-04-20 17:06:288996 return;
[email protected]0a1e9ad2012-05-04 21:13:038997 }
[email protected]43410e92012-04-20 17:06:288998
8999 texture_manager()->SetLevelInfo(
9000 dest_info, GL_TEXTURE_2D, level, internal_format, source_width,
[email protected]0a1e9ad2012-05-04 21:13:039001 source_height, 1, 0, internal_format, dest_type, true);
[email protected]f7024712012-05-15 21:30:259002 } else {
9003 texture_manager()->SetLevelCleared(dest_info, GL_TEXTURE_2D, level);
[email protected]43410e92012-04-20 17:06:289004 }
9005
9006 state_dirty_ = true;
[email protected]0a1e9ad2012-05-04 21:13:039007 glViewport(0, 0, source_width, source_height);
[email protected]43410e92012-04-20 17:06:289008 copy_texture_CHROMIUM_->DoCopyTexture(target, source_info->service_id(),
9009 dest_info->service_id(), level,
9010 unpack_flip_y_,
[email protected]6c75c712012-06-19 15:43:179011 unpack_premultiply_alpha_,
9012 unpack_unpremultiply_alpha_);
[email protected]43410e92012-04-20 17:06:289013 glViewport(viewport_x_, viewport_y_, viewport_width_, viewport_height_);
9014
9015 // Restore all of the state touched by the extension.
9016 if (current_program_)
9017 glUseProgram(current_program_->service_id());
9018 else
9019 glUseProgram(0);
9020
9021 RestoreCurrentFramebufferBindings();
9022 RestoreCurrentTexture2DBindings();
9023 RestoreStateForAttrib(
9024 CopyTextureCHROMIUMResourceManager::kVertexPositionAttrib);
9025 RestoreStateForAttrib(
9026 CopyTextureCHROMIUMResourceManager::kVertexTextureAttrib);
9027
9028 ApplyDirtyState();
9029}
9030
[email protected]97dc7cbe2011-12-06 17:26:179031static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
9032 switch (internalformat) {
9033 case GL_RGB565:
9034 return GL_UNSIGNED_SHORT_5_6_5;
9035 case GL_RGBA4:
9036 return GL_UNSIGNED_SHORT_4_4_4_4;
9037 case GL_RGB5_A1:
9038 return GL_UNSIGNED_SHORT_5_5_5_1;
9039 case GL_RGB8_OES:
9040 return GL_UNSIGNED_BYTE;
9041 case GL_RGBA8_OES:
9042 return GL_UNSIGNED_BYTE;
9043 case GL_LUMINANCE8_ALPHA8_EXT:
9044 return GL_UNSIGNED_BYTE;
9045 case GL_LUMINANCE8_EXT:
9046 return GL_UNSIGNED_BYTE;
9047 case GL_ALPHA8_EXT:
9048 return GL_UNSIGNED_BYTE;
9049 case GL_RGBA32F_EXT:
9050 return GL_FLOAT;
9051 case GL_RGB32F_EXT:
9052 return GL_FLOAT;
9053 case GL_ALPHA32F_EXT:
9054 return GL_FLOAT;
9055 case GL_LUMINANCE32F_EXT:
9056 return GL_FLOAT;
9057 case GL_LUMINANCE_ALPHA32F_EXT:
9058 return GL_FLOAT;
9059 case GL_RGBA16F_EXT:
9060 return GL_HALF_FLOAT_OES;
9061 case GL_RGB16F_EXT:
9062 return GL_HALF_FLOAT_OES;
9063 case GL_ALPHA16F_EXT:
9064 return GL_HALF_FLOAT_OES;
9065 case GL_LUMINANCE16F_EXT:
9066 return GL_HALF_FLOAT_OES;
9067 case GL_LUMINANCE_ALPHA16F_EXT:
9068 return GL_HALF_FLOAT_OES;
9069 case GL_BGRA8_EXT:
9070 return GL_UNSIGNED_BYTE;
9071 default:
9072 return GL_NONE;
9073 }
9074}
9075
9076void GLES2DecoderImpl::DoTexStorage2DEXT(
[email protected]a5d3dad2012-05-26 04:34:449077 GLenum target,
9078 GLint levels,
9079 GLenum internal_format,
9080 GLsizei width,
9081 GLsizei height) {
[email protected]43ed3a72012-05-30 22:55:389082 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
[email protected]80eb6b52012-01-19 00:14:419083 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
[email protected]97dc7cbe2011-12-06 17:26:179084 TextureManager::ComputeMipMapCount(width, height, 1) < levels) {
[email protected]ad84a3a2012-06-08 21:42:439085 SetGLError(
9086 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
[email protected]97dc7cbe2011-12-06 17:26:179087 return;
9088 }
9089 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
9090 if (!info) {
9091 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439092 "glTexStorage2DEXT", "unknown texture for target");
[email protected]97dc7cbe2011-12-06 17:26:179093 return;
9094 }
9095 if (info->IsAttachedToFramebuffer()) {
9096 state_dirty_ = true;
9097 }
9098 if (info->IsImmutable()) {
9099 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439100 "glTexStorage2DEXT", "texture is immutable");
[email protected]97dc7cbe2011-12-06 17:26:179101 return;
9102 }
9103 CopyRealGLErrorsToWrapper();
[email protected]f0e6a34f2012-01-04 20:53:409104 glTexStorage2DEXT(target, levels, GetTexInternalFormat(internal_format),
9105 width, height);
[email protected]97dc7cbe2011-12-06 17:26:179106 GLenum error = PeekGLError();
9107 if (error == GL_NO_ERROR) {
9108 GLenum format = ExtractFormatFromStorageFormat(internal_format);
9109 GLenum type = ExtractTypeFromStorageFormat(internal_format);
[email protected]4502e6492011-12-14 19:39:159110 GLsizei level_width = width;
9111 GLsizei level_height = height;
9112 for (int ii = 0; ii < levels; ++ii) {
9113 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:419114 info, target, 0, format, level_width, level_height, 1, 0, format,
9115 type, false);
[email protected]4502e6492011-12-14 19:39:159116 level_width = std::max(1, level_width >> 1);
9117 level_height = std::max(1, level_height >> 1);
9118 }
[email protected]97dc7cbe2011-12-06 17:26:179119 info->SetImmutable(true);
9120 }
[email protected]97dc7cbe2011-12-06 17:26:179121}
[email protected]e51bdf32011-11-23 22:21:469122
[email protected]78b514b2012-05-01 21:50:599123error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
9124 uint32 immediate_data_size, const gles2::GenMailboxCHROMIUM& c) {
9125 MailboxName name;
9126 mailbox_manager()->GenerateMailboxName(&name);
9127 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
9128 Bucket* bucket = CreateBucket(bucket_id);
9129
9130 bucket->SetSize(GL_MAILBOX_SIZE_CHROMIUM);
9131 bucket->SetData(&name, 0, GL_MAILBOX_SIZE_CHROMIUM);
9132
9133 return error::kNoError;
9134}
9135
9136void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
9137 const GLbyte* mailbox) {
9138 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
9139 if (!info) {
9140 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439141 "glProduceTextureCHROMIUM", "unknown texture for target");
[email protected]78b514b2012-05-01 21:50:599142 return;
9143 }
9144
9145 TextureDefinition* definition = texture_manager()->Save(info);
9146 if (!definition) {
9147 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439148 "glProduceTextureCHROMIUM", "invalid texture");
[email protected]78b514b2012-05-01 21:50:599149 return;
9150 }
9151
9152 if (!group_->mailbox_manager()->ProduceTexture(
9153 target,
9154 *reinterpret_cast<const MailboxName*>(mailbox),
9155 definition,
9156 texture_manager())) {
9157 bool success = texture_manager()->Restore(info, definition);
9158 DCHECK(success);
9159 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439160 "glProduceTextureCHROMIUM", "invalid mailbox name");
[email protected]78b514b2012-05-01 21:50:599161 return;
9162 }
9163
9164 BindAndApplyTextureParameters(info);
9165}
9166
9167void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
9168 const GLbyte* mailbox) {
9169 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
9170 if (!info) {
9171 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439172 "glConsumeTextureCHROMIUM", "unknown texture for target");
[email protected]78b514b2012-05-01 21:50:599173 return;
9174 }
9175
9176 scoped_ptr<TextureDefinition> definition(
9177 group_->mailbox_manager()->ConsumeTexture(
9178 target,
9179 *reinterpret_cast<const MailboxName*>(mailbox)));
9180 if (!definition.get()) {
9181 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439182 "glConsumeTextureCHROMIUM", "invalid mailbox name");
[email protected]78b514b2012-05-01 21:50:599183 return;
9184 }
9185
9186 if (!texture_manager()->Restore(info, definition.release())) {
9187 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439188 "glConsumeTextureCHROMIUM", "invalid texture");
[email protected]78b514b2012-05-01 21:50:599189 return;
9190 }
9191
9192 BindAndApplyTextureParameters(info);
9193}
9194
[email protected]96449d2c2009-11-25 00:01:329195// Include the auto-generated part of this file. We split this because it means
9196// we can easily edit the non-auto generated parts right here in this file
9197// instead of having to edit some template or the code generator.
9198#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
9199
9200} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:259201} // namespace gpu