blob: 4b3c2c33d314dd5795b1200687238fd2405d002d [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]d37231fa2010-04-09 21:16:0225#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3226#define GLES2_GPU_SERVICE 1
27#include "gpu/command_buffer/common/gles2_cmd_format.h"
28#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1029#include "gpu/command_buffer/common/id_allocator.h"
[email protected]3916c97e2010-02-25 03:20:5030#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3231#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5032#include "gpu/command_buffer/service/context_group.h"
[email protected]915a59a12010-09-30 21:29:1133#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5834#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3235#include "gpu/command_buffer/service/gl_utils.h"
[email protected]43410e92012-04-20 17:06:2836#include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
[email protected]ba3176a2009-12-16 18:19:4637#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]e844ae22012-01-14 03:36:2638#include "gpu/command_buffer/service/gpu_switches.h"
[email protected]78b514b2012-05-01 21:50:5939#include "gpu/command_buffer/service/mailbox_manager.h"
[email protected]a93bb842010-02-16 23:03:4740#include "gpu/command_buffer/service/program_manager.h"
[email protected]882ba1e22012-03-08 19:02:5341#include "gpu/command_buffer/service/query_manager.h"
[email protected]a25fa872010-03-25 02:57:5842#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4743#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4544#include "gpu/command_buffer/service/shader_translator.h"
[email protected]b0af4f52011-09-28 22:04:4245#include "gpu/command_buffer/service/stream_texture.h"
46#include "gpu/command_buffer/service/stream_texture_manager.h"
[email protected]78b514b2012-05-01 21:50:5947#include "gpu/command_buffer/service/texture_definition.h"
[email protected]a93bb842010-02-16 23:03:4748#include "gpu/command_buffer/service/texture_manager.h"
[email protected]d8ea9772011-07-11 18:11:4349#include "gpu/command_buffer/service/vertex_attrib_manager.h"
[email protected]5ae0b282011-03-28 19:24:4950#include "ui/gfx/gl/gl_context.h"
51#include "ui/gfx/gl/gl_implementation.h"
[email protected]f62a5ab2011-05-23 20:34:1552#include "ui/gfx/gl/gl_surface.h"
[email protected]e51bdf32011-11-23 22:21:4653#if defined(OS_MACOSX)
[email protected]d353541f2012-05-03 22:45:4154#include "ui/surface/io_surface_support_mac.h"
[email protected]e51bdf32011-11-23 22:21:4655#endif
[email protected]de17df392010-04-23 21:09:4156
[email protected]6217d392010-03-25 22:08:3557#if !defined(GL_DEPTH24_STENCIL8)
58#define GL_DEPTH24_STENCIL8 0x88F0
59#endif
60
[email protected]a7a27ace2009-12-12 00:11:2561namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3262namespace gles2 {
63
[email protected]f0d74742011-10-03 16:31:0464namespace {
65static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
66}
67
[email protected]6217d392010-03-25 22:08:3568class GLES2DecoderImpl;
69
[email protected]07f54fcc2009-12-22 02:46:3070// Check that certain assumptions the code makes are true. There are places in
71// the code where shared memory is passed direclty to GL. Example, glUniformiv,
72// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
73// a few others) are 32bits. If they are not 32bits the code will have to change
74// to call those GL functions with service side memory and then copy the results
75// to shared memory, converting the sizes.
76COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
77 GLint_not_same_size_as_uint32);
78COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
79 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3780COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
81 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3082
[email protected]43f28f832010-02-03 02:28:4883// TODO(kbr): the use of this anonymous namespace core dumps the
84// linker on Mac OS X 10.6 when the symbol ordering file is used
85// namespace {
[email protected]96449d2c2009-11-25 00:01:3286
87// Returns the address of the first byte after a struct.
88template <typename T>
89const void* AddressAfterStruct(const T& pod) {
90 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
91}
92
[email protected]07f54fcc2009-12-22 02:46:3093// Returns the address of the frst byte after the struct or NULL if size >
94// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3295template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3096RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
97 uint32 size,
98 uint32 immediate_data_size) {
99 return (size <= immediate_data_size) ?
100 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
101 NULL;
[email protected]96449d2c2009-11-25 00:01:32102}
103
[email protected]07f54fcc2009-12-22 02:46:30104// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:18105bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:32106 GLuint count,
107 size_t size,
[email protected]a76b0052010-03-05 00:33:18108 unsigned int elements_per_unit,
109 uint32* dst) {
110 uint32 value;
111 if (!SafeMultiplyUint32(count, size, &value)) {
112 return false;
113 }
114 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
115 return false;
116 }
117 *dst = value;
118 return true;
[email protected]96449d2c2009-11-25 00:01:32119}
120
121// A struct to hold info about each command.
122struct CommandInfo {
123 int arg_flags; // How to handle the arguments for this command
124 int arg_count; // How many arguments are expected for this command.
125};
126
127// A table of CommandInfo for all the commands.
128const CommandInfo g_command_info[] = {
129 #define GLES2_CMD_OP(name) { \
130 name::kArgFlags, \
131 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
132
133 GLES2_COMMAND_LIST(GLES2_CMD_OP)
134
135 #undef GLES2_CMD_OP
136};
137
[email protected]258a3313f2011-10-18 20:13:57138// Return true if a character belongs to the ASCII subset as defined in
139// GLSL ES 1.0 spec section 3.1.
140static bool CharacterIsValidForGLES(unsigned char c) {
141 // Printing characters are valid except " $ ` @ \ ' DEL.
142 if (c >= 32 && c <= 126 &&
143 c != '"' &&
144 c != '$' &&
145 c != '`' &&
146 c != '@' &&
147 c != '\\' &&
148 c != '\'') {
149 return true;
150 }
151 // Horizontal tab, line feed, vertical tab, form feed, carriage return
152 // are also valid.
153 if (c >= 9 && c <= 13) {
154 return true;
155 }
156
157 return false;
158}
159
160static bool StringIsValidForGLES(const char* str) {
161 for (; *str; ++str) {
162 if (!CharacterIsValidForGLES(*str)) {
163 return false;
164 }
165 }
166 return true;
167}
168
[email protected]f0e6a34f2012-01-04 20:53:40169static inline GLenum GetTexInternalFormat(GLenum internal_format) {
170 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
171 if (internal_format == GL_BGRA_EXT || internal_format == GL_BGRA8_EXT)
172 return GL_RGBA8;
173 }
174 return internal_format;
175}
176
[email protected]297ca1c2011-06-20 23:08:46177static void WrappedTexImage2D(
[email protected]473c01ccb2011-06-07 01:33:30178 GLenum target,
179 GLint level,
180 GLenum internal_format,
181 GLsizei width,
182 GLsizei height,
183 GLint border,
184 GLenum format,
185 GLenum type,
186 const void* pixels) {
[email protected]f0e6a34f2012-01-04 20:53:40187 GLenum gl_internal_format = GetTexInternalFormat(internal_format);
[email protected]473c01ccb2011-06-07 01:33:30188 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]f0e6a34f2012-01-04 20:53:40189 if (type == GL_FLOAT) {
[email protected]58b75f92012-03-20 21:15:43190 switch (format) {
191 case GL_RGBA:
192 gl_internal_format = GL_RGBA32F_ARB;
193 break;
194 case GL_RGB:
195 gl_internal_format = GL_RGB32F_ARB;
196 break;
197 case GL_LUMINANCE_ALPHA:
198 gl_internal_format = GL_LUMINANCE_ALPHA32F_ARB;
199 break;
200 case GL_LUMINANCE:
201 gl_internal_format = GL_LUMINANCE32F_ARB;
202 break;
203 case GL_ALPHA:
204 gl_internal_format = GL_ALPHA32F_ARB;
205 break;
206 default:
207 NOTREACHED();
208 break;
[email protected]473c01ccb2011-06-07 01:33:30209 }
210 } else if (type == GL_HALF_FLOAT_OES) {
[email protected]58b75f92012-03-20 21:15:43211 switch (format) {
212 case GL_RGBA:
213 gl_internal_format = GL_RGBA16F_ARB;
214 break;
215 case GL_RGB:
216 gl_internal_format = GL_RGB16F_ARB;
217 break;
218 case GL_LUMINANCE_ALPHA:
219 gl_internal_format = GL_LUMINANCE_ALPHA16F_ARB;
220 break;
221 case GL_LUMINANCE:
222 gl_internal_format = GL_LUMINANCE16F_ARB;
223 break;
224 case GL_ALPHA:
225 gl_internal_format = GL_ALPHA16F_ARB;
226 break;
227 default:
228 NOTREACHED();
229 break;
[email protected]473c01ccb2011-06-07 01:33:30230 }
231 }
232 }
233 glTexImage2D(
234 target, level, gl_internal_format, width, height, border, format, type,
235 pixels);
236}
237
[email protected]297ca1c2011-06-20 23:08:46238// Wrapper for glEnable/glDisable that doesn't suck.
239static void EnableDisable(GLenum pname, bool enable) {
240 if (enable) {
241 glEnable(pname);
242 } else {
243 glDisable(pname);
244 }
245}
246
[email protected]6217d392010-03-25 22:08:35247// This class prevents any GL errors that occur when it is in scope from
248// being reported to the client.
249class ScopedGLErrorSuppressor {
250 public:
251 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
252 ~ScopedGLErrorSuppressor();
253 private:
254 GLES2DecoderImpl* decoder_;
255 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
256};
257
258// Temporarily changes a decoder's bound 2D texture and restore it when this
259// object goes out of scope. Also temporarily switches to using active texture
260// unit zero in case the client has changed that to something invalid.
261class ScopedTexture2DBinder {
262 public:
263 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
264 ~ScopedTexture2DBinder();
265
266 private:
267 GLES2DecoderImpl* decoder_;
268 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
269};
270
271// Temporarily changes a decoder's bound render buffer and restore it when this
272// object goes out of scope.
273class ScopedRenderBufferBinder {
274 public:
275 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
276 ~ScopedRenderBufferBinder();
277
278 private:
279 GLES2DecoderImpl* decoder_;
280 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
281};
282
283// Temporarily changes a decoder's bound frame buffer and restore it when this
284// object goes out of scope.
285class ScopedFrameBufferBinder {
286 public:
287 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
288 ~ScopedFrameBufferBinder();
289
290 private:
291 GLES2DecoderImpl* decoder_;
292 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
293};
294
[email protected]34ff8b0c2010-10-01 20:06:02295// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52296// the multisampled offscreen render buffer if that buffer is multisampled, and,
[email protected]de26b3c2011-08-03 21:54:27297// if it is bound or enforce_internal_framebuffer is true. If internal is
298// true, the resolved framebuffer is not visible to the parent.
[email protected]34ff8b0c2010-10-01 20:06:02299class ScopedResolvedFrameBufferBinder {
300 public:
[email protected]e7e38032011-07-26 17:25:25301 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
[email protected]de26b3c2011-08-03 21:54:27302 bool enforce_internal_framebuffer,
303 bool internal);
[email protected]34ff8b0c2010-10-01 20:06:02304 ~ScopedResolvedFrameBufferBinder();
305
306 private:
307 GLES2DecoderImpl* decoder_;
308 bool resolve_and_bind_;
309 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
310};
311
[email protected]6217d392010-03-25 22:08:35312// Encapsulates an OpenGL texture.
313class Texture {
314 public:
315 explicit Texture(GLES2DecoderImpl* decoder);
316 ~Texture();
317
318 // Create a new render texture.
319 void Create();
320
321 // Set the initial size and format of a render texture or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02322 bool AllocateStorage(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35323
324 // Copy the contents of the currently bound frame buffer.
[email protected]3a4d0c52011-06-29 23:11:58325 void Copy(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35326
327 // Destroy the render texture. This must be explicitly called before
328 // destroying this object.
329 void Destroy();
330
[email protected]97872062010-11-03 19:07:05331 // Invalidate the texture. This can be used when a context is lost and it is
332 // not possible to make it current in order to free the resource.
333 void Invalidate();
334
[email protected]6217d392010-03-25 22:08:35335 GLuint id() const {
336 return id_;
337 }
338
[email protected]d37231fa2010-04-09 21:16:02339 gfx::Size size() const {
340 return size_;
341 }
342
[email protected]1078f912011-12-23 13:12:14343 size_t estimated_size() const {
344 return estimated_size_;
345 }
346
[email protected]6217d392010-03-25 22:08:35347 private:
348 GLES2DecoderImpl* decoder_;
349 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02350 gfx::Size size_;
[email protected]1078f912011-12-23 13:12:14351 size_t estimated_size_;
[email protected]6217d392010-03-25 22:08:35352 DISALLOW_COPY_AND_ASSIGN(Texture);
353};
354
355// Encapsulates an OpenGL render buffer of any format.
356class RenderBuffer {
357 public:
358 explicit RenderBuffer(GLES2DecoderImpl* decoder);
359 ~RenderBuffer();
360
361 // Create a new render buffer.
362 void Create();
363
364 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02365 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35366
367 // Destroy the render buffer. This must be explicitly called before destroying
368 // this object.
369 void Destroy();
370
[email protected]97872062010-11-03 19:07:05371 // Invalidate the render buffer. This can be used when a context is lost and
372 // it is not possible to make it current in order to free the resource.
373 void Invalidate();
374
[email protected]6217d392010-03-25 22:08:35375 GLuint id() const {
376 return id_;
377 }
378
[email protected]1078f912011-12-23 13:12:14379 size_t estimated_size() const {
380 return estimated_size_;
381 }
382
[email protected]6217d392010-03-25 22:08:35383 private:
384 GLES2DecoderImpl* decoder_;
385 GLuint id_;
[email protected]1078f912011-12-23 13:12:14386 size_t estimated_size_;
[email protected]6217d392010-03-25 22:08:35387 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
388};
389
390// Encapsulates an OpenGL frame buffer.
391class FrameBuffer {
392 public:
393 explicit FrameBuffer(GLES2DecoderImpl* decoder);
394 ~FrameBuffer();
395
396 // Create a new frame buffer.
397 void Create();
398
399 // Attach a color render buffer to a frame buffer.
400 void AttachRenderTexture(Texture* texture);
401
[email protected]b9363b22010-06-09 22:06:15402 // Attach a render buffer to a frame buffer. Note that this unbinds any
403 // currently bound frame buffer.
404 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35405
[email protected]6217d392010-03-25 22:08:35406 // Destroy the frame buffer. This must be explicitly called before destroying
407 // this object.
408 void Destroy();
409
[email protected]97872062010-11-03 19:07:05410 // Invalidate the frame buffer. This can be used when a context is lost and it
411 // is not possible to make it current in order to free the resource.
412 void Invalidate();
413
[email protected]6217d392010-03-25 22:08:35414 // See glCheckFramebufferStatusEXT.
415 GLenum CheckStatus();
416
417 GLuint id() const {
418 return id_;
419 }
420
421 private:
422 GLES2DecoderImpl* decoder_;
423 GLuint id_;
424 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
425};
[email protected]34ff8b0c2010-10-01 20:06:02426
[email protected]43f28f832010-02-03 02:28:48427// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32428
[email protected]ddb1e5a2010-12-13 20:10:45429bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
430 uint32* service_texture_id) {
431 return false;
432}
433
[email protected]a3ded6d2010-10-19 06:44:39434GLES2Decoder::GLES2Decoder()
[email protected]e844ae22012-01-14 03:36:26435 : debug_(false),
[email protected]b5d647c2012-02-10 01:41:32436 log_commands_(false),
437 log_synthesized_gl_errors_(true) {
[email protected]96449d2c2009-11-25 00:01:32438}
439
[email protected]3916c97e2010-02-25 03:20:50440GLES2Decoder::~GLES2Decoder() {
441}
442
[email protected]57edfdad2012-02-07 04:57:15443bool GLES2Decoder::testing_force_is_angle_;
444
445void GLES2Decoder::set_testing_force_is_angle(bool force) {
446 testing_force_is_angle_ = force;
447}
448
449bool GLES2Decoder::IsAngle() {
450#if defined(OS_WIN)
451 return testing_force_is_angle_ ||
452 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
453#else
454 return testing_force_is_angle_;
455#endif
456}
457
[email protected]f39f4b3f2010-05-12 17:04:08458// This class implements GLES2Decoder so we don't have to expose all the GLES2
459// cmd stuff to outside this class.
460class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
461 public GLES2Decoder {
462 public:
[email protected]fa20ec82012-05-04 04:02:48463 static const int kMaxLogErrors = 256;
464
[email protected]aa7666122011-09-02 19:45:52465 explicit GLES2DecoderImpl(ContextGroup* group);
[email protected]80eb6b52012-01-19 00:14:41466 ~GLES2DecoderImpl();
[email protected]f39f4b3f2010-05-12 17:04:08467
[email protected]96449d2c2009-11-25 00:01:32468 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14469 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50470 unsigned int arg_count,
471 const void* args);
[email protected]96449d2c2009-11-25 00:01:32472
473 // Overridden from AsyncAPIInterface.
474 virtual const char* GetCommandName(unsigned int command_id) const;
475
476 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38477 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
478 const scoped_refptr<gfx::GLContext>& context,
[email protected]069944672012-04-25 20:52:23479 bool offscreen,
[email protected]6217d392010-03-25 22:08:35480 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:29481 const DisallowedFeatures& disallowed_features,
[email protected]a3ded6d2010-10-19 06:44:39482 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:24483 const std::vector<int32>& attribs);
[email protected]96449d2c2009-11-25 00:01:32484 virtual void Destroy();
[email protected]3c644d82011-06-20 19:58:24485 virtual bool SetParent(GLES2Decoder* parent_decoder,
486 uint32 parent_texture_id);
[email protected]799b4b22011-08-22 17:09:59487 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]9a5afa432011-07-22 18:16:39488 void UpdateParentTextureInfo();
[email protected]eb54a562010-01-20 21:55:18489 virtual bool MakeCurrent();
[email protected]a96a6022011-11-04 00:58:12490 virtual void ReleaseCurrent();
[email protected]56ac89b2010-03-17 21:16:55491 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30492 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]f62a5ab2011-05-23 20:34:15493 virtual gfx::GLSurface* GetGLSurface() { return surface_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39494 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]882ba1e22012-03-08 19:02:53495 virtual QueryManager* GetQueryManager() { return query_manager_.get(); }
[email protected]22e3f552012-03-13 01:54:19496 virtual bool ProcessPendingQueries();
[email protected]43f28f832010-02-03 02:28:48497
[email protected]0d6bfdc2011-11-02 01:32:20498 virtual void SetGLError(GLenum error, const char* msg);
[email protected]9d37f062011-11-22 01:24:52499 virtual void SetResizeCallback(
500 const base::Callback<void(gfx::Size)>& callback);
[email protected]22f320a2011-08-30 01:17:00501
[email protected]6b6e7ee2011-12-13 08:04:52502 virtual void SetMsgCallback(const MsgCallback& callback);
[email protected]22f320a2011-08-30 01:17:00503
[email protected]b0af4f52011-09-28 22:04:42504 virtual void SetStreamTextureManager(StreamTextureManager* manager);
[email protected]1318e922010-09-17 22:03:16505 virtual bool GetServiceTextureId(uint32 client_texture_id,
506 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48507
[email protected]8e3e0662010-08-23 18:46:30508 // Restores the current state to the user's settings.
509 void RestoreCurrentFramebufferBindings();
510 void RestoreCurrentRenderbufferBindings();
511 void RestoreCurrentTexture2DBindings();
512
[email protected]297ca1c2011-06-20 23:08:46513 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
514 void ApplyDirtyState();
515
[email protected]78b514b2012-05-01 21:50:59516 // Reapply the texture parameters to the given texture.
517 void BindAndApplyTextureParameters(TextureManager::TextureInfo* info);
518
[email protected]297ca1c2011-06-20 23:08:46519 // These check the state of the currently bound framebuffer or the
520 // backbuffer if no framebuffer is bound.
521 bool BoundFramebufferHasColorAttachmentWithAlpha();
522 bool BoundFramebufferHasDepthAttachment();
523 bool BoundFramebufferHasStencilAttachment();
524
[email protected]38d139d2011-07-14 00:38:43525 virtual error::ContextLostReason GetContextLostReason();
526
[email protected]96449d2c2009-11-25 00:01:32527 private:
[email protected]6217d392010-03-25 22:08:35528 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02529 friend class ScopedResolvedFrameBufferBinder;
[email protected]1078f912011-12-23 13:12:14530 friend class Texture;
[email protected]6217d392010-03-25 22:08:35531 friend class RenderBuffer;
532 friend class FrameBuffer;
533
[email protected]3916c97e2010-02-25 03:20:50534 // State associated with each texture unit.
535 struct TextureUnit {
536 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
537
538 // The last target that was bound to this texture unit.
539 GLenum bind_target;
540
541 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
542 TextureManager::TextureInfo::Ref bound_texture_2d;
543
544 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
545 // glBindTexture
546 TextureManager::TextureInfo::Ref bound_texture_cube_map;
[email protected]61eeb33f2011-07-26 15:30:31547
548 // texture currently bound to this unit's GL_TEXTURE_EXTERNAL_OES with
549 // glBindTexture
550 TextureManager::TextureInfo::Ref bound_texture_external_oes;
551
[email protected]e51bdf32011-11-23 22:21:46552 // texture currently bound to this unit's GL_TEXTURE_RECTANGLE_ARB with
553 // glBindTexture
554 TextureManager::TextureInfo::Ref bound_texture_rectangle_arb;
555
[email protected]61eeb33f2011-07-26 15:30:31556 TextureManager::TextureInfo::Ref GetInfoForSamplerType(GLenum type) {
557 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:46558 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
559 switch (type) {
560 case GL_SAMPLER_2D:
561 return bound_texture_2d;
562 case GL_SAMPLER_CUBE:
563 return bound_texture_cube_map;
564 case GL_SAMPLER_EXTERNAL_OES:
565 return bound_texture_external_oes;
566 case GL_SAMPLER_2D_RECT_ARB:
567 return bound_texture_rectangle_arb;
568 }
569
570 NOTREACHED();
571 return NULL;
[email protected]61eeb33f2011-07-26 15:30:31572 }
[email protected]a0b78dc2011-11-11 10:43:10573
574 void Unbind(TextureManager::TextureInfo* texture) {
575 if (bound_texture_2d == texture) {
576 bound_texture_2d = NULL;
577 }
578 if (bound_texture_cube_map == texture) {
579 bound_texture_cube_map = NULL;
580 }
581 if (bound_texture_external_oes == texture) {
582 bound_texture_external_oes = NULL;
583 }
584 }
[email protected]3916c97e2010-02-25 03:20:50585 };
586
[email protected]c2f8c8402010-12-06 18:07:24587 // Initialize or re-initialize the shader translator.
588 bool InitializeShaderTranslator();
589
[email protected]302ce6d2011-07-07 23:28:11590 void UpdateCapabilities();
591
[email protected]ae51d192010-04-27 00:48:03592 // Helpers for the glGen and glDelete functions.
593 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
594 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
595 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
596 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
597 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
598 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
599 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
600 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]882ba1e22012-03-08 19:02:53601 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
602 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47603
[email protected]3916c97e2010-02-25 03:20:50604 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50605 BufferManager* buffer_manager() {
606 return group_->buffer_manager();
607 }
608
[email protected]a25fa872010-03-25 02:57:58609 RenderbufferManager* renderbuffer_manager() {
610 return group_->renderbuffer_manager();
611 }
612
613 FramebufferManager* framebuffer_manager() {
614 return group_->framebuffer_manager();
615 }
616
[email protected]3916c97e2010-02-25 03:20:50617 ProgramManager* program_manager() {
618 return group_->program_manager();
619 }
620
621 ShaderManager* shader_manager() {
622 return group_->shader_manager();
623 }
624
625 TextureManager* texture_manager() {
626 return group_->texture_manager();
627 }
628
[email protected]78b514b2012-05-01 21:50:59629 MailboxManager* mailbox_manager() {
630 return group_->mailbox_manager();
631 }
632
[email protected]34ff8b0c2010-10-01 20:06:02633 bool IsOffscreenBufferMultisampled() const {
634 return offscreen_target_samples_ > 1;
635 }
636
[email protected]a93bb842010-02-16 23:03:47637 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03638 TextureManager::TextureInfo* CreateTextureInfo(
639 GLuint client_id, GLuint service_id) {
[email protected]80eb6b52012-01-19 00:14:41640 return texture_manager()->CreateTextureInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47641 }
642
643 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03644 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50645 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03646 texture_manager()->GetTextureInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10647 return info;
[email protected]a93bb842010-02-16 23:03:47648 }
649
650 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03651 void RemoveTextureInfo(GLuint client_id) {
[email protected]80eb6b52012-01-19 00:14:41652 texture_manager()->RemoveTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50653 }
[email protected]a93bb842010-02-16 23:03:47654
[email protected]d37231fa2010-04-09 21:16:02655 // Get the size (in pixels) of the currently bound frame buffer (either FBO
656 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30657 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02658
[email protected]9edc6b22010-12-23 02:00:26659 // Get the format of the currently bound frame buffer (either FBO or regular
660 // back buffer)
661 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46662 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26663
[email protected]a93bb842010-02-16 23:03:47664 // Wrapper for CompressedTexImage2D commands.
665 error::Error DoCompressedTexImage2D(
666 GLenum target,
667 GLint level,
668 GLenum internal_format,
669 GLsizei width,
670 GLsizei height,
671 GLint border,
672 GLsizei image_size,
673 const void* data);
674
[email protected]cadde4a2010-07-31 17:10:43675 // Wrapper for CompressedTexSubImage2D.
676 void DoCompressedTexSubImage2D(
677 GLenum target,
678 GLint level,
679 GLint xoffset,
680 GLint yoffset,
681 GLsizei width,
682 GLsizei height,
683 GLenum format,
684 GLsizei imageSize,
685 const void * data);
686
687 // Wrapper for CopyTexImage2D.
688 void DoCopyTexImage2D(
689 GLenum target,
690 GLint level,
691 GLenum internal_format,
692 GLint x,
693 GLint y,
694 GLsizei width,
695 GLsizei height,
696 GLint border);
697
698 // Wrapper for CopyTexSubImage2D.
699 void DoCopyTexSubImage2D(
700 GLenum target,
701 GLint level,
702 GLint xoffset,
703 GLint yoffset,
704 GLint x,
705 GLint y,
706 GLsizei width,
707 GLsizei height);
708
[email protected]a93bb842010-02-16 23:03:47709 // Wrapper for TexImage2D commands.
710 error::Error DoTexImage2D(
711 GLenum target,
712 GLint level,
713 GLenum internal_format,
714 GLsizei width,
715 GLsizei height,
716 GLint border,
717 GLenum format,
718 GLenum type,
719 const void* pixels,
720 uint32 pixels_size);
721
[email protected]cadde4a2010-07-31 17:10:43722 // Wrapper for TexSubImage2D.
723 void DoTexSubImage2D(
724 GLenum target,
725 GLint level,
726 GLint xoffset,
727 GLint yoffset,
728 GLsizei width,
729 GLsizei height,
730 GLenum format,
731 GLenum type,
732 const void * data);
733
[email protected]e51bdf32011-11-23 22:21:46734 // Wrapper for TexImageIOSurface2DCHROMIUM.
735 void DoTexImageIOSurface2DCHROMIUM(
736 GLenum target,
737 GLsizei width,
738 GLsizei height,
739 GLuint io_surface_id,
740 GLuint plane);
741
[email protected]43410e92012-04-20 17:06:28742 void DoCopyTextureCHROMIUM(
743 GLenum target,
744 GLuint source_id,
745 GLuint target_id,
[email protected]0a1e9ad2012-05-04 21:13:03746 GLint level,
747 GLenum internal_format);
[email protected]43410e92012-04-20 17:06:28748
[email protected]97dc7cbe2011-12-06 17:26:17749 // Wrapper for TexStorage2DEXT.
750 void DoTexStorage2DEXT(
751 GLenum target,
752 GLint levels,
753 GLenum internal_format,
754 GLsizei width,
755 GLsizei height);
756
[email protected]78b514b2012-05-01 21:50:59757 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
758 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
759
[email protected]a93bb842010-02-16 23:03:47760 // Creates a ProgramInfo for the given program.
[email protected]d685a682011-04-29 16:19:57761 ProgramManager::ProgramInfo* CreateProgramInfo(
762 GLuint client_id, GLuint service_id) {
763 return program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47764 }
765
[email protected]07f54fcc2009-12-22 02:46:30766 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03767 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14768 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46769 }
[email protected]07f54fcc2009-12-22 02:46:30770
[email protected]6b8cf1a2010-05-06 16:13:58771 // Gets the program info for the given program. If it's not a program
772 // generates a GL error. Returns NULL if not program.
773 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
774 GLuint client_id, const char* function_name) {
775 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
776 if (!info) {
777 if (GetShaderInfo(client_id)) {
778 SetGLError(GL_INVALID_OPERATION,
779 (std::string(function_name) +
780 ": shader passed for program").c_str());
781 } else {
782 SetGLError(GL_INVALID_VALUE,
783 (std::string(function_name) + ": unknown program").c_str());
784 }
785 }
786 return info;
787 }
788
789
[email protected]45bf5152010-02-12 00:11:31790 // Creates a ShaderInfo for the given shader.
[email protected]d685a682011-04-29 16:19:57791 ShaderManager::ShaderInfo* CreateShaderInfo(
792 GLuint client_id,
793 GLuint service_id,
794 GLenum shader_type) {
795 return shader_manager()->CreateShaderInfo(
796 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31797 }
798
799 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03800 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14801 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31802 }
803
[email protected]6b8cf1a2010-05-06 16:13:58804 // Gets the shader info for the given shader. If it's not a shader generates a
805 // GL error. Returns NULL if not shader.
806 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
807 GLuint client_id, const char* function_name) {
808 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
809 if (!info) {
810 if (GetProgramInfo(client_id)) {
811 SetGLError(
812 GL_INVALID_OPERATION,
813 (std::string(function_name) +
814 ": program passed for shader").c_str());
815 } else {
816 SetGLError(GL_INVALID_VALUE,
817 (std::string(function_name) + ": unknown shader").c_str());
818 }
819 }
820 return info;
821 }
822
[email protected]a93bb842010-02-16 23:03:47823 // Creates a buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03824 void CreateBufferInfo(GLuint client_id, GLuint service_id) {
825 return buffer_manager()->CreateBufferInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47826 }
827
[email protected]07f54fcc2009-12-22 02:46:30828 // Gets the buffer info for the given buffer.
[email protected]ae51d192010-04-27 00:48:03829 BufferManager::BufferInfo* GetBufferInfo(GLuint client_id) {
830 BufferManager::BufferInfo* info =
831 buffer_manager()->GetBufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10832 return info;
[email protected]1d32bc82010-01-13 22:06:46833 }
[email protected]07f54fcc2009-12-22 02:46:30834
[email protected]a93bb842010-02-16 23:03:47835 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
836 // on glDeleteBuffers so we can make sure the user does not try to render
837 // with deleted buffers.
[email protected]ae51d192010-04-27 00:48:03838 void RemoveBufferInfo(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47839
[email protected]a25fa872010-03-25 02:57:58840 // Creates a framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03841 void CreateFramebufferInfo(GLuint client_id, GLuint service_id) {
842 return framebuffer_manager()->CreateFramebufferInfo(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58843 }
844
845 // Gets the framebuffer info for the given framebuffer.
846 FramebufferManager::FramebufferInfo* GetFramebufferInfo(
[email protected]ae51d192010-04-27 00:48:03847 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58848 FramebufferManager::FramebufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03849 framebuffer_manager()->GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10850 return info;
[email protected]a25fa872010-03-25 02:57:58851 }
852
853 // Removes the framebuffer info for the given framebuffer.
[email protected]ae51d192010-04-27 00:48:03854 void RemoveFramebufferInfo(GLuint client_id) {
855 framebuffer_manager()->RemoveFramebufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58856 }
857
858 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03859 void CreateRenderbufferInfo(GLuint client_id, GLuint service_id) {
860 return renderbuffer_manager()->CreateRenderbufferInfo(
861 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58862 }
863
864 // Gets the renderbuffer info for the given renderbuffer.
865 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfo(
[email protected]ae51d192010-04-27 00:48:03866 GLuint client_id) {
[email protected]a25fa872010-03-25 02:57:58867 RenderbufferManager::RenderbufferInfo* info =
[email protected]ae51d192010-04-27 00:48:03868 renderbuffer_manager()->GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10869 return info;
[email protected]a25fa872010-03-25 02:57:58870 }
871
872 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ae51d192010-04-27 00:48:03873 void RemoveRenderbufferInfo(GLuint client_id) {
874 renderbuffer_manager()->RemoveRenderbufferInfo(client_id);
[email protected]a25fa872010-03-25 02:57:58875 }
876
[email protected]258a3313f2011-10-18 20:13:57877 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
878
[email protected]558847a2010-03-24 07:02:54879 error::Error GetAttribLocationHelper(
880 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
881 const std::string& name_str);
882
883 error::Error GetUniformLocationHelper(
884 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
885 const std::string& name_str);
886
[email protected]3916c97e2010-02-25 03:20:50887 // Helper for glShaderSource.
888 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:03889 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:30890
[email protected]0d6bfdc2011-11-02 01:32:20891 // Clear any textures used by the current program.
892 bool ClearUnclearedTextures();
893
894 // Clear any uncleared level in texture.
895 // Returns false if there was a generated GL error.
896 bool ClearTexture(TextureManager::TextureInfo* info);
897
898 // Clears any uncleared attachments attached to the given frame buffer.
899 // Returns false if there was a generated GL error.
900 void ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:30901 GLenum target, FramebufferManager::FramebufferInfo* info);
[email protected]3a2e7c7b2010-08-06 01:12:28902
[email protected]0d6bfdc2011-11-02 01:32:20903 // overridden from GLES2Decoder
904 virtual bool ClearLevel(
905 unsigned service_id,
906 unsigned bind_target,
907 unsigned target,
908 int level,
909 unsigned format,
910 unsigned type,
911 int width,
[email protected]4502e6492011-12-14 19:39:15912 int height,
913 bool is_texture_immutable);
[email protected]0d6bfdc2011-11-02 01:32:20914
[email protected]c007aa02010-09-02 22:22:40915 // Restore all GL state that affects clearing.
916 void RestoreClearState();
917
[email protected]3a2e7c7b2010-08-06 01:12:28918 // Remembers the state of some capabilities.
[email protected]297ca1c2011-06-20 23:08:46919 // Returns: true if glEnable/glDisable should actually be called.
920 bool SetCapabilityState(GLenum cap, bool enabled);
[email protected]3a2e7c7b2010-08-06 01:12:28921
[email protected]0d6bfdc2011-11-02 01:32:20922 // Check that the currently bound framebuffers are valid.
923 // Generates GL error if not.
924 bool CheckBoundFramebuffersValid(const char* func_name);
925
926 // Check if a framebuffer meets our requirements.
927 bool CheckFramebufferValid(
928 FramebufferManager::FramebufferInfo* framebuffer,
929 GLenum target,
930 const char* func_name);
[email protected]3a03a8f2011-03-19 00:51:27931
[email protected]939e7362010-05-13 20:49:10932 // Checks if the current program exists and is valid. If not generates the
933 // appropriate GL error. Returns true if the current program is in a usable
934 // state.
935 bool CheckCurrentProgram(const char* function_name);
936
937 // Checks if the current program exists and is valid and that location is not
938 // -1. If the current program is not valid generates the appropriate GL
939 // error. Returns true if the current program is in a usable state and
940 // location is not -1.
941 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
942
943 // Gets the type of a uniform for a location in the current program. Sets GL
944 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:36945 // program is valid and the location exists. Adjusts count so it
946 // does not overflow the uniform.
947 bool PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:12948 GLint fake_location, const char* function_name,
949 GLint* real_location, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:10950
[email protected]b177ae22011-11-01 03:29:11951 // Gets the service id for any simulated backbuffer fbo.
952 GLuint GetBackbufferServiceId();
953
[email protected]b273e432010-04-12 17:23:58954 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
955 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
956
[email protected]96449d2c2009-11-25 00:01:32957 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:03958 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32959
960 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:03961 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:32962
[email protected]3916c97e2010-02-25 03:20:50963 // Wrapper for glActiveTexture
964 void DoActiveTexture(GLenum texture_unit);
965
[email protected]ae51d192010-04-27 00:48:03966 // Wrapper for glAttachShader
967 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
968
[email protected]96449d2c2009-11-25 00:01:32969 // Wrapper for glBindBuffer since we need to track the current targets.
970 void DoBindBuffer(GLenum target, GLuint buffer);
971
[email protected]86093972010-03-11 00:13:56972 // Wrapper for glBindFramebuffer since we need to track the current targets.
973 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
974
975 // Wrapper for glBindRenderbuffer since we need to track the current targets.
976 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
977
[email protected]a93bb842010-02-16 23:03:47978 // Wrapper for glBindTexture since we need to track the current targets.
979 void DoBindTexture(GLenum target, GLuint texture);
980
[email protected]8e3e0662010-08-23 18:46:30981 // Wrapper for glBlitFramebufferEXT.
982 void DoBlitFramebufferEXT(
983 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
984 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
985 GLbitfield mask, GLenum filter);
986
[email protected]36cef8ce2010-03-16 07:34:45987 // Wrapper for glBufferData.
[email protected]0c86dbf2010-03-05 08:14:11988 void DoBufferData(
989 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
990
[email protected]36cef8ce2010-03-16 07:34:45991 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:11992 void DoBufferSubData(
993 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
994
[email protected]36cef8ce2010-03-16 07:34:45995 // Wrapper for glCheckFramebufferStatus
996 GLenum DoCheckFramebufferStatus(GLenum target);
997
[email protected]3a03a8f2011-03-19 00:51:27998 // Wrapper for glClear
999 void DoClear(GLbitfield mask);
1000
[email protected]3a2e7c7b2010-08-06 01:12:281001 // Wrappers for clear and mask settings functions.
1002 void DoClearColor(
1003 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
1004 void DoClearDepthf(GLclampf depth);
1005 void DoClearStencil(GLint s);
1006 void DoColorMask(
1007 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
1008 void DoDepthMask(GLboolean depth);
1009 void DoStencilMask(GLuint mask);
1010 void DoStencilMaskSeparate(GLenum face, GLuint mask);
1011
[email protected]45bf5152010-02-12 00:11:311012 // Wrapper for glCompileShader.
1013 void DoCompileShader(GLuint shader);
1014
[email protected]269200b12010-11-18 22:53:061015 // Helper for DeleteSharedIdsCHROMIUM commands.
1016 void DoDeleteSharedIdsCHROMIUM(
1017 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101018
[email protected]ae51d192010-04-27 00:48:031019 // Wrapper for glDetachShader
1020 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1021
[email protected]3a2e7c7b2010-08-06 01:12:281022 // Wrapper for glDisable
1023 void DoDisable(GLenum cap);
1024
[email protected]07f54fcc2009-12-22 02:46:301025 // Wrapper for glDisableVertexAttribArray.
1026 void DoDisableVertexAttribArray(GLuint index);
1027
[email protected]3a2e7c7b2010-08-06 01:12:281028 // Wrapper for glEnable
1029 void DoEnable(GLenum cap);
1030
[email protected]07f54fcc2009-12-22 02:46:301031 // Wrapper for glEnableVertexAttribArray.
1032 void DoEnableVertexAttribArray(GLuint index);
1033
[email protected]882ba1e22012-03-08 19:02:531034 // Wrapper for glFinish.
1035 void DoFinish();
1036
1037 // Wrapper for glFlush.
1038 void DoFlush();
1039
[email protected]36cef8ce2010-03-16 07:34:451040 // Wrapper for glFramebufferRenderbufffer.
1041 void DoFramebufferRenderbuffer(
1042 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1043 GLuint renderbuffer);
1044
1045 // Wrapper for glFramebufferTexture2D.
1046 void DoFramebufferTexture2D(
1047 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1048 GLint level);
1049
[email protected]a93bb842010-02-16 23:03:471050 // Wrapper for glGenerateMipmap
1051 void DoGenerateMipmap(GLenum target);
1052
[email protected]269200b12010-11-18 22:53:061053 // Helper for GenSharedIdsCHROMIUM commands.
1054 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:101055 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1056
[email protected]b273e432010-04-12 17:23:581057 // Wrapper for DoGetBooleanv.
1058 void DoGetBooleanv(GLenum pname, GLboolean* params);
1059
1060 // Wrapper for DoGetFloatv.
1061 void DoGetFloatv(GLenum pname, GLfloat* params);
1062
[email protected]36cef8ce2010-03-16 07:34:451063 // Wrapper for glGetFramebufferAttachmentParameteriv.
1064 void DoGetFramebufferAttachmentParameteriv(
1065 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1066
[email protected]a0c3e972010-04-21 00:49:131067 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581068 void DoGetIntegerv(GLenum pname, GLint* params);
1069
[email protected]29a9eb52010-04-13 09:04:231070 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:061071 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:231072 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1073
[email protected]a0c3e972010-04-21 00:49:131074 // Wrapper for glGetProgramiv.
1075 void DoGetProgramiv(
1076 GLuint program_id, GLenum pname, GLint* params);
1077
[email protected]36cef8ce2010-03-16 07:34:451078 // Wrapper for glRenderbufferParameteriv.
1079 void DoGetRenderbufferParameteriv(
1080 GLenum target, GLenum pname, GLint* params);
1081
[email protected]ddd968b82010-03-02 00:44:291082 // Wrapper for glGetShaderiv
1083 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1084
[email protected]b1122982010-05-17 23:04:241085 // Wrappers for glGetVertexAttrib.
1086 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1087 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1088
[email protected]1958e0e2010-04-22 05:17:151089 // Wrappers for glIsXXX functions.
1090 bool DoIsBuffer(GLuint client_id);
1091 bool DoIsFramebuffer(GLuint client_id);
1092 bool DoIsProgram(GLuint client_id);
1093 bool DoIsRenderbuffer(GLuint client_id);
1094 bool DoIsShader(GLuint client_id);
1095 bool DoIsTexture(GLuint client_id);
1096
[email protected]07f54fcc2009-12-22 02:46:301097 // Wrapper for glLinkProgram
1098 void DoLinkProgram(GLuint program);
1099
[email protected]269200b12010-11-18 22:53:061100 // Helper for RegisterSharedIdsCHROMIUM.
1101 void DoRegisterSharedIdsCHROMIUM(
1102 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101103
[email protected]36cef8ce2010-03-16 07:34:451104 // Wrapper for glRenderbufferStorage.
1105 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031106 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451107
[email protected]8e3e0662010-08-23 18:46:301108 // Wrapper for glRenderbufferStorageMultisampleEXT.
1109 void DoRenderbufferStorageMultisample(
1110 GLenum target, GLsizei samples, GLenum internalformat,
1111 GLsizei width, GLsizei height);
1112
[email protected]b273e432010-04-12 17:23:581113 // Wrapper for glReleaseShaderCompiler.
1114 void DoReleaseShaderCompiler() { }
1115
[email protected]3916c97e2010-02-25 03:20:501116 // Wrappers for glTexParameter functions.
1117 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1118 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1119 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1120 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1121
1122 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1123 // spec only these 2 functions can be used to set sampler uniforms.
[email protected]1b0a6752012-02-22 03:44:121124 void DoUniform1i(GLint fake_location, GLint v0);
1125 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1126 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1127 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1128 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101129
1130 // Wrappers for glUniformfv because some drivers don't correctly accept
1131 // bool uniforms.
[email protected]1b0a6752012-02-22 03:44:121132 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1133 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1134 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1135 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501136
[email protected]43c2f1f2011-03-25 18:35:361137 void DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:121138 GLint fake_location, GLsizei count, GLboolean transpose,
1139 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361140 void DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:121141 GLint fake_location, GLsizei count, GLboolean transpose,
1142 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361143 void DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:121144 GLint fake_location, GLsizei count, GLboolean transpose,
1145 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361146
[email protected]b1122982010-05-17 23:04:241147 // Wrappers for glVertexAttrib??
1148 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1149 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1150 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1151 void DoVertexAttrib4f(
1152 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1153 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1154 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1155 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1156 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1157
[email protected]43410e92012-04-20 17:06:281158 // Wrapper for glViewport
1159 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1160
[email protected]07f54fcc2009-12-22 02:46:301161 // Wrapper for glUseProgram
1162 void DoUseProgram(GLuint program);
1163
[email protected]ae51d192010-04-27 00:48:031164 // Wrapper for glValidateProgram.
1165 void DoValidateProgram(GLuint program_client_id);
1166
[email protected]4e8a5b122010-05-08 22:00:101167 // Gets the number of values that will be returned by glGetXXX. Returns
1168 // false if pname is unknown.
1169 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1170
[email protected]96449d2c2009-11-25 00:01:321171 // Gets the GLError through our wrapper.
1172 GLenum GetGLError();
1173
[email protected]1002c2d2011-06-28 22:39:041174 // Gets the GLError and stores it in our wrapper. Effectively
1175 // this lets us peek at the error without losing it.
1176 GLenum PeekGLError();
1177
[email protected]07f54fcc2009-12-22 02:46:301178 // Copies the real GL errors to the wrapper. This is so we can
1179 // make sure there are no native GL errors before calling some GL function
1180 // so that on return we know any error generated was for that specific
1181 // command.
1182 void CopyRealGLErrorsToWrapper();
1183
[email protected]6217d392010-03-25 22:08:351184 // Clear all real GL errors. This is to prevent the client from seeing any
1185 // errors caused by GL calls that it was not responsible for issuing.
1186 void ClearRealGLErrors();
1187
[email protected]07f54fcc2009-12-22 02:46:301188 // Checks if the current program and vertex attributes are valid for drawing.
[email protected]c6aef902012-02-14 03:31:421189 bool IsDrawValid(GLuint max_vertex_accessed, GLsizei primcount);
[email protected]07f54fcc2009-12-22 02:46:301190
[email protected]c13e1da62011-09-09 21:48:301191 // Returns true if successful, simulated will be true if attrib0 was
1192 // simulated.
[email protected]c6aef902012-02-14 03:31:421193 bool SimulateAttrib0(
1194 GLuint max_vertex_accessed, bool* simulated);
[email protected]43410e92012-04-20 17:06:281195 void RestoreStateForAttrib(GLuint attrib);
[email protected]b1122982010-05-17 23:04:241196
[email protected]ef526492010-06-02 23:12:251197 // Returns true if textures were set.
1198 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501199 void RestoreStateForNonRenderableTextures();
1200
[email protected]8fbedc02010-11-18 18:43:401201 // Returns true if GL_FIXED attribs were simulated.
[email protected]c6aef902012-02-14 03:31:421202 bool SimulateFixedAttribs(
1203 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
[email protected]8fbedc02010-11-18 18:43:401204 void RestoreStateForSimulatedFixedAttribs();
1205
[email protected]c6aef902012-02-14 03:31:421206 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1207 // cases (primcount is 0 for non-instanced).
1208 error::Error DoDrawArrays(
1209 bool instanced, GLenum mode, GLint first, GLsizei count,
1210 GLsizei primcount);
1211 error::Error DoDrawElements(
1212 bool instanced, GLenum mode, GLsizei count, GLenum type,
1213 int32 offset, GLsizei primcount);
1214
[email protected]07f54fcc2009-12-22 02:46:301215 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501216 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301217 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501218 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1219 bound_array_buffer_ : bound_element_array_buffer_;
[email protected]a0b78dc2011-11-11 10:43:101220 return info;
[email protected]07f54fcc2009-12-22 02:46:301221 }
1222
[email protected]a93bb842010-02-16 23:03:471223 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501224 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1225 TextureUnit& unit = texture_units_[active_texture_unit_];
1226 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471227 switch (target) {
1228 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501229 info = unit.bound_texture_2d;
1230 break;
[email protected]a93bb842010-02-16 23:03:471231 case GL_TEXTURE_CUBE_MAP:
1232 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1233 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1234 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1235 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1236 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1237 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501238 info = unit.bound_texture_cube_map;
1239 break;
[email protected]61eeb33f2011-07-26 15:30:311240 case GL_TEXTURE_EXTERNAL_OES:
1241 info = unit.bound_texture_external_oes;
1242 break;
[email protected]e51bdf32011-11-23 22:21:461243 case GL_TEXTURE_RECTANGLE_ARB:
1244 info = unit.bound_texture_rectangle_arb;
1245 break;
[email protected]a93bb842010-02-16 23:03:471246 default:
1247 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501248 return NULL;
[email protected]a93bb842010-02-16 23:03:471249 }
[email protected]a0b78dc2011-11-11 10:43:101250 return info;
[email protected]a93bb842010-02-16 23:03:471251 }
1252
[email protected]61eeb33f2011-07-26 15:30:311253 GLenum GetBindTargetForSamplerType(GLenum type) {
1254 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:461255 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1256 switch (type) {
1257 case GL_SAMPLER_2D:
1258 return GL_TEXTURE_2D;
1259 case GL_SAMPLER_CUBE:
1260 return GL_TEXTURE_CUBE_MAP;
1261 case GL_SAMPLER_EXTERNAL_OES:
1262 return GL_TEXTURE_EXTERNAL_OES;
1263 case GL_SAMPLER_2D_RECT_ARB:
1264 return GL_TEXTURE_RECTANGLE_ARB;
1265 }
1266
1267 NOTREACHED();
1268 return 0;
[email protected]61eeb33f2011-07-26 15:30:311269 }
1270
[email protected]8e3e0662010-08-23 18:46:301271 // Gets the framebuffer info for a particular target.
1272 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1273 GLenum target) {
1274 FramebufferManager::FramebufferInfo* info = NULL;
1275 switch (target) {
1276 case GL_FRAMEBUFFER:
1277 case GL_DRAW_FRAMEBUFFER:
1278 info = bound_draw_framebuffer_;
1279 break;
1280 case GL_READ_FRAMEBUFFER:
1281 info = bound_read_framebuffer_;
1282 break;
1283 default:
1284 NOTREACHED();
1285 break;
1286 }
[email protected]a0b78dc2011-11-11 10:43:101287 return info;
[email protected]8e3e0662010-08-23 18:46:301288 }
1289
[email protected]0d6bfdc2011-11-02 01:32:201290 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfoForTarget(
1291 GLenum target) {
1292 RenderbufferManager::RenderbufferInfo* info = NULL;
1293 switch (target) {
1294 case GL_RENDERBUFFER:
1295 info = bound_renderbuffer_;
1296 break;
1297 default:
1298 NOTREACHED();
1299 break;
1300 }
[email protected]a0b78dc2011-11-11 10:43:101301 return info;
[email protected]0d6bfdc2011-11-02 01:32:201302 }
1303
[email protected]f7b85372010-02-03 01:11:371304 // Validates the program and location for a glGetUniform call and returns
1305 // a SizeResult setup to receive the result. Returns true if glGetUniform
1306 // should be called.
1307 bool GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:121308 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:371309 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:121310 error::Error* error, GLint* real_location, GLuint* service_id,
1311 void** result, GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371312
[email protected]1078f912011-12-23 13:12:141313 // Computes the estimated memory used for the backbuffer and passes it to
1314 // the tracing system.
1315 void UpdateBackbufferMemoryAccounting();
1316
[email protected]38d139d2011-07-14 00:38:431317 // Returns true if the context was just lost due to e.g. GL_ARB_robustness.
1318 bool WasContextLost();
1319
[email protected]e51bdf32011-11-23 22:21:461320#if defined(OS_MACOSX)
1321 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1322#endif
1323
[email protected]96449d2c2009-11-25 00:01:321324 // Generate a member function prototype for each command in an automated and
1325 // typesafe way.
1326 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141327 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191328 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321329 const gles2::name& args); \
1330
1331 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1332
1333 #undef GLES2_CMD_OP
1334
[email protected]2f2d7042010-04-14 21:45:581335 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381336 scoped_refptr<gfx::GLSurface> surface_;
1337 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021338
[email protected]a3ded6d2010-10-19 06:44:391339 // The ContextGroup for this decoder uses to track resources.
1340 ContextGroup::Ref group_;
1341
[email protected]6217d392010-03-25 22:08:351342 // A parent decoder can access this decoders saved offscreen frame buffer.
1343 // The parent pointer is reset if the parent is destroyed.
1344 base::WeakPtr<GLES2DecoderImpl> parent_;
1345
[email protected]34ff8b0c2010-10-01 20:06:021346 // Current width and height of the offscreen frame buffer.
1347 gfx::Size offscreen_size_;
1348
[email protected]96449d2c2009-11-25 00:01:321349 // Current GL error bits.
1350 uint32 error_bits_;
1351
[email protected]96449d2c2009-11-25 00:01:321352 // Util to help with GL.
1353 GLES2Util util_;
1354
1355 // pack alignment as last set by glPixelStorei
1356 GLint pack_alignment_;
1357
1358 // unpack alignment as last set by glPixelStorei
1359 GLint unpack_alignment_;
1360
[email protected]43410e92012-04-20 17:06:281361 // unpack flip y as last set by glPixelStorei
1362 bool unpack_flip_y_;
1363
1364 // unpack premultiply alpha as last set by glPixelStorei
1365 bool unpack_premultiply_alpha_;
1366
[email protected]96449d2c2009-11-25 00:01:321367 // The currently bound array buffer. If this is 0 it is illegal to call
1368 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501369 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321370
1371 // The currently bound element array buffer. If this is 0 it is illegal
1372 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501373 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301374
[email protected]f39f4b3f2010-05-12 17:04:081375 // Class that manages vertex attribs.
[email protected]3757a372012-01-19 05:20:441376 scoped_ptr<VertexAttribManager> vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301377
[email protected]b1122982010-05-17 23:04:241378 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1379 GLuint attrib_0_buffer_id_;
1380
1381 // The value currently in attrib_0.
1382 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1383
[email protected]fc753442011-02-04 19:49:491384 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1385 bool attrib_0_buffer_matches_value_;
1386
[email protected]b1122982010-05-17 23:04:241387 // The size of attrib 0.
1388 GLsizei attrib_0_size_;
1389
[email protected]8fbedc02010-11-18 18:43:401390 // The buffer used to simulate GL_FIXED attribs.
1391 GLuint fixed_attrib_buffer_id_;
1392
1393 // The size of fiixed attrib buffer.
1394 GLsizei fixed_attrib_buffer_size_;
1395
[email protected]3916c97e2010-02-25 03:20:501396 // Current active texture by 0 - n index.
1397 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1398 // be 2.
1399 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301400
[email protected]3916c97e2010-02-25 03:20:501401 // Which textures are bound to texture units through glActiveTexture.
1402 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471403
[email protected]3a2e7c7b2010-08-06 01:12:281404 // state saved for clearing so we can clear render buffers and then
1405 // restore to these values.
1406 GLclampf clear_red_;
1407 GLclampf clear_green_;
1408 GLclampf clear_blue_;
1409 GLclampf clear_alpha_;
1410 GLboolean mask_red_;
1411 GLboolean mask_green_;
1412 GLboolean mask_blue_;
1413 GLboolean mask_alpha_;
1414 GLint clear_stencil_;
1415 GLuint mask_stencil_front_;
1416 GLuint mask_stencil_back_;
1417 GLclampf clear_depth_;
1418 GLboolean mask_depth_;
[email protected]0a1e9ad2012-05-04 21:13:031419 bool enable_blend_;
[email protected]43410e92012-04-20 17:06:281420 bool enable_cull_face_;
[email protected]3a2e7c7b2010-08-06 01:12:281421 bool enable_scissor_test_;
[email protected]297ca1c2011-06-20 23:08:461422 bool enable_depth_test_;
1423 bool enable_stencil_test_;
1424 bool state_dirty_;
[email protected]3a2e7c7b2010-08-06 01:12:281425
[email protected]1d32bc82010-01-13 22:06:461426 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501427 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301428
[email protected]8e3e0662010-08-23 18:46:301429 // The currently bound framebuffers
1430 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1431 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561432
1433 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081434 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561435
[email protected]b9363b22010-06-09 22:06:151436 // The offscreen frame buffer that the client renders to. With EGL, the
1437 // depth and stencil buffers are separate. With regular GL there is a single
1438 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1439 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351440 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1441 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021442 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151443 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1444 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021445 GLenum offscreen_target_color_format_;
1446 GLenum offscreen_target_depth_format_;
1447 GLenum offscreen_target_stencil_format_;
1448 GLsizei offscreen_target_samples_;
[email protected]8a61d872012-01-20 12:43:561449 GLboolean offscreen_target_buffer_preserved_;
[email protected]6217d392010-03-25 22:08:351450
[email protected]de26b3c2011-08-03 21:54:271451 // The copy that is saved when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021452 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351453 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]8a61d872012-01-20 12:43:561454 TextureManager::TextureInfo::Ref offscreen_saved_color_texture_info_;
[email protected]de26b3c2011-08-03 21:54:271455
1456 // The copy that is used as the destination for multi-sample resolves.
1457 scoped_ptr<FrameBuffer> offscreen_resolved_frame_buffer_;
1458 scoped_ptr<Texture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051459 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351460
[email protected]882ba1e22012-03-08 19:02:531461 scoped_ptr<QueryManager> query_manager_;
1462 QueryManager::Query::Ref current_query_;
1463
[email protected]9d37f062011-11-22 01:24:521464 base::Callback<void(gfx::Size)> resize_callback_;
[email protected]22f320a2011-08-30 01:17:001465
[email protected]6b6e7ee2011-12-13 08:04:521466 MsgCallback msg_callback_;
[email protected]43f28f832010-02-03 02:28:481467
[email protected]b0af4f52011-09-28 22:04:421468 StreamTextureManager* stream_texture_manager_;
1469
[email protected]32fe9aa2011-01-21 23:47:131470 // The format of the back buffer_
1471 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461472 bool back_buffer_has_depth_;
1473 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131474
[email protected]473c01ccb2011-06-07 01:33:301475 bool teximage2d_faster_than_texsubimage2d_;
1476 bool bufferdata_faster_than_buffersubdata_;
1477
[email protected]8eee29c2010-04-29 03:38:291478 // The last error message set.
1479 std::string last_error_;
1480
[email protected]fa20ec82012-05-04 04:02:481481 int error_count_;
1482
[email protected]a3a93e7b2010-08-28 00:48:561483 // The current decoder error.
1484 error::Error current_decoder_error_;
1485
[email protected]b1d2dcb2010-05-17 19:24:181486 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451487 scoped_ptr<ShaderTranslator> vertex_translator_;
1488 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181489
[email protected]e82fb792011-09-22 00:33:291490 DisallowedFeatures disallowed_features_;
[email protected]c410da802011-03-14 19:17:411491
[email protected]915a59a12010-09-30 21:29:111492 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051493 const Validators* validators_;
[email protected]80eb6b52012-01-19 00:14:411494 FeatureInfo::Ref feature_info_;
[email protected]9438b012010-06-15 22:55:051495
[email protected]b493ee622011-04-13 23:52:001496 // This indicates all the following texSubImage2D calls that are part of the
1497 // failed texImage2D call should be ignored.
1498 bool tex_image_2d_failed_;
1499
[email protected]65225772011-05-12 21:10:241500 int frame_number_;
1501
[email protected]38d139d2011-07-14 00:38:431502 bool has_arb_robustness_;
1503 GLenum reset_status_;
1504
[email protected]75c023c2011-08-22 23:54:511505 bool needs_mac_nvidia_driver_workaround_;
[email protected]a2a0fe762011-09-20 00:59:121506 bool needs_glsl_built_in_function_emulation_;
[email protected]75c023c2011-08-22 23:54:511507
[email protected]f0d74742011-10-03 16:31:041508 // These flags are used to override the state of the shared feature_info_
1509 // member. Because the same FeatureInfo instance may be shared among many
1510 // contexts, the assumptions on the availablity of extensions in WebGL
1511 // contexts may be broken. These flags override the shared state to preserve
1512 // WebGL semantics.
1513 bool force_webgl_glsl_validation_;
1514 bool derivatives_explicitly_enabled_;
1515
[email protected]062c38b2012-01-18 03:25:101516 bool compile_shader_always_succeeds_;
1517
[email protected]c892a4e12012-05-08 18:20:191518 bool disable_workarounds_;
1519
[email protected]e51bdf32011-11-23 22:21:461520#if defined(OS_MACOSX)
1521 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1522 TextureToIOSurfaceMap texture_to_io_surface_map_;
1523#endif
1524
[email protected]c826d732012-02-09 04:40:261525 typedef std::vector<GLES2DecoderImpl*> ChildList;
1526 ChildList children_;
1527
[email protected]43410e92012-04-20 17:06:281528 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1529
1530 // Cached values of the currently assigned viewport dimensions.
1531 GLint viewport_x_, viewport_y_;
1532 GLsizei viewport_width_, viewport_height_;
1533 GLsizei viewport_max_width_, viewport_max_height_;
1534
[email protected]96449d2c2009-11-25 00:01:321535 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1536};
1537
[email protected]6217d392010-03-25 22:08:351538ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1539 : decoder_(decoder) {
1540 decoder_->CopyRealGLErrorsToWrapper();
1541}
1542
1543ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1544 decoder_->ClearRealGLErrors();
1545}
1546
1547ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1548 GLuint id)
1549 : decoder_(decoder) {
1550 ScopedGLErrorSuppressor suppressor(decoder_);
1551
1552 // TODO(apatrick): Check if there are any other states that need to be reset
1553 // before binding a new texture.
1554 glActiveTexture(GL_TEXTURE0);
1555 glBindTexture(GL_TEXTURE_2D, id);
1556}
1557
1558ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1559 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301560 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351561}
1562
1563ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1564 GLuint id)
1565 : decoder_(decoder) {
1566 ScopedGLErrorSuppressor suppressor(decoder_);
1567 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1568}
1569
1570ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1571 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301572 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351573}
1574
1575ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1576 GLuint id)
1577 : decoder_(decoder) {
1578 ScopedGLErrorSuppressor suppressor(decoder_);
1579 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1580}
1581
1582ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1583 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301584 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351585}
1586
[email protected]34ff8b0c2010-10-01 20:06:021587ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271588 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521589 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021590 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1591 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]c0701082011-04-20 00:34:521592 (!decoder_->bound_read_framebuffer_.get() ||
1593 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021594 if (!resolve_and_bind_)
1595 return;
1596
1597 ScopedGLErrorSuppressor suppressor(decoder_);
1598 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1599 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271600 GLuint targetid;
1601 if (internal) {
1602 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1603 decoder_->offscreen_resolved_frame_buffer_.reset(
1604 new FrameBuffer(decoder_));
1605 decoder_->offscreen_resolved_frame_buffer_->Create();
1606 decoder_->offscreen_resolved_color_texture_.reset(new Texture(decoder_));
1607 decoder_->offscreen_resolved_color_texture_->Create();
1608
1609 DCHECK(decoder_->offscreen_saved_color_format_);
1610 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1611 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_);
[email protected]de26b3c2011-08-03 21:54:271612 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1613 decoder_->offscreen_resolved_color_texture_.get());
1614 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1615 GL_FRAMEBUFFER_COMPLETE) {
1616 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1617 << "because offscreen resolved FBO was incomplete.";
1618 return;
1619 }
1620 }
1621 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1622 } else {
1623 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1624 }
1625 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021626 const int width = decoder_->offscreen_size_.width();
1627 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181628 glDisable(GL_SCISSOR_TEST);
[email protected]57edfdad2012-02-07 04:57:151629 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021630 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1631 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1632 } else {
1633 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1634 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1635 }
[email protected]de26b3c2011-08-03 21:54:271636 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021637}
1638
1639ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1640 if (!resolve_and_bind_)
1641 return;
1642
1643 ScopedGLErrorSuppressor suppressor(decoder_);
1644 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181645 if (decoder_->enable_scissor_test_) {
1646 glEnable(GL_SCISSOR_TEST);
1647 }
[email protected]34ff8b0c2010-10-01 20:06:021648}
1649
[email protected]6217d392010-03-25 22:08:351650Texture::Texture(GLES2DecoderImpl* decoder)
1651 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141652 id_(0),
1653 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351654}
1655
1656Texture::~Texture() {
1657 // This does not destroy the render texture because that would require that
1658 // the associated GL context was current. Just check that it was explicitly
1659 // destroyed.
1660 DCHECK_EQ(id_, 0u);
1661}
1662
1663void Texture::Create() {
1664 ScopedGLErrorSuppressor suppressor(decoder_);
1665 Destroy();
1666 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581667 ScopedTexture2DBinder binder(decoder_, id_);
1668 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1669 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1670 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1671 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]62788802011-10-03 17:57:161672
1673 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1674 // never called on an offscreen context, no data will ever be uploaded to the
1675 // saved offscreen color texture (it is deferred until to when SwapBuffers
1676 // is called). My idea is that some nvidia drivers might have a bug where
1677 // deleting a texture that has never been populated might cause a
1678 // crash.
1679 glTexImage2D(
1680 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
[email protected]1078f912011-12-23 13:12:141681 estimated_size_ = 16u * 16u * 4u;
1682 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351683}
1684
[email protected]34ff8b0c2010-10-01 20:06:021685bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351686 DCHECK_NE(id_, 0u);
1687 ScopedGLErrorSuppressor suppressor(decoder_);
1688 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]6217d392010-03-25 22:08:351689
[email protected]f0e6a34f2012-01-04 20:53:401690 WrappedTexImage2D(GL_TEXTURE_2D,
1691 0, // mip level
1692 format,
1693 size.width(),
1694 size.height(),
1695 0, // border
1696 format,
1697 GL_UNSIGNED_BYTE,
1698 NULL);
[email protected]6217d392010-03-25 22:08:351699
[email protected]d37231fa2010-04-09 21:16:021700 size_ = size;
1701
[email protected]1078f912011-12-23 13:12:141702 bool success = glGetError() == GL_NO_ERROR;
1703 if (success) {
1704 uint32 image_size = 0;
[email protected]3458a64a2012-04-10 17:39:341705 GLES2Util::ComputeImageDataSizes(
1706 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 4, &image_size,
1707 NULL, NULL);
[email protected]1078f912011-12-23 13:12:141708 estimated_size_ = image_size;
1709 decoder_->UpdateBackbufferMemoryAccounting();
1710 }
1711 return success;
[email protected]6217d392010-03-25 22:08:351712}
1713
[email protected]3a4d0c52011-06-29 23:11:581714void Texture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351715 DCHECK_NE(id_, 0u);
1716 ScopedGLErrorSuppressor suppressor(decoder_);
1717 ScopedTexture2DBinder binder(decoder_, id_);
1718 glCopyTexImage2D(GL_TEXTURE_2D,
1719 0, // level
[email protected]3a4d0c52011-06-29 23:11:581720 format,
[email protected]6217d392010-03-25 22:08:351721 0, 0,
1722 size.width(),
1723 size.height(),
1724 0); // border
1725}
1726
1727void Texture::Destroy() {
1728 if (id_ != 0) {
1729 ScopedGLErrorSuppressor suppressor(decoder_);
1730 glDeleteTextures(1, &id_);
1731 id_ = 0;
[email protected]1078f912011-12-23 13:12:141732 estimated_size_ = 0;
1733 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351734 }
1735}
1736
[email protected]97872062010-11-03 19:07:051737void Texture::Invalidate() {
1738 id_ = 0;
1739}
1740
[email protected]6217d392010-03-25 22:08:351741RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1742 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141743 id_(0),
1744 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351745}
1746
1747RenderBuffer::~RenderBuffer() {
1748 // This does not destroy the render buffer because that would require that
1749 // the associated GL context was current. Just check that it was explicitly
1750 // destroyed.
1751 DCHECK_EQ(id_, 0u);
1752}
1753
1754void RenderBuffer::Create() {
1755 ScopedGLErrorSuppressor suppressor(decoder_);
1756 Destroy();
1757 glGenRenderbuffersEXT(1, &id_);
1758}
1759
[email protected]34ff8b0c2010-10-01 20:06:021760bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1761 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351762 ScopedGLErrorSuppressor suppressor(decoder_);
1763 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021764 if (samples <= 1) {
1765 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1766 format,
1767 size.width(),
1768 size.height());
1769 } else {
[email protected]57edfdad2012-02-07 04:57:151770 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021771 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1772 samples,
1773 format,
1774 size.width(),
1775 size.height());
1776 } else {
1777 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1778 samples,
1779 format,
1780 size.width(),
1781 size.height());
1782 }
1783 }
[email protected]1078f912011-12-23 13:12:141784 bool success = glGetError() == GL_NO_ERROR;
1785 if (success) {
1786 estimated_size_ = size.width() * size.height() * samples *
1787 GLES2Util::RenderbufferBytesPerPixel(format);
1788 decoder_->UpdateBackbufferMemoryAccounting();
1789 }
1790 return success;
[email protected]6217d392010-03-25 22:08:351791}
1792
1793void RenderBuffer::Destroy() {
1794 if (id_ != 0) {
1795 ScopedGLErrorSuppressor suppressor(decoder_);
1796 glDeleteRenderbuffersEXT(1, &id_);
1797 id_ = 0;
[email protected]1078f912011-12-23 13:12:141798 estimated_size_ = 0;
1799 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351800 }
1801}
1802
[email protected]97872062010-11-03 19:07:051803void RenderBuffer::Invalidate() {
1804 id_ = 0;
1805}
1806
[email protected]6217d392010-03-25 22:08:351807FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1808 : decoder_(decoder),
1809 id_(0) {
1810}
1811
1812FrameBuffer::~FrameBuffer() {
1813 // This does not destroy the frame buffer because that would require that
1814 // the associated GL context was current. Just check that it was explicitly
1815 // destroyed.
1816 DCHECK_EQ(id_, 0u);
1817}
1818
1819void FrameBuffer::Create() {
1820 ScopedGLErrorSuppressor suppressor(decoder_);
1821 Destroy();
1822 glGenFramebuffersEXT(1, &id_);
1823}
1824
1825void FrameBuffer::AttachRenderTexture(Texture* texture) {
1826 DCHECK_NE(id_, 0u);
1827 ScopedGLErrorSuppressor suppressor(decoder_);
1828 ScopedFrameBufferBinder binder(decoder_, id_);
1829 GLuint attach_id = texture ? texture->id() : 0;
1830 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1831 GL_COLOR_ATTACHMENT0,
1832 GL_TEXTURE_2D,
1833 attach_id,
1834 0);
1835}
1836
[email protected]b9363b22010-06-09 22:06:151837void FrameBuffer::AttachRenderBuffer(GLenum target,
1838 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351839 DCHECK_NE(id_, 0u);
1840 ScopedGLErrorSuppressor suppressor(decoder_);
1841 ScopedFrameBufferBinder binder(decoder_, id_);
1842 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1843 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151844 target,
[email protected]6217d392010-03-25 22:08:351845 GL_RENDERBUFFER,
1846 attach_id);
1847}
1848
[email protected]6217d392010-03-25 22:08:351849void FrameBuffer::Destroy() {
1850 if (id_ != 0) {
1851 ScopedGLErrorSuppressor suppressor(decoder_);
1852 glDeleteFramebuffersEXT(1, &id_);
1853 id_ = 0;
1854 }
1855}
1856
[email protected]97872062010-11-03 19:07:051857void FrameBuffer::Invalidate() {
1858 id_ = 0;
1859}
1860
[email protected]6217d392010-03-25 22:08:351861GLenum FrameBuffer::CheckStatus() {
1862 DCHECK_NE(id_, 0u);
1863 ScopedGLErrorSuppressor suppressor(decoder_);
1864 ScopedFrameBufferBinder binder(decoder_, id_);
1865 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1866}
1867
[email protected]aa7666122011-09-02 19:45:521868GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1869 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321870}
1871
[email protected]aa7666122011-09-02 19:45:521872GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391873 : GLES2Decoder(),
[email protected]3b1ecc262011-08-03 22:49:571874 group_(group),
[email protected]96449d2c2009-11-25 00:01:321875 error_bits_(0),
[email protected]96449d2c2009-11-25 00:01:321876 pack_alignment_(4),
1877 unpack_alignment_(4),
[email protected]43410e92012-04-20 17:06:281878 unpack_flip_y_(false),
1879 unpack_premultiply_alpha_(false),
[email protected]b1122982010-05-17 23:04:241880 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491881 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241882 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401883 fixed_attrib_buffer_id_(0),
1884 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501885 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281886 clear_red_(0),
1887 clear_green_(0),
1888 clear_blue_(0),
1889 clear_alpha_(0),
1890 mask_red_(true),
1891 mask_green_(true),
1892 mask_blue_(true),
1893 mask_alpha_(true),
1894 clear_stencil_(0),
1895 mask_stencil_front_(-1),
1896 mask_stencil_back_(-1),
1897 clear_depth_(1.0f),
1898 mask_depth_(true),
[email protected]0a1e9ad2012-05-04 21:13:031899 enable_blend_(false),
[email protected]43410e92012-04-20 17:06:281900 enable_cull_face_(false),
[email protected]3a2e7c7b2010-08-06 01:12:281901 enable_scissor_test_(false),
[email protected]297ca1c2011-06-20 23:08:461902 enable_depth_test_(false),
1903 enable_stencil_test_(false),
1904 state_dirty_(true),
[email protected]34ff8b0c2010-10-01 20:06:021905 offscreen_target_color_format_(0),
1906 offscreen_target_depth_format_(0),
1907 offscreen_target_stencil_format_(0),
1908 offscreen_target_samples_(0),
[email protected]8a61d872012-01-20 12:43:561909 offscreen_target_buffer_preserved_(true),
[email protected]97872062010-11-03 19:07:051910 offscreen_saved_color_format_(0),
[email protected]b0af4f52011-09-28 22:04:421911 stream_texture_manager_(NULL),
[email protected]32fe9aa2011-01-21 23:47:131912 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:461913 back_buffer_has_depth_(false),
1914 back_buffer_has_stencil_(false),
[email protected]473c01ccb2011-06-07 01:33:301915 teximage2d_faster_than_texsubimage2d_(true),
1916 bufferdata_faster_than_buffersubdata_(true),
[email protected]fa20ec82012-05-04 04:02:481917 error_count_(0),
[email protected]a3a93e7b2010-08-28 00:48:561918 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051919 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111920 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001921 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241922 tex_image_2d_failed_(false),
[email protected]38d139d2011-07-14 00:38:431923 frame_number_(0),
1924 has_arb_robustness_(false),
[email protected]75c023c2011-08-22 23:54:511925 reset_status_(GL_NO_ERROR),
[email protected]a2a0fe762011-09-20 00:59:121926 needs_mac_nvidia_driver_workaround_(false),
[email protected]f0d74742011-10-03 16:31:041927 needs_glsl_built_in_function_emulation_(false),
1928 force_webgl_glsl_validation_(false),
[email protected]062c38b2012-01-18 03:25:101929 derivatives_explicitly_enabled_(false),
[email protected]43410e92012-04-20 17:06:281930 compile_shader_always_succeeds_(false),
[email protected]c892a4e12012-05-08 18:20:191931 disable_workarounds_(
1932 CommandLine::ForCurrentProcess()->HasSwitch(
1933 switches::kDisableGpuDriverBugWorkarounds)),
[email protected]43410e92012-04-20 17:06:281934 viewport_x_(0),
1935 viewport_y_(0),
1936 viewport_width_(0),
1937 viewport_height_(0),
1938 viewport_max_width_(0),
1939 viewport_max_height_(0) {
[email protected]3b1ecc262011-08-03 22:49:571940 DCHECK(group);
1941
[email protected]b1122982010-05-17 23:04:241942 attrib_0_value_.v[0] = 0.0f;
1943 attrib_0_value_.v[1] = 0.0f;
1944 attrib_0_value_.v[2] = 0.0f;
1945 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151946
[email protected]c2f8c8402010-12-06 18:07:241947 // The shader translator is used for WebGL even when running on EGL
1948 // because additional restrictions are needed (like only enabling
1949 // GL_OES_standard_derivatives on demand). It is used for the unit
1950 // tests because
1951 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1952 // empty string to CompileShader and this is not a valid shader.
1953 // TODO(apatrick): fix this test.
1954 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:041955 !feature_info_->feature_flags().chromium_webglsl &&
1956 !force_webgl_glsl_validation_) ||
[email protected]39ba4f02012-03-26 01:16:001957 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
1958 CommandLine::ForCurrentProcess()->HasSwitch(
1959 switches::kDisableGLSLTranslator)) {
[email protected]b9363b22010-06-09 22:06:151960 use_shader_translator_ = false;
1961 }
[email protected]473c01ccb2011-06-07 01:33:301962
1963 // TODO(gman): Consider setting these based on GPU and/or driver.
1964 if (IsAngle()) {
1965 teximage2d_faster_than_texsubimage2d_ = false;
1966 bufferdata_faster_than_buffersubdata_ = false;
1967 }
[email protected]96449d2c2009-11-25 00:01:321968}
1969
[email protected]80eb6b52012-01-19 00:14:411970GLES2DecoderImpl::~GLES2DecoderImpl() {
1971}
1972
[email protected]c410da802011-03-14 19:17:411973bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:381974 const scoped_refptr<gfx::GLSurface>& surface,
1975 const scoped_refptr<gfx::GLContext>& context,
[email protected]069944672012-04-25 20:52:231976 bool offscreen,
[email protected]c410da802011-03-14 19:17:411977 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:291978 const DisallowedFeatures& disallowed_features,
[email protected]c410da802011-03-14 19:17:411979 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:241980 const std::vector<int32>& attribs) {
[email protected]4bedba72010-04-20 22:08:541981 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301982 DCHECK(!context_.get());
1983
[email protected]e844ae22012-01-14 03:36:261984 if (CommandLine::ForCurrentProcess()->HasSwitch(
1985 switches::kEnableGPUDebugging)) {
1986 set_debug(true);
1987 }
1988
[email protected]39ba4f02012-03-26 01:16:001989 if (CommandLine::ForCurrentProcess()->HasSwitch(
1990 switches::kEnableGPUCommandLogging)) {
1991 set_log_commands(true);
1992 }
1993
[email protected]062c38b2012-01-18 03:25:101994 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
1995 switches::kCompileShaderAlwaysSucceeds);
1996
[email protected]fbe20372011-06-01 01:46:381997 // Take ownership of the GLSurface. TODO(apatrick): once the parent / child
1998 // context is retired, the decoder should not take an initial surface as
1999 // an argument to this function.
2000 // Maybe create a short lived offscreen GLSurface for the purpose of
2001 // initializing the decoder's GLContext.
2002 surface_ = surface;
[email protected]f62a5ab2011-05-23 20:34:152003
[email protected]66791e382010-07-14 20:48:302004 // Take ownership of the GLContext.
[email protected]fbe20372011-06-01 01:46:382005 context_ = context;
[email protected]d37231fa2010-04-09 21:16:022006
[email protected]246a70452010-03-05 21:53:502007 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:012008 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
2009 << "MakeCurrent failed.";
[email protected]1871a092011-10-10 21:46:422010 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]246a70452010-03-05 21:53:502011 Destroy();
2012 return false;
[email protected]eb54a562010-01-20 21:55:182013 }
2014
[email protected]e82fb792011-09-22 00:33:292015 if (!group_->Initialize(disallowed_features, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:222016 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:392017 << "failed to initialize.";
[email protected]1871a092011-10-10 21:46:422018 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]a3ded6d2010-10-19 06:44:392019 Destroy();
[email protected]ae1741092010-11-17 19:16:032020 return false;
[email protected]a3ded6d2010-10-19 06:44:392021 }
[email protected]b64c24952012-04-19 03:20:272022 CHECK_GL_ERROR();
[email protected]43410e92012-04-20 17:06:282023
2024 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
2025 copy_texture_CHROMIUM_->Initialize();
2026 CHECK_GL_ERROR();
2027
[email protected]e82fb792011-09-22 00:33:292028 disallowed_features_ = disallowed_features;
[email protected]246a70452010-03-05 21:53:502029
[email protected]3757a372012-01-19 05:20:442030 vertex_attrib_manager_.reset(new VertexAttribManager());
2031 vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:322032
[email protected]c45f1972012-03-14 07:27:362033 query_manager_.reset(new QueryManager(this, feature_info_->feature_flags(
2034 ).use_arb_occlusion_query2_for_occlusion_query_boolean));
[email protected]882ba1e22012-03-08 19:02:532035
[email protected]302ce6d2011-07-07 23:28:112036 util_.set_num_compressed_texture_formats(
2037 validators_->compressed_texture_format.GetValues().size());
2038
[email protected]1071e572011-02-09 20:00:122039 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2040 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2041 // OpenGL ES 2.0 does not have this issue.
2042 glEnableVertexAttribArray(0);
2043 }
[email protected]b1122982010-05-17 23:04:242044 glGenBuffersARB(1, &attrib_0_buffer_id_);
2045 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2046 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2047 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:402048 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:082049
[email protected]246a70452010-03-05 21:53:502050 texture_units_.reset(
2051 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:152052 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:492053 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:312054 // We want the last bind to be 2D.
2055 TextureManager::TextureInfo* info;
2056 if (feature_info_->feature_flags().oes_egl_image_external) {
2057 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_EXTERNAL_OES);
2058 texture_units_[tt].bound_texture_external_oes = info;
2059 glBindTexture(GL_TEXTURE_EXTERNAL_OES, info->service_id());
2060 }
[email protected]e51bdf32011-11-23 22:21:462061 if (feature_info_->feature_flags().arb_texture_rectangle) {
2062 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_RECTANGLE_ARB);
2063 texture_units_[tt].bound_texture_rectangle_arb = info;
2064 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, info->service_id());
2065 }
[email protected]61eeb33f2011-07-26 15:30:312066 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:492067 texture_units_[tt].bound_texture_cube_map = info;
2068 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
2069 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2070 texture_units_[tt].bound_texture_2d = info;
2071 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:152072 }
[email protected]00f893d2010-08-24 18:55:492073 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:502074 CHECK_GL_ERROR();
2075
[email protected]297ca1c2011-06-20 23:08:462076 ContextCreationAttribParser attrib_parser;
2077 if (!attrib_parser.Parse(attribs))
2078 return false;
[email protected]41c56362011-06-14 16:47:432079
[email protected]297ca1c2011-06-20 23:08:462080 // These are NOT if the back buffer has these proprorties. They are
2081 // if we want the command buffer to enforce them regardless of what
2082 // the real backbuffer is assuming the real back buffer gives us more than
2083 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2084 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2085 // can't do anything about that.
2086
2087 GLint v = 0;
2088 glGetIntegerv(GL_ALPHA_BITS, &v);
2089 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2090 // user requested RGB then RGB. If the user did not specify a preference than
2091 // use whatever we were given. Same for DEPTH and STENCIL.
2092 back_buffer_color_format_ =
2093 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2094 glGetIntegerv(GL_DEPTH_BITS, &v);
2095 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2096 glGetIntegerv(GL_STENCIL_BITS, &v);
2097 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2098
[email protected]069944672012-04-25 20:52:232099 if (offscreen) {
[email protected]34ff8b0c2010-10-01 20:06:022100 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:542101 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:022102 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
2103 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:432104 // max_sample_count must be initialized to a sane value. If
2105 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2106 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:022107 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2108 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2109 max_sample_count);
2110 } else {
2111 offscreen_target_samples_ = 1;
2112 }
[email protected]8a61d872012-01-20 12:43:562113 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
[email protected]34ff8b0c2010-10-01 20:06:022114
2115 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2116 const bool rgb8_supported =
2117 context_->HasExtension("GL_OES_rgb8_rgba8");
2118 // The only available default render buffer formats in GLES2 have very
2119 // little precision. Don't enable multisampling unless 8-bit render
2120 // buffer formats are available--instead fall back to 8-bit textures.
2121 if (rgb8_supported && offscreen_target_samples_ > 1) {
2122 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2123 GL_RGBA8 : GL_RGB8;
2124 } else {
2125 offscreen_target_samples_ = 1;
2126 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2127 GL_RGBA : GL_RGB;
2128 }
2129
2130 // ANGLE only supports packed depth/stencil formats, so use it if it is
2131 // available.
2132 const bool depth24_stencil8_supported =
2133 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272134 VLOG(1) << "GL_OES_packed_depth_stencil "
2135 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:002136 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2137 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022138 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2139 offscreen_target_stencil_format_ = 0;
2140 } else {
2141 // It may be the case that this depth/stencil combination is not
2142 // supported, but this will be checked later by CheckFramebufferStatus.
2143 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2144 GL_DEPTH_COMPONENT16 : 0;
2145 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2146 GL_STENCIL_INDEX8 : 0;
2147 }
2148 } else {
2149 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2150 GL_RGBA : GL_RGB;
2151
2152 // If depth is requested at all, use the packed depth stencil format if
2153 // it's available, as some desktop GL drivers don't support any non-packed
2154 // formats for depth attachments.
2155 const bool depth24_stencil8_supported =
2156 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272157 VLOG(1) << "GL_EXT_packed_depth_stencil "
2158 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:022159
[email protected]71ee3642010-10-14 18:08:002160 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2161 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022162 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2163 offscreen_target_stencil_format_ = 0;
2164 } else {
2165 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2166 GL_DEPTH_COMPONENT : 0;
2167 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2168 GL_STENCIL_INDEX : 0;
2169 }
2170 }
2171
[email protected]97872062010-11-03 19:07:052172 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2173 GL_RGBA : GL_RGB;
2174
[email protected]6217d392010-03-25 22:08:352175 // Create the target frame buffer. This is the one that the client renders
2176 // directly to.
2177 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
2178 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022179 // Due to GLES2 format limitations, either the color texture (for
2180 // non-multisampling) or the color render buffer (for multisampling) will be
2181 // attached to the offscreen frame buffer. The render buffer has more
2182 // limited formats available to it, but the texture can't do multisampling.
2183 if (IsOffscreenBufferMultisampled()) {
2184 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
2185 offscreen_target_color_render_buffer_->Create();
2186 } else {
2187 offscreen_target_color_texture_.reset(new Texture(this));
2188 offscreen_target_color_texture_->Create();
2189 }
2190 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152191 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022192 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152193 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:352194
2195 // Create the saved offscreen texture. The target frame buffer is copied
2196 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:022197 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
2198 offscreen_saved_frame_buffer_->Create();
2199 //
[email protected]6217d392010-03-25 22:08:352200 offscreen_saved_color_texture_.reset(new Texture(this));
2201 offscreen_saved_color_texture_->Create();
2202
[email protected]6217d392010-03-25 22:08:352203 // Allocate the render buffers at their initial size and check the status
2204 // of the frame buffers is okay.
[email protected]799b4b22011-08-22 17:09:592205 if (!ResizeOffscreenFrameBuffer(size)) {
[email protected]d0498742010-09-20 20:27:012206 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:352207 Destroy();
2208 return false;
2209 }
2210
2211 // Bind to the new default frame buffer (the offscreen target frame buffer).
2212 // This should now be associated with ID zero.
2213 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2214 }
2215
[email protected]295faf4b2012-01-25 23:31:412216 // Clear the backbuffer.
2217 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2218
[email protected]76a0ee102010-04-07 21:03:042219 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2220 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2221 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372222 // mailing list archives. It also implicitly enables the desktop GL
2223 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2224 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152225 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2226 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372227 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152228 }
[email protected]de17df392010-04-23 21:09:412229
[email protected]38d139d2011-07-14 00:38:432230 has_arb_robustness_ = context->HasExtension("GL_ARB_robustness");
2231
[email protected]c892a4e12012-05-08 18:20:192232 if (!disable_workarounds_) {
[email protected]75c023c2011-08-22 23:54:512233#if defined(OS_MACOSX)
[email protected]a2a0fe762011-09-20 00:59:122234 const char* vendor_str = reinterpret_cast<const char*>(
2235 glGetString(GL_VENDOR));
2236 needs_mac_nvidia_driver_workaround_ =
2237 vendor_str && strstr(vendor_str, "NVIDIA");
2238 needs_glsl_built_in_function_emulation_ =
2239 vendor_str && (strstr(vendor_str, "ATI") || strstr(vendor_str, "AMD"));
[email protected]75c023c2011-08-22 23:54:512240#endif
[email protected]a2a0fe762011-09-20 00:59:122241 }
[email protected]75c023c2011-08-22 23:54:512242
[email protected]c2f8c8402010-12-06 18:07:242243 if (!InitializeShaderTranslator()) {
2244 return false;
[email protected]de17df392010-04-23 21:09:412245 }
[email protected]76a0ee102010-04-07 21:03:042246
[email protected]5904806b2012-05-08 18:10:222247 viewport_width_ = size.width();
2248 viewport_height_ = size.height();
2249 glViewport(viewport_x_, viewport_y_, viewport_width_, viewport_height_);
[email protected]43410e92012-04-20 17:06:282250
[email protected]5904806b2012-05-08 18:10:222251 GLint viewport_params[4] = { 0 };
[email protected]43410e92012-04-20 17:06:282252 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2253 viewport_max_width_ = viewport_params[0];
[email protected]5904806b2012-05-08 18:10:222254 viewport_max_height_ = viewport_params[1];
[email protected]43410e92012-04-20 17:06:282255
[email protected]246a70452010-03-05 21:53:502256 return true;
[email protected]96449d2c2009-11-25 00:01:322257}
2258
[email protected]302ce6d2011-07-07 23:28:112259void GLES2DecoderImpl::UpdateCapabilities() {
2260 util_.set_num_compressed_texture_formats(
2261 validators_->compressed_texture_format.GetValues().size());
2262 util_.set_num_shader_binary_formats(
2263 validators_->shader_binary_format.GetValues().size());
2264}
2265
[email protected]c2f8c8402010-12-06 18:07:242266bool GLES2DecoderImpl::InitializeShaderTranslator() {
2267 // Re-check the state of use_shader_translator_ each time this is called.
2268 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:042269 (feature_info_->feature_flags().chromium_webglsl ||
2270 force_webgl_glsl_validation_) &&
[email protected]c2f8c8402010-12-06 18:07:242271 !use_shader_translator_) {
2272 use_shader_translator_ = true;
2273 }
2274 if (!use_shader_translator_) {
2275 return true;
2276 }
2277 ShBuiltInResources resources;
2278 ShInitBuiltInResources(&resources);
2279 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2280 resources.MaxVertexUniformVectors =
2281 group_->max_vertex_uniform_vectors();
2282 resources.MaxVaryingVectors = group_->max_varying_vectors();
2283 resources.MaxVertexTextureImageUnits =
2284 group_->max_vertex_texture_image_units();
2285 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2286 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2287 resources.MaxFragmentUniformVectors =
2288 group_->max_fragment_uniform_vectors();
2289 resources.MaxDrawBuffers = 1;
[email protected]f0d74742011-10-03 16:31:042290
2291 if (force_webgl_glsl_validation_) {
2292 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2293 } else {
2294 resources.OES_standard_derivatives =
2295 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
[email protected]e51bdf32011-11-23 22:21:462296 resources.ARB_texture_rectangle =
2297 feature_info_->feature_flags().arb_texture_rectangle ? 1 : 0;
[email protected]f0d74742011-10-03 16:31:042298 }
2299
[email protected]c2f8c8402010-12-06 18:07:242300 vertex_translator_.reset(new ShaderTranslator);
[email protected]f0d74742011-10-03 16:31:042301 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ||
2302 feature_info_->feature_flags().chromium_webglsl ?
2303 SH_WEBGL_SPEC : SH_GLES2_SPEC;
[email protected]a2a0fe762011-09-20 00:59:122304 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2305 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2306 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2307 ShaderTranslatorInterface::GlslBuiltInFunctionBehavior function_behavior =
2308 needs_glsl_built_in_function_emulation_ ?
2309 ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated :
2310 ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal;
[email protected]c2f8c8402010-12-06 18:07:242311 if (!vertex_translator_->Init(
[email protected]a2a0fe762011-09-20 00:59:122312 SH_VERTEX_SHADER, shader_spec, &resources,
2313 implementation_type, function_behavior)) {
[email protected]c2f8c8402010-12-06 18:07:242314 LOG(ERROR) << "Could not initialize vertex shader translator.";
2315 Destroy();
2316 return false;
2317 }
2318 fragment_translator_.reset(new ShaderTranslator);
2319 if (!fragment_translator_->Init(
[email protected]a2a0fe762011-09-20 00:59:122320 SH_FRAGMENT_SHADER, shader_spec, &resources,
2321 implementation_type, function_behavior)) {
[email protected]c2f8c8402010-12-06 18:07:242322 LOG(ERROR) << "Could not initialize fragment shader translator.";
2323 Destroy();
2324 return false;
2325 }
2326 return true;
2327}
2328
[email protected]ae51d192010-04-27 00:48:032329bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472330 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032331 if (GetBufferInfo(client_ids[ii])) {
2332 return false;
2333 }
2334 }
2335 scoped_array<GLuint> service_ids(new GLuint[n]);
2336 glGenBuffersARB(n, service_ids.get());
2337 for (GLsizei ii = 0; ii < n; ++ii) {
2338 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2339 }
2340 return true;
2341}
2342
2343bool GLES2DecoderImpl::GenFramebuffersHelper(
2344 GLsizei n, const GLuint* client_ids) {
2345 for (GLsizei ii = 0; ii < n; ++ii) {
2346 if (GetFramebufferInfo(client_ids[ii])) {
2347 return false;
2348 }
2349 }
2350 scoped_array<GLuint> service_ids(new GLuint[n]);
2351 glGenFramebuffersEXT(n, service_ids.get());
2352 for (GLsizei ii = 0; ii < n; ++ii) {
2353 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2354 }
2355 return true;
2356}
2357
2358bool GLES2DecoderImpl::GenRenderbuffersHelper(
2359 GLsizei n, const GLuint* client_ids) {
2360 for (GLsizei ii = 0; ii < n; ++ii) {
2361 if (GetRenderbufferInfo(client_ids[ii])) {
2362 return false;
2363 }
2364 }
2365 scoped_array<GLuint> service_ids(new GLuint[n]);
2366 glGenRenderbuffersEXT(n, service_ids.get());
2367 for (GLsizei ii = 0; ii < n; ++ii) {
2368 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2369 }
2370 return true;
2371}
2372
2373bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2374 for (GLsizei ii = 0; ii < n; ++ii) {
2375 if (GetTextureInfo(client_ids[ii])) {
2376 return false;
2377 }
2378 }
2379 scoped_array<GLuint> service_ids(new GLuint[n]);
2380 glGenTextures(n, service_ids.get());
2381 for (GLsizei ii = 0; ii < n; ++ii) {
2382 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2383 }
2384 return true;
2385}
2386
2387void GLES2DecoderImpl::DeleteBuffersHelper(
2388 GLsizei n, const GLuint* client_ids) {
2389 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102390 BufferManager::BufferInfo* buffer = GetBufferInfo(client_ids[ii]);
2391 if (buffer && !buffer->IsDeleted()) {
[email protected]3757a372012-01-19 05:20:442392 vertex_attrib_manager_->Unbind(buffer);
[email protected]a0b78dc2011-11-11 10:43:102393 if (bound_array_buffer_ == buffer) {
2394 bound_array_buffer_ = NULL;
2395 }
2396 if (bound_element_array_buffer_ == buffer) {
2397 bound_element_array_buffer_ = NULL;
2398 }
[email protected]ae51d192010-04-27 00:48:032399 RemoveBufferInfo(client_ids[ii]);
2400 }
[email protected]a93bb842010-02-16 23:03:472401 }
[email protected]07f54fcc2009-12-22 02:46:302402}
2403
[email protected]ae51d192010-04-27 00:48:032404void GLES2DecoderImpl::DeleteFramebuffersHelper(
2405 GLsizei n, const GLuint* client_ids) {
[email protected]b177ae22011-11-01 03:29:112406 bool supports_seperate_framebuffer_binds =
2407 feature_info_->feature_flags().chromium_framebuffer_multisample;
2408
[email protected]a25fa872010-03-25 02:57:582409 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102410 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ae51d192010-04-27 00:48:032411 GetFramebufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102412 if (framebuffer && !framebuffer->IsDeleted()) {
2413 if (framebuffer == bound_draw_framebuffer_) {
[email protected]297ca1c2011-06-20 23:08:462414 bound_draw_framebuffer_ = NULL;
2415 state_dirty_ = true;
[email protected]b177ae22011-11-01 03:29:112416 GLenum target = supports_seperate_framebuffer_binds ?
2417 GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER;
2418 glBindFramebufferEXT(target, GetBackbufferServiceId());
2419 }
[email protected]a0b78dc2011-11-11 10:43:102420 if (framebuffer == bound_read_framebuffer_) {
[email protected]b177ae22011-11-01 03:29:112421 bound_read_framebuffer_ = NULL;
2422 GLenum target = supports_seperate_framebuffer_binds ?
2423 GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER;
2424 glBindFramebufferEXT(target, GetBackbufferServiceId());
[email protected]297ca1c2011-06-20 23:08:462425 }
[email protected]ae51d192010-04-27 00:48:032426 RemoveFramebufferInfo(client_ids[ii]);
2427 }
[email protected]a25fa872010-03-25 02:57:582428 }
[email protected]07f54fcc2009-12-22 02:46:302429}
2430
[email protected]ae51d192010-04-27 00:48:032431void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2432 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102433 bool supports_seperate_framebuffer_binds =
2434 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a25fa872010-03-25 02:57:582435 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102436 RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]ae51d192010-04-27 00:48:032437 GetRenderbufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102438 if (renderbuffer && !renderbuffer->IsDeleted()) {
2439 if (bound_renderbuffer_ == renderbuffer) {
2440 bound_renderbuffer_ = NULL;
2441 }
2442 // Unbind from current framebuffers.
2443 if (supports_seperate_framebuffer_binds) {
2444 if (bound_read_framebuffer_) {
2445 bound_read_framebuffer_->UnbindRenderbuffer(
2446 GL_READ_FRAMEBUFFER, renderbuffer);
2447 }
2448 if (bound_draw_framebuffer_) {
2449 bound_draw_framebuffer_->UnbindRenderbuffer(
2450 GL_DRAW_FRAMEBUFFER, renderbuffer);
2451 }
2452 } else {
2453 if (bound_draw_framebuffer_) {
2454 bound_draw_framebuffer_->UnbindRenderbuffer(
2455 GL_FRAMEBUFFER, renderbuffer);
2456 }
2457 }
[email protected]297ca1c2011-06-20 23:08:462458 state_dirty_ = true;
[email protected]ae51d192010-04-27 00:48:032459 RemoveRenderbufferInfo(client_ids[ii]);
2460 }
[email protected]a25fa872010-03-25 02:57:582461 }
[email protected]07f54fcc2009-12-22 02:46:302462}
2463
[email protected]ae51d192010-04-27 00:48:032464void GLES2DecoderImpl::DeleteTexturesHelper(
2465 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102466 bool supports_seperate_framebuffer_binds =
2467 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a93bb842010-02-16 23:03:472468 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102469 TextureManager::TextureInfo* texture = GetTextureInfo(client_ids[ii]);
2470 if (texture && !texture->IsDeleted()) {
2471 if (texture->IsAttachedToFramebuffer()) {
[email protected]297ca1c2011-06-20 23:08:462472 state_dirty_ = true;
2473 }
[email protected]a0b78dc2011-11-11 10:43:102474 // Unbind texture from texture units.
2475 for (size_t jj = 0; jj < group_->max_texture_units(); ++jj) {
2476 texture_units_[ii].Unbind(texture);
2477 }
2478 // Unbind from current framebuffers.
2479 if (supports_seperate_framebuffer_binds) {
2480 if (bound_read_framebuffer_) {
2481 bound_read_framebuffer_->UnbindTexture(GL_READ_FRAMEBUFFER, texture);
2482 }
2483 if (bound_draw_framebuffer_) {
2484 bound_draw_framebuffer_->UnbindTexture(GL_DRAW_FRAMEBUFFER, texture);
2485 }
2486 } else {
2487 if (bound_draw_framebuffer_) {
2488 bound_draw_framebuffer_->UnbindTexture(GL_FRAMEBUFFER, texture);
2489 }
2490 }
2491 GLuint service_id = texture->service_id();
2492 if (texture->IsStreamTexture() && stream_texture_manager_) {
[email protected]b0af4f52011-09-28 22:04:422493 stream_texture_manager_->DestroyStreamTexture(service_id);
2494 }
[email protected]e51bdf32011-11-23 22:21:462495#if defined(OS_MACOSX)
2496 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2497 ReleaseIOSurfaceForTexture(service_id);
2498 }
2499#endif
[email protected]ae51d192010-04-27 00:48:032500 RemoveTextureInfo(client_ids[ii]);
2501 }
[email protected]a93bb842010-02-16 23:03:472502 }
[email protected]07f54fcc2009-12-22 02:46:302503}
2504
[email protected]43f28f832010-02-03 02:28:482505// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322506
[email protected]eb54a562010-01-20 21:55:182507bool GLES2DecoderImpl::MakeCurrent() {
[email protected]38d139d2011-07-14 00:38:432508 bool result = context_.get() ? context_->MakeCurrent(surface_.get()) : false;
2509 if (result && WasContextLost()) {
2510 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2511 result = false;
2512 }
2513
2514 return result;
[email protected]eb54a562010-01-20 21:55:182515}
2516
[email protected]a96a6022011-11-04 00:58:122517void GLES2DecoderImpl::ReleaseCurrent() {
2518 if (context_.get())
2519 context_->ReleaseCurrent(surface_.get());
2520}
2521
[email protected]8e3e0662010-08-23 18:46:302522void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
[email protected]0d6bfdc2011-11-02 01:32:202523 RenderbufferManager::RenderbufferInfo* renderbuffer =
2524 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
[email protected]8e3e0662010-08-23 18:46:302525 glBindRenderbufferEXT(
[email protected]0d6bfdc2011-11-02 01:32:202526 GL_RENDERBUFFER, renderbuffer ? renderbuffer->service_id() : 0);
[email protected]8e3e0662010-08-23 18:46:302527}
2528
2529static void RebindCurrentFramebuffer(
2530 GLenum target,
2531 FramebufferManager::FramebufferInfo* info,
[email protected]a3783712012-01-20 22:18:242532 GLuint back_buffer_service_id) {
[email protected]8e3e0662010-08-23 18:46:302533 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462534
[email protected]a3783712012-01-20 22:18:242535 if (framebuffer_id == 0) {
2536 framebuffer_id = back_buffer_service_id;
[email protected]8e3e0662010-08-23 18:46:302537 }
[email protected]297ca1c2011-06-20 23:08:462538
[email protected]8e3e0662010-08-23 18:46:302539 glBindFramebufferEXT(target, framebuffer_id);
2540}
2541
2542void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]297ca1c2011-06-20 23:08:462543 state_dirty_ = true;
2544
[email protected]a3ded6d2010-10-19 06:44:392545 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302546 RebindCurrentFramebuffer(
2547 GL_FRAMEBUFFER,
2548 bound_draw_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242549 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302550 } else {
2551 RebindCurrentFramebuffer(
2552 GL_READ_FRAMEBUFFER_EXT,
2553 bound_read_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242554 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302555 RebindCurrentFramebuffer(
2556 GL_DRAW_FRAMEBUFFER_EXT,
2557 bound_draw_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242558 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302559 }
2560}
2561
2562void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2563 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2564 GLuint last_id;
2565 if (info.bound_texture_2d) {
2566 last_id = info.bound_texture_2d->service_id();
2567 } else {
2568 last_id = 0;
2569 }
2570
2571 glBindTexture(GL_TEXTURE_2D, last_id);
2572 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2573}
2574
[email protected]0d6bfdc2011-11-02 01:32:202575bool GLES2DecoderImpl::CheckFramebufferValid(
2576 FramebufferManager::FramebufferInfo* framebuffer,
2577 GLenum target, const char* func_name) {
[email protected]a0b78dc2011-11-11 10:43:102578 if (!framebuffer) {
[email protected]0d6bfdc2011-11-02 01:32:202579 return true;
2580 }
2581
[email protected]968351b2011-12-20 08:26:512582 if (framebuffer_manager()->IsComplete(framebuffer)) {
2583 return true;
2584 }
2585
[email protected]0d6bfdc2011-11-02 01:32:202586 GLenum completeness = framebuffer->IsPossiblyComplete();
2587 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
2588 SetGLError(
2589 GL_INVALID_FRAMEBUFFER_OPERATION,
2590 (std::string(func_name) + " framebuffer incomplete").c_str());
[email protected]3a03a8f2011-03-19 00:51:272591 return false;
2592 }
[email protected]0d6bfdc2011-11-02 01:32:202593
2594 // Are all the attachments cleared?
2595 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2596 texture_manager()->HaveUnclearedMips()) {
2597 if (!framebuffer->IsCleared()) {
2598 // Can we clear them?
2599 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2600 SetGLError(
2601 GL_INVALID_FRAMEBUFFER_OPERATION,
2602 (std::string(func_name) +
2603 " framebuffer incomplete (clear)").c_str());
2604 return false;
2605 }
2606 ClearUnclearedAttachments(target, framebuffer);
2607 }
2608 }
2609
[email protected]968351b2011-12-20 08:26:512610 if (!framebuffer_manager()->IsComplete(framebuffer)) {
2611 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2612 SetGLError(
2613 GL_INVALID_FRAMEBUFFER_OPERATION,
2614 (std::string(func_name) +
2615 " framebuffer incomplete (check)").c_str());
2616 return false;
2617 }
2618 framebuffer_manager()->MarkAsComplete(framebuffer);
2619 }
2620
[email protected]0d6bfdc2011-11-02 01:32:202621 // NOTE: At this point we don't know if the framebuffer is complete but
2622 // we DO know that everything that needs to be cleared has been cleared.
[email protected]3a03a8f2011-03-19 00:51:272623 return true;
2624}
2625
[email protected]0d6bfdc2011-11-02 01:32:202626bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
2627 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
2628 return CheckFramebufferValid(
2629 bound_draw_framebuffer_, GL_FRAMEBUFFER_EXT, func_name);
2630 }
2631 return CheckFramebufferValid(
2632 bound_draw_framebuffer_, GL_DRAW_FRAMEBUFFER_EXT, func_name) &&
2633 CheckFramebufferValid(
2634 bound_read_framebuffer_, GL_READ_FRAMEBUFFER_EXT, func_name);
2635}
2636
[email protected]8e3e0662010-08-23 18:46:302637gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
[email protected]0d6bfdc2011-11-02 01:32:202638 FramebufferManager::FramebufferInfo* framebuffer =
2639 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2640 if (framebuffer != NULL) {
[email protected]9edc6b22010-12-23 02:00:262641 const FramebufferManager::FramebufferInfo::Attachment* attachment =
[email protected]0d6bfdc2011-11-02 01:32:202642 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
[email protected]9edc6b22010-12-23 02:00:262643 if (attachment) {
2644 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502645 }
[email protected]9edc6b22010-12-23 02:00:262646 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022647 } else if (offscreen_target_frame_buffer_.get()) {
2648 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352649 } else {
[email protected]f62a5ab2011-05-23 20:34:152650 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022651 }
[email protected]246a70452010-03-05 21:53:502652}
2653
[email protected]9edc6b22010-12-23 02:00:262654GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202655 FramebufferManager::FramebufferInfo* framebuffer =
2656 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2657 if (framebuffer != NULL) {
2658 return framebuffer->GetColorAttachmentFormat();
[email protected]297ca1c2011-06-20 23:08:462659 } else if (offscreen_target_frame_buffer_.get()) {
2660 return offscreen_target_color_format_;
2661 } else {
2662 return back_buffer_color_format_;
2663 }
2664}
2665
2666GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202667 FramebufferManager::FramebufferInfo* framebuffer =
2668 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
2669 if (framebuffer != NULL) {
2670 return framebuffer->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262671 } else if (offscreen_target_frame_buffer_.get()) {
2672 return offscreen_target_color_format_;
2673 } else {
[email protected]32fe9aa2011-01-21 23:47:132674 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262675 }
2676}
2677
[email protected]9a5afa432011-07-22 18:16:392678void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]34ff8b0c2010-10-01 20:06:022679 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582680 // Update the info about the offscreen saved color texture in the parent.
2681 // The reference to the parent is a weak pointer and will become null if the
2682 // parent is later destroyed.
[email protected]262d7aa2010-12-03 22:07:292683 TextureManager* parent_texture_manager = parent_->texture_manager();
[email protected]262d7aa2010-12-03 22:07:292684 parent_texture_manager->SetLevelInfo(
[email protected]8a61d872012-01-20 12:43:562685 offscreen_saved_color_texture_info_,
[email protected]ef526492010-06-02 23:12:252686 GL_TEXTURE_2D,
2687 0, // level
2688 GL_RGBA,
[email protected]799b4b22011-08-22 17:09:592689 offscreen_size_.width(),
2690 offscreen_size_.height(),
[email protected]ef526492010-06-02 23:12:252691 1, // depth
2692 0, // border
2693 GL_RGBA,
[email protected]0d6bfdc2011-11-02 01:32:202694 GL_UNSIGNED_BYTE,
2695 true);
[email protected]262d7aa2010-12-03 22:07:292696 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562697 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042698 GL_TEXTURE_MAG_FILTER,
2699 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292700 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562701 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042702 GL_TEXTURE_MIN_FILTER,
2703 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292704 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562705 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042706 GL_TEXTURE_WRAP_S,
2707 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292708 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562709 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042710 GL_TEXTURE_WRAP_T,
2711 GL_CLAMP_TO_EDGE);
[email protected]8a61d872012-01-20 12:43:562712 } else {
2713 offscreen_saved_color_texture_info_ = NULL;
[email protected]0c8c9d22010-06-25 17:36:392714 }
[email protected]6217d392010-03-25 22:08:352715}
2716
[email protected]799b4b22011-08-22 17:09:592717void GLES2DecoderImpl::SetResizeCallback(
[email protected]9d37f062011-11-22 01:24:522718 const base::Callback<void(gfx::Size)>& callback) {
2719 resize_callback_ = callback;
[email protected]7ff86b92010-11-25 17:50:002720}
2721
[email protected]6b6e7ee2011-12-13 08:04:522722void GLES2DecoderImpl::SetMsgCallback(const MsgCallback& callback) {
2723 msg_callback_ = callback;
2724}
2725
[email protected]b0af4f52011-09-28 22:04:422726void GLES2DecoderImpl::SetStreamTextureManager(StreamTextureManager* manager) {
2727 stream_texture_manager_ = manager;
2728}
2729
[email protected]1318e922010-09-17 22:03:162730bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2731 uint32* service_texture_id) {
2732 TextureManager::TextureInfo* texture =
2733 texture_manager()->GetTextureInfo(client_texture_id);
2734 if (texture) {
2735 *service_texture_id = texture->service_id();
2736 return true;
2737 }
2738 return false;
2739}
2740
[email protected]96449d2c2009-11-25 00:01:322741void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392742 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052743
[email protected]c826d732012-02-09 04:40:262744 ChildList children = children_;
2745 for (ChildList::iterator it = children.begin(); it != children.end(); ++it)
2746 (*it)->SetParent(NULL, 0);
2747 DCHECK(children_.empty());
[email protected]3c644d82011-06-20 19:58:242748 SetParent(NULL, 0);
2749
[email protected]80eb6b52012-01-19 00:14:412750 // Unbind everything.
[email protected]3757a372012-01-19 05:20:442751 vertex_attrib_manager_.reset();
[email protected]80eb6b52012-01-19 00:14:412752 texture_units_.reset();
2753 bound_array_buffer_ = NULL;
2754 bound_element_array_buffer_ = NULL;
[email protected]882ba1e22012-03-08 19:02:532755 current_query_ = NULL;
[email protected]80eb6b52012-01-19 00:14:412756 current_program_ = NULL;
2757 bound_read_framebuffer_ = NULL;
2758 bound_draw_framebuffer_ = NULL;
2759 bound_renderbuffer_ = NULL;
2760
[email protected]eadc96792010-10-27 19:39:392761 if (have_context) {
[email protected]43410e92012-04-20 17:06:282762 copy_texture_CHROMIUM_->Destroy();
2763
[email protected]ca488e12010-12-13 20:06:142764 if (current_program_) {
2765 program_manager()->UnuseProgram(shader_manager(), current_program_);
2766 current_program_ = NULL;
2767 }
2768
[email protected]b1122982010-05-17 23:04:242769 if (attrib_0_buffer_id_) {
2770 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2771 }
[email protected]8fbedc02010-11-18 18:43:402772 if (fixed_attrib_buffer_id_) {
2773 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2774 }
[email protected]b1122982010-05-17 23:04:242775
[email protected]97872062010-11-03 19:07:052776 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542777 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052778 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542779 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052780 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022781 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052782 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152783 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052784 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152785 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052786 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022787 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052788 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542789 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:272790 if (offscreen_resolved_frame_buffer_.get())
2791 offscreen_resolved_frame_buffer_->Destroy();
2792 if (offscreen_resolved_color_texture_.get())
2793 offscreen_resolved_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052794 } else {
2795 if (offscreen_target_frame_buffer_.get())
2796 offscreen_target_frame_buffer_->Invalidate();
2797 if (offscreen_target_color_texture_.get())
2798 offscreen_target_color_texture_->Invalidate();
2799 if (offscreen_target_color_render_buffer_.get())
2800 offscreen_target_color_render_buffer_->Invalidate();
2801 if (offscreen_target_depth_render_buffer_.get())
2802 offscreen_target_depth_render_buffer_->Invalidate();
2803 if (offscreen_target_stencil_render_buffer_.get())
2804 offscreen_target_stencil_render_buffer_->Invalidate();
2805 if (offscreen_saved_frame_buffer_.get())
2806 offscreen_saved_frame_buffer_->Invalidate();
2807 if (offscreen_saved_color_texture_.get())
2808 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:272809 if (offscreen_resolved_frame_buffer_.get())
2810 offscreen_resolved_frame_buffer_->Invalidate();
2811 if (offscreen_resolved_color_texture_.get())
2812 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022813 }
[email protected]43410e92012-04-20 17:06:282814 copy_texture_CHROMIUM_.reset();
[email protected]97872062010-11-03 19:07:052815
[email protected]882ba1e22012-03-08 19:02:532816 if (query_manager_.get()) {
2817 query_manager_->Destroy(have_context);
2818 query_manager_.reset();
2819 }
2820
[email protected]1871a092011-10-10 21:46:422821 if (group_) {
2822 group_->Destroy(have_context);
2823 group_ = NULL;
2824 }
[email protected]3ae019382011-10-05 19:42:412825
[email protected]fe871662011-06-16 20:43:052826 if (context_.get()) {
2827 context_->ReleaseCurrent(NULL);
[email protected]79311e82011-09-20 00:40:502828 context_ = NULL;
[email protected]fe871662011-06-16 20:43:052829 }
[email protected]0fc35742011-04-13 17:57:542830
[email protected]97872062010-11-03 19:07:052831 offscreen_target_frame_buffer_.reset();
2832 offscreen_target_color_texture_.reset();
2833 offscreen_target_color_render_buffer_.reset();
2834 offscreen_target_depth_render_buffer_.reset();
2835 offscreen_target_stencil_render_buffer_.reset();
2836 offscreen_saved_frame_buffer_.reset();
2837 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:272838 offscreen_resolved_frame_buffer_.reset();
2839 offscreen_resolved_color_texture_.reset();
[email protected]e51bdf32011-11-23 22:21:462840
2841#if defined(OS_MACOSX)
2842 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
2843 it != texture_to_io_surface_map_.end(); ++it) {
2844 CFRelease(it->second);
2845 }
2846 texture_to_io_surface_map_.clear();
2847#endif
[email protected]96449d2c2009-11-25 00:01:322848}
2849
[email protected]3c644d82011-06-20 19:58:242850bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
2851 uint32 new_parent_texture_id) {
[email protected]9a5afa432011-07-22 18:16:392852 if (!offscreen_saved_color_texture_.get())
2853 return false;
2854
[email protected]3c644d82011-06-20 19:58:242855 // Remove the saved frame buffer mapping from the parent decoder. The
2856 // parent pointer is a weak pointer so it will be null if the parent has
2857 // already been destroyed.
2858 if (parent_) {
[email protected]c826d732012-02-09 04:40:262859 ChildList::iterator it = std::find(
2860 parent_->children_.begin(),
2861 parent_->children_.end(),
2862 this);
2863 DCHECK(it != parent_->children_.end());
2864 parent_->children_.erase(it);
[email protected]3c644d82011-06-20 19:58:242865 // First check the texture has been mapped into the parent. This might not
2866 // be the case if initialization failed midway through.
2867 GLuint service_id = offscreen_saved_color_texture_->id();
2868 GLuint client_id = 0;
2869 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
[email protected]80eb6b52012-01-19 00:14:412870 parent_->texture_manager()->RemoveTextureInfo(client_id);
[email protected]3c644d82011-06-20 19:58:242871 }
2872 }
2873
2874 GLES2DecoderImpl* new_parent_impl = static_cast<GLES2DecoderImpl*>(
2875 new_parent);
2876 if (new_parent_impl) {
[email protected]c826d732012-02-09 04:40:262877#ifndef NDEBUG
2878 ChildList::iterator it = std::find(
2879 new_parent_impl->children_.begin(),
2880 new_parent_impl->children_.end(),
2881 this);
2882 DCHECK(it == new_parent_impl->children_.end());
2883#endif
2884 new_parent_impl->children_.push_back(this);
[email protected]3c644d82011-06-20 19:58:242885 // Map the ID of the saved offscreen texture into the parent so that
2886 // it can reference it.
2887 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]98687862011-07-11 23:31:302888
2889 // Replace texture info when ID is already in use by parent.
2890 if (new_parent_impl->texture_manager()->GetTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412891 new_parent_texture_id))
[email protected]98687862011-07-11 23:31:302892 new_parent_impl->texture_manager()->RemoveTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412893 new_parent_texture_id);
[email protected]98687862011-07-11 23:31:302894
[email protected]8a61d872012-01-20 12:43:562895 offscreen_saved_color_texture_info_ =
[email protected]5f4f2a732011-07-30 00:47:552896 new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id);
[email protected]8a61d872012-01-20 12:43:562897 offscreen_saved_color_texture_info_->SetNotOwned();
2898 new_parent_impl->texture_manager()->
2899 SetInfoTarget(offscreen_saved_color_texture_info_, GL_TEXTURE_2D);
[email protected]3c644d82011-06-20 19:58:242900
2901 parent_ = new_parent_impl->AsWeakPtr();
[email protected]9a5afa432011-07-22 18:16:392902
2903 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:242904 } else {
2905 parent_.reset();
[email protected]8a61d872012-01-20 12:43:562906 offscreen_saved_color_texture_info_ = NULL;
[email protected]3c644d82011-06-20 19:58:242907 }
2908
2909 return true;
2910}
2911
[email protected]1078f912011-12-23 13:12:142912void GLES2DecoderImpl::UpdateBackbufferMemoryAccounting() {
2913 size_t total = 0;
2914 if (offscreen_target_frame_buffer_.get()) {
2915 if (offscreen_target_color_texture_.get()) {
2916 total += offscreen_target_color_texture_->estimated_size();
2917 }
2918 if (offscreen_target_color_render_buffer_.get()) {
2919 total += offscreen_target_color_render_buffer_->estimated_size();
2920 }
2921 if (offscreen_target_depth_render_buffer_.get()) {
2922 total += offscreen_target_depth_render_buffer_->estimated_size();
2923 }
2924 if (offscreen_target_stencil_render_buffer_.get()) {
2925 total += offscreen_target_stencil_render_buffer_->estimated_size();
2926 }
2927 if (offscreen_saved_color_texture_.get()) {
2928 total += offscreen_saved_color_texture_->estimated_size();
2929 }
2930 if (offscreen_resolved_color_texture_.get()) {
2931 total += offscreen_resolved_color_texture_->estimated_size();
2932 }
2933 } else {
2934 gfx::Size size = surface_->GetSize();
2935 total += size.width() * size.height() *
2936 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_);
2937 }
2938 TRACE_COUNTER_ID1(
2939 "GLES2DecoderImpl", "BackbufferMemory", this, total);
2940}
2941
[email protected]799b4b22011-08-22 17:09:592942bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2943 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
2944 if (!is_offscreen) {
2945 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
2946 << " with an onscreen framebuffer.";
2947 return false;
2948 }
2949
2950 if (offscreen_size_ == size)
2951 return true;
2952
2953 offscreen_size_ = size;
2954 int w = offscreen_size_.width();
2955 int h = offscreen_size_.height();
2956 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
2957 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2958 << "to allocate storage due to excessive dimensions.";
2959 return false;
2960 }
2961
2962 // Reallocate the offscreen target buffers.
2963 DCHECK(offscreen_target_color_format_);
2964 if (IsOffscreenBufferMultisampled()) {
2965 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2966 offscreen_size_, offscreen_target_color_format_,
2967 offscreen_target_samples_)) {
2968 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2969 << "to allocate storage for offscreen target color buffer.";
2970 return false;
2971 }
2972 } else {
2973 if (!offscreen_target_color_texture_->AllocateStorage(
2974 offscreen_size_, offscreen_target_color_format_)) {
2975 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2976 << "to allocate storage for offscreen target color texture.";
2977 return false;
2978 }
2979 }
2980 if (offscreen_target_depth_format_ &&
2981 !offscreen_target_depth_render_buffer_->AllocateStorage(
2982 offscreen_size_, offscreen_target_depth_format_,
2983 offscreen_target_samples_)) {
2984 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2985 << "to allocate storage for offscreen target depth buffer.";
2986 return false;
2987 }
2988 if (offscreen_target_stencil_format_ &&
2989 !offscreen_target_stencil_render_buffer_->AllocateStorage(
2990 offscreen_size_, offscreen_target_stencil_format_,
2991 offscreen_target_samples_)) {
2992 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2993 << "to allocate storage for offscreen target stencil buffer.";
2994 return false;
2995 }
[email protected]1078f912011-12-23 13:12:142996 UpdateBackbufferMemoryAccounting();
[email protected]799b4b22011-08-22 17:09:592997
2998 // Attach the offscreen target buffers to the target frame buffer.
2999 if (IsOffscreenBufferMultisampled()) {
3000 offscreen_target_frame_buffer_->AttachRenderBuffer(
3001 GL_COLOR_ATTACHMENT0,
3002 offscreen_target_color_render_buffer_.get());
3003 } else {
3004 offscreen_target_frame_buffer_->AttachRenderTexture(
3005 offscreen_target_color_texture_.get());
3006 }
3007 if (offscreen_target_depth_format_) {
3008 offscreen_target_frame_buffer_->AttachRenderBuffer(
3009 GL_DEPTH_ATTACHMENT,
3010 offscreen_target_depth_render_buffer_.get());
3011 }
3012 const bool packed_depth_stencil =
3013 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3014 if (packed_depth_stencil) {
3015 offscreen_target_frame_buffer_->AttachRenderBuffer(
3016 GL_STENCIL_ATTACHMENT,
3017 offscreen_target_depth_render_buffer_.get());
3018 } else if (offscreen_target_stencil_format_) {
3019 offscreen_target_frame_buffer_->AttachRenderBuffer(
3020 GL_STENCIL_ATTACHMENT,
3021 offscreen_target_stencil_render_buffer_.get());
3022 }
3023
3024 if (offscreen_target_frame_buffer_->CheckStatus() !=
3025 GL_FRAMEBUFFER_COMPLETE) {
3026 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3027 << "because offscreen FBO was incomplete.";
3028 return false;
3029 }
3030
3031 // Clear the target frame buffer.
3032 {
3033 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3034 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3035 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3036 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3037 glClearStencil(0);
3038 glStencilMaskSeparate(GL_FRONT, -1);
3039 glStencilMaskSeparate(GL_BACK, -1);
3040 glClearDepth(0);
3041 glDepthMask(GL_TRUE);
3042 glDisable(GL_SCISSOR_TEST);
3043 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3044 RestoreClearState();
3045 }
[email protected]d85ef76d2011-09-08 22:21:433046
3047 // Destroy the offscreen resolved framebuffers.
3048 if (offscreen_resolved_frame_buffer_.get())
3049 offscreen_resolved_frame_buffer_->Destroy();
3050 if (offscreen_resolved_color_texture_.get())
3051 offscreen_resolved_color_texture_->Destroy();
3052 offscreen_resolved_color_texture_.reset();
3053 offscreen_resolved_frame_buffer_.reset();
3054
[email protected]799b4b22011-08-22 17:09:593055 return true;
[email protected]6217d392010-03-25 22:08:353056}
3057
[email protected]799b4b22011-08-22 17:09:593058error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3059 uint32 immediate_data_size, const gles2::ResizeCHROMIUM& c) {
3060 GLuint width = static_cast<GLuint>(c.width);
3061 GLuint height = static_cast<GLuint>(c.height);
3062 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
[email protected]a0d989162011-11-22 13:15:073063#if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3064 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
[email protected]7ff86b92010-11-25 17:50:003065 // Make sure that we are done drawing to the back buffer before resizing.
3066 glFinish();
3067#endif
[email protected]799b4b22011-08-22 17:09:593068 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3069 if (is_offscreen) {
[email protected]7794d512012-04-17 20:36:493070 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3071 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3072 << "ResizeOffscreenFrameBuffer failed.";
[email protected]799b4b22011-08-22 17:09:593073 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:493074 }
[email protected]7ff86b92010-11-25 17:50:003075 }
[email protected]799b4b22011-08-22 17:09:593076
[email protected]9d37f062011-11-22 01:24:523077 if (!resize_callback_.is_null()) {
3078 resize_callback_.Run(gfx::Size(width, height));
[email protected]c777de52011-09-09 23:08:563079 DCHECK(context_->IsCurrent(surface_.get()));
[email protected]7794d512012-04-17 20:36:493080 if (!context_->IsCurrent(surface_.get())) {
3081 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3082 << "current after resize callback.";
[email protected]658f7562011-09-09 05:24:053083 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:493084 }
[email protected]658f7562011-09-09 05:24:053085 }
[email protected]799b4b22011-08-22 17:09:593086
[email protected]1078f912011-12-23 13:12:143087 UpdateBackbufferMemoryAccounting();
3088
[email protected]799b4b22011-08-22 17:09:593089 return error::kNoError;
[email protected]43ecf372010-11-16 19:19:393090}
3091
[email protected]96449d2c2009-11-25 00:01:323092const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3093 if (command_id > kStartPoint && command_id < kNumCommands) {
3094 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3095 }
3096 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3097}
3098
3099// Decode command with its arguments, and call the corresponding GL function.
3100// Note: args is a pointer to the command buffer. As such, it could be changed
3101// by a (malicious) client at any time, so if validation has to happen, it
3102// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:143103error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:323104 unsigned int command,
3105 unsigned int arg_count,
3106 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:143107 error::Error result = error::kNoError;
[email protected]e844ae22012-01-14 03:36:263108 if (log_commands()) {
[email protected]39ba4f02012-03-26 01:16:003109 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3110 // LOG(INFO), tried VLOG(1), no luck.
3111 LOG(ERROR) << "[" << this << "]" << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193112 }
[email protected]96449d2c2009-11-25 00:01:323113 unsigned int command_index = command - kStartPoint - 1;
3114 if (command_index < arraysize(g_command_info)) {
3115 const CommandInfo& info = g_command_info[command_index];
3116 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3117 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3118 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:193119 uint32 immediate_data_size =
3120 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:323121 switch (command) {
3122 #define GLES2_CMD_OP(name) \
3123 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:193124 result = Handle ## name( \
3125 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:323126 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:193127 break; \
[email protected]96449d2c2009-11-25 00:01:323128
3129 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:323130 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:383131 }
3132 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:303133 GLenum error;
3134 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]39ba4f02012-03-26 01:16:003135 LOG(ERROR) << "[" << this << "] "
3136 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3137 << GetCommandName(command);
[email protected]e844ae22012-01-14 03:36:263138 SetGLError(error, "GL error from driver");
[email protected]b9849abf2009-11-25 19:13:193139 }
[email protected]96449d2c2009-11-25 00:01:323140 }
3141 } else {
[email protected]f7a64ee2010-02-01 22:24:143142 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:323143 }
[email protected]b9849abf2009-11-25 19:13:193144 } else {
3145 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:323146 }
[email protected]a3a93e7b2010-08-28 00:48:563147 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3148 result = current_decoder_error_;
3149 current_decoder_error_ = error::kNoError;
3150 }
[email protected]b9849abf2009-11-25 19:13:193151 return result;
[email protected]96449d2c2009-11-25 00:01:323152}
3153
[email protected]ae51d192010-04-27 00:48:033154void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
3155 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:503156}
3157
[email protected]ae51d192010-04-27 00:48:033158bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3159 if (GetProgramInfo(client_id)) {
3160 return false;
3161 }
[email protected]96449d2c2009-11-25 00:01:323162 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:033163 if (service_id != 0) {
3164 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:323165 }
[email protected]ae51d192010-04-27 00:48:033166 return true;
[email protected]96449d2c2009-11-25 00:01:323167}
3168
[email protected]ae51d192010-04-27 00:48:033169bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3170 if (GetShaderInfo(client_id)) {
3171 return false;
[email protected]96449d2c2009-11-25 00:01:323172 }
[email protected]ae51d192010-04-27 00:48:033173 GLuint service_id = glCreateShader(type);
3174 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:383175 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:033176 }
3177 return true;
[email protected]96449d2c2009-11-25 00:01:323178}
3179
[email protected]882ba1e22012-03-08 19:02:533180void GLES2DecoderImpl::DoFinish() {
3181 glFinish();
[email protected]22e3f552012-03-13 01:54:193182 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533183}
3184
3185void GLES2DecoderImpl::DoFlush() {
3186 glFlush();
[email protected]22e3f552012-03-13 01:54:193187 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533188}
3189
[email protected]3916c97e2010-02-25 03:20:503190void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:453191 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]660858b2011-07-13 23:16:143192 if (texture_index >= group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:293193 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:503194 return;
3195 }
[email protected]36cef8ce2010-03-16 07:34:453196 active_texture_unit_ = texture_index;
3197 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:503198}
3199
[email protected]051b1372010-04-12 02:42:083200void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:503201 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083202 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033203 if (client_id != 0) {
3204 info = GetBufferInfo(client_id);
3205 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353206 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153207 LOG(ERROR) << "glBindBuffer: id not generated by glGenBuffers";
3208 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353209 return;
3210 }
3211
[email protected]ae51d192010-04-27 00:48:033212 // It's a new id so make a buffer info for it.
3213 glGenBuffersARB(1, &service_id);
3214 CreateBufferInfo(client_id, service_id);
3215 info = GetBufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573216 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103217 group_->GetIdAllocator(id_namespaces::kBuffers);
3218 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033219 }
[email protected]051b1372010-04-12 02:42:083220 }
[email protected]ae51d192010-04-27 00:48:033221 if (info) {
[email protected]4e8a5b122010-05-08 22:00:103222 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:293223 SetGLError(GL_INVALID_OPERATION,
3224 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:473225 return;
3226 }
[email protected]ae51d192010-04-27 00:48:033227 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:473228 }
[email protected]96449d2c2009-11-25 00:01:323229 switch (target) {
3230 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503231 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323232 break;
3233 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503234 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323235 break;
3236 default:
[email protected]a93bb842010-02-16 23:03:473237 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:323238 break;
3239 }
[email protected]051b1372010-04-12 02:42:083240 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:323241}
3242
[email protected]297ca1c2011-06-20 23:08:463243bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
3244 return (GLES2Util::GetChannelsForFormat(
3245 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3246}
3247
3248bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203249 FramebufferManager::FramebufferInfo* framebuffer =
3250 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3251 if (framebuffer) {
3252 return framebuffer->HasDepthAttachment();
[email protected]297ca1c2011-06-20 23:08:463253 }
3254 if (offscreen_target_frame_buffer_.get()) {
3255 return offscreen_target_depth_format_ != 0;
3256 }
3257 return back_buffer_has_depth_;
3258}
3259
3260bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203261 FramebufferManager::FramebufferInfo* framebuffer =
3262 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3263 if (framebuffer) {
3264 return framebuffer->HasStencilAttachment();
[email protected]297ca1c2011-06-20 23:08:463265 }
3266 if (offscreen_target_frame_buffer_.get()) {
3267 return offscreen_target_stencil_format_ != 0 ||
3268 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3269 }
3270 return back_buffer_has_stencil_;
3271}
3272
3273void GLES2DecoderImpl::ApplyDirtyState() {
3274 if (state_dirty_) {
3275 glColorMask(
3276 mask_red_, mask_green_, mask_blue_,
3277 mask_alpha_ && BoundFramebufferHasColorAttachmentWithAlpha());
3278 bool have_depth = BoundFramebufferHasDepthAttachment();
3279 glDepthMask(mask_depth_ && have_depth);
3280 EnableDisable(GL_DEPTH_TEST, enable_depth_test_ && have_depth);
3281 bool have_stencil = BoundFramebufferHasStencilAttachment();
3282 glStencilMaskSeparate(GL_FRONT, have_stencil ? mask_stencil_front_ : 0);
3283 glStencilMaskSeparate(GL_BACK, have_stencil ? mask_stencil_back_ : 0);
3284 EnableDisable(GL_STENCIL_TEST, enable_stencil_test_ && have_stencil);
[email protected]43410e92012-04-20 17:06:283285 EnableDisable(GL_CULL_FACE, enable_cull_face_);
3286 EnableDisable(GL_SCISSOR_TEST, enable_scissor_test_);
[email protected]0a1e9ad2012-05-04 21:13:033287 EnableDisable(GL_BLEND, enable_blend_);
[email protected]297ca1c2011-06-20 23:08:463288 state_dirty_ = false;
3289 }
3290}
3291
[email protected]78b514b2012-05-01 21:50:593292void GLES2DecoderImpl::BindAndApplyTextureParameters(
3293 TextureManager::TextureInfo* info) {
3294 glBindTexture(info->target(), info->service_id());
3295 glTexParameteri(info->target(), GL_TEXTURE_MIN_FILTER, info->min_filter());
3296 glTexParameteri(info->target(), GL_TEXTURE_MAG_FILTER, info->mag_filter());
3297 glTexParameteri(info->target(), GL_TEXTURE_WRAP_S, info->wrap_s());
3298 glTexParameteri(info->target(), GL_TEXTURE_WRAP_T, info->wrap_t());
3299}
3300
[email protected]b177ae22011-11-01 03:29:113301GLuint GLES2DecoderImpl::GetBackbufferServiceId() {
3302 return (offscreen_target_frame_buffer_.get()) ?
3303 offscreen_target_frame_buffer_->id() :
3304 surface_->GetBackingFrameBufferObject();
3305}
3306
[email protected]051b1372010-04-12 02:42:083307void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3308 FramebufferManager::FramebufferInfo* info = NULL;
3309 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033310 if (client_id != 0) {
3311 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083312 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353313 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153314 LOG(ERROR)
3315 << "glBindFramebuffer: id not generated by glGenFramebuffers";
3316 current_decoder_error_ = error::kGenericError;
3317 return;
[email protected]bf5a8d132011-08-16 08:39:353318 }
3319
[email protected]ae51d192010-04-27 00:48:033320 // It's a new id so make a framebuffer info for it.
3321 glGenFramebuffersEXT(1, &service_id);
3322 CreateFramebufferInfo(client_id, service_id);
3323 info = GetFramebufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573324 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103325 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3326 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033327 } else {
3328 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083329 }
[email protected]06c8b082011-01-05 18:00:363330 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083331 }
[email protected]8e3e0662010-08-23 18:46:303332
3333 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
3334 bound_draw_framebuffer_ = info;
3335 }
3336 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
3337 bound_read_framebuffer_ = info;
3338 }
[email protected]6217d392010-03-25 22:08:353339
[email protected]297ca1c2011-06-20 23:08:463340 state_dirty_ = true;
3341
[email protected]b177ae22011-11-01 03:29:113342 // If we are rendering to the backbuffer get the FBO id for any simulated
3343 // backbuffer.
3344 if (info == NULL) {
3345 service_id = GetBackbufferServiceId();
[email protected]297ca1c2011-06-20 23:08:463346 }
[email protected]6217d392010-03-25 22:08:353347
[email protected]051b1372010-04-12 02:42:083348 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563349}
3350
[email protected]051b1372010-04-12 02:42:083351void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
3352 RenderbufferManager::RenderbufferInfo* info = NULL;
3353 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033354 if (client_id != 0) {
3355 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083356 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353357 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153358 LOG(ERROR)
3359 << "glBindRenderbuffer: id not generated by glGenRenderbuffers";
3360 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353361 return;
3362 }
3363
[email protected]ae51d192010-04-27 00:48:033364 // It's a new id so make a renderbuffer info for it.
3365 glGenRenderbuffersEXT(1, &service_id);
3366 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:103367 info = GetRenderbufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573368 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103369 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3370 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033371 } else {
3372 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083373 }
[email protected]06c8b082011-01-05 18:00:363374 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083375 }
3376 bound_renderbuffer_ = info;
3377 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563378}
3379
[email protected]051b1372010-04-12 02:42:083380void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033381 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083382 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033383 if (client_id != 0) {
3384 info = GetTextureInfo(client_id);
3385 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353386 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153387 LOG(ERROR) << "glBindTexture: id not generated by glGenTextures";
3388 current_decoder_error_ = error::kGenericError;
3389 return;
[email protected]bf5a8d132011-08-16 08:39:353390 }
3391
[email protected]ae51d192010-04-27 00:48:033392 // It's a new id so make a texture info for it.
3393 glGenTextures(1, &service_id);
[email protected]80eb6b52012-01-19 00:14:413394 DCHECK_NE(0u, service_id);
[email protected]ae51d192010-04-27 00:48:033395 CreateTextureInfo(client_id, service_id);
3396 info = GetTextureInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573397 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103398 group_->GetIdAllocator(id_namespaces::kTextures);
3399 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033400 }
3401 } else {
3402 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:083403 }
[email protected]ae51d192010-04-27 00:48:033404
[email protected]1958e0e2010-04-22 05:17:153405 // Check the texture exists
3406 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:033407 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:293408 SetGLError(GL_INVALID_OPERATION,
3409 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:153410 return;
3411 }
[email protected]b0af4f52011-09-28 22:04:423412 if (info->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
3413 SetGLError(GL_INVALID_OPERATION,
3414 "glBindTexture: illegal target for stream texture.");
3415 return;
3416 }
[email protected]1958e0e2010-04-22 05:17:153417 if (info->target() == 0) {
[email protected]80eb6b52012-01-19 00:14:413418 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:473419 }
[email protected]ae51d192010-04-27 00:48:033420 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:503421 TextureUnit& unit = texture_units_[active_texture_unit_];
3422 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:473423 switch (target) {
3424 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:503425 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:473426 break;
3427 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:503428 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:473429 break;
[email protected]61eeb33f2011-07-26 15:30:313430 case GL_TEXTURE_EXTERNAL_OES:
3431 unit.bound_texture_external_oes = info;
[email protected]b0af4f52011-09-28 22:04:423432 if (info->IsStreamTexture()) {
3433 DCHECK(stream_texture_manager_);
3434 StreamTexture* stream_tex =
3435 stream_texture_manager_->LookupStreamTexture(info->service_id());
3436 if (stream_tex)
3437 stream_tex->Update();
3438 }
[email protected]61eeb33f2011-07-26 15:30:313439 break;
[email protected]e51bdf32011-11-23 22:21:463440 case GL_TEXTURE_RECTANGLE_ARB:
3441 unit.bound_texture_rectangle_arb = info;
3442 break;
[email protected]a93bb842010-02-16 23:03:473443 default:
3444 NOTREACHED(); // Validation should prevent us getting here.
3445 break;
3446 }
3447}
3448
[email protected]07f54fcc2009-12-22 02:46:303449void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443450 if (vertex_attrib_manager_->Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:123451 if (index != 0 ||
3452 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:243453 glDisableVertexAttribArray(index);
3454 }
[email protected]07f54fcc2009-12-22 02:46:303455 } else {
[email protected]8eee29c2010-04-29 03:38:293456 SetGLError(GL_INVALID_VALUE,
3457 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:303458 }
3459}
3460
3461void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443462 if (vertex_attrib_manager_->Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:303463 glEnableVertexAttribArray(index);
3464 } else {
[email protected]8eee29c2010-04-29 03:38:293465 SetGLError(GL_INVALID_VALUE,
3466 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:303467 }
3468}
3469
[email protected]a93bb842010-02-16 23:03:473470void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:503471 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]97dc7cbe2011-12-06 17:26:173472 if (!info ||
[email protected]80eb6b52012-01-19 00:14:413473 !texture_manager()->MarkMipmapsGenerated(info)) {
[email protected]8eee29c2010-04-29 03:38:293474 SetGLError(GL_INVALID_OPERATION,
[email protected]237bad712012-04-05 20:04:023475 "glGenerateMipmaps: Can not generate mips");
[email protected]a93bb842010-02-16 23:03:473476 return;
3477 }
[email protected]59f3ca02011-03-26 22:24:193478 // Workaround for Mac driver bug. In the large scheme of things setting
3479 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
[email protected]a8bad262011-10-21 18:28:563480 // hit so there's probably no need to make this conditional. The bug appears
3481 // to be that if the filtering mode is set to something that doesn't require
3482 // mipmaps for rendering, or is never set to something other than the default,
3483 // then glGenerateMipmap misbehaves.
[email protected]c892a4e12012-05-08 18:20:193484 if (!disable_workarounds_) {
3485 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3486 }
[email protected]a93bb842010-02-16 23:03:473487 glGenerateMipmapEXT(target);
[email protected]c892a4e12012-05-08 18:20:193488 if (!disable_workarounds_) {
3489 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
3490 }
[email protected]a93bb842010-02-16 23:03:473491}
3492
[email protected]b273e432010-04-12 17:23:583493bool GLES2DecoderImpl::GetHelper(
3494 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:583495 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:153496 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
3497 switch (pname) {
[email protected]b273e432010-04-12 17:23:583498 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
3499 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103500 if (params) {
[email protected]5094b0f2010-11-09 19:45:243501 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:103502 }
[email protected]b273e432010-04-12 17:23:583503 return true;
3504 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3505 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103506 if (params) {
[email protected]5094b0f2010-11-09 19:45:243507 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:103508 }
[email protected]b273e432010-04-12 17:23:583509 return true;
3510 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
3511 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103512 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483513 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:103514 }
[email protected]b273e432010-04-12 17:23:583515 return true;
3516 case GL_MAX_VARYING_VECTORS:
3517 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103518 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483519 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:103520 }
[email protected]b273e432010-04-12 17:23:583521 return true;
3522 case GL_MAX_VERTEX_UNIFORM_VECTORS:
3523 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103524 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483525 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:103526 }
[email protected]b273e432010-04-12 17:23:583527 return true;
[email protected]5cb735d2011-10-13 01:37:233528 }
3529 }
3530 switch (pname) {
[email protected]5094b0f2010-11-09 19:45:243531 case GL_MAX_VIEWPORT_DIMS:
3532 if (offscreen_target_frame_buffer_.get()) {
3533 *num_written = 2;
3534 if (params) {
3535 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3536 params[1] = renderbuffer_manager()->max_renderbuffer_size();
3537 }
3538 return true;
3539 }
[email protected]5cb735d2011-10-13 01:37:233540 return false;
[email protected]84afefa2011-10-19 21:45:533541 case GL_MAX_SAMPLES:
3542 *num_written = 1;
3543 if (params) {
3544 params[0] = renderbuffer_manager()->max_samples();
3545 }
3546 return true;
3547 case GL_MAX_RENDERBUFFER_SIZE:
3548 *num_written = 1;
3549 if (params) {
3550 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3551 }
3552 return true;
[email protected]5cb735d2011-10-13 01:37:233553 case GL_MAX_TEXTURE_SIZE:
3554 *num_written = 1;
3555 if (params) {
3556 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
3557 }
3558 return true;
3559 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
3560 *num_written = 1;
3561 if (params) {
3562 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
3563 }
3564 return true;
[email protected]297ca1c2011-06-20 23:08:463565 case GL_COLOR_WRITEMASK:
3566 *num_written = 4;
3567 if (params) {
3568 params[0] = mask_red_;
3569 params[1] = mask_green_;
3570 params[2] = mask_blue_;
3571 params[3] = mask_alpha_;
3572 }
3573 return true;
3574 case GL_DEPTH_WRITEMASK:
3575 *num_written = 1;
3576 if (params) {
3577 params[0] = mask_depth_;
3578 }
3579 return true;
3580 case GL_STENCIL_BACK_WRITEMASK:
3581 *num_written = 1;
3582 if (params) {
3583 params[0] = mask_stencil_back_;
3584 }
3585 return true;
3586 case GL_STENCIL_WRITEMASK:
3587 *num_written = 1;
3588 if (params) {
3589 params[0] = mask_stencil_front_;
3590 }
3591 return true;
3592 case GL_DEPTH_TEST:
3593 *num_written = 1;
3594 if (params) {
3595 params[0] = enable_depth_test_;
3596 }
3597 return true;
3598 case GL_STENCIL_TEST:
3599 *num_written = 1;
3600 if (params) {
3601 params[0] = enable_stencil_test_;
3602 }
3603 return true;
3604 case GL_ALPHA_BITS:
3605 *num_written = 1;
3606 if (params) {
3607 GLint v = 0;
3608 glGetIntegerv(GL_ALPHA_BITS, &v);
3609 params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0;
3610 }
3611 return true;
3612 case GL_DEPTH_BITS:
3613 *num_written = 1;
3614 if (params) {
3615 GLint v = 0;
3616 glGetIntegerv(GL_DEPTH_BITS, &v);
3617 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
3618 }
3619 return true;
3620 case GL_STENCIL_BITS:
3621 *num_written = 1;
3622 if (params) {
3623 GLint v = 0;
3624 glGetIntegerv(GL_STENCIL_BITS, &v);
3625 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
3626 }
3627 return true;
[email protected]656dcaad2010-05-07 17:18:373628 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113629 *num_written = validators_->compressed_texture_format.GetValues().size();
3630 if (params) {
3631 for (GLint ii = 0; ii < *num_written; ++ii) {
3632 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
3633 }
3634 }
[email protected]656dcaad2010-05-07 17:18:373635 return true;
[email protected]b273e432010-04-12 17:23:583636 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
3637 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103638 if (params) {
[email protected]302ce6d2011-07-07 23:28:113639 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103640 }
[email protected]b273e432010-04-12 17:23:583641 return true;
3642 case GL_NUM_SHADER_BINARY_FORMATS:
3643 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103644 if (params) {
[email protected]302ce6d2011-07-07 23:28:113645 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103646 }
[email protected]b273e432010-04-12 17:23:583647 return true;
3648 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113649 *num_written = validators_->shader_binary_format.GetValues().size();
3650 if (params) {
3651 for (GLint ii = 0; ii < *num_written; ++ii) {
3652 params[ii] = validators_->shader_binary_format.GetValues()[ii];
3653 }
3654 }
3655 return true;
[email protected]b273e432010-04-12 17:23:583656 case GL_SHADER_COMPILER:
3657 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103658 if (params) {
3659 *params = GL_TRUE;
3660 }
[email protected]b273e432010-04-12 17:23:583661 return true;
[email protected]6b8cf1a2010-05-06 16:13:583662 case GL_ARRAY_BUFFER_BINDING:
3663 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103664 if (params) {
3665 if (bound_array_buffer_) {
3666 GLuint client_id = 0;
3667 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
3668 &client_id);
3669 *params = client_id;
3670 } else {
3671 *params = 0;
3672 }
[email protected]6b8cf1a2010-05-06 16:13:583673 }
3674 return true;
3675 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3676 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103677 if (params) {
3678 if (bound_element_array_buffer_) {
3679 GLuint client_id = 0;
3680 buffer_manager()->GetClientId(
3681 bound_element_array_buffer_->service_id(),
3682 &client_id);
3683 *params = client_id;
3684 } else {
3685 *params = 0;
3686 }
[email protected]6b8cf1a2010-05-06 16:13:583687 }
3688 return true;
3689 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:303690 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:583691 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103692 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203693 FramebufferManager::FramebufferInfo* framebuffer =
3694 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3695 if (framebuffer) {
[email protected]4e8a5b122010-05-08 22:00:103696 GLuint client_id = 0;
3697 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203698 framebuffer->service_id(), &client_id);
[email protected]8e3e0662010-08-23 18:46:303699 *params = client_id;
3700 } else {
3701 *params = 0;
3702 }
3703 }
3704 return true;
3705 case GL_READ_FRAMEBUFFER_BINDING:
3706 *num_written = 1;
3707 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203708 FramebufferManager::FramebufferInfo* framebuffer =
3709 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
3710 if (framebuffer) {
[email protected]8e3e0662010-08-23 18:46:303711 GLuint client_id = 0;
3712 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203713 framebuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103714 *params = client_id;
3715 } else {
3716 *params = 0;
3717 }
[email protected]6b8cf1a2010-05-06 16:13:583718 }
3719 return true;
3720 case GL_RENDERBUFFER_BINDING:
3721 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103722 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203723 RenderbufferManager::RenderbufferInfo* renderbuffer =
3724 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
3725 if (renderbuffer) {
[email protected]4e8a5b122010-05-08 22:00:103726 GLuint client_id = 0;
3727 renderbuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203728 renderbuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103729 *params = client_id;
3730 } else {
3731 *params = 0;
3732 }
[email protected]6b8cf1a2010-05-06 16:13:583733 }
3734 return true;
3735 case GL_CURRENT_PROGRAM:
3736 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103737 if (params) {
3738 if (current_program_) {
3739 GLuint client_id = 0;
3740 program_manager()->GetClientId(
3741 current_program_->service_id(), &client_id);
3742 *params = client_id;
3743 } else {
3744 *params = 0;
3745 }
[email protected]6b8cf1a2010-05-06 16:13:583746 }
3747 return true;
[email protected]4e8a5b122010-05-08 22:00:103748 case GL_TEXTURE_BINDING_2D:
3749 *num_written = 1;
3750 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583751 TextureUnit& unit = texture_units_[active_texture_unit_];
3752 if (unit.bound_texture_2d) {
3753 GLuint client_id = 0;
3754 texture_manager()->GetClientId(
3755 unit.bound_texture_2d->service_id(), &client_id);
3756 *params = client_id;
3757 } else {
3758 *params = 0;
3759 }
[email protected]6b8cf1a2010-05-06 16:13:583760 }
[email protected]4e8a5b122010-05-08 22:00:103761 return true;
3762 case GL_TEXTURE_BINDING_CUBE_MAP:
3763 *num_written = 1;
3764 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583765 TextureUnit& unit = texture_units_[active_texture_unit_];
3766 if (unit.bound_texture_cube_map) {
3767 GLuint client_id = 0;
3768 texture_manager()->GetClientId(
3769 unit.bound_texture_cube_map->service_id(), &client_id);
3770 *params = client_id;
3771 } else {
3772 *params = 0;
3773 }
[email protected]6b8cf1a2010-05-06 16:13:583774 }
[email protected]4e8a5b122010-05-08 22:00:103775 return true;
[email protected]61eeb33f2011-07-26 15:30:313776 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3777 *num_written = 1;
3778 if (params) {
3779 TextureUnit& unit = texture_units_[active_texture_unit_];
3780 if (unit.bound_texture_external_oes) {
3781 GLuint client_id = 0;
3782 texture_manager()->GetClientId(
3783 unit.bound_texture_external_oes->service_id(), &client_id);
3784 *params = client_id;
3785 } else {
3786 *params = 0;
3787 }
3788 }
3789 return true;
[email protected]e51bdf32011-11-23 22:21:463790 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
3791 *num_written = 1;
3792 if (params) {
3793 TextureUnit& unit = texture_units_[active_texture_unit_];
3794 if (unit.bound_texture_rectangle_arb) {
3795 GLuint client_id = 0;
3796 texture_manager()->GetClientId(
3797 unit.bound_texture_rectangle_arb->service_id(), &client_id);
3798 *params = client_id;
3799 } else {
3800 *params = 0;
3801 }
3802 }
3803 return true;
[email protected]b273e432010-04-12 17:23:583804 default:
[email protected]4e8a5b122010-05-08 22:00:103805 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533806 return false;
[email protected]b273e432010-04-12 17:23:583807 }
3808}
3809
[email protected]4e8a5b122010-05-08 22:00:103810bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3811 GLenum pname, GLsizei* num_values) {
3812 return GetHelper(pname, NULL, num_values);
3813}
3814
[email protected]b273e432010-04-12 17:23:583815void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3816 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103817 GLsizei num_written = 0;
3818 if (GetHelper(pname, NULL, &num_written)) {
3819 scoped_array<GLint> values(new GLint[num_written]);
3820 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583821 for (GLsizei ii = 0; ii < num_written; ++ii) {
3822 params[ii] = static_cast<GLboolean>(values[ii]);
3823 }
3824 } else {
3825 glGetBooleanv(pname, params);
3826 }
3827}
3828
3829void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3830 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103831 GLsizei num_written = 0;
3832 if (GetHelper(pname, NULL, &num_written)) {
3833 scoped_array<GLint> values(new GLint[num_written]);
3834 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583835 for (GLsizei ii = 0; ii < num_written; ++ii) {
3836 params[ii] = static_cast<GLfloat>(values[ii]);
3837 }
3838 } else {
3839 glGetFloatv(pname, params);
3840 }
3841}
3842
3843void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3844 DCHECK(params);
3845 GLsizei num_written;
3846 if (!GetHelper(pname, params, &num_written)) {
3847 glGetIntegerv(pname, params);
3848 }
3849}
3850
[email protected]a0c3e972010-04-21 00:49:133851void GLES2DecoderImpl::DoGetProgramiv(
3852 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583853 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3854 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133855 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133856 return;
3857 }
3858 info->GetProgramiv(pname, params);
3859}
3860
[email protected]258a3313f2011-10-18 20:13:573861void GLES2DecoderImpl::DoBindAttribLocation(
3862 GLuint program, GLuint index, const char* name) {
3863 if (!StringIsValidForGLES(name)) {
3864 SetGLError(GL_INVALID_VALUE, "glBindAttribLocation: Invalid character");
3865 return;
3866 }
[email protected]68dcb1f2012-04-07 00:14:563867 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
3868 SetGLError(GL_INVALID_OPERATION, "glBindAttribLocation: reserved prefix");
3869 return;
3870 }
3871 if (index >= group_->max_vertex_attribs()) {
3872 SetGLError(GL_INVALID_VALUE, "glBindAttribLocation: index out of range");
3873 return;
3874 }
[email protected]6b8cf1a2010-05-06 16:13:583875 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3876 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033877 if (!info) {
[email protected]258a3313f2011-10-18 20:13:573878 return;
[email protected]558847a2010-03-24 07:02:543879 }
[email protected]c3e4c4e2012-03-02 19:23:243880 info->SetAttribLocationBinding(name, static_cast<GLint>(index));
[email protected]258a3313f2011-10-18 20:13:573881 glBindAttribLocation(info->service_id(), index, name);
3882}
3883
3884error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3885 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
3886 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543887 GLuint index = static_cast<GLuint>(c.index);
3888 uint32 name_size = c.data_size;
3889 const char* name = GetSharedMemoryAs<const char*>(
3890 c.name_shm_id, c.name_shm_offset, name_size);
3891 if (name == NULL) {
3892 return error::kOutOfBounds;
3893 }
3894 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573895 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543896 return error::kNoError;
3897}
3898
3899error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3900 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583901 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543902 GLuint index = static_cast<GLuint>(c.index);
3903 uint32 name_size = c.data_size;
3904 const char* name = GetImmediateDataAs<const char*>(
3905 c, name_size, immediate_data_size);
3906 if (name == NULL) {
3907 return error::kOutOfBounds;
3908 }
3909 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573910 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543911 return error::kNoError;
3912}
3913
3914error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3915 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583916 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543917 GLuint index = static_cast<GLuint>(c.index);
3918 Bucket* bucket = GetBucket(c.name_bucket_id);
3919 if (!bucket || bucket->size() == 0) {
3920 return error::kInvalidArguments;
3921 }
3922 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183923 if (!bucket->GetAsString(&name_str)) {
3924 return error::kInvalidArguments;
3925 }
[email protected]258a3313f2011-10-18 20:13:573926 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543927 return error::kNoError;
3928}
3929
[email protected]f7a64ee2010-02-01 22:24:143930error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463931 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033932 GLuint client_id = c.shader;
3933 if (client_id) {
3934 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3935 if (info) {
[email protected]ca488e12010-12-13 20:06:143936 if (!info->IsDeleted()) {
3937 glDeleteShader(info->service_id());
3938 shader_manager()->MarkAsDeleted(info);
3939 }
[email protected]ae51d192010-04-27 00:48:033940 } else {
[email protected]8eee29c2010-04-29 03:38:293941 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033942 }
[email protected]96449d2c2009-11-25 00:01:323943 }
[email protected]f7a64ee2010-02-01 22:24:143944 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323945}
3946
[email protected]f7a64ee2010-02-01 22:24:143947error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463948 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033949 GLuint client_id = c.program;
3950 if (client_id) {
3951 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3952 if (info) {
[email protected]ca488e12010-12-13 20:06:143953 if (!info->IsDeleted()) {
[email protected]ca488e12010-12-13 20:06:143954 program_manager()->MarkAsDeleted(shader_manager(), info);
3955 }
[email protected]ae51d192010-04-27 00:48:033956 } else {
[email protected]8eee29c2010-04-29 03:38:293957 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033958 }
[email protected]96449d2c2009-11-25 00:01:323959 }
[email protected]f7a64ee2010-02-01 22:24:143960 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323961}
3962
[email protected]269200b12010-11-18 22:53:063963void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103964 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573965 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103966 for (GLsizei ii = 0; ii < n; ++ii) {
3967 id_allocator->FreeID(ids[ii]);
3968 }
3969}
3970
[email protected]269200b12010-11-18 22:53:063971error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
3972 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103973 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3974 GLsizei n = static_cast<GLsizei>(c.n);
3975 uint32 data_size;
3976 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3977 return error::kOutOfBounds;
3978 }
3979 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3980 c.ids_shm_id, c.ids_shm_offset, data_size);
3981 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063982 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103983 return error::kNoError;
3984 }
3985 if (ids == NULL) {
3986 return error::kOutOfBounds;
3987 }
[email protected]269200b12010-11-18 22:53:063988 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103989 return error::kNoError;
3990}
3991
[email protected]269200b12010-11-18 22:53:063992void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103993 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573994 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103995 if (id_offset == 0) {
3996 for (GLsizei ii = 0; ii < n; ++ii) {
3997 ids[ii] = id_allocator->AllocateID();
3998 }
3999 } else {
4000 for (GLsizei ii = 0; ii < n; ++ii) {
4001 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4002 id_offset = ids[ii] + 1;
4003 }
4004 }
4005}
4006
[email protected]269200b12010-11-18 22:53:064007error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4008 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104009 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4010 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4011 GLsizei n = static_cast<GLsizei>(c.n);
4012 uint32 data_size;
4013 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4014 return error::kOutOfBounds;
4015 }
4016 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4017 c.ids_shm_id, c.ids_shm_offset, data_size);
4018 if (n < 0) {
[email protected]269200b12010-11-18 22:53:064019 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:104020 return error::kNoError;
4021 }
4022 if (ids == NULL) {
4023 return error::kOutOfBounds;
4024 }
[email protected]269200b12010-11-18 22:53:064025 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:104026 return error::kNoError;
4027}
4028
[email protected]269200b12010-11-18 22:53:064029void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104030 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574031 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104032 for (GLsizei ii = 0; ii < n; ++ii) {
4033 if (!id_allocator->MarkAsUsed(ids[ii])) {
4034 for (GLsizei jj = 0; jj < ii; ++jj) {
4035 id_allocator->FreeID(ids[jj]);
4036 }
4037 SetGLError(
4038 GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:064039 "RegisterSharedIdsCHROMIUM: attempt to register "
4040 "id that already exists");
[email protected]066849e32010-05-03 19:14:104041 return;
4042 }
4043 }
4044}
4045
[email protected]269200b12010-11-18 22:53:064046error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4047 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104048 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4049 GLsizei n = static_cast<GLsizei>(c.n);
4050 uint32 data_size;
4051 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4052 return error::kOutOfBounds;
4053 }
4054 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4055 c.ids_shm_id, c.ids_shm_offset, data_size);
4056 if (n < 0) {
[email protected]269200b12010-11-18 22:53:064057 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:104058 return error::kNoError;
4059 }
4060 if (ids == NULL) {
4061 return error::kOutOfBounds;
4062 }
[email protected]269200b12010-11-18 22:53:064063 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:104064 return error::kNoError;
4065}
4066
[email protected]3a03a8f2011-03-19 00:51:274067void GLES2DecoderImpl::DoClear(GLbitfield mask) {
[email protected]0d6bfdc2011-11-02 01:32:204068 if (CheckBoundFramebuffersValid("glClear")) {
[email protected]529c6672012-01-04 02:18:264069 UNSHIPPED_TRACE_EVENT_INSTANT2("test_gpu", "DoClear", "red", clear_red_,
4070 "green", clear_green_);
[email protected]297ca1c2011-06-20 23:08:464071 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:274072 glClear(mask);
4073 }
4074}
4075
[email protected]36cef8ce2010-03-16 07:34:454076void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4077 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:034078 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:304079 FramebufferManager::FramebufferInfo* framebuffer_info =
4080 GetFramebufferInfoForTarget(target);
4081 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294082 SetGLError(GL_INVALID_OPERATION,
4083 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454084 return;
4085 }
[email protected]ae51d192010-04-27 00:48:034086 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:284087 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:034088 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:284089 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:034090 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294091 SetGLError(GL_INVALID_OPERATION,
4092 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:034093 return;
4094 }
4095 service_id = info->service_id();
4096 }
[email protected]9edc6b22010-12-23 02:00:264097 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034098 glFramebufferRenderbufferEXT(
4099 target, attachment, renderbuffertarget, service_id);
[email protected]1002c2d2011-06-28 22:39:044100 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264101 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:304102 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]3a2e7c7b2010-08-06 01:12:284103 }
[email protected]297ca1c2011-06-20 23:08:464104 if (framebuffer_info == bound_draw_framebuffer_) {
4105 state_dirty_ = true;
4106 }
[email protected]3a2e7c7b2010-08-06 01:12:284107}
4108
[email protected]297ca1c2011-06-20 23:08:464109bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
[email protected]3a2e7c7b2010-08-06 01:12:284110 switch (cap) {
[email protected]0a1e9ad2012-05-04 21:13:034111 case GL_BLEND:
4112 enable_blend_ = enabled;
4113 return true;
[email protected]43410e92012-04-20 17:06:284114 case GL_CULL_FACE:
4115 enable_cull_face_ = enabled;
4116 return true;
[email protected]3a2e7c7b2010-08-06 01:12:284117 case GL_SCISSOR_TEST:
4118 enable_scissor_test_ = enabled;
[email protected]297ca1c2011-06-20 23:08:464119 return true;
4120 case GL_DEPTH_TEST: {
4121 if (enable_depth_test_ != enabled) {
4122 enable_depth_test_ = enabled;
4123 state_dirty_ = true;
4124 }
4125 return false;
4126 }
4127 case GL_STENCIL_TEST:
4128 if (enable_stencil_test_ != enabled) {
4129 enable_stencil_test_ = enabled;
4130 state_dirty_ = true;
4131 }
4132 return false;
[email protected]3a2e7c7b2010-08-06 01:12:284133 default:
[email protected]297ca1c2011-06-20 23:08:464134 return true;
[email protected]3a2e7c7b2010-08-06 01:12:284135 }
4136}
4137
4138void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464139 if (SetCapabilityState(cap, false)) {
4140 glDisable(cap);
4141 }
[email protected]3a2e7c7b2010-08-06 01:12:284142}
4143
4144void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464145 if (SetCapabilityState(cap, true)) {
4146 glEnable(cap);
4147 }
[email protected]3a2e7c7b2010-08-06 01:12:284148}
4149
4150void GLES2DecoderImpl::DoClearColor(
4151 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
4152 clear_red_ = red;
4153 clear_green_ = green;
4154 clear_blue_ = blue;
4155 clear_alpha_ = alpha;
4156 glClearColor(red, green, blue, alpha);
4157}
4158
4159void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
4160 clear_depth_ = depth;
4161 glClearDepth(depth);
4162}
4163
4164void GLES2DecoderImpl::DoClearStencil(GLint s) {
4165 clear_stencil_ = s;
4166 glClearStencil(s);
4167}
4168
4169void GLES2DecoderImpl::DoColorMask(
4170 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
4171 mask_red_ = red;
4172 mask_green_ = green;
4173 mask_blue_ = blue;
4174 mask_alpha_ = alpha;
[email protected]297ca1c2011-06-20 23:08:464175 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284176}
4177
4178void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
4179 mask_depth_ = depth;
[email protected]297ca1c2011-06-20 23:08:464180 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284181}
4182
4183void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
4184 mask_stencil_front_ = mask;
4185 mask_stencil_back_ = mask;
[email protected]297ca1c2011-06-20 23:08:464186 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284187}
4188
4189void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
[email protected]297ca1c2011-06-20 23:08:464190 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284191 mask_stencil_front_ = mask;
[email protected]297ca1c2011-06-20 23:08:464192 }
4193 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284194 mask_stencil_back_ = mask;
4195 }
[email protected]297ca1c2011-06-20 23:08:464196 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284197}
4198
[email protected]0d6bfdc2011-11-02 01:32:204199// Assumes framebuffer is complete.
4200void GLES2DecoderImpl::ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:304201 GLenum target, FramebufferManager::FramebufferInfo* info) {
4202 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204203 // bind this to the DRAW point, clear then bind back to READ
4204 // TODO(gman): I don't think there is any guarantee that an FBO that
4205 // is complete on the READ attachment will be complete as a DRAW
4206 // attachment.
4207 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
4208 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, info->service_id());
[email protected]8e3e0662010-08-23 18:46:304209 }
[email protected]3a2e7c7b2010-08-06 01:12:284210 GLbitfield clear_bits = 0;
4211 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:464212 glClearColor(
[email protected]0d6bfdc2011-11-02 01:32:204213 0.0f, 0.0f, 0.0f,
[email protected]297ca1c2011-06-20 23:08:464214 (GLES2Util::GetChannelsForFormat(
[email protected]0d6bfdc2011-11-02 01:32:204215 info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f : 1.0f);
[email protected]3a2e7c7b2010-08-06 01:12:284216 glColorMask(true, true, true, true);
4217 clear_bits |= GL_COLOR_BUFFER_BIT;
4218 }
4219
4220 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4221 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4222 glClearStencil(0);
4223 glStencilMask(-1);
4224 clear_bits |= GL_STENCIL_BUFFER_BIT;
4225 }
4226
4227 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4228 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4229 glClearDepth(1.0f);
4230 glDepthMask(true);
4231 clear_bits |= GL_DEPTH_BUFFER_BIT;
4232 }
4233
4234 glDisable(GL_SCISSOR_TEST);
4235 glClear(clear_bits);
4236
[email protected]968351b2011-12-20 08:26:514237 framebuffer_manager()->MarkAttachmentsAsCleared(
4238 info, renderbuffer_manager(), texture_manager());
[email protected]3a2e7c7b2010-08-06 01:12:284239
[email protected]c007aa02010-09-02 22:22:404240 RestoreClearState();
4241
4242 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204243 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, info->service_id());
[email protected]87d1a3fe2011-12-01 04:25:484244 FramebufferManager::FramebufferInfo* framebuffer =
4245 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4246 GLuint service_id =
4247 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
4248 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
[email protected]c007aa02010-09-02 22:22:404249 }
4250}
4251
4252void GLES2DecoderImpl::RestoreClearState() {
[email protected]297ca1c2011-06-20 23:08:464253 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284254 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
[email protected]3a2e7c7b2010-08-06 01:12:284255 glClearStencil(clear_stencil_);
[email protected]3a2e7c7b2010-08-06 01:12:284256 glClearDepth(clear_depth_);
[email protected]3a2e7c7b2010-08-06 01:12:284257 if (enable_scissor_test_) {
4258 glEnable(GL_SCISSOR_TEST);
4259 }
[email protected]36cef8ce2010-03-16 07:34:454260}
4261
4262GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]0d6bfdc2011-11-02 01:32:204263 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]8e3e0662010-08-23 18:46:304264 GetFramebufferInfoForTarget(target);
[email protected]0d6bfdc2011-11-02 01:32:204265 if (!framebuffer) {
[email protected]36cef8ce2010-03-16 07:34:454266 return GL_FRAMEBUFFER_COMPLETE;
4267 }
[email protected]0d6bfdc2011-11-02 01:32:204268 GLenum completeness = framebuffer->IsPossiblyComplete();
4269 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4270 return completeness;
4271 }
[email protected]36cef8ce2010-03-16 07:34:454272 return glCheckFramebufferStatusEXT(target);
4273}
4274
4275void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:034276 GLenum target, GLenum attachment, GLenum textarget,
4277 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:304278 FramebufferManager::FramebufferInfo* framebuffer_info =
4279 GetFramebufferInfoForTarget(target);
4280 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294281 SetGLError(GL_INVALID_OPERATION,
4282 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:454283 return;
4284 }
[email protected]ae51d192010-04-27 00:48:034285 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:284286 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:034287 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:284288 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:034289 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294290 SetGLError(GL_INVALID_OPERATION,
4291 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:034292 return;
4293 }
4294 service_id = info->service_id();
4295 }
[email protected]0d6bfdc2011-11-02 01:32:204296
[email protected]80eb6b52012-01-19 00:14:414297 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
[email protected]0d6bfdc2011-11-02 01:32:204298 SetGLError(GL_INVALID_VALUE,
4299 "glFramebufferTexture2D: level out of range");
4300 return;
4301 }
4302
[email protected]9edc6b22010-12-23 02:00:264303 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034304 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]1002c2d2011-06-28 22:39:044305 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264306 if (error == GL_NO_ERROR) {
4307 framebuffer_info->AttachTexture(attachment, info, textarget, level);
[email protected]3a2e7c7b2010-08-06 01:12:284308 }
[email protected]297ca1c2011-06-20 23:08:464309 if (framebuffer_info == bound_draw_framebuffer_) {
4310 state_dirty_ = true;
4311 }
[email protected]36cef8ce2010-03-16 07:34:454312}
4313
4314void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4315 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:304316 FramebufferManager::FramebufferInfo* framebuffer_info =
4317 GetFramebufferInfoForTarget(target);
4318 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294319 SetGLError(GL_INVALID_OPERATION,
4320 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454321 return;
4322 }
4323 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:574324 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4325 GLint type = 0;
4326 GLuint client_id = 0;
4327 glGetFramebufferAttachmentParameterivEXT(
4328 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
4329 switch (type) {
4330 case GL_RENDERBUFFER: {
4331 renderbuffer_manager()->GetClientId(*params, &client_id);
4332 break;
4333 }
4334 case GL_TEXTURE: {
4335 texture_manager()->GetClientId(*params, &client_id);
4336 break;
4337 }
4338 default:
4339 break;
4340 }
4341 *params = client_id;
4342 }
[email protected]36cef8ce2010-03-16 07:34:454343}
4344
4345void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4346 GLenum target, GLenum pname, GLint* params) {
[email protected]0d6bfdc2011-11-02 01:32:204347 RenderbufferManager::RenderbufferInfo* renderbuffer =
4348 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4349 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294350 SetGLError(GL_INVALID_OPERATION,
4351 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454352 return;
4353 }
[email protected]3a03a8f2011-03-19 00:51:274354 switch (pname) {
4355 case GL_RENDERBUFFER_INTERNAL_FORMAT:
[email protected]0d6bfdc2011-11-02 01:32:204356 *params = renderbuffer->internal_format();
[email protected]3a03a8f2011-03-19 00:51:274357 break;
4358 case GL_RENDERBUFFER_WIDTH:
[email protected]0d6bfdc2011-11-02 01:32:204359 *params = renderbuffer->width();
[email protected]3a03a8f2011-03-19 00:51:274360 break;
4361 case GL_RENDERBUFFER_HEIGHT:
[email protected]0d6bfdc2011-11-02 01:32:204362 *params = renderbuffer->height();
[email protected]3a03a8f2011-03-19 00:51:274363 break;
4364 default:
4365 glGetRenderbufferParameterivEXT(target, pname, params);
4366 break;
[email protected]b71f52c2010-06-18 22:20:204367 }
[email protected]36cef8ce2010-03-16 07:34:454368}
4369
[email protected]8e3e0662010-08-23 18:46:304370void GLES2DecoderImpl::DoBlitFramebufferEXT(
4371 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
4372 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
4373 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:394374 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304375 SetGLError(GL_INVALID_OPERATION,
4376 "glBlitFramebufferEXT: function not available");
4377 }
[email protected]5094b0f2010-11-09 19:45:244378 if (IsAngle()) {
4379 glBlitFramebufferANGLE(
4380 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4381 } else {
4382 glBlitFramebufferEXT(
4383 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4384 }
[email protected]529c6672012-01-04 02:18:264385 UNSHIPPED_TRACE_EVENT_INSTANT1("test_gpu", "DoBlit", "width", srcX1 - srcX0);
[email protected]8e3e0662010-08-23 18:46:304386}
4387
4388void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
4389 GLenum target, GLsizei samples, GLenum internalformat,
4390 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:394391 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304392 SetGLError(GL_INVALID_OPERATION,
4393 "glRenderbufferStorageMultisampleEXT: function not available");
4394 return;
4395 }
[email protected]8e3e0662010-08-23 18:46:304396
[email protected]0d6bfdc2011-11-02 01:32:204397 RenderbufferManager::RenderbufferInfo* renderbuffer =
4398 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4399 if (!renderbuffer) {
4400 SetGLError(GL_INVALID_OPERATION,
4401 "glGetRenderbufferStorageMultisample: no renderbuffer bound");
4402 return;
4403 }
4404
[email protected]84afefa2011-10-19 21:45:534405 if (samples > renderbuffer_manager()->max_samples()) {
4406 SetGLError(GL_INVALID_VALUE,
4407 "glGetRenderbufferStorageMultisample: samples too large");
4408 return;
4409 }
4410
4411 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4412 height > renderbuffer_manager()->max_renderbuffer_size()) {
4413 SetGLError(GL_INVALID_VALUE,
4414 "glGetRenderbufferStorageMultisample: size too large");
4415 return;
4416 }
4417
[email protected]9edc6b22010-12-23 02:00:264418 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:304419 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264420 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:304421 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264422 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:304423 break;
4424 case GL_RGBA4:
4425 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264426 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:304427 break;
4428 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264429 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:304430 break;
4431 }
4432 }
4433
[email protected]9edc6b22010-12-23 02:00:264434 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:084435 if (IsAngle()) {
4436 glRenderbufferStorageMultisampleANGLE(
4437 target, samples, impl_format, width, height);
4438 } else {
4439 glRenderbufferStorageMultisampleEXT(
4440 target, samples, impl_format, width, height);
4441 }
[email protected]1002c2d2011-06-28 22:39:044442 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264443 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514444 // TODO(gman): If renderbuffers tracked which framebuffers they were
4445 // attached to we could just mark those framebuffers as not complete.
4446 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204447 renderbuffer_manager()->SetInfo(
4448 renderbuffer, samples, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264449 }
[email protected]8e3e0662010-08-23 18:46:304450}
4451
[email protected]36cef8ce2010-03-16 07:34:454452void GLES2DecoderImpl::DoRenderbufferStorage(
4453 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]0d6bfdc2011-11-02 01:32:204454 RenderbufferManager::RenderbufferInfo* renderbuffer =
4455 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4456 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294457 SetGLError(GL_INVALID_OPERATION,
4458 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454459 return;
4460 }
[email protected]876f6fee2010-08-02 23:10:324461
[email protected]84afefa2011-10-19 21:45:534462 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4463 height > renderbuffer_manager()->max_renderbuffer_size()) {
4464 SetGLError(GL_INVALID_VALUE,
4465 "glGetRenderbufferStorage: size too large");
4466 return;
4467 }
4468
[email protected]9edc6b22010-12-23 02:00:264469 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:324470 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264471 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:324472 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264473 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:324474 break;
4475 case GL_RGBA4:
4476 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264477 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:324478 break;
4479 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264480 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:324481 break;
4482 }
[email protected]b71f52c2010-06-18 22:20:204483 }
[email protected]876f6fee2010-08-02 23:10:324484
[email protected]9edc6b22010-12-23 02:00:264485 CopyRealGLErrorsToWrapper();
4486 glRenderbufferStorageEXT(target, impl_format, width, height);
[email protected]1002c2d2011-06-28 22:39:044487 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264488 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514489 // TODO(gman): If tetxures tracked which framebuffers they were attached to
4490 // we could just mark those framebuffers as not complete.
4491 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204492 renderbuffer_manager()->SetInfo(
4493 renderbuffer, 0, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264494 }
[email protected]36cef8ce2010-03-16 07:34:454495}
4496
[email protected]07f54fcc2009-12-22 02:46:304497void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]0c8fabf2011-06-14 19:35:224498 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]6b8cf1a2010-05-06 16:13:584499 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4500 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:474501 if (!info) {
[email protected]a93bb842010-02-16 23:03:474502 return;
4503 }
[email protected]05afda12011-01-20 00:17:344504
[email protected]2df73892012-04-28 01:09:544505 if (info->Link()) {
4506 if (info == current_program_.get()) {
4507 program_manager()->ClearUniforms(info);
4508 }
4509 }
[email protected]07f54fcc2009-12-22 02:46:304510};
4511
[email protected]3916c97e2010-02-25 03:20:504512void GLES2DecoderImpl::DoTexParameterf(
4513 GLenum target, GLenum pname, GLfloat param) {
4514 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:304515 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294516 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244517 return;
[email protected]07f54fcc2009-12-22 02:46:304518 }
[email protected]cbb22e42011-05-12 23:36:244519
4520 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414521 info, pname, static_cast<GLint>(param))) {
[email protected]cbb22e42011-05-12 23:36:244522 SetGLError(GL_INVALID_ENUM, "glTexParameterf: param GL_INVALID_ENUM");
4523 return;
4524 }
4525 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:304526}
4527
[email protected]3916c97e2010-02-25 03:20:504528void GLES2DecoderImpl::DoTexParameteri(
4529 GLenum target, GLenum pname, GLint param) {
4530 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4531 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294532 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244533 return;
[email protected]3916c97e2010-02-25 03:20:504534 }
[email protected]cbb22e42011-05-12 23:36:244535
[email protected]80eb6b52012-01-19 00:14:414536 if (!texture_manager()->SetParameter(info, pname, param)) {
[email protected]cbb22e42011-05-12 23:36:244537 SetGLError(GL_INVALID_ENUM, "glTexParameteri: param GL_INVALID_ENUM");
4538 return;
4539 }
4540 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:504541}
4542
4543void GLES2DecoderImpl::DoTexParameterfv(
4544 GLenum target, GLenum pname, const GLfloat* params) {
4545 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4546 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294547 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244548 return;
[email protected]3916c97e2010-02-25 03:20:504549 }
[email protected]cbb22e42011-05-12 23:36:244550
4551 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414552 info, pname, static_cast<GLint>(params[0]))) {
[email protected]cbb22e42011-05-12 23:36:244553 SetGLError(GL_INVALID_ENUM, "glTexParameterfv: param GL_INVALID_ENUM");
4554 return;
4555 }
4556 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504557}
4558
4559void GLES2DecoderImpl::DoTexParameteriv(
4560 GLenum target, GLenum pname, const GLint* params) {
4561 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4562 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294563 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244564 return;
[email protected]3916c97e2010-02-25 03:20:504565 }
[email protected]cbb22e42011-05-12 23:36:244566
[email protected]80eb6b52012-01-19 00:14:414567 if (!texture_manager()->SetParameter(info, pname, *params)) {
[email protected]cbb22e42011-05-12 23:36:244568 SetGLError(GL_INVALID_ENUM, "glTexParameteriv: param GL_INVALID_ENUM");
4569 return;
4570 }
4571 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504572}
4573
[email protected]939e7362010-05-13 20:49:104574bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:144575 if (!current_program_) {
[email protected]939e7362010-05-13 20:49:104576 // The program does not exist.
4577 SetGLError(GL_INVALID_OPERATION,
4578 (std::string(function_name) + ": no program in use").c_str());
4579 return false;
4580 }
[email protected]ca488e12010-12-13 20:06:144581 if (!current_program_->InUse()) {
[email protected]939e7362010-05-13 20:49:104582 SetGLError(GL_INVALID_OPERATION,
4583 (std::string(function_name) + ": program not linked").c_str());
4584 return false;
4585 }
4586 return true;
4587}
4588
4589bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
4590 GLint location, const char* function_name) {
4591 if (!CheckCurrentProgram(function_name)) {
4592 return false;
4593 }
4594 return location != -1;
4595}
4596
[email protected]43c2f1f2011-03-25 18:35:364597bool GLES2DecoderImpl::PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124598 GLint fake_location, const char* function_name,
4599 GLint* real_location, GLenum* type, GLsizei* count) {
[email protected]43c2f1f2011-03-25 18:35:364600 DCHECK(type);
4601 DCHECK(count);
[email protected]1b0a6752012-02-22 03:44:124602 DCHECK(real_location);
4603 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
[email protected]939e7362010-05-13 20:49:104604 return false;
4605 }
[email protected]43c2f1f2011-03-25 18:35:364606 GLint array_index = -1;
4607 const ProgramManager::ProgramInfo::UniformInfo* info =
[email protected]1b0a6752012-02-22 03:44:124608 current_program_->GetUniformInfoByFakeLocation(
4609 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:364610 if (!info) {
[email protected]939e7362010-05-13 20:49:104611 SetGLError(GL_INVALID_OPERATION,
[email protected]43c2f1f2011-03-25 18:35:364612 (std::string(function_name) + ": unknown location").c_str());
[email protected]939e7362010-05-13 20:49:104613 return false;
4614 }
[email protected]43c2f1f2011-03-25 18:35:364615 if (*count > 1 && !info->is_array) {
4616 SetGLError(
4617 GL_INVALID_OPERATION,
4618 (std::string(function_name) + ": count > 1 for non-array").c_str());
4619 return false;
4620 }
4621 *count = std::min(info->size - array_index, *count);
4622 if (*count <= 0) {
4623 return false;
4624 }
4625 *type = info->type;
[email protected]939e7362010-05-13 20:49:104626 return true;
4627}
4628
[email protected]1b0a6752012-02-22 03:44:124629void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
4630 GLenum type = 0;
4631 GLsizei count = 1;
4632 GLint real_location = -1;
4633 if (!PrepForSetUniformByLocation(
4634 fake_location, "glUniform1iv", &real_location, &type, &count)) {
[email protected]3916c97e2010-02-25 03:20:504635 return;
4636 }
[email protected]d20a6512012-05-02 20:17:464637 if (!current_program_->SetSamplers(
4638 group_->max_texture_units(), fake_location, 1, &v0)) {
4639 SetGLError(GL_INVALID_VALUE, "glUniform1i: texture unit out of range");
4640 return;
4641 }
[email protected]1b0a6752012-02-22 03:44:124642 glUniform1i(real_location, v0);
[email protected]3916c97e2010-02-25 03:20:504643}
4644
4645void GLES2DecoderImpl::DoUniform1iv(
[email protected]1b0a6752012-02-22 03:44:124646 GLint fake_location, GLsizei count, const GLint *value) {
[email protected]43c2f1f2011-03-25 18:35:364647 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124648 GLint real_location = -1;
4649 if (!PrepForSetUniformByLocation(
4650 fake_location, "glUniform1iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364651 return;
4652 }
[email protected]61eeb33f2011-07-26 15:30:314653 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
4654 type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]d20a6512012-05-02 20:17:464655 if (!current_program_->SetSamplers(
4656 group_->max_texture_units(), fake_location, count, value)) {
4657 SetGLError(GL_INVALID_VALUE, "glUniform1iv: texture unit out of range");
4658 return;
4659 }
[email protected]43c2f1f2011-03-25 18:35:364660 }
[email protected]1b0a6752012-02-22 03:44:124661 glUniform1iv(real_location, count, value);
[email protected]3916c97e2010-02-25 03:20:504662}
4663
[email protected]939e7362010-05-13 20:49:104664void GLES2DecoderImpl::DoUniform1fv(
[email protected]1b0a6752012-02-22 03:44:124665 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364666 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124667 GLint real_location = -1;
4668 if (!PrepForSetUniformByLocation(
4669 fake_location, "glUniform1fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104670 return;
4671 }
4672 if (type == GL_BOOL) {
4673 scoped_array<GLint> temp(new GLint[count]);
4674 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:534675 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104676 }
[email protected]1b0a6752012-02-22 03:44:124677 DoUniform1iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104678 } else {
[email protected]1b0a6752012-02-22 03:44:124679 glUniform1fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104680 }
4681}
4682
4683void GLES2DecoderImpl::DoUniform2fv(
[email protected]1b0a6752012-02-22 03:44:124684 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364685 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124686 GLint real_location = -1;
4687 if (!PrepForSetUniformByLocation(
4688 fake_location, "glUniform2fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104689 return;
4690 }
4691 if (type == GL_BOOL_VEC2) {
4692 GLsizei num_values = count * 2;
4693 scoped_array<GLint> temp(new GLint[num_values]);
4694 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534695 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104696 }
[email protected]1b0a6752012-02-22 03:44:124697 glUniform2iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104698 } else {
[email protected]1b0a6752012-02-22 03:44:124699 glUniform2fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104700 }
4701}
4702
4703void GLES2DecoderImpl::DoUniform3fv(
[email protected]1b0a6752012-02-22 03:44:124704 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364705 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124706 GLint real_location = -1;
4707 if (!PrepForSetUniformByLocation(
4708 fake_location, "glUniform3fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104709 return;
4710 }
4711 if (type == GL_BOOL_VEC3) {
4712 GLsizei num_values = count * 3;
4713 scoped_array<GLint> temp(new GLint[num_values]);
4714 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534715 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104716 }
[email protected]1b0a6752012-02-22 03:44:124717 glUniform3iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104718 } else {
[email protected]1b0a6752012-02-22 03:44:124719 glUniform3fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104720 }
4721}
4722
4723void GLES2DecoderImpl::DoUniform4fv(
[email protected]1b0a6752012-02-22 03:44:124724 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364725 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124726 GLint real_location = -1;
4727 if (!PrepForSetUniformByLocation(
4728 fake_location, "glUniform4fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104729 return;
4730 }
4731 if (type == GL_BOOL_VEC4) {
4732 GLsizei num_values = count * 4;
4733 scoped_array<GLint> temp(new GLint[num_values]);
4734 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534735 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104736 }
[email protected]1b0a6752012-02-22 03:44:124737 glUniform4iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104738 } else {
[email protected]1b0a6752012-02-22 03:44:124739 glUniform4fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104740 }
4741}
4742
[email protected]43c2f1f2011-03-25 18:35:364743void GLES2DecoderImpl::DoUniform2iv(
[email protected]1b0a6752012-02-22 03:44:124744 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364745 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124746 GLint real_location = -1;
4747 if (!PrepForSetUniformByLocation(
4748 fake_location, "glUniform2iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364749 return;
4750 }
[email protected]1b0a6752012-02-22 03:44:124751 glUniform2iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364752}
4753
4754void GLES2DecoderImpl::DoUniform3iv(
[email protected]1b0a6752012-02-22 03:44:124755 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364756 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124757 GLint real_location = -1;
4758 if (!PrepForSetUniformByLocation(
4759 fake_location, "glUniform3iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364760 return;
4761 }
[email protected]1b0a6752012-02-22 03:44:124762 glUniform3iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364763}
4764
4765void GLES2DecoderImpl::DoUniform4iv(
[email protected]1b0a6752012-02-22 03:44:124766 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364767 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124768 GLint real_location = -1;
4769 if (!PrepForSetUniformByLocation(
4770 fake_location, "glUniform4iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364771 return;
4772 }
[email protected]1b0a6752012-02-22 03:44:124773 glUniform4iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364774}
4775
4776void GLES2DecoderImpl::DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:124777 GLint fake_location, GLsizei count, GLboolean transpose,
4778 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364779 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124780 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364781 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124782 fake_location, "glUniformMatrix2fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364783 return;
4784 }
[email protected]1b0a6752012-02-22 03:44:124785 glUniformMatrix2fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364786}
4787
4788void GLES2DecoderImpl::DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:124789 GLint fake_location, GLsizei count, GLboolean transpose,
4790 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364791 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124792 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364793 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124794 fake_location, "glUniformMatrix3fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364795 return;
4796 }
[email protected]1b0a6752012-02-22 03:44:124797 glUniformMatrix3fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364798}
4799
4800void GLES2DecoderImpl::DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:124801 GLint fake_location, GLsizei count, GLboolean transpose,
4802 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364803 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124804 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364805 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124806 fake_location, "glUniformMatrix4fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364807 return;
4808 }
[email protected]1b0a6752012-02-22 03:44:124809 glUniformMatrix4fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364810}
4811
[email protected]3916c97e2010-02-25 03:20:504812void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:034813 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:504814 ProgramManager::ProgramInfo* info = NULL;
4815 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:584816 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:504817 if (!info) {
[email protected]ae51d192010-04-27 00:48:034818 return;
4819 }
4820 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:504821 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:294822 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:504823 return;
4824 }
[email protected]ae51d192010-04-27 00:48:034825 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:504826 }
[email protected]ca488e12010-12-13 20:06:144827 if (current_program_) {
4828 program_manager()->UnuseProgram(shader_manager(), current_program_);
4829 }
[email protected]3916c97e2010-02-25 03:20:504830 current_program_ = info;
[email protected]2df73892012-04-28 01:09:544831 glUseProgram(service_id);
[email protected]ca488e12010-12-13 20:06:144832 if (current_program_) {
4833 program_manager()->UseProgram(current_program_);
4834 }
[email protected]3916c97e2010-02-25 03:20:504835}
4836
[email protected]96449d2c2009-11-25 00:01:324837GLenum GLES2DecoderImpl::GetGLError() {
4838 // Check the GL error first, then our wrapped error.
4839 GLenum error = glGetError();
4840 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:374841 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:324842 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:294843 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:324844 break;
4845 }
4846 }
4847 }
4848
4849 if (error != GL_NO_ERROR) {
4850 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:294851 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324852 }
4853 return error;
4854}
4855
[email protected]1002c2d2011-06-28 22:39:044856GLenum GLES2DecoderImpl::PeekGLError() {
4857 GLenum error = glGetError();
4858 if (error != GL_NO_ERROR) {
4859 SetGLError(error, "");
4860 }
4861 return error;
4862}
4863
[email protected]8eee29c2010-04-29 03:38:294864void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
4865 if (msg) {
4866 last_error_ = msg;
[email protected]fa20ec82012-05-04 04:02:484867 if (error_count_ < kMaxLogErrors ||
4868 CommandLine::ForCurrentProcess()->HasSwitch(
4869 switches::kDisableGLErrorLimit)) {
4870 ++error_count_;
4871 // LOG this unless logging is turned off as any chromium code that
4872 // generates these errors probably has a bug.
4873 if (log_synthesized_gl_errors()) {
4874 LOG(ERROR) << last_error_;
4875 }
4876 if (!msg_callback_.is_null()) {
4877 msg_callback_.Run(0, GLES2Util::GetStringEnum(error) + " : " + msg);
4878 }
4879 } else {
4880 if (error_count_ == kMaxLogErrors) {
4881 ++error_count_;
4882 LOG(ERROR)
4883 << "Too many GL errors, not reporting any more for this context."
4884 << " use --disable-gl-error-limit to see all errors.";
4885 }
[email protected]6b6e7ee2011-12-13 08:04:524886 }
[email protected]8eee29c2010-04-29 03:38:294887 }
[email protected]ddd968b82010-03-02 00:44:294888 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324889}
4890
[email protected]07f54fcc2009-12-22 02:46:304891void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
4892 GLenum error;
4893 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294894 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:304895 }
4896}
4897
[email protected]6217d392010-03-25 22:08:354898void GLES2DecoderImpl::ClearRealGLErrors() {
4899 GLenum error;
4900 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]3ed14d112011-12-13 22:05:514901 if (error != GL_OUT_OF_MEMORY) {
4902 // GL_OUT_OF_MEMORY can legally happen on lost device.
4903 NOTREACHED() << "GL error " << error << " was unhandled.";
4904 }
[email protected]6217d392010-03-25 22:08:354905 }
4906}
4907
[email protected]ef526492010-06-02 23:12:254908bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:504909 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:254910 // Only check if there are some unrenderable textures.
4911 if (!texture_manager()->HaveUnrenderableTextures()) {
4912 return false;
4913 }
4914 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:504915 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4916 current_program_->sampler_indices();
4917 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4918 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4919 current_program_->GetUniformInfo(sampler_indices[ii]);
4920 DCHECK(uniform_info);
4921 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4922 GLuint texture_unit_index = uniform_info->texture_units[jj];
4923 if (texture_unit_index < group_->max_texture_units()) {
4924 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4925 TextureManager::TextureInfo* texture_info =
[email protected]61eeb33f2011-07-26 15:30:314926 texture_unit.GetInfoForSamplerType(uniform_info->type);
[email protected]80eb6b52012-01-19 00:14:414927 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]ef526492010-06-02 23:12:254928 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:504929 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4930 glBindTexture(
[email protected]61eeb33f2011-07-26 15:30:314931 GetBindTargetForSamplerType(uniform_info->type),
[email protected]00f893d2010-08-24 18:55:494932 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:504933 }
4934 }
4935 // else: should this be an error?
4936 }
4937 }
[email protected]ef526492010-06-02 23:12:254938 return textures_set;
[email protected]3916c97e2010-02-25 03:20:504939}
4940
4941void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
4942 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:504943 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4944 current_program_->sampler_indices();
4945 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4946 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4947 current_program_->GetUniformInfo(sampler_indices[ii]);
4948 DCHECK(uniform_info);
4949 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4950 GLuint texture_unit_index = uniform_info->texture_units[jj];
4951 if (texture_unit_index < group_->max_texture_units()) {
4952 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4953 TextureManager::TextureInfo* texture_info =
4954 uniform_info->type == GL_SAMPLER_2D ?
4955 texture_unit.bound_texture_2d :
4956 texture_unit.bound_texture_cube_map;
[email protected]80eb6b52012-01-19 00:14:414957 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]3916c97e2010-02-25 03:20:504958 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4959 // Get the texture info that was previously bound here.
4960 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
4961 texture_unit.bound_texture_2d :
4962 texture_unit.bound_texture_cube_map;
4963 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:034964 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:504965 }
4966 }
4967 }
4968 }
4969 // Set the active texture back to whatever the user had it as.
4970 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:304971}
4972
[email protected]0d6bfdc2011-11-02 01:32:204973bool GLES2DecoderImpl::ClearUnclearedTextures() {
4974 // Only check if there are some uncleared textures.
4975 if (!texture_manager()->HaveUnsafeTextures()) {
4976 return true;
4977 }
4978
4979 // 1: Check all textures we are about to render with.
4980 if (current_program_) {
4981 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4982 current_program_->sampler_indices();
4983 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4984 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4985 current_program_->GetUniformInfo(sampler_indices[ii]);
4986 DCHECK(uniform_info);
4987 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4988 GLuint texture_unit_index = uniform_info->texture_units[jj];
4989 if (texture_unit_index < group_->max_texture_units()) {
4990 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4991 TextureManager::TextureInfo* texture_info =
4992 texture_unit.GetInfoForSamplerType(uniform_info->type);
4993 if (texture_info && !texture_info->SafeToRenderFrom()) {
4994 if (!texture_manager()->ClearRenderableLevels(this, texture_info)) {
4995 return false;
4996 }
4997 }
4998 }
4999 }
5000 }
5001 }
5002 return true;
5003}
5004
[email protected]c6aef902012-02-14 03:31:425005bool GLES2DecoderImpl::IsDrawValid(
5006 GLuint max_vertex_accessed, GLsizei primcount) {
[email protected]689fa1c52010-06-09 18:35:035007 // NOTE: We specifically do not check current_program->IsValid() because
5008 // it could never be invalid since glUseProgram would have failed. While
5009 // glLinkProgram could later mark the program as invalid the previous
5010 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:145011 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:505012 // The program does not exist.
5013 // But GL says no ERROR.
5014 return false;
5015 }
[email protected]c6aef902012-02-14 03:31:425016
5017 // true if any enabled, used divisor is zero
5018 bool divisor0 = false;
[email protected]f39f4b3f2010-05-12 17:04:085019 // Validate all attribs currently enabled. If they are used by the current
5020 // program then check that they have enough elements to handle the draw call.
5021 // If they are not used by the current program check that they have a buffer
5022 // assigned.
5023 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:445024 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]f39f4b3f2010-05-12 17:04:085025 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:405026 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:085027 const VertexAttribManager::VertexAttribInfo* info = *it;
5028 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5029 current_program_->GetAttribInfoByLocation(info->index());
5030 if (attrib_info) {
[email protected]c6aef902012-02-14 03:31:425031 divisor0 |= (info->divisor() == 0);
5032 GLuint count = info->MaxVertexAccessed(primcount, max_vertex_accessed);
[email protected]f39f4b3f2010-05-12 17:04:085033 // This attrib is used in the current program.
[email protected]c6aef902012-02-14 03:31:425034 if (!info->CanAccess(count)) {
[email protected]f39f4b3f2010-05-12 17:04:085035 SetGLError(GL_INVALID_OPERATION,
5036 "glDrawXXX: attempt to access out of range vertices");
5037 return false;
5038 }
5039 } else {
5040 // This attrib is not used in the current program.
[email protected]a0b78dc2011-11-11 10:43:105041 if (!info->buffer()) {
[email protected]f39f4b3f2010-05-12 17:04:085042 SetGLError(
5043 GL_INVALID_OPERATION,
5044 "glDrawXXX: attempt to render with no buffer attached to enabled "
5045 "attrib");
5046 return false;
5047 }
[email protected]1d32bc82010-01-13 22:06:465048 }
[email protected]07f54fcc2009-12-22 02:46:305049 }
[email protected]c6aef902012-02-14 03:31:425050
5051 if (primcount && !divisor0) {
5052 SetGLError(
5053 GL_INVALID_OPERATION,
5054 "glDrawXXX: attempt instanced render with all attributes having "
5055 "non-zero divisors");
5056 return false;
5057 }
5058
[email protected]3916c97e2010-02-25 03:20:505059 return true;
[email protected]b1122982010-05-17 23:04:245060}
5061
[email protected]c13e1da62011-09-09 21:48:305062bool GLES2DecoderImpl::SimulateAttrib0(
5063 GLuint max_vertex_accessed, bool* simulated) {
5064 DCHECK(simulated);
5065 *simulated = false;
5066
[email protected]876f6fee2010-08-02 23:10:325067 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
[email protected]c13e1da62011-09-09 21:48:305068 return true;
[email protected]876f6fee2010-08-02 23:10:325069
[email protected]b1122982010-05-17 23:04:245070 const VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445071 vertex_attrib_manager_->GetVertexAttribInfo(0);
[email protected]b1122982010-05-17 23:04:245072 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:495073 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
5074 if (info->enabled() && attrib_0_used) {
[email protected]c13e1da62011-09-09 21:48:305075 return true;
[email protected]b1122982010-05-17 23:04:245076 }
5077
[email protected]b1122982010-05-17 23:04:245078 // Make a buffer with a single repeated vec4 value enough to
5079 // simulate the constant value that is supposed to be here.
5080 // This is required to emulate GLES2 on GL.
[email protected]c13e1da62011-09-09 21:48:305081 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
5082
5083 GLuint num_vertices = max_vertex_accessed + 1;
5084 GLuint size_needed = 0;
5085
5086 if (num_vertices == 0 ||
5087 !SafeMultiply(num_vertices, static_cast<GLuint>(sizeof(Vec4)),
5088 &size_needed) ||
5089 size_needed > 0x7FFFFFFFU) {
5090 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
5091 return false;
5092 }
5093
5094 CopyRealGLErrorsToWrapper();
5095 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
5096
[email protected]8f0b86c2f2012-04-10 05:48:285097 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
5098 if (new_buffer) {
[email protected]fc753442011-02-04 19:49:495099 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305100 GLenum error = glGetError();
5101 if (error != GL_NO_ERROR) {
5102 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
5103 return false;
5104 }
[email protected]fc753442011-02-04 19:49:495105 }
[email protected]8f0b86c2f2012-04-10 05:48:285106 if (new_buffer ||
5107 (attrib_0_used &&
5108 (!attrib_0_buffer_matches_value_ ||
5109 (info->value().v[0] != attrib_0_value_.v[0] ||
5110 info->value().v[1] != attrib_0_value_.v[1] ||
5111 info->value().v[2] != attrib_0_value_.v[2] ||
5112 info->value().v[3] != attrib_0_value_.v[3])))) {
[email protected]fc753442011-02-04 19:49:495113 std::vector<Vec4> temp(num_vertices, info->value());
5114 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
5115 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:245116 attrib_0_value_ = info->value();
5117 attrib_0_size_ = size_needed;
5118 }
5119
5120 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5121
[email protected]c6aef902012-02-14 03:31:425122 if (info->divisor())
5123 glVertexAttribDivisorANGLE(0, 0);
5124
[email protected]c13e1da62011-09-09 21:48:305125 *simulated = true;
[email protected]b1122982010-05-17 23:04:245126 return true;
[email protected]b1122982010-05-17 23:04:245127}
5128
[email protected]43410e92012-04-20 17:06:285129void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib) {
[email protected]b1122982010-05-17 23:04:245130 const VertexAttribManager::VertexAttribInfo* info =
[email protected]43410e92012-04-20 17:06:285131 vertex_attrib_manager_->GetVertexAttribInfo(attrib);
[email protected]b1122982010-05-17 23:04:245132 const void* ptr = reinterpret_cast<const void*>(info->offset());
5133 BufferManager::BufferInfo* buffer_info = info->buffer();
5134 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
5135 glVertexAttribPointer(
[email protected]43410e92012-04-20 17:06:285136 attrib, info->size(), info->type(), info->normalized(), info->gl_stride(),
[email protected]b1122982010-05-17 23:04:245137 ptr);
[email protected]c6aef902012-02-14 03:31:425138 if (info->divisor())
[email protected]43410e92012-04-20 17:06:285139 glVertexAttribDivisorANGLE(attrib, info->divisor());
[email protected]b1122982010-05-17 23:04:245140 glBindBuffer(GL_ARRAY_BUFFER,
5141 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
[email protected]43410e92012-04-20 17:06:285142
5143 if (info->enabled()) {
5144 glEnableVertexAttribArray(attrib);
5145 } else {
5146 glDisableVertexAttribArray(attrib);
5147 }
[email protected]b1122982010-05-17 23:04:245148}
[email protected]07f54fcc2009-12-22 02:46:305149
[email protected]8fbedc02010-11-18 18:43:405150bool GLES2DecoderImpl::SimulateFixedAttribs(
[email protected]c6aef902012-02-14 03:31:425151 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
[email protected]8fbedc02010-11-18 18:43:405152 DCHECK(simulated);
5153 *simulated = false;
5154 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
5155 return true;
5156
[email protected]3757a372012-01-19 05:20:445157 if (!vertex_attrib_manager_->HaveFixedAttribs()) {
[email protected]8fbedc02010-11-18 18:43:405158 return true;
5159 }
5160
5161 // NOTE: we could be smart and try to check if a buffer is used
5162 // twice in 2 different attribs, find the overlapping parts and therefore
5163 // duplicate the minimum amount of data but this whole code path is not meant
5164 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
5165 // tests so we just add to the buffer attrib used.
5166
[email protected]c13e1da62011-09-09 21:48:305167 GLuint elements_needed = 0;
[email protected]8fbedc02010-11-18 18:43:405168 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:445169 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]8fbedc02010-11-18 18:43:405170 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5171 infos.begin(); it != infos.end(); ++it) {
5172 const VertexAttribManager::VertexAttribInfo* info = *it;
5173 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5174 current_program_->GetAttribInfoByLocation(info->index());
[email protected]c6aef902012-02-14 03:31:425175 GLuint max_accessed = info->MaxVertexAccessed(primcount,
5176 max_vertex_accessed);
5177 GLuint num_vertices = max_accessed + 1;
5178 if (num_vertices == 0) {
5179 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
5180 return false;
5181 }
[email protected]8fbedc02010-11-18 18:43:405182 if (attrib_info &&
[email protected]c6aef902012-02-14 03:31:425183 info->CanAccess(max_accessed) &&
[email protected]8fbedc02010-11-18 18:43:405184 info->type() == GL_FIXED) {
[email protected]c13e1da62011-09-09 21:48:305185 GLuint elements_used = 0;
5186 if (!SafeMultiply(num_vertices,
5187 static_cast<GLuint>(info->size()), &elements_used) ||
[email protected]8fbedc02010-11-18 18:43:405188 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
5189 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5190 return false;
5191 }
5192 }
5193 }
5194
[email protected]c13e1da62011-09-09 21:48:305195 const GLuint kSizeOfFloat = sizeof(float); // NOLINT
5196 GLuint size_needed = 0;
5197 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed) ||
5198 size_needed > 0x7FFFFFFFU) {
[email protected]8fbedc02010-11-18 18:43:405199 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5200 return false;
5201 }
5202
[email protected]c13e1da62011-09-09 21:48:305203 CopyRealGLErrorsToWrapper();
[email protected]8fbedc02010-11-18 18:43:405204
5205 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
[email protected]c13e1da62011-09-09 21:48:305206 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
[email protected]8fbedc02010-11-18 18:43:405207 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305208 GLenum error = glGetError();
5209 if (error != GL_NO_ERROR) {
5210 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5211 return false;
5212 }
[email protected]8fbedc02010-11-18 18:43:405213 }
5214
5215 // Copy the elements and convert to float
5216 GLintptr offset = 0;
5217 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5218 infos.begin(); it != infos.end(); ++it) {
5219 const VertexAttribManager::VertexAttribInfo* info = *it;
5220 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5221 current_program_->GetAttribInfoByLocation(info->index());
[email protected]c6aef902012-02-14 03:31:425222 GLuint max_accessed = info->MaxVertexAccessed(primcount,
5223 max_vertex_accessed);
5224 GLuint num_vertices = max_accessed + 1;
5225 if (num_vertices == 0) {
5226 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
5227 return false;
5228 }
[email protected]8fbedc02010-11-18 18:43:405229 if (attrib_info &&
[email protected]c6aef902012-02-14 03:31:425230 info->CanAccess(max_accessed) &&
[email protected]8fbedc02010-11-18 18:43:405231 info->type() == GL_FIXED) {
5232 int num_elements = info->size() * kSizeOfFloat;
5233 int size = num_elements * num_vertices;
5234 scoped_array<float> data(new float[size]);
5235 const int32* src = reinterpret_cast<const int32 *>(
5236 info->buffer()->GetRange(info->offset(), size));
5237 const int32* end = src + num_elements;
5238 float* dst = data.get();
5239 while (src != end) {
5240 *dst++ = static_cast<float>(*src++) / 65536.0f;
5241 }
5242 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
5243 glVertexAttribPointer(
5244 info->index(), info->size(), GL_FLOAT, false, 0,
5245 reinterpret_cast<GLvoid*>(offset));
5246 offset += size;
5247 }
5248 }
5249 *simulated = true;
5250 return true;
5251}
5252
5253void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
5254 // There's no need to call glVertexAttribPointer because we shadow all the
5255 // settings and passing GL_FIXED to it will not work.
5256 glBindBuffer(GL_ARRAY_BUFFER,
5257 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
5258}
5259
[email protected]c6aef902012-02-14 03:31:425260error::Error GLES2DecoderImpl::DoDrawArrays(bool instanced,
5261 GLenum mode,
5262 GLint first,
5263 GLsizei count,
5264 GLsizei primcount) {
[email protected]38d139d2011-07-14 00:38:435265 if (!validators_->draw_mode.IsValid(mode)) {
5266 SetGLError(GL_INVALID_ENUM, "glDrawArrays: mode GL_INVALID_ENUM");
5267 return error::kNoError;
5268 }
5269 if (count < 0) {
5270 SetGLError(GL_INVALID_VALUE, "glDrawArrays: count < 0");
5271 return error::kNoError;
5272 }
[email protected]c6aef902012-02-14 03:31:425273 if (primcount < 0) {
5274 SetGLError(GL_INVALID_VALUE, "glDrawArrays: primcount < 0");
5275 return error::kNoError;
5276 }
[email protected]0d6bfdc2011-11-02 01:32:205277 if (!CheckBoundFramebuffersValid("glDrawArrays")) {
[email protected]38d139d2011-07-14 00:38:435278 return error::kNoError;
5279 }
5280 // We have to check this here because the prototype for glDrawArrays
5281 // is GLint not GLsizei.
5282 if (first < 0) {
5283 SetGLError(GL_INVALID_VALUE, "glDrawArrays: first < 0");
5284 return error::kNoError;
5285 }
5286
[email protected]c6aef902012-02-14 03:31:425287 if (count == 0 || (instanced && primcount == 0)) {
[email protected]38d139d2011-07-14 00:38:435288 return error::kNoError;
5289 }
5290
5291 GLuint max_vertex_accessed = first + count - 1;
[email protected]c6aef902012-02-14 03:31:425292 if (IsDrawValid(max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:205293 if (!ClearUnclearedTextures()) {
5294 SetGLError(GL_INVALID_VALUE, "glDrawArrays: out of memory");
5295 return error::kNoError;
5296 }
[email protected]c13e1da62011-09-09 21:48:305297 bool simulated_attrib_0 = false;
5298 if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
5299 return error::kNoError;
5300 }
[email protected]38d139d2011-07-14 00:38:435301 bool simulated_fixed_attribs = false;
[email protected]c6aef902012-02-14 03:31:425302 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs,
5303 primcount)) {
[email protected]38d139d2011-07-14 00:38:435304 bool textures_set = SetBlackTextureForNonRenderableTextures();
5305 ApplyDirtyState();
[email protected]c6aef902012-02-14 03:31:425306 if (!instanced) {
5307 glDrawArrays(mode, first, count);
5308 } else {
5309 glDrawArraysInstancedANGLE(mode, first, count, primcount);
5310 }
[email protected]22e3f552012-03-13 01:54:195311 ProcessPendingQueries();
[email protected]38d139d2011-07-14 00:38:435312 if (textures_set) {
5313 RestoreStateForNonRenderableTextures();
5314 }
5315 if (simulated_fixed_attribs) {
5316 RestoreStateForSimulatedFixedAttribs();
5317 }
5318 }
5319 if (simulated_attrib_0) {
[email protected]43410e92012-04-20 17:06:285320 RestoreStateForAttrib(0);
[email protected]38d139d2011-07-14 00:38:435321 }
5322 if (WasContextLost()) {
5323 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawArrays.";
5324 return error::kLostContext;
5325 }
5326 }
5327 return error::kNoError;
5328}
5329
[email protected]c6aef902012-02-14 03:31:425330error::Error GLES2DecoderImpl::HandleDrawArrays(
5331 uint32 immediate_data_size, const gles2::DrawArrays& c) {
5332 return DoDrawArrays(false,
5333 static_cast<GLenum>(c.mode),
5334 static_cast<GLint>(c.first),
5335 static_cast<GLsizei>(c.count),
5336 0);
5337}
5338
5339error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
5340 uint32 immediate_data_size, const gles2::DrawArraysInstancedANGLE& c) {
5341 if (!feature_info_->feature_flags().angle_instanced_arrays) {
5342 SetGLError(GL_INVALID_OPERATION,
5343 "glDrawArraysInstancedANGLE: function not available");
5344 return error::kNoError;
5345 }
5346 return DoDrawArrays(true,
5347 static_cast<GLenum>(c.mode),
5348 static_cast<GLint>(c.first),
5349 static_cast<GLsizei>(c.count),
5350 static_cast<GLsizei>(c.primcount));
5351}
5352
5353error::Error GLES2DecoderImpl::DoDrawElements(bool instanced,
5354 GLenum mode,
5355 GLsizei count,
5356 GLenum type,
5357 int32 offset,
5358 GLsizei primcount) {
[email protected]a0b78dc2011-11-11 10:43:105359 if (!bound_element_array_buffer_) {
[email protected]8eee29c2010-04-29 03:38:295360 SetGLError(GL_INVALID_OPERATION,
5361 "glDrawElements: No element array buffer bound");
5362 return error::kNoError;
5363 }
5364
[email protected]8eee29c2010-04-29 03:38:295365 if (count < 0) {
5366 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
5367 return error::kNoError;
5368 }
5369 if (offset < 0) {
5370 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
5371 return error::kNoError;
5372 }
[email protected]9438b012010-06-15 22:55:055373 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:295374 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
5375 return error::kNoError;
5376 }
[email protected]9438b012010-06-15 22:55:055377 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295378 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
5379 return error::kNoError;
5380 }
[email protected]c6aef902012-02-14 03:31:425381 if (primcount < 0) {
5382 SetGLError(GL_INVALID_VALUE, "glDrawElements: primcount < 0");
5383 return error::kNoError;
5384 }
[email protected]8eee29c2010-04-29 03:38:295385
[email protected]0d6bfdc2011-11-02 01:32:205386 if (!CheckBoundFramebuffersValid("glDrawElements")) {
[email protected]3a03a8f2011-03-19 00:51:275387 return error::kNoError;
5388 }
5389
[email protected]c6aef902012-02-14 03:31:425390 if (count == 0 || (instanced && primcount == 0)) {
[email protected]6c788fb72010-08-26 02:16:315391 return error::kNoError;
5392 }
5393
[email protected]8eee29c2010-04-29 03:38:295394 GLuint max_vertex_accessed;
5395 if (!bound_element_array_buffer_->GetMaxValueForRange(
5396 offset, count, type, &max_vertex_accessed)) {
5397 SetGLError(GL_INVALID_OPERATION,
5398 "glDrawElements: range out of bounds for buffer");
5399 return error::kNoError;
5400 }
5401
[email protected]c6aef902012-02-14 03:31:425402 if (IsDrawValid(max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:205403 if (!ClearUnclearedTextures()) {
5404 SetGLError(GL_INVALID_VALUE, "glDrawElements: out of memory");
5405 return error::kNoError;
5406 }
[email protected]c13e1da62011-09-09 21:48:305407 bool simulated_attrib_0 = false;
5408 if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
5409 return error::kNoError;
5410 }
[email protected]8fbedc02010-11-18 18:43:405411 bool simulated_fixed_attribs = false;
[email protected]c6aef902012-02-14 03:31:425412 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs,
5413 primcount)) {
[email protected]8fbedc02010-11-18 18:43:405414 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:465415 ApplyDirtyState();
[email protected]8fbedc02010-11-18 18:43:405416 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
[email protected]c6aef902012-02-14 03:31:425417 if (!instanced) {
5418 glDrawElements(mode, count, type, indices);
5419 } else {
5420 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
5421 }
[email protected]22e3f552012-03-13 01:54:195422 ProcessPendingQueries();
[email protected]8fbedc02010-11-18 18:43:405423 if (textures_set) {
5424 RestoreStateForNonRenderableTextures();
5425 }
5426 if (simulated_fixed_attribs) {
5427 RestoreStateForSimulatedFixedAttribs();
5428 }
[email protected]ba3176a2009-12-16 18:19:465429 }
[email protected]b1122982010-05-17 23:04:245430 if (simulated_attrib_0) {
[email protected]43410e92012-04-20 17:06:285431 RestoreStateForAttrib(0);
[email protected]b1122982010-05-17 23:04:245432 }
[email protected]38d139d2011-07-14 00:38:435433 if (WasContextLost()) {
5434 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawElements.";
5435 return error::kLostContext;
5436 }
[email protected]96449d2c2009-11-25 00:01:325437 }
[email protected]f7a64ee2010-02-01 22:24:145438 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325439}
5440
[email protected]c6aef902012-02-14 03:31:425441error::Error GLES2DecoderImpl::HandleDrawElements(
5442 uint32 immediate_data_size, const gles2::DrawElements& c) {
5443 return DoDrawElements(false,
5444 static_cast<GLenum>(c.mode),
5445 static_cast<GLsizei>(c.count),
5446 static_cast<GLenum>(c.type),
5447 static_cast<int32>(c.index_offset),
5448 0);
5449}
5450
5451error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
5452 uint32 immediate_data_size, const gles2::DrawElementsInstancedANGLE& c) {
5453 if (!feature_info_->feature_flags().angle_instanced_arrays) {
5454 SetGLError(GL_INVALID_OPERATION,
5455 "glDrawElementsInstancedANGLE: function not available");
5456 return error::kNoError;
5457 }
5458 return DoDrawElements(true,
5459 static_cast<GLenum>(c.mode),
5460 static_cast<GLsizei>(c.count),
5461 static_cast<GLenum>(c.type),
5462 static_cast<int32>(c.index_offset),
5463 static_cast<GLsizei>(c.primcount));
5464}
5465
[email protected]269200b12010-11-18 22:53:065466GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:235467 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
5468 GLuint max_vertex_accessed = 0;
5469 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:295470 if (!info) {
[email protected]ae51d192010-04-27 00:48:035471 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:295472 SetGLError(GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:065473 "GetMaxValueInBufferCHROMIUM: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:235474 } else {
5475 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:035476 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:065477 SetGLError(
5478 GL_INVALID_OPERATION,
5479 "GetMaxValueInBufferCHROMIUM: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:235480 }
5481 }
5482 return max_vertex_accessed;
5483}
5484
[email protected]96449d2c2009-11-25 00:01:325485// Calls glShaderSource for the various versions of the ShaderSource command.
5486// Assumes that data / data_size points to a piece of memory that is in range
5487// of whatever context it came from (shared memory, immediate memory, bucket
5488// memory.)
[email protected]45bf5152010-02-12 00:11:315489error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035490 GLuint client_id, const char* data, uint32 data_size) {
[email protected]258a3313f2011-10-18 20:13:575491 std::string str(data, data + data_size);
[email protected]6b8cf1a2010-05-06 16:13:585492 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5493 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:315494 if (!info) {
[email protected]45bf5152010-02-12 00:11:315495 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325496 }
[email protected]45bf5152010-02-12 00:11:315497 // Note: We don't actually call glShaderSource here. We wait until
5498 // the call to glCompileShader.
[email protected]258a3313f2011-10-18 20:13:575499 info->UpdateSource(str.c_str());
[email protected]f7a64ee2010-02-01 22:24:145500 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325501}
5502
[email protected]f7a64ee2010-02-01 22:24:145503error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:195504 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:325505 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315506 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:325507 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:465508 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145509 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325510 }
[email protected]ae51d192010-04-27 00:48:035511 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:325512}
5513
[email protected]f7a64ee2010-02-01 22:24:145514error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:195515 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:325516 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315517 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:305518 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465519 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145520 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325521 }
[email protected]ae51d192010-04-27 00:48:035522 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:315523}
5524
[email protected]558847a2010-03-24 07:02:545525error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
5526 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:545527 Bucket* bucket = GetBucket(c.data_bucket_id);
5528 if (!bucket || bucket->size() == 0) {
5529 return error::kInvalidArguments;
5530 }
5531 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035532 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:545533 bucket->size() - 1);
5534}
5535
[email protected]ae51d192010-04-27 00:48:035536void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]0c8fabf2011-06-14 19:35:225537 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]6b8cf1a2010-05-06 16:13:585538 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5539 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:315540 if (!info) {
[email protected]45bf5152010-02-12 00:11:315541 return;
5542 }
[email protected]de17df392010-04-23 21:09:415543 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
5544 // glShaderSource and then glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:525545 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:345546 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:185547 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:345548 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:455549 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:235550
[email protected]a550584e2010-09-17 18:01:455551 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:345552 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:185553 return;
5554 }
[email protected]a550584e2010-09-17 18:01:455555 shader_src = translator->translated_shader();
[email protected]93297702011-11-05 05:09:465556 if (!feature_info_->feature_flags().angle_translated_shader_source)
[email protected]d6a53e42011-10-05 00:09:365557 info->UpdateTranslatedSource(shader_src);
[email protected]de17df392010-04-23 21:09:415558 }
[email protected]de17df392010-04-23 21:09:415559
[email protected]ae51d192010-04-27 00:48:035560 glShaderSource(info->service_id(), 1, &shader_src, NULL);
5561 glCompileShader(info->service_id());
[email protected]93297702011-11-05 05:09:465562 if (feature_info_->feature_flags().angle_translated_shader_source) {
[email protected]d6a53e42011-10-05 00:09:365563 GLint max_len = 0;
5564 glGetShaderiv(info->service_id(),
5565 GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
5566 &max_len);
5567 scoped_array<char> temp(new char[max_len]);
5568 GLint len = 0;
5569 glGetTranslatedShaderSourceANGLE(
5570 info->service_id(), max_len, &len, temp.get());
5571 DCHECK(max_len == 0 || len < max_len);
5572 DCHECK(len == 0 || temp[len] == '\0');
5573 info->UpdateTranslatedSource(temp.get());
5574 }
5575
[email protected]e5186162010-06-14 18:54:415576 GLint status = GL_FALSE;
5577 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
5578 if (status) {
[email protected]f57bb282010-11-12 00:51:345579 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:415580 } else {
[email protected]d9977d42010-09-01 20:27:025581 // We cannot reach here if we are using the shader translator.
5582 // All invalid shaders must be rejected by the translator.
5583 // All translated shaders must compile.
5584 LOG_IF(ERROR, use_shader_translator_)
5585 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:335586 GLint max_len = 0;
5587 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
5588 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:415589 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:335590 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
5591 DCHECK(max_len == 0 || len < max_len);
[email protected]d6a53e42011-10-05 00:09:365592 DCHECK(len == 0 || temp[len] == '\0');
[email protected]df6cf1ad2011-01-29 01:20:525593 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
[email protected]e5186162010-06-14 18:54:415594 }
[email protected]45bf5152010-02-12 00:11:315595};
5596
[email protected]ddd968b82010-03-02 00:44:295597void GLES2DecoderImpl::DoGetShaderiv(
5598 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:585599 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5600 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:295601 if (!info) {
[email protected]ddd968b82010-03-02 00:44:295602 return;
5603 }
[email protected]8f1ccdac2010-05-19 21:01:485604 switch (pname) {
5605 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525606 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:485607 return;
5608 case GL_COMPILE_STATUS:
[email protected]062c38b2012-01-18 03:25:105609 *params = compile_shader_always_succeeds_ ? true : info->IsValid();
[email protected]e5186162010-06-14 18:54:415610 return;
[email protected]8f1ccdac2010-05-19 21:01:485611 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525612 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:415613 return;
[email protected]d6a53e42011-10-05 00:09:365614 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5615 *params = info->translated_source() ?
5616 info->translated_source()->size() + 1 : 0;
5617 return;
[email protected]8f1ccdac2010-05-19 21:01:485618 default:
5619 break;
[email protected]ddd968b82010-03-02 00:44:295620 }
[email protected]8f1ccdac2010-05-19 21:01:485621 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:295622}
5623
[email protected]ae51d192010-04-27 00:48:035624error::Error GLES2DecoderImpl::HandleGetShaderSource(
5625 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
5626 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:035627 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5628 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:585629 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5630 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:525631 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:295632 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:295633 return error::kNoError;
5634 }
[email protected]df6cf1ad2011-01-29 01:20:525635 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:035636 return error::kNoError;
5637}
5638
[email protected]d6a53e42011-10-05 00:09:365639error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
5640 uint32 immediate_data_size,
5641 const gles2::GetTranslatedShaderSourceANGLE& c) {
5642 GLuint shader = c.shader;
5643
5644 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5645 Bucket* bucket = CreateBucket(bucket_id);
5646 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5647 shader, "glTranslatedGetShaderSourceANGLE");
5648 if (!info) {
5649 bucket->SetSize(0);
5650 return error::kNoError;
5651 }
5652
5653 bucket->SetFromString(info->translated_source() ?
5654 info->translated_source()->c_str() : NULL);
5655 return error::kNoError;
5656}
5657
[email protected]ae51d192010-04-27 00:48:035658error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
5659 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
5660 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:585661 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5662 Bucket* bucket = CreateBucket(bucket_id);
5663 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5664 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525665 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465666 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035667 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:315668 }
[email protected]df6cf1ad2011-01-29 01:20:525669 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035670 return error::kNoError;
5671}
5672
5673error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
5674 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
5675 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:585676 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5677 Bucket* bucket = CreateBucket(bucket_id);
5678 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5679 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525680 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465681 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035682 return error::kNoError;
5683 }
[email protected]df6cf1ad2011-01-29 01:20:525684 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035685 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325686}
5687
[email protected]1958e0e2010-04-22 05:17:155688bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105689 const BufferManager::BufferInfo* buffer = GetBufferInfo(client_id);
5690 return buffer && buffer->IsValid() && !buffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155691}
5692
5693bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105694 const FramebufferManager::FramebufferInfo* framebuffer =
[email protected]06c8b082011-01-05 18:00:365695 GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105696 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155697}
5698
5699bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365700 // IsProgram is true for programs as soon as they are created, until they are
5701 // deleted and no longer in use.
[email protected]a0b78dc2011-11-11 10:43:105702 const ProgramManager::ProgramInfo* program = GetProgramInfo(client_id);
5703 return program != NULL && !program->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155704}
5705
5706bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105707 const RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]06c8b082011-01-05 18:00:365708 GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105709 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155710}
5711
5712bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365713 // IsShader is true for shaders as soon as they are created, until they
5714 // are deleted and not attached to any programs.
[email protected]a0b78dc2011-11-11 10:43:105715 const ShaderManager::ShaderInfo* shader = GetShaderInfo(client_id);
5716 return shader != NULL && !shader->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155717}
5718
5719bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105720 const TextureManager::TextureInfo* texture = GetTextureInfo(client_id);
5721 return texture && texture->IsValid() && !texture->IsDeleted();
[email protected]ae51d192010-04-27 00:48:035722}
5723
5724void GLES2DecoderImpl::DoAttachShader(
5725 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585726 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5727 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035728 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035729 return;
[email protected]1958e0e2010-04-22 05:17:155730 }
[email protected]6b8cf1a2010-05-06 16:13:585731 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5732 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035733 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035734 return;
5735 }
[email protected]ca488e12010-12-13 20:06:145736 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:315737 SetGLError(GL_INVALID_OPERATION,
5738 "glAttachShader: can not attach more than"
5739 " one shader of the same type.");
5740 return;
5741 }
[email protected]ae51d192010-04-27 00:48:035742 glAttachShader(program_info->service_id(), shader_info->service_id());
5743}
5744
5745void GLES2DecoderImpl::DoDetachShader(
5746 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585747 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5748 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035749 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035750 return;
5751 }
[email protected]6b8cf1a2010-05-06 16:13:585752 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5753 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035754 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035755 return;
5756 }
[email protected]9a0ccd42011-03-16 23:58:225757 if (!program_info->DetachShader(shader_manager(), shader_info)) {
5758 SetGLError(GL_INVALID_OPERATION,
5759 "glDetachShader: shader not attached to program");
5760 return;
5761 }
[email protected]ae51d192010-04-27 00:48:035762 glDetachShader(program_info->service_id(), shader_info->service_id());
5763}
5764
5765void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585766 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5767 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:035768 if (!info) {
[email protected]ae51d192010-04-27 00:48:035769 return;
5770 }
[email protected]d685a682011-04-29 16:19:575771 info->Validate();
[email protected]1958e0e2010-04-22 05:17:155772}
5773
[email protected]b1122982010-05-17 23:04:245774void GLES2DecoderImpl::DoGetVertexAttribfv(
5775 GLuint index, GLenum pname, GLfloat* params) {
5776 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445777 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245778 if (!info) {
5779 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
5780 return;
5781 }
5782 switch (pname) {
5783 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5784 BufferManager::BufferInfo* buffer = info->buffer();
5785 if (buffer && !buffer->IsDeleted()) {
5786 GLuint client_id;
5787 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5788 *params = static_cast<GLfloat>(client_id);
5789 }
5790 break;
5791 }
5792 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5793 *params = static_cast<GLfloat>(info->enabled());
5794 break;
5795 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5796 *params = static_cast<GLfloat>(info->size());
5797 break;
5798 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5799 *params = static_cast<GLfloat>(info->gl_stride());
5800 break;
5801 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5802 *params = static_cast<GLfloat>(info->type());
5803 break;
5804 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5805 *params = static_cast<GLfloat>(info->normalized());
5806 break;
5807 case GL_CURRENT_VERTEX_ATTRIB:
5808 params[0] = info->value().v[0];
5809 params[1] = info->value().v[1];
5810 params[2] = info->value().v[2];
5811 params[3] = info->value().v[3];
5812 break;
[email protected]c6aef902012-02-14 03:31:425813 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
5814 *params = static_cast<GLfloat>(info->divisor());
5815 break;
[email protected]b1122982010-05-17 23:04:245816 default:
5817 NOTREACHED();
5818 break;
5819 }
5820}
5821
5822void GLES2DecoderImpl::DoGetVertexAttribiv(
5823 GLuint index, GLenum pname, GLint* params) {
5824 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445825 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245826 if (!info) {
5827 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
5828 return;
5829 }
5830 switch (pname) {
5831 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5832 BufferManager::BufferInfo* buffer = info->buffer();
5833 if (buffer && !buffer->IsDeleted()) {
5834 GLuint client_id;
5835 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5836 *params = client_id;
5837 }
5838 break;
5839 }
5840 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5841 *params = info->enabled();
5842 break;
5843 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5844 *params = info->size();
5845 break;
5846 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5847 *params = info->gl_stride();
5848 break;
5849 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5850 *params = info->type();
5851 break;
5852 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5853 *params = static_cast<GLint>(info->normalized());
5854 break;
[email protected]c6aef902012-02-14 03:31:425855 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
5856 *params = info->divisor();
5857 break;
[email protected]b1122982010-05-17 23:04:245858 case GL_CURRENT_VERTEX_ATTRIB:
5859 params[0] = static_cast<GLint>(info->value().v[0]);
5860 params[1] = static_cast<GLint>(info->value().v[1]);
5861 params[2] = static_cast<GLint>(info->value().v[2]);
5862 params[3] = static_cast<GLint>(info->value().v[3]);
5863 break;
5864 default:
5865 NOTREACHED();
5866 break;
5867 }
5868}
5869
5870void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
5871 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445872 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245873 if (!info) {
5874 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
5875 return;
5876 }
5877 VertexAttribManager::VertexAttribInfo::Vec4 value;
5878 value.v[0] = v0;
5879 value.v[1] = 0.0f;
5880 value.v[2] = 0.0f;
5881 value.v[3] = 1.0f;
5882 info->set_value(value);
5883 glVertexAttrib1f(index, v0);
5884}
5885
5886void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
5887 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445888 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245889 if (!info) {
5890 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
5891 return;
5892 }
5893 VertexAttribManager::VertexAttribInfo::Vec4 value;
5894 value.v[0] = v0;
5895 value.v[1] = v1;
5896 value.v[2] = 0.0f;
5897 value.v[3] = 1.0f;
5898 info->set_value(value);
5899 glVertexAttrib2f(index, v0, v1);
5900}
5901
5902void GLES2DecoderImpl::DoVertexAttrib3f(
5903 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
5904 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445905 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245906 if (!info) {
5907 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
5908 return;
5909 }
5910 VertexAttribManager::VertexAttribInfo::Vec4 value;
5911 value.v[0] = v0;
5912 value.v[1] = v1;
5913 value.v[2] = v2;
5914 value.v[3] = 1.0f;
5915 info->set_value(value);
5916 glVertexAttrib3f(index, v0, v1, v2);
5917}
5918
5919void GLES2DecoderImpl::DoVertexAttrib4f(
5920 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
5921 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445922 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245923 if (!info) {
5924 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
5925 return;
5926 }
5927 VertexAttribManager::VertexAttribInfo::Vec4 value;
5928 value.v[0] = v0;
5929 value.v[1] = v1;
5930 value.v[2] = v2;
5931 value.v[3] = v3;
5932 info->set_value(value);
5933 glVertexAttrib4f(index, v0, v1, v2, v3);
5934}
5935
5936void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
5937 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445938 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245939 if (!info) {
5940 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
5941 return;
5942 }
5943 VertexAttribManager::VertexAttribInfo::Vec4 value;
5944 value.v[0] = v[0];
5945 value.v[1] = 0.0f;
5946 value.v[2] = 0.0f;
5947 value.v[3] = 1.0f;
5948 info->set_value(value);
5949 glVertexAttrib1fv(index, v);
5950}
5951
5952void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
5953 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445954 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245955 if (!info) {
5956 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
5957 return;
5958 }
5959 VertexAttribManager::VertexAttribInfo::Vec4 value;
5960 value.v[0] = v[0];
5961 value.v[1] = v[1];
5962 value.v[2] = 0.0f;
5963 value.v[3] = 1.0f;
5964 info->set_value(value);
5965 glVertexAttrib2fv(index, v);
5966}
5967
5968void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
5969 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445970 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245971 if (!info) {
5972 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
5973 return;
5974 }
5975 VertexAttribManager::VertexAttribInfo::Vec4 value;
5976 value.v[0] = v[0];
5977 value.v[1] = v[1];
5978 value.v[2] = v[2];
5979 value.v[3] = 1.0f;
5980 info->set_value(value);
5981 glVertexAttrib3fv(index, v);
5982}
5983
5984void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
5985 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445986 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245987 if (!info) {
5988 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
5989 return;
5990 }
5991 VertexAttribManager::VertexAttribInfo::Vec4 value;
5992 value.v[0] = v[0];
5993 value.v[1] = v[1];
5994 value.v[2] = v[2];
5995 value.v[3] = v[3];
5996 info->set_value(value);
5997 glVertexAttrib4fv(index, v);
5998}
5999
[email protected]f7a64ee2010-02-01 22:24:146000error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:196001 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:296002 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
6003 SetGLError(GL_INVALID_VALUE,
6004 "glVertexAttribPointer: no array buffer bound");
6005 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326006 }
[email protected]8eee29c2010-04-29 03:38:296007
6008 GLuint indx = c.indx;
6009 GLint size = c.size;
6010 GLenum type = c.type;
6011 GLboolean normalized = c.normalized;
6012 GLsizei stride = c.stride;
6013 GLsizei offset = c.offset;
6014 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:056015 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:296016 SetGLError(GL_INVALID_ENUM,
6017 "glVertexAttribPointer: type GL_INVALID_ENUM");
6018 return error::kNoError;
6019 }
[email protected]9438b012010-06-15 22:55:056020 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:316021 SetGLError(GL_INVALID_VALUE,
[email protected]8eee29c2010-04-29 03:38:296022 "glVertexAttribPointer: size GL_INVALID_VALUE");
6023 return error::kNoError;
6024 }
6025 if (indx >= group_->max_vertex_attribs()) {
6026 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
6027 return error::kNoError;
6028 }
6029 if (stride < 0) {
6030 SetGLError(GL_INVALID_VALUE,
6031 "glVertexAttribPointer: stride < 0");
6032 return error::kNoError;
6033 }
6034 if (stride > 255) {
6035 SetGLError(GL_INVALID_VALUE,
6036 "glVertexAttribPointer: stride > 255");
6037 return error::kNoError;
6038 }
6039 if (offset < 0) {
6040 SetGLError(GL_INVALID_VALUE,
6041 "glVertexAttribPointer: offset < 0");
6042 return error::kNoError;
6043 }
6044 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:316045 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:296046 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:316047 SetGLError(GL_INVALID_OPERATION,
6048 "glVertexAttribPointer: offset not valid for type");
6049 return error::kNoError;
6050 }
6051 if (stride % component_size > 0) {
6052 SetGLError(GL_INVALID_OPERATION,
[email protected]8eee29c2010-04-29 03:38:296053 "glVertexAttribPointer: stride not valid for type");
6054 return error::kNoError;
6055 }
[email protected]3757a372012-01-19 05:20:446056 vertex_attrib_manager_->SetAttribInfo(
[email protected]8fbedc02010-11-18 18:43:406057 indx,
[email protected]8eee29c2010-04-29 03:38:296058 bound_array_buffer_,
6059 size,
6060 type,
[email protected]b1122982010-05-17 23:04:246061 normalized,
6062 stride,
6063 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:296064 offset);
[email protected]8fbedc02010-11-18 18:43:406065 if (type != GL_FIXED) {
6066 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
6067 }
[email protected]f7a64ee2010-02-01 22:24:146068 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326069}
6070
[email protected]43410e92012-04-20 17:06:286071void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
6072 GLsizei height) {
6073 viewport_x_ = x;
6074 viewport_y_ = y;
6075 viewport_width_ = std::min(width, viewport_max_width_);
6076 viewport_height_ = std::min(height, viewport_max_height_);
6077 glViewport(x, y, width, height);
6078}
6079
[email protected]c6aef902012-02-14 03:31:426080error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
6081 uint32 immediate_data_size, const gles2::VertexAttribDivisorANGLE& c) {
6082 if (!feature_info_->feature_flags().angle_instanced_arrays) {
6083 SetGLError(GL_INVALID_OPERATION,
6084 "glVertexAttribDivisorANGLE: function not available");
6085 }
6086 GLuint index = c.index;
6087 GLuint divisor = c.divisor;
6088 if (index >= group_->max_vertex_attribs()) {
6089 SetGLError(GL_INVALID_VALUE,
6090 "glVertexAttribDivisorANGLE: index out of range");
6091 return error::kNoError;
6092 }
6093
6094 vertex_attrib_manager_->SetDivisor(
6095 index,
6096 divisor);
6097 glVertexAttribDivisorANGLE(index, divisor);
6098 return error::kNoError;
6099}
6100
[email protected]f7a64ee2010-02-01 22:24:146101error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:196102 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:316103 GLint x = c.x;
6104 GLint y = c.y;
6105 GLsizei width = c.width;
6106 GLsizei height = c.height;
6107 GLenum format = c.format;
6108 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:566109 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:296110 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:566111 return error::kNoError;
6112 }
[email protected]a51788e2010-02-24 21:54:256113 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:186114 uint32 pixels_size;
[email protected]3458a64a2012-04-10 17:39:346115 if (!GLES2Util::ComputeImageDataSizes(
6116 width, height, format, type, pack_alignment_, &pixels_size, NULL, NULL)) {
[email protected]a76b0052010-03-05 00:33:186117 return error::kOutOfBounds;
6118 }
[email protected]612d2f82009-12-08 20:49:316119 void* pixels = GetSharedMemoryAs<void*>(
6120 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:256121 Result* result = GetSharedMemoryAs<Result*>(
6122 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6123 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:146124 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466125 }
[email protected]a51788e2010-02-24 21:54:256126
[email protected]9438b012010-06-15 22:55:056127 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:296128 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
6129 return error::kNoError;
6130 }
[email protected]9438b012010-06-15 22:55:056131 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:296132 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:126133 return error::kNoError;
6134 }
[email protected]57f223832010-03-19 01:57:566135 if (width == 0 || height == 0) {
6136 return error::kNoError;
6137 }
6138
[email protected]57f223832010-03-19 01:57:566139 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:306140 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:566141
6142 GLint max_x;
6143 GLint max_y;
6144 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:296145 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:146146 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:316147 }
[email protected]57f223832010-03-19 01:57:566148
[email protected]0d6bfdc2011-11-02 01:32:206149 if (!CheckBoundFramebuffersValid("glReadPixels")) {
6150 return error::kNoError;
6151 }
6152
[email protected]a0b78dc2011-11-11 10:43:106153 CopyRealGLErrorsToWrapper();
6154
6155 ScopedResolvedFrameBufferBinder binder(this, false, true);
6156
[email protected]d37231fa2010-04-09 21:16:026157 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:566158 // The user requested an out of range area. Get the results 1 line
6159 // at a time.
6160 uint32 temp_size;
[email protected]3458a64a2012-04-10 17:39:346161 uint32 unpadded_row_size;
6162 uint32 padded_row_size;
6163 if (!GLES2Util::ComputeImageDataSizes(
6164 width, 2, format, type, pack_alignment_, &temp_size,
6165 &unpadded_row_size, &padded_row_size)) {
[email protected]8eee29c2010-04-29 03:38:296166 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:566167 return error::kNoError;
6168 }
6169
6170 GLint dest_x_offset = std::max(-x, 0);
6171 uint32 dest_row_offset;
[email protected]3458a64a2012-04-10 17:39:346172 if (!GLES2Util::ComputeImageDataSizes(
6173 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset, NULL,
6174 NULL)) {
[email protected]8eee29c2010-04-29 03:38:296175 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:566176 return error::kNoError;
6177 }
6178
6179 // Copy each row into the larger dest rect.
6180 int8* dst = static_cast<int8*>(pixels);
6181 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:026182 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:566183 GLint read_width = read_end_x - read_x;
6184 for (GLint yy = 0; yy < height; ++yy) {
6185 GLint ry = y + yy;
6186
6187 // Clear the row.
6188 memset(dst, 0, unpadded_row_size);
6189
6190 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:026191 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:566192 glReadPixels(
6193 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
6194 }
6195 dst += padded_row_size;
6196 }
6197 } else {
6198 glReadPixels(x, y, width, height, format, type, pixels);
6199 }
[email protected]1002c2d2011-06-28 22:39:046200 GLenum error = PeekGLError();
[email protected]a51788e2010-02-24 21:54:256201 if (error == GL_NO_ERROR) {
6202 *result = true;
[email protected]4848b9f82011-03-10 18:37:566203
6204 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6205 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
[email protected]c892a4e12012-05-08 18:20:196206 if ((channels_exist & 0x0008) == 0 && !disable_workarounds_) {
[email protected]4848b9f82011-03-10 18:37:566207 // Set the alpha to 255 because some drivers are buggy in this regard.
6208 uint32 temp_size;
[email protected]3458a64a2012-04-10 17:39:346209
6210 uint32 unpadded_row_size;
6211 uint32 padded_row_size;
6212 if (!GLES2Util::ComputeImageDataSizes(
6213 width, 2, format, type, pack_alignment_, &temp_size,
6214 &unpadded_row_size, &padded_row_size)) {
[email protected]4848b9f82011-03-10 18:37:566215 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
6216 return error::kNoError;
6217 }
6218 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
6219 // of this implementation.
6220 if (type != GL_UNSIGNED_BYTE) {
6221 SetGLError(GL_INVALID_OPERATION, "unsupported readPixel format");
6222 return error::kNoError;
6223 }
6224 switch (format) {
6225 case GL_RGBA:
[email protected]297ca1c2011-06-20 23:08:466226 case GL_BGRA_EXT:
[email protected]4848b9f82011-03-10 18:37:566227 case GL_ALPHA: {
6228 int offset = (format == GL_ALPHA) ? 0 : 3;
6229 int step = (format == GL_ALPHA) ? 1 : 4;
6230 uint8* dst = static_cast<uint8*>(pixels) + offset;
6231 for (GLint yy = 0; yy < height; ++yy) {
6232 uint8* end = dst + unpadded_row_size;
6233 for (uint8* d = dst; d < end; d += step) {
6234 *d = 255;
6235 }
6236 dst += padded_row_size;
6237 }
6238 break;
6239 }
6240 default:
6241 break;
6242 }
6243 }
[email protected]a51788e2010-02-24 21:54:256244 }
[email protected]4848b9f82011-03-10 18:37:566245
[email protected]f7a64ee2010-02-01 22:24:146246 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326247}
6248
[email protected]f7a64ee2010-02-01 22:24:146249error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:196250 uint32 immediate_data_size, const gles2::PixelStorei& c) {
6251 GLenum pname = c.pname;
6252 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:056253 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:296254 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:126255 return error::kNoError;
6256 }
[email protected]222471d2011-11-30 18:06:396257 switch (pname) {
6258 case GL_PACK_ALIGNMENT:
6259 case GL_UNPACK_ALIGNMENT:
6260 if (!validators_->pixel_store_alignment.IsValid(param)) {
6261 SetGLError(GL_INVALID_VALUE,
6262 "glPixelSTore: param GL_INVALID_VALUE");
6263 return error::kNoError;
6264 }
[email protected]164d6d52012-05-05 00:55:036265 break;
[email protected]0a1e9ad2012-05-04 21:13:036266 case GL_UNPACK_FLIP_Y_CHROMIUM:
6267 unpack_flip_y_ = (param != 0);
6268 return error::kNoError;
6269 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
6270 unpack_premultiply_alpha_ = (param != 0);
6271 return error::kNoError;
[email protected]222471d2011-11-30 18:06:396272 default:
6273 break;
[email protected]b9849abf2009-11-25 19:13:196274 }
6275 glPixelStorei(pname, param);
6276 switch (pname) {
6277 case GL_PACK_ALIGNMENT:
6278 pack_alignment_ = param;
6279 break;
[email protected]222471d2011-11-30 18:06:396280 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
6281 break;
[email protected]b9849abf2009-11-25 19:13:196282 case GL_UNPACK_ALIGNMENT:
6283 unpack_alignment_ = param;
6284 break;
[email protected]b9849abf2009-11-25 19:13:196285 default:
6286 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:376287 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:196288 break;
6289 }
[email protected]f7a64ee2010-02-01 22:24:146290 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196291}
6292
[email protected]1c75a3702011-11-11 14:15:286293error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
6294 uint32 immediate_data_size, const gles2::PostSubBufferCHROMIUM& c) {
6295 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
[email protected]aa258822011-11-22 13:52:256296 if (!context_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
[email protected]1c75a3702011-11-11 14:15:286297 SetGLError(GL_INVALID_OPERATION,
6298 "glPostSubBufferCHROMIUM: command not supported by surface");
6299 return error::kNoError;
6300 }
[email protected]7794d512012-04-17 20:36:496301 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
[email protected]1c75a3702011-11-11 14:15:286302 return error::kNoError;
[email protected]7794d512012-04-17 20:36:496303 } else {
6304 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
[email protected]1c75a3702011-11-11 14:15:286305 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:496306 }
[email protected]1c75a3702011-11-11 14:15:286307}
6308
[email protected]558847a2010-03-24 07:02:546309error::Error GLES2DecoderImpl::GetAttribLocationHelper(
6310 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6311 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576312 if (!StringIsValidForGLES(name_str.c_str())) {
6313 SetGLError(GL_INVALID_VALUE, "glGetAttribLocation: Invalid character");
6314 return error::kNoError;
6315 }
[email protected]6b8cf1a2010-05-06 16:13:586316 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6317 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:036318 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146319 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196320 }
[email protected]ae51d192010-04-27 00:48:036321 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:296322 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:256323 return error::kNoError;
6324 }
[email protected]b9849abf2009-11-25 19:13:196325 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546326 location_shm_id, location_shm_offset, sizeof(GLint));
6327 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146328 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196329 }
[email protected]558847a2010-03-24 07:02:546330 // Require the client to init this incase the context is lost and we are no
6331 // longer executing commands.
6332 if (*location != -1) {
6333 return error::kGenericError;
6334 }
[email protected]0bfd9882010-02-05 23:02:256335 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:146336 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196337}
6338
[email protected]558847a2010-03-24 07:02:546339error::Error GLES2DecoderImpl::HandleGetAttribLocation(
6340 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
6341 uint32 name_size = c.data_size;
6342 const char* name = GetSharedMemoryAs<const char*>(
6343 c.name_shm_id, c.name_shm_offset, name_size);
6344 if (!name) {
6345 return error::kOutOfBounds;
6346 }
6347 String name_str(name, name_size);
6348 return GetAttribLocationHelper(
6349 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6350}
6351
[email protected]f7a64ee2010-02-01 22:24:146352error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196353 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:546354 uint32 name_size = c.data_size;
6355 const char* name = GetImmediateDataAs<const char*>(
6356 c, name_size, immediate_data_size);
6357 if (!name) {
6358 return error::kOutOfBounds;
6359 }
6360 String name_str(name, name_size);
6361 return GetAttribLocationHelper(
6362 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6363}
6364
6365error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
6366 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
6367 Bucket* bucket = GetBucket(c.name_bucket_id);
6368 if (!bucket) {
6369 return error::kInvalidArguments;
6370 }
6371 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186372 if (!bucket->GetAsString(&name_str)) {
6373 return error::kInvalidArguments;
6374 }
[email protected]558847a2010-03-24 07:02:546375 return GetAttribLocationHelper(
6376 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6377}
6378
6379error::Error GLES2DecoderImpl::GetUniformLocationHelper(
6380 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6381 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576382 if (!StringIsValidForGLES(name_str.c_str())) {
6383 SetGLError(GL_INVALID_VALUE, "glGetUniformLocation: Invalid character");
6384 return error::kNoError;
6385 }
[email protected]6b8cf1a2010-05-06 16:13:586386 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6387 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:036388 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146389 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196390 }
[email protected]ae51d192010-04-27 00:48:036391 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:296392 SetGLError(GL_INVALID_OPERATION,
6393 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:256394 return error::kNoError;
6395 }
[email protected]b9849abf2009-11-25 19:13:196396 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546397 location_shm_id, location_shm_offset, sizeof(GLint));
6398 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146399 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196400 }
[email protected]558847a2010-03-24 07:02:546401 // Require the client to init this incase the context is lost an we are no
6402 // longer executing commands.
6403 if (*location != -1) {
6404 return error::kGenericError;
6405 }
[email protected]5d4c6b22012-02-07 08:22:286406 *location = program_manager()->SwizzleLocation(
[email protected]1b0a6752012-02-22 03:44:126407 info->GetUniformFakeLocation(name_str));
[email protected]f7a64ee2010-02-01 22:24:146408 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196409}
6410
[email protected]f7a64ee2010-02-01 22:24:146411error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:196412 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:196413 uint32 name_size = c.data_size;
6414 const char* name = GetSharedMemoryAs<const char*>(
6415 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:546416 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146417 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196418 }
6419 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546420 return GetUniformLocationHelper(
6421 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196422}
6423
[email protected]f7a64ee2010-02-01 22:24:146424error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196425 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:196426 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:306427 const char* name = GetImmediateDataAs<const char*>(
6428 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:546429 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146430 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196431 }
6432 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546433 return GetUniformLocationHelper(
6434 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6435}
6436
6437error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
6438 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
6439 Bucket* bucket = GetBucket(c.name_bucket_id);
6440 if (!bucket) {
6441 return error::kInvalidArguments;
6442 }
6443 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186444 if (!bucket->GetAsString(&name_str)) {
6445 return error::kInvalidArguments;
6446 }
[email protected]558847a2010-03-24 07:02:546447 return GetUniformLocationHelper(
6448 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196449}
6450
[email protected]ddd968b82010-03-02 00:44:296451error::Error GLES2DecoderImpl::HandleGetString(
6452 uint32 immediate_data_size, const gles2::GetString& c) {
6453 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:056454 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:296455 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:296456 return error::kNoError;
6457 }
[email protected]1958e0e2010-04-22 05:17:156458 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
6459 const char* str = NULL;
[email protected]f0d74742011-10-03 16:31:046460 std::string extensions;
[email protected]1958e0e2010-04-22 05:17:156461 switch (name) {
6462 case GL_VERSION:
6463 str = "OpenGL ES 2.0 Chromium";
6464 break;
6465 case GL_SHADING_LANGUAGE_VERSION:
6466 str = "OpenGL ES GLSL ES 1.0 Chromium";
6467 break;
6468 case GL_EXTENSIONS:
[email protected]f0d74742011-10-03 16:31:046469 {
6470 // For WebGL contexts, strip out the OES derivatives extension if it has
6471 // not been enabled.
6472 if (force_webgl_glsl_validation_ &&
6473 !derivatives_explicitly_enabled_) {
6474 extensions = feature_info_->extensions();
6475 size_t offset = extensions.find(kOESDerivativeExtension);
6476 if (std::string::npos != offset) {
6477 extensions.replace(offset,
6478 offset + arraysize(kOESDerivativeExtension),
6479 std::string());
6480 }
6481 str = extensions.c_str();
6482 } else {
6483 str = feature_info_->extensions().c_str();
6484 }
[email protected]f0d74742011-10-03 16:31:046485 }
[email protected]1958e0e2010-04-22 05:17:156486 break;
6487 default:
6488 str = gl_str;
6489 break;
6490 }
[email protected]ddd968b82010-03-02 00:44:296491 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:156492 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:296493 return error::kNoError;
6494}
6495
[email protected]0c86dbf2010-03-05 08:14:116496void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:156497 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:056498 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296499 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
6500 return;
6501 }
[email protected]9438b012010-06-15 22:55:056502 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:296503 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:116504 return;
[email protected]3b6ec202010-03-05 05:16:236505 }
6506 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:296507 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:286508 return;
[email protected]3b6ec202010-03-05 05:16:236509 }
6510 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
6511 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296512 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:286513 return;
[email protected]3b6ec202010-03-05 05:16:236514 }
6515 // Clear the buffer to 0 if no initial data was passed in.
6516 scoped_array<int8> zero;
6517 if (!data) {
6518 zero.reset(new int8[size]);
6519 memset(zero.get(), 0, size);
6520 data = zero.get();
6521 }
[email protected]473c01ccb2011-06-07 01:33:306522
6523 if (!bufferdata_faster_than_buffersubdata_ &&
6524 size == info->size() && usage == info->usage()) {
6525 glBufferSubData(target, 0, size, data);
6526 info->SetRange(0, size, data);
6527 return;
6528 }
6529
[email protected]3b6ec202010-03-05 05:16:236530 CopyRealGLErrorsToWrapper();
6531 glBufferData(target, size, data, usage);
[email protected]1002c2d2011-06-28 22:39:046532 GLenum error = PeekGLError();
6533 if (error == GL_NO_ERROR) {
[email protected]473c01ccb2011-06-07 01:33:306534 buffer_manager()->SetInfo(info, size, usage);
[email protected]0c86dbf2010-03-05 08:14:116535 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:236536 }
[email protected]0c86dbf2010-03-05 08:14:116537}
6538
6539error::Error GLES2DecoderImpl::HandleBufferData(
6540 uint32 immediate_data_size, const gles2::BufferData& c) {
6541 GLenum target = static_cast<GLenum>(c.target);
6542 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
6543 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6544 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6545 GLenum usage = static_cast<GLenum>(c.usage);
6546 const void* data = NULL;
6547 if (data_shm_id != 0 || data_shm_offset != 0) {
6548 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
6549 if (!data) {
6550 return error::kOutOfBounds;
6551 }
6552 }
6553 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:146554 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196555}
6556
[email protected]f7a64ee2010-02-01 22:24:146557error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:196558 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
6559 GLenum target = static_cast<GLenum>(c.target);
6560 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:306561 const void* data = GetImmediateDataAs<const void*>(
6562 c, size, immediate_data_size);
6563 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146564 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:306565 }
[email protected]b9849abf2009-11-25 19:13:196566 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:116567 DoBufferData(target, size, data, usage);
6568 return error::kNoError;
6569}
6570
6571void GLES2DecoderImpl::DoBufferSubData(
6572 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:506573 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476574 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296575 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:286576 return;
[email protected]a93bb842010-02-16 23:03:476577 }
[email protected]0c86dbf2010-03-05 08:14:116578 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:296579 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]473c01ccb2011-06-07 01:33:306580 return;
[email protected]07f54fcc2009-12-22 02:46:306581 }
[email protected]473c01ccb2011-06-07 01:33:306582 if (bufferdata_faster_than_buffersubdata_ &&
6583 offset == 0 && size == info->size()) {
6584 glBufferData(target, size, data, info->usage());
6585 return;
6586 }
6587 glBufferSubData(target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:196588}
6589
[email protected]0d6bfdc2011-11-02 01:32:206590bool GLES2DecoderImpl::ClearLevel(
6591 unsigned service_id,
6592 unsigned bind_target,
6593 unsigned target,
6594 int level,
6595 unsigned format,
6596 unsigned type,
6597 int width,
[email protected]4502e6492011-12-14 19:39:156598 int height,
6599 bool is_texture_immutable) {
[email protected]45d15a62012-04-18 14:33:176600 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
6601
6602 uint32 size;
6603 uint32 padded_row_size;
[email protected]3458a64a2012-04-10 17:39:346604 if (!GLES2Util::ComputeImageDataSizes(
[email protected]45d15a62012-04-18 14:33:176605 width, height, format, type, unpack_alignment_, &size,
6606 NULL, &padded_row_size)) {
[email protected]0d6bfdc2011-11-02 01:32:206607 return false;
6608 }
[email protected]45d15a62012-04-18 14:33:176609
6610 int tile_height;
6611
6612 if (size > kMaxZeroSize) {
6613 if (kMaxZeroSize < padded_row_size) {
6614 // That'd be an awfully large texture.
6615 return false;
6616 }
6617 // We should never have a large total size with a zero row size.
6618 DCHECK_GT(padded_row_size, 0U);
6619 tile_height = kMaxZeroSize / padded_row_size;
6620 if (!GLES2Util::ComputeImageDataSizes(
6621 width, tile_height, format, type, unpack_alignment_, &size, NULL,
6622 NULL)) {
6623 return false;
6624 }
[email protected]4502e6492011-12-14 19:39:156625 } else {
[email protected]45d15a62012-04-18 14:33:176626 tile_height = height;
6627 }
6628
6629 // Assumes the size has already been checked.
6630 scoped_array<char> zero(new char[size]);
6631 memset(zero.get(), 0, size);
6632 glBindTexture(bind_target, service_id);
6633
6634 GLint y = 0;
6635 while (y < height) {
6636 GLint h = y + tile_height > height ? height - y : tile_height;
6637 if (is_texture_immutable || h != height) {
6638 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
6639 } else {
6640 WrappedTexImage2D(
6641 target, level, format, width, h, 0, format, type, zero.get());
6642 }
6643 y += tile_height;
[email protected]4502e6492011-12-14 19:39:156644 }
[email protected]0d6bfdc2011-11-02 01:32:206645 TextureManager::TextureInfo* info = GetTextureInfoForTarget(bind_target);
6646 glBindTexture(bind_target, info ? info->service_id() : 0);
6647 return true;
6648}
6649
[email protected]a93bb842010-02-16 23:03:476650error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
6651 GLenum target,
6652 GLint level,
6653 GLenum internal_format,
6654 GLsizei width,
6655 GLsizei height,
6656 GLint border,
6657 GLsizei image_size,
6658 const void* data) {
[email protected]a93bb842010-02-16 23:03:476659 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:056660 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296661 SetGLError(GL_INVALID_ENUM,
6662 "glCompressedTexImage2D: target GL_INVALID_ENUM");
6663 return error::kNoError;
6664 }
[email protected]9438b012010-06-15 22:55:056665 if (!validators_->compressed_texture_format.IsValid(
6666 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296667 SetGLError(GL_INVALID_ENUM,
6668 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:476669 return error::kNoError;
6670 }
[email protected]80eb6b52012-01-19 00:14:416671 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476672 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296673 SetGLError(GL_INVALID_VALUE,
6674 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476675 return error::kNoError;
6676 }
[email protected]3916c97e2010-02-25 03:20:506677 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476678 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296679 SetGLError(GL_INVALID_VALUE,
6680 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:476681 return error::kNoError;
6682 }
[email protected]97dc7cbe2011-12-06 17:26:176683 if (info->IsImmutable()) {
6684 SetGLError(GL_INVALID_OPERATION,
6685 "glCompressedTexImage2D: texture is immutable");
6686 return error::kNoError;
6687 }
[email protected]968351b2011-12-20 08:26:516688
6689 if (info->IsAttachedToFramebuffer()) {
6690 state_dirty_ = true;
6691 // TODO(gman): If textures tracked which framebuffers they were attached to
6692 // we could just mark those framebuffers as not complete.
6693 framebuffer_manager()->IncFramebufferStateChangeCount();
6694 }
6695
[email protected]a93bb842010-02-16 23:03:476696 scoped_array<int8> zero;
6697 if (!data) {
6698 zero.reset(new int8[image_size]);
6699 memset(zero.get(), 0, image_size);
6700 data = zero.get();
6701 }
[email protected]cadde4a2010-07-31 17:10:436702 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:476703 glCompressedTexImage2D(
6704 target, level, internal_format, width, height, border, image_size, data);
[email protected]1002c2d2011-06-28 22:39:046705 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436706 if (error == GL_NO_ERROR) {
6707 texture_manager()->SetLevelInfo(
[email protected]0d6bfdc2011-11-02 01:32:206708 info, target, level, internal_format, width, height, 1, border, 0, 0,
6709 true);
[email protected]cadde4a2010-07-31 17:10:436710 }
[email protected]a93bb842010-02-16 23:03:476711 return error::kNoError;
6712}
6713
[email protected]f7a64ee2010-02-01 22:24:146714error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196715 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
6716 GLenum target = static_cast<GLenum>(c.target);
6717 GLint level = static_cast<GLint>(c.level);
6718 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6719 GLsizei width = static_cast<GLsizei>(c.width);
6720 GLsizei height = static_cast<GLsizei>(c.height);
6721 GLint border = static_cast<GLint>(c.border);
6722 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
6723 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6724 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6725 const void* data = NULL;
6726 if (data_shm_id != 0 || data_shm_offset != 0) {
6727 data = GetSharedMemoryAs<const void*>(
6728 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:466729 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146730 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196731 }
6732 }
[email protected]a93bb842010-02-16 23:03:476733 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196734 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:196735}
6736
[email protected]f7a64ee2010-02-01 22:24:146737error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:196738 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
6739 GLenum target = static_cast<GLenum>(c.target);
6740 GLint level = static_cast<GLint>(c.level);
6741 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6742 GLsizei width = static_cast<GLsizei>(c.width);
6743 GLsizei height = static_cast<GLsizei>(c.height);
6744 GLint border = static_cast<GLint>(c.border);
6745 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:306746 const void* data = GetImmediateDataAs<const void*>(
6747 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466748 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146749 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466750 }
[email protected]a93bb842010-02-16 23:03:476751 return DoCompressedTexImage2D(
6752 target, level, internal_format, width, height, border, image_size, data);
6753}
6754
[email protected]b6140d02010-05-17 14:47:166755error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
6756 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
6757 GLenum target = static_cast<GLenum>(c.target);
6758 GLint level = static_cast<GLint>(c.level);
6759 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6760 GLsizei width = static_cast<GLsizei>(c.width);
6761 GLsizei height = static_cast<GLsizei>(c.height);
6762 GLint border = static_cast<GLint>(c.border);
6763 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:286764 if (!bucket) {
6765 return error::kInvalidArguments;
6766 }
6767 uint32 data_size = bucket->size();
6768 GLsizei imageSize = data_size;
6769 const void* data = bucket->GetData(0, data_size);
6770 if (!data) {
6771 return error::kInvalidArguments;
6772 }
[email protected]b6140d02010-05-17 14:47:166773 return DoCompressedTexImage2D(
6774 target, level, internal_format, width, height, border,
[email protected]12f93d82011-10-17 21:16:286775 imageSize, data);
[email protected]b6140d02010-05-17 14:47:166776}
6777
6778error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
6779 uint32 immediate_data_size,
6780 const gles2::CompressedTexSubImage2DBucket& c) {
6781 GLenum target = static_cast<GLenum>(c.target);
6782 GLint level = static_cast<GLint>(c.level);
6783 GLint xoffset = static_cast<GLint>(c.xoffset);
6784 GLint yoffset = static_cast<GLint>(c.yoffset);
6785 GLsizei width = static_cast<GLsizei>(c.width);
6786 GLsizei height = static_cast<GLsizei>(c.height);
6787 GLenum format = static_cast<GLenum>(c.format);
6788 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:286789 if (!bucket) {
6790 return error::kInvalidArguments;
6791 }
[email protected]b6140d02010-05-17 14:47:166792 uint32 data_size = bucket->size();
6793 GLsizei imageSize = data_size;
6794 const void* data = bucket->GetData(0, data_size);
[email protected]12f93d82011-10-17 21:16:286795 if (!data) {
6796 return error::kInvalidArguments;
6797 }
[email protected]9438b012010-06-15 22:55:056798 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:166799 SetGLError(
6800 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
6801 return error::kNoError;
6802 }
[email protected]9438b012010-06-15 22:55:056803 if (!validators_->compressed_texture_format.IsValid(format)) {
6804 SetGLError(GL_INVALID_ENUM,
6805 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
6806 return error::kNoError;
6807 }
[email protected]b6140d02010-05-17 14:47:166808 if (width < 0) {
6809 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
6810 return error::kNoError;
6811 }
6812 if (height < 0) {
6813 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
6814 return error::kNoError;
6815 }
6816 if (imageSize < 0) {
6817 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
6818 return error::kNoError;
6819 }
[email protected]cadde4a2010-07-31 17:10:436820 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:166821 target, level, xoffset, yoffset, width, height, format, imageSize, data);
6822 return error::kNoError;
6823}
6824
[email protected]a93bb842010-02-16 23:03:476825error::Error GLES2DecoderImpl::DoTexImage2D(
6826 GLenum target,
6827 GLint level,
6828 GLenum internal_format,
6829 GLsizei width,
6830 GLsizei height,
6831 GLint border,
6832 GLenum format,
6833 GLenum type,
6834 const void* pixels,
6835 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:056836 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296837 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
6838 return error::kNoError;
6839 }
[email protected]9438b012010-06-15 22:55:056840 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296841 SetGLError(GL_INVALID_ENUM,
6842 "glTexImage2D: internal_format GL_INVALID_ENUM");
6843 return error::kNoError;
6844 }
[email protected]9438b012010-06-15 22:55:056845 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:296846 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
6847 return error::kNoError;
6848 }
[email protected]9438b012010-06-15 22:55:056849 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:296850 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:146851 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196852 }
[email protected]7b92c412010-07-20 17:48:256853 if (format != internal_format) {
6854 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
6855 return error::kNoError;
6856 }
[email protected]80eb6b52012-01-19 00:14:416857 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476858 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296859 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476860 return error::kNoError;
6861 }
[email protected]3916c97e2010-02-25 03:20:506862 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476863 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296864 SetGLError(GL_INVALID_OPERATION,
6865 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:476866 return error::kNoError;
6867 }
[email protected]0226c112011-07-22 03:25:076868
[email protected]97dc7cbe2011-12-06 17:26:176869 if (info->IsImmutable()) {
6870 SetGLError(GL_INVALID_OPERATION,
6871 "glTexImage2D: texture is immutable");
6872 return error::kNoError;
6873 }
6874
[email protected]0226c112011-07-22 03:25:076875 GLsizei tex_width = 0;
6876 GLsizei tex_height = 0;
6877 GLenum tex_type = 0;
6878 GLenum tex_format = 0;
6879 bool level_is_same =
6880 info->GetLevelSize(target, level, &tex_width, &tex_height) &&
6881 info->GetLevelType(target, level, &tex_type, &tex_format) &&
6882 width == tex_width && height == tex_height &&
6883 type == tex_type && format == tex_format;
6884
6885 if (level_is_same && !pixels) {
[email protected]1bed6222011-12-21 11:21:396886 // Just set the level info but mark the texture as uncleared.
6887 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416888 info,
[email protected]1bed6222011-12-21 11:21:396889 target, level, internal_format, width, height, 1, border, format, type,
6890 false);
[email protected]ea72ed222011-08-17 18:58:436891 tex_image_2d_failed_ = false;
[email protected]0226c112011-07-22 03:25:076892 return error::kNoError;
6893 }
6894
[email protected]297ca1c2011-06-20 23:08:466895 if (info->IsAttachedToFramebuffer()) {
6896 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:516897 // TODO(gman): If textures tracked which framebuffers they were attached to
6898 // we could just mark those framebuffers as not complete.
6899 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:466900 }
6901
[email protected]1bed6222011-12-21 11:21:396902 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same && pixels) {
[email protected]0226c112011-07-22 03:25:076903 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
[email protected]57edfdad2012-02-07 04:57:156904 texture_manager()->SetLevelCleared(info, target, level);
[email protected]0226c112011-07-22 03:25:076905 tex_image_2d_failed_ = false;
6906 return error::kNoError;
[email protected]7488d962010-07-16 02:41:586907 }
[email protected]876f6fee2010-08-02 23:10:326908
[email protected]cadde4a2010-07-31 17:10:436909 CopyRealGLErrorsToWrapper();
[email protected]473c01ccb2011-06-07 01:33:306910 WrappedTexImage2D(
6911 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476912 pixels);
[email protected]1002c2d2011-06-28 22:39:046913 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436914 if (error == GL_NO_ERROR) {
[email protected]0d6bfdc2011-11-02 01:32:206915 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416916 info,
[email protected]0d6bfdc2011-11-02 01:32:206917 target, level, internal_format, width, height, 1, border, format, type,
6918 pixels != NULL);
[email protected]b493ee622011-04-13 23:52:006919 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:436920 }
[email protected]f7a64ee2010-02-01 22:24:146921 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196922}
6923
[email protected]f7a64ee2010-02-01 22:24:146924error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196925 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]366ae242011-05-10 02:23:586926 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:006927 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:196928 GLenum target = static_cast<GLenum>(c.target);
6929 GLint level = static_cast<GLint>(c.level);
6930 GLint internal_format = static_cast<GLint>(c.internalformat);
6931 GLsizei width = static_cast<GLsizei>(c.width);
6932 GLsizei height = static_cast<GLsizei>(c.height);
6933 GLint border = static_cast<GLint>(c.border);
6934 GLenum format = static_cast<GLenum>(c.format);
6935 GLenum type = static_cast<GLenum>(c.type);
6936 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
6937 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:186938 uint32 pixels_size;
[email protected]3458a64a2012-04-10 17:39:346939 if (!GLES2Util::ComputeImageDataSizes(
6940 width, height, format, type, unpack_alignment_, &pixels_size, NULL,
6941 NULL)) {
[email protected]a76b0052010-03-05 00:33:186942 return error::kOutOfBounds;
6943 }
[email protected]b9849abf2009-11-25 19:13:196944 const void* pixels = NULL;
6945 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
6946 pixels = GetSharedMemoryAs<const void*>(
6947 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:466948 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146949 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196950 }
6951 }
[email protected]a93bb842010-02-16 23:03:476952 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196953 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476954 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:196955}
6956
[email protected]f7a64ee2010-02-01 22:24:146957error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:196958 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
6959 GLenum target = static_cast<GLenum>(c.target);
6960 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:466961 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:196962 GLsizei width = static_cast<GLsizei>(c.width);
6963 GLsizei height = static_cast<GLsizei>(c.height);
6964 GLint border = static_cast<GLint>(c.border);
6965 GLenum format = static_cast<GLenum>(c.format);
6966 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:186967 uint32 size;
[email protected]3458a64a2012-04-10 17:39:346968 if (!GLES2Util::ComputeImageDataSizes(
6969 width, height, format, type, unpack_alignment_, &size, NULL, NULL)) {
[email protected]a76b0052010-03-05 00:33:186970 return error::kOutOfBounds;
6971 }
[email protected]07f54fcc2009-12-22 02:46:306972 const void* pixels = GetImmediateDataAs<const void*>(
6973 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466974 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146975 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466976 }
[email protected]a93bb842010-02-16 23:03:476977 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:466978 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476979 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:146980 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326981}
6982
[email protected]cadde4a2010-07-31 17:10:436983void GLES2DecoderImpl::DoCompressedTexSubImage2D(
6984 GLenum target,
6985 GLint level,
6986 GLint xoffset,
6987 GLint yoffset,
6988 GLsizei width,
6989 GLsizei height,
6990 GLenum format,
6991 GLsizei image_size,
6992 const void * data) {
6993 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
6994 if (!info) {
6995 SetGLError(GL_INVALID_OPERATION,
6996 "glCompressedTexSubImage2D: unknown texture for target");
6997 return;
6998 }
6999 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:527000 GLenum internal_format = 0;
7001 if (!info->GetLevelType(target, level, &type, &internal_format)) {
7002 SetGLError(
7003 GL_INVALID_OPERATION,
[email protected]4502e6492011-12-14 19:39:157004 "glCompressedTexSubImage2D: level does not exist.");
[email protected]df6cf1ad2011-01-29 01:20:527005 return;
7006 }
7007 if (internal_format != format) {
7008 SetGLError(
7009 GL_INVALID_OPERATION,
[email protected]4502e6492011-12-14 19:39:157010 "glCompressedTexSubImage2D: format does not match internal format.");
[email protected]df6cf1ad2011-01-29 01:20:527011 return;
7012 }
7013 if (!info->ValidForTexture(
7014 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:437015 SetGLError(GL_INVALID_VALUE,
[email protected]4502e6492011-12-14 19:39:157016 "glCompressedTexSubImage2D: bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:437017 return;
7018 }
[email protected]0d6bfdc2011-11-02 01:32:207019 // Note: There is no need to deal with texture cleared tracking here
7020 // because the validation above means you can only get here if the level
7021 // is already a matching compressed format and in that case
7022 // CompressedTexImage2D already cleared the texture.
[email protected]cadde4a2010-07-31 17:10:437023 glCompressedTexSubImage2D(
7024 target, level, xoffset, yoffset, width, height, format, image_size, data);
7025}
7026
[email protected]6e288612010-12-21 20:45:037027static void Clip(
7028 GLint start, GLint range, GLint sourceRange,
7029 GLint* out_start, GLint* out_range) {
7030 DCHECK(out_start);
7031 DCHECK(out_range);
7032 if (start < 0) {
7033 range += start;
7034 start = 0;
7035 }
7036 GLint end = start + range;
7037 if (end > sourceRange) {
7038 range -= end - sourceRange;
7039 }
7040 *out_start = start;
7041 *out_range = range;
7042}
7043
[email protected]cadde4a2010-07-31 17:10:437044void GLES2DecoderImpl::DoCopyTexImage2D(
7045 GLenum target,
7046 GLint level,
7047 GLenum internal_format,
7048 GLint x,
7049 GLint y,
7050 GLsizei width,
7051 GLsizei height,
7052 GLint border) {
7053 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7054 if (!info) {
7055 SetGLError(GL_INVALID_OPERATION,
7056 "glCopyTexImage2D: unknown texture for target");
7057 return;
7058 }
[email protected]97dc7cbe2011-12-06 17:26:177059 if (info->IsImmutable()) {
7060 SetGLError(GL_INVALID_OPERATION,
7061 "glCopyTexImage2D: texture is immutable");
7062 }
[email protected]80eb6b52012-01-19 00:14:417063 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:187064 border != 0) {
7065 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
7066 return;
7067 }
7068
[email protected]9edc6b22010-12-23 02:00:267069 // Check we have compatible formats.
7070 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7071 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7072 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
7073
7074 if ((channels_needed & channels_exist) != channels_needed) {
7075 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
7076 return;
7077 }
7078
[email protected]a0b78dc2011-11-11 10:43:107079 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
7080 return;
7081 }
7082
[email protected]cadde4a2010-07-31 17:10:437083 CopyRealGLErrorsToWrapper();
[email protected]de26b3c2011-08-03 21:54:277084 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:037085 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:267086
[email protected]297ca1c2011-06-20 23:08:467087 if (info->IsAttachedToFramebuffer()) {
7088 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:517089 // TODO(gman): If textures tracked which framebuffers they were attached to
7090 // we could just mark those framebuffers as not complete.
7091 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:467092 }
7093
[email protected]9edc6b22010-12-23 02:00:267094 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:037095 GLint copyX = 0;
7096 GLint copyY = 0;
7097 GLint copyWidth = 0;
7098 GLint copyHeight = 0;
7099 Clip(x, width, size.width(), &copyX, &copyWidth);
7100 Clip(y, height, size.height(), &copyY, &copyHeight);
7101
7102 if (copyX != x ||
7103 copyY != y ||
7104 copyWidth != width ||
7105 copyHeight != height) {
7106 // some part was clipped so clear the texture.
[email protected]0d6bfdc2011-11-02 01:32:207107 if (!ClearLevel(
7108 info->service_id(), info->target(),
[email protected]4502e6492011-12-14 19:39:157109 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
7110 info->IsImmutable())) {
[email protected]0d6bfdc2011-11-02 01:32:207111 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexImage2D: dimensions too big");
[email protected]6e288612010-12-21 20:45:037112 return;
7113 }
[email protected]6e288612010-12-21 20:45:037114 if (copyHeight > 0 && copyWidth > 0) {
7115 GLint dx = copyX - x;
7116 GLint dy = copyY - y;
7117 GLint destX = dx;
7118 GLint destY = dy;
7119 glCopyTexSubImage2D(target, level,
7120 destX, destY, copyX, copyY,
7121 copyWidth, copyHeight);
7122 }
7123 } else {
7124 glCopyTexImage2D(target, level, internal_format,
7125 copyX, copyY, copyWidth, copyHeight, border);
7126 }
[email protected]1002c2d2011-06-28 22:39:047127 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:437128 if (error == GL_NO_ERROR) {
7129 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:417130 info, target, level, internal_format, width, height, 1,
[email protected]0d6bfdc2011-11-02 01:32:207131 border, internal_format, GL_UNSIGNED_BYTE, true);
[email protected]cadde4a2010-07-31 17:10:437132 }
7133}
7134
7135void GLES2DecoderImpl::DoCopyTexSubImage2D(
7136 GLenum target,
7137 GLint level,
7138 GLint xoffset,
7139 GLint yoffset,
7140 GLint x,
7141 GLint y,
7142 GLsizei width,
7143 GLsizei height) {
7144 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7145 if (!info) {
7146 SetGLError(GL_INVALID_OPERATION,
7147 "glCopyTexSubImage2D: unknown texture for target");
7148 return;
7149 }
7150 GLenum type = 0;
7151 GLenum format = 0;
7152 if (!info->GetLevelType(target, level, &type, &format) ||
7153 !info->ValidForTexture(
7154 target, level, xoffset, yoffset, width, height, format, type)) {
7155 SetGLError(GL_INVALID_VALUE,
7156 "glCopyTexSubImage2D: bad dimensions.");
7157 return;
7158 }
[email protected]9edc6b22010-12-23 02:00:267159
7160 // Check we have compatible formats.
7161 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7162 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7163 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
7164
7165 if ((channels_needed & channels_exist) != channels_needed) {
7166 SetGLError(
7167 GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
7168 return;
7169 }
7170
[email protected]a0b78dc2011-11-11 10:43:107171 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
7172 return;
7173 }
7174
[email protected]de26b3c2011-08-03 21:54:277175 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:037176 gfx::Size size = GetBoundReadFrameBufferSize();
7177 GLint copyX = 0;
7178 GLint copyY = 0;
7179 GLint copyWidth = 0;
7180 GLint copyHeight = 0;
7181 Clip(x, width, size.width(), &copyX, &copyWidth);
7182 Clip(y, height, size.height(), &copyY, &copyHeight);
[email protected]0d6bfdc2011-11-02 01:32:207183
7184 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
7185 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D: dimensions too big");
7186 return;
7187 }
7188
[email protected]6e288612010-12-21 20:45:037189 if (copyX != x ||
7190 copyY != y ||
7191 copyWidth != width ||
7192 copyHeight != height) {
[email protected]0d6bfdc2011-11-02 01:32:207193 // some part was clipped so clear the sub rect.
[email protected]6e288612010-12-21 20:45:037194 uint32 pixels_size = 0;
[email protected]3458a64a2012-04-10 17:39:347195 if (!GLES2Util::ComputeImageDataSizes(
7196 width, height, format, type, unpack_alignment_, &pixels_size, NULL,
7197 NULL)) {
[email protected]6e288612010-12-21 20:45:037198 SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large");
7199 return;
7200 }
7201 scoped_array<char> zero(new char[pixels_size]);
7202 memset(zero.get(), 0, pixels_size);
7203 glTexSubImage2D(
7204 target, level, xoffset, yoffset, width, height,
7205 format, type, zero.get());
7206 }
[email protected]0d6bfdc2011-11-02 01:32:207207
[email protected]6e288612010-12-21 20:45:037208 if (copyHeight > 0 && copyWidth > 0) {
7209 GLint dx = copyX - x;
7210 GLint dy = copyY - y;
7211 GLint destX = xoffset + dx;
7212 GLint destY = yoffset + dy;
7213 glCopyTexSubImage2D(target, level,
7214 destX, destY, copyX, copyY,
7215 copyWidth, copyHeight);
7216 }
[email protected]cadde4a2010-07-31 17:10:437217}
7218
7219void GLES2DecoderImpl::DoTexSubImage2D(
7220 GLenum target,
7221 GLint level,
7222 GLint xoffset,
7223 GLint yoffset,
7224 GLsizei width,
7225 GLsizei height,
7226 GLenum format,
7227 GLenum type,
7228 const void * data) {
7229 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7230 if (!info) {
7231 SetGLError(GL_INVALID_OPERATION,
7232 "glTexSubImage2D: unknown texture for target");
7233 return;
7234 }
[email protected]df6cf1ad2011-01-29 01:20:527235 GLenum current_type = 0;
7236 GLenum internal_format = 0;
7237 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
7238 SetGLError(
7239 GL_INVALID_OPERATION,
7240 "glTexSubImage2D: level does not exist.");
7241 return;
7242 }
7243 if (format != internal_format) {
7244 SetGLError(GL_INVALID_OPERATION,
7245 "glTexSubImage2D: format does not match internal format.");
7246 return;
7247 }
7248 if (type != current_type) {
7249 SetGLError(GL_INVALID_OPERATION,
7250 "glTexSubImage2D: type does not match type of texture.");
7251 return;
7252 }
7253
[email protected]cadde4a2010-07-31 17:10:437254 if (!info->ValidForTexture(
7255 target, level, xoffset, yoffset, width, height, format, type)) {
7256 SetGLError(GL_INVALID_VALUE,
7257 "glTexSubImage2D: bad dimensions.");
7258 return;
7259 }
[email protected]473c01ccb2011-06-07 01:33:307260
[email protected]4502e6492011-12-14 19:39:157261 GLsizei tex_width = 0;
7262 GLsizei tex_height = 0;
7263 bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height);
7264 DCHECK(ok);
7265 if (xoffset != 0 || yoffset != 0 ||
7266 width != tex_width || height != tex_height) {
7267 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
7268 SetGLError(GL_OUT_OF_MEMORY, "glTexSubImage2D: dimensions too big");
[email protected]473c01ccb2011-06-07 01:33:307269 return;
7270 }
[email protected]4502e6492011-12-14 19:39:157271 glTexSubImage2D(
7272 target, level, xoffset, yoffset, width, height, format, type, data);
[email protected]0d6bfdc2011-11-02 01:32:207273 return;
7274 }
[email protected]4502e6492011-12-14 19:39:157275
7276 if (teximage2d_faster_than_texsubimage2d_ && !info->IsImmutable()) {
7277 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
7278 // same as internal_foramt. If that changes we'll need to look them up.
7279 WrappedTexImage2D(
7280 target, level, format, width, height, 0, format, type, data);
7281 } else {
7282 glTexSubImage2D(
7283 target, level, xoffset, yoffset, width, height, format, type, data);
7284 }
7285 texture_manager()->SetLevelCleared(info, target, level);
[email protected]cadde4a2010-07-31 17:10:437286}
7287
[email protected]b493ee622011-04-13 23:52:007288error::Error GLES2DecoderImpl::HandleTexSubImage2D(
7289 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]366ae242011-05-10 02:23:587290 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:007291 GLboolean internal = static_cast<GLboolean>(c.internal);
7292 if (internal == GL_TRUE && tex_image_2d_failed_)
7293 return error::kNoError;
7294
7295 GLenum target = static_cast<GLenum>(c.target);
7296 GLint level = static_cast<GLint>(c.level);
7297 GLint xoffset = static_cast<GLint>(c.xoffset);
7298 GLint yoffset = static_cast<GLint>(c.yoffset);
7299 GLsizei width = static_cast<GLsizei>(c.width);
7300 GLsizei height = static_cast<GLsizei>(c.height);
7301 GLenum format = static_cast<GLenum>(c.format);
7302 GLenum type = static_cast<GLenum>(c.type);
7303 uint32 data_size;
[email protected]3458a64a2012-04-10 17:39:347304 if (!GLES2Util::ComputeImageDataSizes(
7305 width, height, format, type, unpack_alignment_, &data_size, NULL, NULL)) {
[email protected]b493ee622011-04-13 23:52:007306 return error::kOutOfBounds;
7307 }
7308 const void* pixels = GetSharedMemoryAs<const void*>(
7309 c.pixels_shm_id, c.pixels_shm_offset, data_size);
7310 if (!validators_->texture_target.IsValid(target)) {
7311 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
7312 return error::kNoError;
7313 }
7314 if (width < 0) {
7315 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
7316 return error::kNoError;
7317 }
7318 if (height < 0) {
7319 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
7320 return error::kNoError;
7321 }
7322 if (!validators_->texture_format.IsValid(format)) {
7323 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
7324 return error::kNoError;
7325 }
7326 if (!validators_->pixel_type.IsValid(type)) {
7327 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
7328 return error::kNoError;
7329 }
7330 if (pixels == NULL) {
7331 return error::kOutOfBounds;
7332 }
7333 DoTexSubImage2D(
7334 target, level, xoffset, yoffset, width, height, format, type, pixels);
7335 return error::kNoError;
7336}
7337
7338error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
7339 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
7340 GLboolean internal = static_cast<GLboolean>(c.internal);
7341 if (internal == GL_TRUE && tex_image_2d_failed_)
7342 return error::kNoError;
7343
7344 GLenum target = static_cast<GLenum>(c.target);
7345 GLint level = static_cast<GLint>(c.level);
7346 GLint xoffset = static_cast<GLint>(c.xoffset);
7347 GLint yoffset = static_cast<GLint>(c.yoffset);
7348 GLsizei width = static_cast<GLsizei>(c.width);
7349 GLsizei height = static_cast<GLsizei>(c.height);
7350 GLenum format = static_cast<GLenum>(c.format);
7351 GLenum type = static_cast<GLenum>(c.type);
7352 uint32 data_size;
[email protected]3458a64a2012-04-10 17:39:347353 if (!GLES2Util::ComputeImageDataSizes(
7354 width, height, format, type, unpack_alignment_, &data_size, NULL, NULL)) {
[email protected]b493ee622011-04-13 23:52:007355 return error::kOutOfBounds;
7356 }
7357 const void* pixels = GetImmediateDataAs<const void*>(
7358 c, data_size, immediate_data_size);
7359 if (!validators_->texture_target.IsValid(target)) {
7360 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
7361 return error::kNoError;
7362 }
7363 if (width < 0) {
7364 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
7365 return error::kNoError;
7366 }
7367 if (height < 0) {
7368 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
7369 return error::kNoError;
7370 }
7371 if (!validators_->texture_format.IsValid(format)) {
7372 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
7373 return error::kNoError;
7374 }
7375 if (!validators_->pixel_type.IsValid(type)) {
7376 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
7377 return error::kNoError;
7378 }
7379 if (pixels == NULL) {
7380 return error::kOutOfBounds;
7381 }
7382 DoTexSubImage2D(
7383 target, level, xoffset, yoffset, width, height, format, type, pixels);
7384 return error::kNoError;
7385}
7386
[email protected]f7a64ee2010-02-01 22:24:147387error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:197388 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:367389 GLuint index = static_cast<GLuint>(c.index);
7390 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:257391 typedef gles2::GetVertexAttribPointerv::Result Result;
7392 Result* result = GetSharedMemoryAs<Result*>(
7393 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:367394 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:147395 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:367396 }
[email protected]07d0cc82010-02-17 04:51:407397 // Check that the client initialized the result.
7398 if (result->size != 0) {
7399 return error::kInvalidArguments;
7400 }
[email protected]9438b012010-06-15 22:55:057401 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:297402 SetGLError(GL_INVALID_ENUM,
7403 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:147404 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367405 }
[email protected]3916c97e2010-02-25 03:20:507406 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:297407 SetGLError(GL_INVALID_VALUE,
7408 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:147409 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367410 }
[email protected]0bfd9882010-02-05 23:02:257411 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:087412 *result->GetData() =
[email protected]3757a372012-01-19 05:20:447413 vertex_attrib_manager_->GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:147414 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327415}
7416
[email protected]f7b85372010-02-03 01:11:377417bool GLES2DecoderImpl::GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127418 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:377419 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:127420 error::Error* error, GLint* real_location,
7421 GLuint* service_id, void** result_pointer, GLenum* result_type) {
[email protected]939e7362010-05-13 20:49:107422 DCHECK(error);
7423 DCHECK(service_id);
7424 DCHECK(result_pointer);
7425 DCHECK(result_type);
[email protected]1b0a6752012-02-22 03:44:127426 DCHECK(real_location);
[email protected]f7b85372010-02-03 01:11:377427 *error = error::kNoError;
7428 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:257429 SizedResult<GLint>* result;
7430 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7431 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
7432 if (!result) {
[email protected]f7b85372010-02-03 01:11:377433 *error = error::kOutOfBounds;
7434 return false;
7435 }
[email protected]0bfd9882010-02-05 23:02:257436 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:377437 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:257438 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:587439 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7440 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:377441 if (!info) {
[email protected]ae51d192010-04-27 00:48:037442 return false;
7443 }
7444 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:377445 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:297446 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:377447 return false;
7448 }
[email protected]ae51d192010-04-27 00:48:037449 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:367450 GLint array_index = -1;
7451 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
[email protected]1b0a6752012-02-22 03:44:127452 info->GetUniformInfoByFakeLocation(
7453 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:367454 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:377455 // No such location.
[email protected]8eee29c2010-04-29 03:38:297456 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:377457 return false;
7458 }
[email protected]43c2f1f2011-03-25 18:35:367459 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:507460 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:377461 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:297462 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:377463 return false;
7464 }
[email protected]0bfd9882010-02-05 23:02:257465 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7466 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
7467 if (!result) {
[email protected]f7b85372010-02-03 01:11:377468 *error = error::kOutOfBounds;
7469 return false;
7470 }
[email protected]0bfd9882010-02-05 23:02:257471 result->size = size;
[email protected]939e7362010-05-13 20:49:107472 *result_type = type;
[email protected]f7b85372010-02-03 01:11:377473 return true;
7474}
7475
[email protected]f7a64ee2010-02-01 22:24:147476error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:197477 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:377478 GLuint program = c.program;
[email protected]1b0a6752012-02-22 03:44:127479 GLint fake_location = program_manager()->UnswizzleLocation(c.location);
[email protected]f7b85372010-02-03 01:11:377480 GLuint service_id;
[email protected]939e7362010-05-13 20:49:107481 GLenum result_type;
[email protected]1b0a6752012-02-22 03:44:127482 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:377483 Error error;
[email protected]0bfd9882010-02-05 23:02:257484 void* result;
[email protected]f7b85372010-02-03 01:11:377485 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127486 program, fake_location, c.params_shm_id, c.params_shm_offset,
7487 &error, &real_location, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:257488 glGetUniformiv(
[email protected]1b0a6752012-02-22 03:44:127489 service_id, real_location,
[email protected]0bfd9882010-02-05 23:02:257490 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:377491 }
7492 return error;
[email protected]96449d2c2009-11-25 00:01:327493}
7494
[email protected]f7a64ee2010-02-01 22:24:147495error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:197496 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:377497 GLuint program = c.program;
[email protected]1b0a6752012-02-22 03:44:127498 GLint fake_location = program_manager()->UnswizzleLocation(c.location);
[email protected]f7b85372010-02-03 01:11:377499 GLuint service_id;
[email protected]1b0a6752012-02-22 03:44:127500 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:377501 Error error;
[email protected]0bfd9882010-02-05 23:02:257502 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:107503 Result* result;
7504 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:377505 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127506 program, fake_location, c.params_shm_id, c.params_shm_offset,
7507 &error, &real_location, &service_id,
7508 reinterpret_cast<void**>(&result), &result_type)) {
[email protected]939e7362010-05-13 20:49:107509 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
7510 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
7511 GLsizei num_values = result->GetNumResults();
7512 scoped_array<GLint> temp(new GLint[num_values]);
[email protected]1b0a6752012-02-22 03:44:127513 glGetUniformiv(service_id, real_location, temp.get());
[email protected]939e7362010-05-13 20:49:107514 GLfloat* dst = result->GetData();
7515 for (GLsizei ii = 0; ii < num_values; ++ii) {
7516 dst[ii] = (temp[ii] != 0);
7517 }
7518 } else {
[email protected]1b0a6752012-02-22 03:44:127519 glGetUniformfv(service_id, real_location, result->GetData());
[email protected]939e7362010-05-13 20:49:107520 }
[email protected]f7b85372010-02-03 01:11:377521 }
7522 return error;
[email protected]96449d2c2009-11-25 00:01:327523}
7524
[email protected]f7a64ee2010-02-01 22:24:147525error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:197526 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:257527 GLenum shader_type = static_cast<GLenum>(c.shadertype);
7528 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
7529 typedef gles2::GetShaderPrecisionFormat::Result Result;
7530 Result* result = GetSharedMemoryAs<Result*>(
7531 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7532 if (!result) {
7533 return error::kOutOfBounds;
7534 }
[email protected]07d0cc82010-02-17 04:51:407535 // Check that the client initialized the result.
7536 if (result->success != 0) {
7537 return error::kInvalidArguments;
7538 }
[email protected]9438b012010-06-15 22:55:057539 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:297540 SetGLError(GL_INVALID_ENUM,
7541 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
7542 return error::kNoError;
7543 }
[email protected]9438b012010-06-15 22:55:057544 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:297545 SetGLError(GL_INVALID_ENUM,
7546 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
7547 return error::kNoError;
7548 }
7549
7550 result->success = 1; // true
7551 switch (precision_type) {
7552 case GL_LOW_INT:
7553 case GL_MEDIUM_INT:
7554 case GL_HIGH_INT:
[email protected]0a34b582012-04-09 22:42:567555 // These values are for a 32-bit twos-complement integer format.
7556 result->min_range = 31;
7557 result->max_range = 30;
[email protected]8eee29c2010-04-29 03:38:297558 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:107559 break;
[email protected]8eee29c2010-04-29 03:38:297560 case GL_LOW_FLOAT:
7561 case GL_MEDIUM_FLOAT:
7562 case GL_HIGH_FLOAT:
[email protected]0a34b582012-04-09 22:42:567563 // These values are for an IEEE single-precision floating-point format.
7564 result->min_range = 127;
7565 result->max_range = 127;
7566 result->precision = 23;
[email protected]8eee29c2010-04-29 03:38:297567 break;
7568 default:
7569 NOTREACHED();
7570 break;
[email protected]0bfd9882010-02-05 23:02:257571 }
[email protected]f7a64ee2010-02-01 22:24:147572 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327573}
7574
[email protected]f7a64ee2010-02-01 22:24:147575error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:197576 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:257577 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:587578 GLuint program = static_cast<GLuint>(c.program);
7579 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7580 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:037581 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257582 return error::kNoError;
7583 }
7584 typedef gles2::GetAttachedShaders::Result Result;
7585 uint32 max_count = Result::ComputeMaxResults(result_size);
7586 Result* result = GetSharedMemoryAs<Result*>(
7587 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
7588 if (!result) {
7589 return error::kOutOfBounds;
7590 }
[email protected]07d0cc82010-02-17 04:51:407591 // Check that the client initialized the result.
7592 if (result->size != 0) {
7593 return error::kInvalidArguments;
7594 }
[email protected]0bfd9882010-02-05 23:02:257595 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:037596 glGetAttachedShaders(
7597 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:257598 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:037599 if (!shader_manager()->GetClientId(result->GetData()[ii],
7600 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:257601 NOTREACHED();
7602 return error::kGenericError;
7603 }
7604 }
7605 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:147606 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327607}
7608
[email protected]f7a64ee2010-02-01 22:24:147609error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:197610 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:257611 GLuint program = c.program;
7612 GLuint index = c.index;
7613 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:257614 typedef gles2::GetActiveUniform::Result Result;
7615 Result* result = GetSharedMemoryAs<Result*>(
7616 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7617 if (!result) {
7618 return error::kOutOfBounds;
7619 }
[email protected]07d0cc82010-02-17 04:51:407620 // Check that the client initialized the result.
7621 if (result->success != 0) {
7622 return error::kInvalidArguments;
7623 }
[email protected]6b8cf1a2010-05-06 16:13:587624 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7625 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:037626 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257627 return error::kNoError;
7628 }
7629 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
7630 info->GetUniformInfo(index);
7631 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:297632 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:257633 return error::kNoError;
7634 }
7635 result->success = 1; // true.
7636 result->size = uniform_info->size;
7637 result->type = uniform_info->type;
7638 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297639 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:147640 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327641}
7642
[email protected]f7a64ee2010-02-01 22:24:147643error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:197644 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:257645 GLuint program = c.program;
7646 GLuint index = c.index;
7647 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:257648 typedef gles2::GetActiveAttrib::Result Result;
7649 Result* result = GetSharedMemoryAs<Result*>(
7650 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7651 if (!result) {
7652 return error::kOutOfBounds;
7653 }
[email protected]07d0cc82010-02-17 04:51:407654 // Check that the client initialized the result.
7655 if (result->success != 0) {
7656 return error::kInvalidArguments;
7657 }
[email protected]6b8cf1a2010-05-06 16:13:587658 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7659 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:037660 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257661 return error::kNoError;
7662 }
7663 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
7664 info->GetAttribInfo(index);
7665 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:297666 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:257667 return error::kNoError;
7668 }
7669 result->success = 1; // true.
7670 result->size = attrib_info->size;
7671 result->type = attrib_info->type;
7672 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297673 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:147674 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327675}
7676
[email protected]b273e432010-04-12 17:23:587677error::Error GLES2DecoderImpl::HandleShaderBinary(
7678 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
7679#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:297680 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:587681 return error::kNoError;
7682#else
7683 GLsizei n = static_cast<GLsizei>(c.n);
7684 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:297685 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:587686 return error::kNoError;
7687 }
7688 GLsizei length = static_cast<GLsizei>(c.length);
7689 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:297690 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:587691 return error::kNoError;
7692 }
7693 uint32 data_size;
7694 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
7695 return error::kOutOfBounds;
7696 }
7697 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
7698 c.shaders_shm_id, c.shaders_shm_offset, data_size);
7699 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
7700 const void* binary = GetSharedMemoryAs<const void*>(
7701 c.binary_shm_id, c.binary_shm_offset, length);
7702 if (shaders == NULL || binary == NULL) {
7703 return error::kOutOfBounds;
7704 }
7705 scoped_array<GLuint> service_ids(new GLuint[n]);
7706 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:037707 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
7708 if (!info) {
[email protected]8eee29c2010-04-29 03:38:297709 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:587710 return error::kNoError;
7711 }
[email protected]ae51d192010-04-27 00:48:037712 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:587713 }
7714 // TODO(gman): call glShaderBinary
7715 return error::kNoError;
7716#endif
7717}
7718
[email protected]6217d392010-03-25 22:08:357719error::Error GLES2DecoderImpl::HandleSwapBuffers(
7720 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:497721 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7722 int this_frame_number = frame_number_++;
[email protected]da151512011-11-11 23:27:387723 // TRACE_EVENT for gpu tests:
[email protected]529c6672012-01-04 02:18:267724 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers",
7725 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
7726 "width", (is_offscreen ? offscreen_size_.width() :
7727 surface_->GetSize().width()));
[email protected]64ace852011-05-19 21:49:497728 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
7729 "offscreen", is_offscreen,
7730 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:357731 // If offscreen then don't actually SwapBuffers to the display. Just copy
7732 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:497733 if (is_offscreen) {
[email protected]1fb8c482011-08-31 01:01:537734 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
7735 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
7736 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
7737 // fix this.
7738 if (needs_mac_nvidia_driver_workaround_) {
7739 offscreen_saved_frame_buffer_->Create();
7740 glFinish();
7741 }
7742
7743 // Allocate the offscreen saved color texture.
7744 DCHECK(offscreen_saved_color_format_);
7745 offscreen_saved_color_texture_->AllocateStorage(
7746 offscreen_size_, offscreen_saved_color_format_);
[email protected]1078f912011-12-23 13:12:147747 UpdateBackbufferMemoryAccounting();
[email protected]1fb8c482011-08-31 01:01:537748
7749 offscreen_saved_frame_buffer_->AttachRenderTexture(
7750 offscreen_saved_color_texture_.get());
7751 if (offscreen_saved_frame_buffer_->CheckStatus() !=
7752 GL_FRAMEBUFFER_COMPLETE) {
7753 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
7754 << "because offscreen saved FBO was incomplete.";
7755 return error::kLostContext;
7756 }
7757
[email protected]1fb8c482011-08-31 01:01:537758 // Clear the offscreen color texture.
7759 // TODO(piman): Is this still necessary?
7760 {
7761 ScopedFrameBufferBinder binder(this,
7762 offscreen_saved_frame_buffer_->id());
7763 glClearColor(0, 0, 0, 0);
7764 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
7765 glDisable(GL_SCISSOR_TEST);
7766 glClear(GL_COLOR_BUFFER_BIT);
7767 RestoreClearState();
7768 }
7769
7770 UpdateParentTextureInfo();
7771 }
7772
[email protected]6217d392010-03-25 22:08:357773 ScopedGLErrorSuppressor suppressor(this);
7774
[email protected]34ff8b0c2010-10-01 20:06:027775 if (IsOffscreenBufferMultisampled()) {
[email protected]51411e32012-01-19 20:21:137776 // For multisampled buffers, resolve the frame buffer.
[email protected]de26b3c2011-08-03 21:54:277777 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]89d6ed02011-04-20 00:23:237778 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:487779 } else {
[email protected]069944672012-04-25 20:52:237780 ScopedFrameBufferBinder binder(this,
7781 offscreen_target_frame_buffer_->id());
[email protected]51411e32012-01-19 20:21:137782
[email protected]069944672012-04-25 20:52:237783 if (offscreen_target_buffer_preserved_) {
7784 // Copy the target frame buffer to the saved offscreen texture.
7785 offscreen_saved_color_texture_->Copy(
7786 offscreen_saved_color_texture_->size(),
7787 offscreen_saved_color_format_);
7788 } else {
7789 // Flip the textures in the parent context via the texture manager.
7790 if (!!offscreen_saved_color_texture_info_.get())
7791 offscreen_saved_color_texture_info_->
7792 SetServiceId(offscreen_target_color_texture_->id());
[email protected]8a61d872012-01-20 12:43:567793
[email protected]069944672012-04-25 20:52:237794 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
7795 offscreen_target_frame_buffer_->AttachRenderTexture(
7796 offscreen_target_color_texture_.get());
[email protected]b86b14982010-10-11 18:45:487797 }
[email protected]069944672012-04-25 20:52:237798
7799 // Ensure the side effects of the copy are visible to the parent
7800 // context. There is no need to do this for ANGLE because it uses a
7801 // single D3D device for all contexts.
7802 if (!IsAngle())
7803 glFlush();
[email protected]89d6ed02011-04-20 00:23:237804 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:397805 }
[email protected]6217d392010-03-25 22:08:357806 } else {
[email protected]64ace852011-05-19 21:49:497807 TRACE_EVENT1("gpu", "GLContext::SwapBuffers", "frame", this_frame_number);
[email protected]f62a5ab2011-05-23 20:34:157808 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:017809 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:027810 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:017811 }
[email protected]6217d392010-03-25 22:08:357812 }
7813
[email protected]89d6ed02011-04-20 00:23:237814 return error::kNoError;
[email protected]6217d392010-03-25 22:08:357815}
7816
[email protected]d4239852011-08-12 04:51:227817error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
7818 uint32 immediate_data_size, const gles2::EnableFeatureCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:187819 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287820 if (!bucket || bucket->size() == 0) {
7821 return error::kInvalidArguments;
7822 }
[email protected]d4239852011-08-12 04:51:227823 typedef gles2::EnableFeatureCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:187824 Result* result = GetSharedMemoryAs<Result*>(
7825 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7826 if (!result) {
7827 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:107828 }
[email protected]b1d2dcb2010-05-17 19:24:187829 // Check that the client initialized the result.
7830 if (*result != 0) {
7831 return error::kInvalidArguments;
7832 }
7833 std::string feature_str;
7834 if (!bucket->GetAsString(&feature_str)) {
7835 return error::kInvalidArguments;
7836 }
7837
7838 // TODO(gman): make this some kind of table to function pointer thingy.
[email protected]d4239852011-08-12 04:51:227839 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
[email protected]b1d2dcb2010-05-17 19:24:187840 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]d4239852011-08-12 04:51:227841 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
[email protected]8fbedc02010-11-18 18:43:407842 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
7843 // TODO(gman): decide how to remove the need for this const_cast.
7844 // I could make validators_ non const but that seems bad as this is the only
7845 // place it is needed. I could make some special friend class of validators
7846 // just to allow this to set them. That seems silly. I could refactor this
7847 // code to use the extension mechanism or the initialization attributes to
7848 // turn this feature on. Given that the only real point of this is to make
7849 // the conformance tests pass and given that there is lots of real work that
7850 // needs to be done it seems like refactoring for one to one of those
7851 // methods is a very low priority.
7852 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]f0d74742011-10-03 16:31:047853 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
7854 force_webgl_glsl_validation_ = true;
7855 InitializeShaderTranslator();
[email protected]b1d2dcb2010-05-17 19:24:187856 } else {
7857 return error::kNoError;
7858 }
7859
7860 *result = 1; // true.
7861 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:107862}
7863
[email protected]c2f8c8402010-12-06 18:07:247864error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
7865 uint32 immediate_data_size,
7866 const gles2::GetRequestableExtensionsCHROMIUM& c) {
7867 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]80eb6b52012-01-19 00:14:417868 FeatureInfo::Ref info(new FeatureInfo());
[email protected]e82fb792011-09-22 00:33:297869 info->Initialize(disallowed_features_, NULL);
[email protected]c2f8c8402010-12-06 18:07:247870 bucket->SetFromString(info->extensions().c_str());
7871 return error::kNoError;
7872}
7873
7874error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
7875 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
7876 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287877 if (!bucket || bucket->size() == 0) {
7878 return error::kInvalidArguments;
7879 }
[email protected]c2f8c8402010-12-06 18:07:247880 std::string feature_str;
7881 if (!bucket->GetAsString(&feature_str)) {
7882 return error::kInvalidArguments;
7883 }
7884
7885 bool std_derivatives_enabled =
7886 feature_info_->feature_flags().oes_standard_derivatives;
7887 bool webglsl_enabled =
7888 feature_info_->feature_flags().chromium_webglsl;
7889
7890 feature_info_->AddFeatures(feature_str.c_str());
7891
[email protected]f0d74742011-10-03 16:31:047892 bool initialization_required = false;
7893 if (force_webgl_glsl_validation_ && !derivatives_explicitly_enabled_) {
7894 size_t derivatives_offset = feature_str.find(kOESDerivativeExtension);
7895 if (std::string::npos != derivatives_offset) {
7896 derivatives_explicitly_enabled_ = true;
7897 initialization_required = true;
7898 }
7899 }
7900
[email protected]c2f8c8402010-12-06 18:07:247901 // If we just enabled a feature which affects the shader translator,
7902 // we may need to re-initialize it.
7903 if (std_derivatives_enabled !=
7904 feature_info_->feature_flags().oes_standard_derivatives ||
7905 webglsl_enabled !=
[email protected]f0d74742011-10-03 16:31:047906 feature_info_->feature_flags().chromium_webglsl ||
7907 initialization_required) {
[email protected]c2f8c8402010-12-06 18:07:247908 InitializeShaderTranslator();
7909 }
7910
[email protected]302ce6d2011-07-07 23:28:117911 UpdateCapabilities();
7912
[email protected]c2f8c8402010-12-06 18:07:247913 return error::kNoError;
7914}
7915
[email protected]372e0412011-06-28 16:08:567916error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
7917 uint32 immediate_data_size, const gles2::GetMultipleIntegervCHROMIUM& c) {
7918 GLuint count = c.count;
7919 uint32 pnames_size;
7920 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
7921 return error::kOutOfBounds;
7922 }
7923 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
7924 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
7925 if (pnames == NULL) {
7926 return error::kOutOfBounds;
7927 }
7928
7929 // We have to copy them since we use them twice so the client
7930 // can't change them between the time we validate them and the time we use
7931 // them.
7932 scoped_array<GLenum> enums(new GLenum[count]);
7933 memcpy(enums.get(), pnames, pnames_size);
7934
7935 // Count up the space needed for the result.
7936 uint32 num_results = 0;
7937 for (GLuint ii = 0; ii < count; ++ii) {
7938 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
7939 if (num == 0) {
7940 SetGLError(GL_INVALID_ENUM,
7941 "glGetMulitpleCHROMIUM: pname GL_INVALID_ENUM");
7942 return error::kNoError;
7943 }
7944 // Num will never be more than 4.
7945 DCHECK_LE(num, 4u);
7946 if (!SafeAdd(num_results, num, &num_results)) {
7947 return error::kOutOfBounds;
7948 }
7949 }
7950
7951 uint32 result_size = 0;
7952 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
7953 return error::kOutOfBounds;
7954 }
7955
7956 if (result_size != static_cast<uint32>(c.size)) {
7957 SetGLError(GL_INVALID_VALUE,
7958 "glGetMulitpleCHROMIUM: bad size GL_INVALID_VALUE");
7959 return error::kNoError;
7960 }
7961
7962 GLint* results = GetSharedMemoryAs<GLint*>(
7963 c.results_shm_id, c.results_shm_offset, result_size);
7964 if (results == NULL) {
7965 return error::kOutOfBounds;
7966 }
7967
7968 // Check the results have been cleared in case the context was lost.
7969 for (uint32 ii = 0; ii < num_results; ++ii) {
7970 if (results[ii]) {
7971 return error::kInvalidArguments;
7972 }
7973 }
7974
7975 // Get each result.
7976 GLint* start = results;
7977 for (GLuint ii = 0; ii < count; ++ii) {
7978 GLsizei num_written = 0;
7979 if (!GetHelper(enums[ii], results, &num_written)) {
7980 glGetIntegerv(enums[ii], results);
7981 }
7982 results += num_written;
7983 }
7984
7985 // Just to verify. Should this be a DCHECK?
7986 if (static_cast<uint32>(results - start) != num_results) {
7987 return error::kOutOfBounds;
7988 }
7989
7990 return error::kNoError;
7991}
7992
[email protected]2318d342011-07-11 22:27:427993error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
7994 uint32 immediate_data_size, const gles2::GetProgramInfoCHROMIUM& c) {
7995 GLuint program = static_cast<GLuint>(c.program);
7996 uint32 bucket_id = c.bucket_id;
7997 Bucket* bucket = CreateBucket(bucket_id);
7998 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
7999 ProgramManager::ProgramInfo* info = NULL;
[email protected]9a14ae612011-08-08 17:51:468000 info = GetProgramInfo(program);
8001 if (!info || !info->IsValid()) {
8002 return error::kNoError;
[email protected]2318d342011-07-11 22:27:428003 }
[email protected]5d4c6b22012-02-07 08:22:288004 info->GetProgramInfo(program_manager(), bucket);
[email protected]2318d342011-07-11 22:27:428005 return error::kNoError;
8006}
8007
[email protected]38d139d2011-07-14 00:38:438008error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
8009 switch (reset_status_) {
8010 case GL_NO_ERROR:
8011 // TODO(kbr): improve the precision of the error code in this case.
8012 // Consider delegating to context for error code if MakeCurrent fails.
8013 return error::kUnknown;
8014 case GL_GUILTY_CONTEXT_RESET_ARB:
8015 return error::kGuilty;
8016 case GL_INNOCENT_CONTEXT_RESET_ARB:
8017 return error::kInnocent;
8018 case GL_UNKNOWN_CONTEXT_RESET_ARB:
8019 return error::kUnknown;
8020 }
8021
8022 NOTREACHED();
8023 return error::kUnknown;
8024}
8025
8026bool GLES2DecoderImpl::WasContextLost() {
8027 if (context_->WasAllocatedUsingARBRobustness() && has_arb_robustness_) {
8028 GLenum status = glGetGraphicsResetStatusARB();
8029 if (status != GL_NO_ERROR) {
8030 // The graphics card was reset. Signal a lost context to the application.
8031 reset_status_ = status;
8032 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
8033 << " context lost via ARB_robustness. Reset status = 0x"
8034 << std::hex << status << std::dec;
8035 return true;
8036 }
8037 }
8038 return false;
8039}
8040
[email protected]882ba1e22012-03-08 19:02:538041bool GLES2DecoderImpl::GenQueriesEXTHelper(
8042 GLsizei n, const GLuint* client_ids) {
8043 for (GLsizei ii = 0; ii < n; ++ii) {
8044 if (query_manager_->GetQuery(client_ids[ii])) {
8045 return false;
8046 }
8047 }
[email protected]c45f1972012-03-14 07:27:368048 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
[email protected]882ba1e22012-03-08 19:02:538049 return true;
8050}
8051
8052void GLES2DecoderImpl::DeleteQueriesEXTHelper(
8053 GLsizei n, const GLuint* client_ids) {
8054 for (GLsizei ii = 0; ii < n; ++ii) {
8055 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
8056 if (query && !query->IsDeleted()) {
8057 if (query == current_query_) {
8058 current_query_ = NULL;
8059 }
[email protected]c45f1972012-03-14 07:27:368060 query->Destroy(true);
[email protected]882ba1e22012-03-08 19:02:538061 query_manager_->RemoveQuery(client_ids[ii]);
8062 }
8063 }
8064}
8065
[email protected]22e3f552012-03-13 01:54:198066bool GLES2DecoderImpl::ProcessPendingQueries() {
8067 if (query_manager_.get() == NULL) {
8068 return false;
8069 }
[email protected]c45f1972012-03-14 07:27:368070 if (!query_manager_->ProcessPendingQueries()) {
[email protected]22e3f552012-03-13 01:54:198071 current_decoder_error_ = error::kOutOfBounds;
8072 }
8073 return query_manager_->HavePendingQueries();
8074}
8075
[email protected]882ba1e22012-03-08 19:02:538076error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
8077 uint32 immediate_data_size, const gles2::BeginQueryEXT& c) {
8078 GLenum target = static_cast<GLenum>(c.target);
8079 GLuint client_id = static_cast<GLuint>(c.id);
8080 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
8081 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
8082
[email protected]c45f1972012-03-14 07:27:368083 switch (target) {
8084 case GL_COMMANDS_ISSUED_CHROMIUM:
8085 break;
8086 default:
8087 if (!feature_info_->feature_flags().occlusion_query_boolean) {
8088 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT: not enabled");
8089 return error::kNoError;
8090 }
8091 break;
[email protected]882ba1e22012-03-08 19:02:538092 }
8093
8094 if (current_query_) {
8095 SetGLError(
8096 GL_INVALID_OPERATION, "glBeginQueryEXT: query already in progress");
8097 return error::kNoError;
8098 }
8099
8100 if (client_id == 0) {
8101 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT: id is 0");
8102 return error::kNoError;
8103 }
8104
8105 QueryManager::Query* query = query_manager_->GetQuery(client_id);
8106 if (!query) {
[email protected]c45f1972012-03-14 07:27:368107 // TODO(gman): Decide if we need this check.
8108 //
[email protected]882ba1e22012-03-08 19:02:538109 // Checks id was made by glGenQueries
[email protected]c45f1972012-03-14 07:27:368110 //
8111 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
8112 // for all Query ids but from the POV of the command buffer service maybe
8113 // you don't.
8114 //
8115 // The client can enforce this. I don't think the service cares.
8116 //
8117 // IdAllocatorInterface* id_allocator =
8118 // group_->GetIdAllocator(id_namespaces::kQueries);
8119 // if (!id_allocator->InUse(client_id)) {
8120 // SetGLError(GL_INVALID_OPERATION,
8121 // "glBeginQueryEXT: id not made by glGenQueriesEXT");
8122 // return error::kNoError;
8123 // }
8124 query = query_manager_->CreateQuery(
8125 target, client_id, sync_shm_id, sync_shm_offset);
[email protected]882ba1e22012-03-08 19:02:538126 }
8127
[email protected]c45f1972012-03-14 07:27:368128 if (query->target() != target) {
[email protected]882ba1e22012-03-08 19:02:538129 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT: target does not match");
8130 return error::kNoError;
8131 } else if (query->shm_id() != sync_shm_id ||
8132 query->shm_offset() != sync_shm_offset) {
8133 DLOG(ERROR) << "Shared memory used by query not the same as before";
8134 return error::kInvalidArguments;
8135 }
8136
[email protected]c45f1972012-03-14 07:27:368137 if (!query_manager_->BeginQuery(query)) {
8138 return error::kOutOfBounds;
8139 }
[email protected]882ba1e22012-03-08 19:02:538140
[email protected]882ba1e22012-03-08 19:02:538141 current_query_ = query;
[email protected]882ba1e22012-03-08 19:02:538142 return error::kNoError;
8143}
8144
8145error::Error GLES2DecoderImpl::HandleEndQueryEXT(
8146 uint32 immediate_data_size, const gles2::EndQueryEXT& c) {
8147 GLenum target = static_cast<GLenum>(c.target);
8148 uint32 submit_count = static_cast<GLuint>(c.submit_count);
8149
8150 if (!current_query_) {
8151 SetGLError(GL_INVALID_OPERATION, "glEndQueryEXT: No active query");
8152 return error::kNoError;
8153 }
8154 if (current_query_->target() != target) {
8155 SetGLError(GL_INVALID_OPERATION,
8156 "glEndQueryEXT: target does not match active query");
8157 return error::kNoError;
8158 }
[email protected]882ba1e22012-03-08 19:02:538159
[email protected]c45f1972012-03-14 07:27:368160 if (!query_manager_->EndQuery(current_query_, submit_count)) {
8161 return error::kOutOfBounds;
8162 }
8163
8164 current_query_ = NULL;
[email protected]882ba1e22012-03-08 19:02:538165 return error::kNoError;
8166}
8167
[email protected]b0af4f52011-09-28 22:04:428168error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
8169 uint32 immediate_data_size,
8170 const gles2::CreateStreamTextureCHROMIUM& c) {
8171 if (!feature_info_->feature_flags().chromium_stream_texture) {
8172 SetGLError(GL_INVALID_OPERATION,
8173 "glOpenStreamTextureCHROMIUM: "
8174 "not supported.");
8175 return error::kNoError;
8176 }
8177
8178 uint32 client_id = c.client_id;
8179 typedef gles2::CreateStreamTextureCHROMIUM::Result Result;
8180 Result* result = GetSharedMemoryAs<Result*>(
8181 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8182
[email protected]e5081262012-01-05 23:09:038183 if (!result)
8184 return error::kOutOfBounds;
[email protected]b0af4f52011-09-28 22:04:428185 *result = GL_ZERO;
8186 TextureManager::TextureInfo* info =
8187 texture_manager()->GetTextureInfo(client_id);
8188 if (!info) {
8189 SetGLError(GL_INVALID_VALUE,
8190 "glCreateStreamTextureCHROMIUM: "
8191 "bad texture id.");
8192 return error::kNoError;
8193 }
8194
8195 if (info->IsStreamTexture()) {
8196 SetGLError(GL_INVALID_OPERATION,
8197 "glCreateStreamTextureCHROMIUM: "
8198 "is already a stream texture.");
8199 return error::kNoError;
8200 }
8201
8202 if (info->target() && info->target() != GL_TEXTURE_EXTERNAL_OES) {
8203 SetGLError(GL_INVALID_OPERATION,
8204 "glCreateStreamTextureCHROMIUM: "
8205 "is already bound to incompatible target.");
8206 return error::kNoError;
8207 }
8208
8209 if (!stream_texture_manager_)
8210 return error::kInvalidArguments;
8211
8212 GLuint object_id = stream_texture_manager_->CreateStreamTexture(
8213 info->service_id(), client_id);
8214
8215 if (object_id) {
8216 info->SetStreamTexture(true);
8217 } else {
8218 SetGLError(GL_OUT_OF_MEMORY,
8219 "glCreateStreamTextureCHROMIUM: "
8220 "failed to create platform texture.");
8221 }
8222
8223 *result = object_id;
8224 return error::kNoError;
8225}
8226
8227error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
8228 uint32 immediate_data_size,
8229 const gles2::DestroyStreamTextureCHROMIUM& c) {
8230 GLuint client_id = c.texture;
8231 TextureManager::TextureInfo* info =
8232 texture_manager()->GetTextureInfo(client_id);
8233 if (info && info->IsStreamTexture()) {
8234 if (!stream_texture_manager_)
8235 return error::kInvalidArguments;
8236
8237 stream_texture_manager_->DestroyStreamTexture(info->service_id());
8238 info->SetStreamTexture(false);
[email protected]80eb6b52012-01-19 00:14:418239 texture_manager()->SetInfoTarget(info, 0);
[email protected]b0af4f52011-09-28 22:04:428240 } else {
8241 SetGLError(GL_INVALID_VALUE,
8242 "glDestroyStreamTextureCHROMIUM: bad texture id.");
8243 }
8244
8245 return error::kNoError;
8246}
8247
[email protected]e51bdf32011-11-23 22:21:468248#if defined(OS_MACOSX)
8249void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
8250 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
8251 texture_id);
8252 if (it != texture_to_io_surface_map_.end()) {
8253 // Found a previous IOSurface bound to this texture; release it.
8254 CFTypeRef surface = it->second;
8255 CFRelease(surface);
8256 texture_to_io_surface_map_.erase(it);
8257 }
8258}
8259#endif
8260
8261void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
8262 GLenum target, GLsizei width, GLsizei height,
8263 GLuint io_surface_id, GLuint plane) {
8264#if defined(OS_MACOSX)
8265 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
8266 SetGLError(GL_INVALID_OPERATION,
8267 "glTexImageIOSurface2DCHROMIUM: only supported on desktop GL.");
8268 return;
8269 }
8270
8271 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
8272 if (!surface_support) {
8273 SetGLError(GL_INVALID_OPERATION,
8274 "glTexImageIOSurface2DCHROMIUM: only supported on 10.6.");
8275 return;
8276 }
8277
8278 if (target != GL_TEXTURE_RECTANGLE_ARB) {
8279 // This might be supported in the future, and if we could require
8280 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
8281 // could delete a lot of code. For now, perform strict validation so we
8282 // know what's going on.
8283 SetGLError(
8284 GL_INVALID_OPERATION,
8285 "glTexImageIOSurface2DCHROMIUM: requires TEXTURE_RECTANGLE_ARB target");
8286 return;
8287 }
8288
8289 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8290 if (!info) {
8291 SetGLError(GL_INVALID_OPERATION,
8292 "glTexImageIOSurface2DCHROMIUM: no rectangle texture bound");
8293 return;
8294 }
8295 if (info == texture_manager()->GetDefaultTextureInfo(target)) {
8296 // Maybe this is conceptually valid, but disallow it to avoid accidents.
8297 SetGLError(GL_INVALID_OPERATION,
8298 "glTexImageIOSurface2DCHROMIUM: can't bind default texture");
8299 return;
8300 }
8301
8302 // Look up the new IOSurface. Note that because of asynchrony
8303 // between processes this might fail; during live resizing the
8304 // plugin process might allocate and release an IOSurface before
8305 // this process gets a chance to look it up. Hold on to any old
8306 // IOSurface in this case.
8307 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
8308 if (!surface) {
8309 SetGLError(GL_INVALID_OPERATION,
8310 "glTexImageIOSurface2DCHROMIUM: no IOSurface with the given ID");
8311 return;
8312 }
8313
8314 // Release any IOSurface previously bound to this texture.
8315 ReleaseIOSurfaceForTexture(info->service_id());
8316
8317 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
8318 texture_to_io_surface_map_.insert(
8319 std::make_pair(info->service_id(), surface));
8320
8321 CGLContextObj context =
8322 static_cast<CGLContextObj>(context_->GetHandle());
8323
8324 CGLError err = surface_support->CGLTexImageIOSurface2D(
8325 context,
8326 target,
8327 GL_RGBA,
8328 width,
8329 height,
8330 GL_BGRA,
8331 GL_UNSIGNED_INT_8_8_8_8_REV,
8332 surface,
8333 plane);
8334
8335 if (err != kCGLNoError) {
8336 SetGLError(
8337 GL_INVALID_OPERATION,
8338 "glTexImageIOSurface2DCHROMIUM: error in CGLTexImageIOSurface2D");
8339 return;
8340 }
8341
8342 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:418343 info, target, 0, GL_RGBA, width, height, 1, 0,
[email protected]e51bdf32011-11-23 22:21:468344 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
8345
8346#else
8347 SetGLError(GL_INVALID_OPERATION,
8348 "glTexImageIOSurface2DCHROMIUM: not supported.");
8349#endif
8350}
8351
[email protected]97dc7cbe2011-12-06 17:26:178352static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
8353 switch (internalformat) {
8354 case GL_RGB565:
8355 return GL_RGB;
8356 case GL_RGBA4:
8357 return GL_RGBA;
8358 case GL_RGB5_A1:
8359 return GL_RGBA;
8360 case GL_RGB8_OES:
8361 return GL_RGB;
8362 case GL_RGBA8_OES:
8363 return GL_RGBA;
8364 case GL_LUMINANCE8_ALPHA8_EXT:
8365 return GL_LUMINANCE_ALPHA;
8366 case GL_LUMINANCE8_EXT:
8367 return GL_LUMINANCE;
8368 case GL_ALPHA8_EXT:
8369 return GL_ALPHA;
8370 case GL_RGBA32F_EXT:
8371 return GL_RGBA;
8372 case GL_RGB32F_EXT:
8373 return GL_RGB;
8374 case GL_ALPHA32F_EXT:
8375 return GL_ALPHA;
8376 case GL_LUMINANCE32F_EXT:
8377 return GL_LUMINANCE;
8378 case GL_LUMINANCE_ALPHA32F_EXT:
8379 return GL_LUMINANCE_ALPHA;
8380 case GL_RGBA16F_EXT:
8381 return GL_RGBA;
8382 case GL_RGB16F_EXT:
8383 return GL_RGB;
8384 case GL_ALPHA16F_EXT:
8385 return GL_ALPHA;
8386 case GL_LUMINANCE16F_EXT:
8387 return GL_LUMINANCE;
8388 case GL_LUMINANCE_ALPHA16F_EXT:
8389 return GL_LUMINANCE_ALPHA;
8390 case GL_BGRA8_EXT:
8391 return GL_BGRA_EXT;
8392 default:
8393 return GL_NONE;
8394 }
8395}
8396
[email protected]43410e92012-04-20 17:06:288397void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
[email protected]0a1e9ad2012-05-04 21:13:038398 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
8399 GLenum internal_format) {
[email protected]43410e92012-04-20 17:06:288400 TextureManager::TextureInfo* dest_info = GetTextureInfo(dest_id);
8401 TextureManager::TextureInfo* source_info = GetTextureInfo(source_id);
8402
8403 if (!source_info || !dest_info) {
8404 SetGLError(GL_INVALID_VALUE, "glCopyTextureCHROMIUM: unknown texture id");
8405 return;
8406 }
8407
8408 if (GL_TEXTURE_2D != target) {
8409 SetGLError(GL_INVALID_VALUE,
8410 "glCopyTextureCHROMIUM: invalid texture target");
8411 return;
8412 }
8413
[email protected]0a1e9ad2012-05-04 21:13:038414 if (dest_info->target() != GL_TEXTURE_2D ||
8415 source_info->target() != GL_TEXTURE_2D) {
8416 SetGLError(GL_INVALID_VALUE,
8417 "glCopyTextureCHROMIUM: invalid texture target binding");
8418 return;
8419 }
8420
[email protected]43410e92012-04-20 17:06:288421 int source_width, source_height, dest_width, dest_height;
8422 if (!source_info->GetLevelSize(GL_TEXTURE_2D, 0, &source_width,
8423 &source_height)) {
8424 SetGLError(GL_INVALID_VALUE,
8425 "glCopyTextureChromium: source texture has no level 0");
8426 return;
8427 }
8428
[email protected]43410e92012-04-20 17:06:288429 // Check that this type of texture is allowed.
8430 if (!texture_manager()->ValidForTarget(GL_TEXTURE_2D, level, source_width,
8431 source_height, 1)) {
8432 SetGLError(GL_INVALID_VALUE,
8433 "glCopyTextureCHROMIUM: Bad dimensions");
8434 return;
8435 }
8436
[email protected]0a1e9ad2012-05-04 21:13:038437 GLenum dest_type;
8438 GLenum dest_internal_format;
8439 bool dest_level_defined = dest_info->GetLevelSize(GL_TEXTURE_2D, level,
8440 &dest_width,
8441 &dest_height);
[email protected]43410e92012-04-20 17:06:288442
[email protected]0a1e9ad2012-05-04 21:13:038443 if (dest_level_defined) {
8444 dest_info->GetLevelType(GL_TEXTURE_2D, level, &dest_type,
8445 &dest_internal_format);
8446 } else {
8447 GLenum source_internal_format;
8448 source_info->GetLevelType(GL_TEXTURE_2D, 0, &dest_type,
8449 &source_internal_format);
8450 }
8451
8452 // Resize the destination texture to the dimensions of the source texture.
8453 if (!dest_level_defined || dest_width != source_width ||
8454 dest_height != source_height ||
8455 dest_internal_format != internal_format) {
[email protected]43410e92012-04-20 17:06:288456 // Ensure that the glTexImage2D succeeds.
8457 CopyRealGLErrorsToWrapper();
[email protected]0a1e9ad2012-05-04 21:13:038458 glBindTexture(GL_TEXTURE_2D, dest_info->service_id());
[email protected]43410e92012-04-20 17:06:288459 WrappedTexImage2D(
8460 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
[email protected]0a1e9ad2012-05-04 21:13:038461 0, internal_format, dest_type, NULL);
[email protected]43410e92012-04-20 17:06:288462 GLenum error = PeekGLError();
[email protected]0a1e9ad2012-05-04 21:13:038463 if (error != GL_NO_ERROR) {
8464 RestoreCurrentTexture2DBindings();
[email protected]43410e92012-04-20 17:06:288465 return;
[email protected]0a1e9ad2012-05-04 21:13:038466 }
[email protected]43410e92012-04-20 17:06:288467
8468 texture_manager()->SetLevelInfo(
8469 dest_info, GL_TEXTURE_2D, level, internal_format, source_width,
[email protected]0a1e9ad2012-05-04 21:13:038470 source_height, 1, 0, internal_format, dest_type, true);
[email protected]43410e92012-04-20 17:06:288471 }
8472
8473 state_dirty_ = true;
[email protected]0a1e9ad2012-05-04 21:13:038474 glViewport(0, 0, source_width, source_height);
[email protected]43410e92012-04-20 17:06:288475 copy_texture_CHROMIUM_->DoCopyTexture(target, source_info->service_id(),
8476 dest_info->service_id(), level,
8477 unpack_flip_y_,
8478 unpack_premultiply_alpha_);
8479 glViewport(viewport_x_, viewport_y_, viewport_width_, viewport_height_);
8480
8481 // Restore all of the state touched by the extension.
8482 if (current_program_)
8483 glUseProgram(current_program_->service_id());
8484 else
8485 glUseProgram(0);
8486
8487 RestoreCurrentFramebufferBindings();
8488 RestoreCurrentTexture2DBindings();
8489 RestoreStateForAttrib(
8490 CopyTextureCHROMIUMResourceManager::kVertexPositionAttrib);
8491 RestoreStateForAttrib(
8492 CopyTextureCHROMIUMResourceManager::kVertexTextureAttrib);
8493
8494 ApplyDirtyState();
8495}
8496
[email protected]97dc7cbe2011-12-06 17:26:178497static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
8498 switch (internalformat) {
8499 case GL_RGB565:
8500 return GL_UNSIGNED_SHORT_5_6_5;
8501 case GL_RGBA4:
8502 return GL_UNSIGNED_SHORT_4_4_4_4;
8503 case GL_RGB5_A1:
8504 return GL_UNSIGNED_SHORT_5_5_5_1;
8505 case GL_RGB8_OES:
8506 return GL_UNSIGNED_BYTE;
8507 case GL_RGBA8_OES:
8508 return GL_UNSIGNED_BYTE;
8509 case GL_LUMINANCE8_ALPHA8_EXT:
8510 return GL_UNSIGNED_BYTE;
8511 case GL_LUMINANCE8_EXT:
8512 return GL_UNSIGNED_BYTE;
8513 case GL_ALPHA8_EXT:
8514 return GL_UNSIGNED_BYTE;
8515 case GL_RGBA32F_EXT:
8516 return GL_FLOAT;
8517 case GL_RGB32F_EXT:
8518 return GL_FLOAT;
8519 case GL_ALPHA32F_EXT:
8520 return GL_FLOAT;
8521 case GL_LUMINANCE32F_EXT:
8522 return GL_FLOAT;
8523 case GL_LUMINANCE_ALPHA32F_EXT:
8524 return GL_FLOAT;
8525 case GL_RGBA16F_EXT:
8526 return GL_HALF_FLOAT_OES;
8527 case GL_RGB16F_EXT:
8528 return GL_HALF_FLOAT_OES;
8529 case GL_ALPHA16F_EXT:
8530 return GL_HALF_FLOAT_OES;
8531 case GL_LUMINANCE16F_EXT:
8532 return GL_HALF_FLOAT_OES;
8533 case GL_LUMINANCE_ALPHA16F_EXT:
8534 return GL_HALF_FLOAT_OES;
8535 case GL_BGRA8_EXT:
8536 return GL_UNSIGNED_BYTE;
8537 default:
8538 return GL_NONE;
8539 }
8540}
8541
8542void GLES2DecoderImpl::DoTexStorage2DEXT(
8543 GLenum target,
8544 GLint levels,
8545 GLenum internal_format,
8546 GLsizei width,
8547 GLsizei height) {
[email protected]cf57fbc2012-04-26 22:18:418548 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
[email protected]80eb6b52012-01-19 00:14:418549 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
[email protected]97dc7cbe2011-12-06 17:26:178550 TextureManager::ComputeMipMapCount(width, height, 1) < levels) {
8551 SetGLError(GL_INVALID_VALUE, "glTexStorage2DEXT: dimensions out of range");
8552 return;
8553 }
8554 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8555 if (!info) {
8556 SetGLError(GL_INVALID_OPERATION,
8557 "glTexStorage2DEXT: unknown texture for target");
8558 return;
8559 }
8560 if (info->IsAttachedToFramebuffer()) {
8561 state_dirty_ = true;
8562 }
8563 if (info->IsImmutable()) {
8564 SetGLError(GL_INVALID_OPERATION,
8565 "glTexStorage2DEXT: texture is immutable");
8566 return;
8567 }
8568 CopyRealGLErrorsToWrapper();
[email protected]f0e6a34f2012-01-04 20:53:408569 glTexStorage2DEXT(target, levels, GetTexInternalFormat(internal_format),
8570 width, height);
[email protected]97dc7cbe2011-12-06 17:26:178571 GLenum error = PeekGLError();
8572 if (error == GL_NO_ERROR) {
8573 GLenum format = ExtractFormatFromStorageFormat(internal_format);
8574 GLenum type = ExtractTypeFromStorageFormat(internal_format);
[email protected]4502e6492011-12-14 19:39:158575 GLsizei level_width = width;
8576 GLsizei level_height = height;
8577 for (int ii = 0; ii < levels; ++ii) {
8578 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:418579 info, target, 0, format, level_width, level_height, 1, 0, format,
8580 type, false);
[email protected]4502e6492011-12-14 19:39:158581 level_width = std::max(1, level_width >> 1);
8582 level_height = std::max(1, level_height >> 1);
8583 }
[email protected]97dc7cbe2011-12-06 17:26:178584 info->SetImmutable(true);
8585 }
[email protected]97dc7cbe2011-12-06 17:26:178586}
[email protected]e51bdf32011-11-23 22:21:468587
[email protected]78b514b2012-05-01 21:50:598588error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
8589 uint32 immediate_data_size, const gles2::GenMailboxCHROMIUM& c) {
8590 MailboxName name;
8591 mailbox_manager()->GenerateMailboxName(&name);
8592 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
8593 Bucket* bucket = CreateBucket(bucket_id);
8594
8595 bucket->SetSize(GL_MAILBOX_SIZE_CHROMIUM);
8596 bucket->SetData(&name, 0, GL_MAILBOX_SIZE_CHROMIUM);
8597
8598 return error::kNoError;
8599}
8600
8601void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
8602 const GLbyte* mailbox) {
8603 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8604 if (!info) {
8605 SetGLError(GL_INVALID_OPERATION,
8606 "glProduceTextureCHROMIUM: unknown texture for target");
8607 return;
8608 }
8609
8610 TextureDefinition* definition = texture_manager()->Save(info);
8611 if (!definition) {
8612 SetGLError(GL_INVALID_OPERATION,
8613 "glProduceTextureCHROMIUM: invalid texture");
8614 return;
8615 }
8616
8617 if (!group_->mailbox_manager()->ProduceTexture(
8618 target,
8619 *reinterpret_cast<const MailboxName*>(mailbox),
8620 definition,
8621 texture_manager())) {
8622 bool success = texture_manager()->Restore(info, definition);
8623 DCHECK(success);
8624 SetGLError(GL_INVALID_OPERATION,
8625 "glProduceTextureCHROMIUM: invalid mailbox name");
8626 return;
8627 }
8628
8629 BindAndApplyTextureParameters(info);
8630}
8631
8632void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
8633 const GLbyte* mailbox) {
8634 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8635 if (!info) {
8636 SetGLError(GL_INVALID_OPERATION,
8637 "glConsumeTextureCHROMIUM: unknown texture for target");
8638 return;
8639 }
8640
8641 scoped_ptr<TextureDefinition> definition(
8642 group_->mailbox_manager()->ConsumeTexture(
8643 target,
8644 *reinterpret_cast<const MailboxName*>(mailbox)));
8645 if (!definition.get()) {
8646 SetGLError(GL_INVALID_OPERATION,
8647 "glConsumeTextureCHROMIUM: invalid mailbox name");
8648 return;
8649 }
8650
8651 if (!texture_manager()->Restore(info, definition.release())) {
8652 SetGLError(GL_INVALID_OPERATION,
8653 "glConsumeTextureCHROMIUM: invalid texture");
8654 return;
8655 }
8656
8657 BindAndApplyTextureParameters(info);
8658}
8659
[email protected]96449d2c2009-11-25 00:01:328660// Include the auto-generated part of this file. We split this because it means
8661// we can easily edit the non-auto generated parts right here in this file
8662// instead of having to edit some template or the code generator.
8663#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
8664
8665} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:258666} // namespace gpu