blob: 0af984b981c2413851f85da98f7a40a38a3d7e73 [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]c9e2cbbb2012-05-12 21:17:2750#include "ui/gl/gl_context.h"
51#include "ui/gl/gl_implementation.h"
52#include "ui/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.
[email protected]3dc69c42012-05-12 02:29:241090 bool DoIsEnabled(GLenum cap);
[email protected]1958e0e2010-04-22 05:17:151091 bool DoIsBuffer(GLuint client_id);
1092 bool DoIsFramebuffer(GLuint client_id);
1093 bool DoIsProgram(GLuint client_id);
1094 bool DoIsRenderbuffer(GLuint client_id);
1095 bool DoIsShader(GLuint client_id);
1096 bool DoIsTexture(GLuint client_id);
1097
[email protected]07f54fcc2009-12-22 02:46:301098 // Wrapper for glLinkProgram
1099 void DoLinkProgram(GLuint program);
1100
[email protected]269200b12010-11-18 22:53:061101 // Helper for RegisterSharedIdsCHROMIUM.
1102 void DoRegisterSharedIdsCHROMIUM(
1103 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101104
[email protected]36cef8ce2010-03-16 07:34:451105 // Wrapper for glRenderbufferStorage.
1106 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031107 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451108
[email protected]8e3e0662010-08-23 18:46:301109 // Wrapper for glRenderbufferStorageMultisampleEXT.
1110 void DoRenderbufferStorageMultisample(
1111 GLenum target, GLsizei samples, GLenum internalformat,
1112 GLsizei width, GLsizei height);
1113
[email protected]b273e432010-04-12 17:23:581114 // Wrapper for glReleaseShaderCompiler.
1115 void DoReleaseShaderCompiler() { }
1116
[email protected]3916c97e2010-02-25 03:20:501117 // Wrappers for glTexParameter functions.
1118 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1119 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1120 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1121 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1122
1123 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1124 // spec only these 2 functions can be used to set sampler uniforms.
[email protected]1b0a6752012-02-22 03:44:121125 void DoUniform1i(GLint fake_location, GLint v0);
1126 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1127 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1128 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1129 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101130
1131 // Wrappers for glUniformfv because some drivers don't correctly accept
1132 // bool uniforms.
[email protected]1b0a6752012-02-22 03:44:121133 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1134 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1135 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1136 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501137
[email protected]43c2f1f2011-03-25 18:35:361138 void DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:121139 GLint fake_location, GLsizei count, GLboolean transpose,
1140 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361141 void DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:121142 GLint fake_location, GLsizei count, GLboolean transpose,
1143 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361144 void DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:121145 GLint fake_location, GLsizei count, GLboolean transpose,
1146 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361147
[email protected]b1122982010-05-17 23:04:241148 // Wrappers for glVertexAttrib??
1149 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1150 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1151 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1152 void DoVertexAttrib4f(
1153 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1154 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1155 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1156 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1157 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1158
[email protected]43410e92012-04-20 17:06:281159 // Wrapper for glViewport
1160 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1161
[email protected]07f54fcc2009-12-22 02:46:301162 // Wrapper for glUseProgram
1163 void DoUseProgram(GLuint program);
1164
[email protected]ae51d192010-04-27 00:48:031165 // Wrapper for glValidateProgram.
1166 void DoValidateProgram(GLuint program_client_id);
1167
[email protected]4e8a5b122010-05-08 22:00:101168 // Gets the number of values that will be returned by glGetXXX. Returns
1169 // false if pname is unknown.
1170 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1171
[email protected]96449d2c2009-11-25 00:01:321172 // Gets the GLError through our wrapper.
1173 GLenum GetGLError();
1174
[email protected]1002c2d2011-06-28 22:39:041175 // Gets the GLError and stores it in our wrapper. Effectively
1176 // this lets us peek at the error without losing it.
1177 GLenum PeekGLError();
1178
[email protected]07f54fcc2009-12-22 02:46:301179 // Copies the real GL errors to the wrapper. This is so we can
1180 // make sure there are no native GL errors before calling some GL function
1181 // so that on return we know any error generated was for that specific
1182 // command.
1183 void CopyRealGLErrorsToWrapper();
1184
[email protected]6217d392010-03-25 22:08:351185 // Clear all real GL errors. This is to prevent the client from seeing any
1186 // errors caused by GL calls that it was not responsible for issuing.
1187 void ClearRealGLErrors();
1188
[email protected]07f54fcc2009-12-22 02:46:301189 // Checks if the current program and vertex attributes are valid for drawing.
[email protected]c6aef902012-02-14 03:31:421190 bool IsDrawValid(GLuint max_vertex_accessed, GLsizei primcount);
[email protected]07f54fcc2009-12-22 02:46:301191
[email protected]c13e1da62011-09-09 21:48:301192 // Returns true if successful, simulated will be true if attrib0 was
1193 // simulated.
[email protected]c6aef902012-02-14 03:31:421194 bool SimulateAttrib0(
1195 GLuint max_vertex_accessed, bool* simulated);
[email protected]43410e92012-04-20 17:06:281196 void RestoreStateForAttrib(GLuint attrib);
[email protected]b1122982010-05-17 23:04:241197
[email protected]ef526492010-06-02 23:12:251198 // Returns true if textures were set.
1199 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501200 void RestoreStateForNonRenderableTextures();
1201
[email protected]8fbedc02010-11-18 18:43:401202 // Returns true if GL_FIXED attribs were simulated.
[email protected]c6aef902012-02-14 03:31:421203 bool SimulateFixedAttribs(
1204 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
[email protected]8fbedc02010-11-18 18:43:401205 void RestoreStateForSimulatedFixedAttribs();
1206
[email protected]c6aef902012-02-14 03:31:421207 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1208 // cases (primcount is 0 for non-instanced).
1209 error::Error DoDrawArrays(
1210 bool instanced, GLenum mode, GLint first, GLsizei count,
1211 GLsizei primcount);
1212 error::Error DoDrawElements(
1213 bool instanced, GLenum mode, GLsizei count, GLenum type,
1214 int32 offset, GLsizei primcount);
1215
[email protected]07f54fcc2009-12-22 02:46:301216 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501217 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301218 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501219 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1220 bound_array_buffer_ : bound_element_array_buffer_;
[email protected]a0b78dc2011-11-11 10:43:101221 return info;
[email protected]07f54fcc2009-12-22 02:46:301222 }
1223
[email protected]a93bb842010-02-16 23:03:471224 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501225 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1226 TextureUnit& unit = texture_units_[active_texture_unit_];
1227 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471228 switch (target) {
1229 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501230 info = unit.bound_texture_2d;
1231 break;
[email protected]a93bb842010-02-16 23:03:471232 case GL_TEXTURE_CUBE_MAP:
1233 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1234 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1235 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1236 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1237 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1238 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501239 info = unit.bound_texture_cube_map;
1240 break;
[email protected]61eeb33f2011-07-26 15:30:311241 case GL_TEXTURE_EXTERNAL_OES:
1242 info = unit.bound_texture_external_oes;
1243 break;
[email protected]e51bdf32011-11-23 22:21:461244 case GL_TEXTURE_RECTANGLE_ARB:
1245 info = unit.bound_texture_rectangle_arb;
1246 break;
[email protected]a93bb842010-02-16 23:03:471247 default:
1248 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501249 return NULL;
[email protected]a93bb842010-02-16 23:03:471250 }
[email protected]a0b78dc2011-11-11 10:43:101251 return info;
[email protected]a93bb842010-02-16 23:03:471252 }
1253
[email protected]61eeb33f2011-07-26 15:30:311254 GLenum GetBindTargetForSamplerType(GLenum type) {
1255 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:461256 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1257 switch (type) {
1258 case GL_SAMPLER_2D:
1259 return GL_TEXTURE_2D;
1260 case GL_SAMPLER_CUBE:
1261 return GL_TEXTURE_CUBE_MAP;
1262 case GL_SAMPLER_EXTERNAL_OES:
1263 return GL_TEXTURE_EXTERNAL_OES;
1264 case GL_SAMPLER_2D_RECT_ARB:
1265 return GL_TEXTURE_RECTANGLE_ARB;
1266 }
1267
1268 NOTREACHED();
1269 return 0;
[email protected]61eeb33f2011-07-26 15:30:311270 }
1271
[email protected]8e3e0662010-08-23 18:46:301272 // Gets the framebuffer info for a particular target.
1273 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1274 GLenum target) {
1275 FramebufferManager::FramebufferInfo* info = NULL;
1276 switch (target) {
1277 case GL_FRAMEBUFFER:
1278 case GL_DRAW_FRAMEBUFFER:
1279 info = bound_draw_framebuffer_;
1280 break;
1281 case GL_READ_FRAMEBUFFER:
1282 info = bound_read_framebuffer_;
1283 break;
1284 default:
1285 NOTREACHED();
1286 break;
1287 }
[email protected]a0b78dc2011-11-11 10:43:101288 return info;
[email protected]8e3e0662010-08-23 18:46:301289 }
1290
[email protected]0d6bfdc2011-11-02 01:32:201291 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfoForTarget(
1292 GLenum target) {
1293 RenderbufferManager::RenderbufferInfo* info = NULL;
1294 switch (target) {
1295 case GL_RENDERBUFFER:
1296 info = bound_renderbuffer_;
1297 break;
1298 default:
1299 NOTREACHED();
1300 break;
1301 }
[email protected]a0b78dc2011-11-11 10:43:101302 return info;
[email protected]0d6bfdc2011-11-02 01:32:201303 }
1304
[email protected]f7b85372010-02-03 01:11:371305 // Validates the program and location for a glGetUniform call and returns
1306 // a SizeResult setup to receive the result. Returns true if glGetUniform
1307 // should be called.
1308 bool GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:121309 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:371310 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:121311 error::Error* error, GLint* real_location, GLuint* service_id,
1312 void** result, GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371313
[email protected]1078f912011-12-23 13:12:141314 // Computes the estimated memory used for the backbuffer and passes it to
1315 // the tracing system.
1316 void UpdateBackbufferMemoryAccounting();
1317
[email protected]38d139d2011-07-14 00:38:431318 // Returns true if the context was just lost due to e.g. GL_ARB_robustness.
1319 bool WasContextLost();
1320
[email protected]e51bdf32011-11-23 22:21:461321#if defined(OS_MACOSX)
1322 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1323#endif
1324
[email protected]96449d2c2009-11-25 00:01:321325 // Generate a member function prototype for each command in an automated and
1326 // typesafe way.
1327 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141328 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191329 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321330 const gles2::name& args); \
1331
1332 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1333
1334 #undef GLES2_CMD_OP
1335
[email protected]2f2d7042010-04-14 21:45:581336 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381337 scoped_refptr<gfx::GLSurface> surface_;
1338 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021339
[email protected]a3ded6d2010-10-19 06:44:391340 // The ContextGroup for this decoder uses to track resources.
1341 ContextGroup::Ref group_;
1342
[email protected]6217d392010-03-25 22:08:351343 // A parent decoder can access this decoders saved offscreen frame buffer.
1344 // The parent pointer is reset if the parent is destroyed.
1345 base::WeakPtr<GLES2DecoderImpl> parent_;
1346
[email protected]34ff8b0c2010-10-01 20:06:021347 // Current width and height of the offscreen frame buffer.
1348 gfx::Size offscreen_size_;
1349
[email protected]96449d2c2009-11-25 00:01:321350 // Current GL error bits.
1351 uint32 error_bits_;
1352
[email protected]96449d2c2009-11-25 00:01:321353 // Util to help with GL.
1354 GLES2Util util_;
1355
1356 // pack alignment as last set by glPixelStorei
1357 GLint pack_alignment_;
1358
1359 // unpack alignment as last set by glPixelStorei
1360 GLint unpack_alignment_;
1361
[email protected]43410e92012-04-20 17:06:281362 // unpack flip y as last set by glPixelStorei
1363 bool unpack_flip_y_;
1364
1365 // unpack premultiply alpha as last set by glPixelStorei
1366 bool unpack_premultiply_alpha_;
1367
[email protected]96449d2c2009-11-25 00:01:321368 // The currently bound array buffer. If this is 0 it is illegal to call
1369 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501370 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321371
1372 // The currently bound element array buffer. If this is 0 it is illegal
1373 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501374 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301375
[email protected]f39f4b3f2010-05-12 17:04:081376 // Class that manages vertex attribs.
[email protected]3757a372012-01-19 05:20:441377 scoped_ptr<VertexAttribManager> vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301378
[email protected]b1122982010-05-17 23:04:241379 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1380 GLuint attrib_0_buffer_id_;
1381
1382 // The value currently in attrib_0.
1383 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1384
[email protected]fc753442011-02-04 19:49:491385 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1386 bool attrib_0_buffer_matches_value_;
1387
[email protected]b1122982010-05-17 23:04:241388 // The size of attrib 0.
1389 GLsizei attrib_0_size_;
1390
[email protected]8fbedc02010-11-18 18:43:401391 // The buffer used to simulate GL_FIXED attribs.
1392 GLuint fixed_attrib_buffer_id_;
1393
1394 // The size of fiixed attrib buffer.
1395 GLsizei fixed_attrib_buffer_size_;
1396
[email protected]3916c97e2010-02-25 03:20:501397 // Current active texture by 0 - n index.
1398 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1399 // be 2.
1400 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301401
[email protected]3916c97e2010-02-25 03:20:501402 // Which textures are bound to texture units through glActiveTexture.
1403 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471404
[email protected]3a2e7c7b2010-08-06 01:12:281405 // state saved for clearing so we can clear render buffers and then
1406 // restore to these values.
1407 GLclampf clear_red_;
1408 GLclampf clear_green_;
1409 GLclampf clear_blue_;
1410 GLclampf clear_alpha_;
1411 GLboolean mask_red_;
1412 GLboolean mask_green_;
1413 GLboolean mask_blue_;
1414 GLboolean mask_alpha_;
1415 GLint clear_stencil_;
1416 GLuint mask_stencil_front_;
1417 GLuint mask_stencil_back_;
1418 GLclampf clear_depth_;
1419 GLboolean mask_depth_;
[email protected]0a1e9ad2012-05-04 21:13:031420 bool enable_blend_;
[email protected]43410e92012-04-20 17:06:281421 bool enable_cull_face_;
[email protected]3a2e7c7b2010-08-06 01:12:281422 bool enable_scissor_test_;
[email protected]297ca1c2011-06-20 23:08:461423 bool enable_depth_test_;
1424 bool enable_stencil_test_;
1425 bool state_dirty_;
[email protected]3a2e7c7b2010-08-06 01:12:281426
[email protected]1d32bc82010-01-13 22:06:461427 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501428 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301429
[email protected]8e3e0662010-08-23 18:46:301430 // The currently bound framebuffers
1431 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1432 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561433
1434 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081435 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561436
[email protected]b9363b22010-06-09 22:06:151437 // The offscreen frame buffer that the client renders to. With EGL, the
1438 // depth and stencil buffers are separate. With regular GL there is a single
1439 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1440 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351441 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1442 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021443 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151444 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1445 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021446 GLenum offscreen_target_color_format_;
1447 GLenum offscreen_target_depth_format_;
1448 GLenum offscreen_target_stencil_format_;
1449 GLsizei offscreen_target_samples_;
[email protected]8a61d872012-01-20 12:43:561450 GLboolean offscreen_target_buffer_preserved_;
[email protected]6217d392010-03-25 22:08:351451
[email protected]de26b3c2011-08-03 21:54:271452 // The copy that is saved when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021453 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351454 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]8a61d872012-01-20 12:43:561455 TextureManager::TextureInfo::Ref offscreen_saved_color_texture_info_;
[email protected]de26b3c2011-08-03 21:54:271456
1457 // The copy that is used as the destination for multi-sample resolves.
1458 scoped_ptr<FrameBuffer> offscreen_resolved_frame_buffer_;
1459 scoped_ptr<Texture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051460 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351461
[email protected]882ba1e22012-03-08 19:02:531462 scoped_ptr<QueryManager> query_manager_;
1463 QueryManager::Query::Ref current_query_;
1464
[email protected]9d37f062011-11-22 01:24:521465 base::Callback<void(gfx::Size)> resize_callback_;
[email protected]22f320a2011-08-30 01:17:001466
[email protected]6b6e7ee2011-12-13 08:04:521467 MsgCallback msg_callback_;
[email protected]43f28f832010-02-03 02:28:481468
[email protected]b0af4f52011-09-28 22:04:421469 StreamTextureManager* stream_texture_manager_;
1470
[email protected]32fe9aa2011-01-21 23:47:131471 // The format of the back buffer_
1472 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461473 bool back_buffer_has_depth_;
1474 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131475
[email protected]473c01ccb2011-06-07 01:33:301476 bool teximage2d_faster_than_texsubimage2d_;
1477 bool bufferdata_faster_than_buffersubdata_;
1478
[email protected]8eee29c2010-04-29 03:38:291479 // The last error message set.
1480 std::string last_error_;
1481
[email protected]fa20ec82012-05-04 04:02:481482 int error_count_;
1483
[email protected]a3a93e7b2010-08-28 00:48:561484 // The current decoder error.
1485 error::Error current_decoder_error_;
1486
[email protected]b1d2dcb2010-05-17 19:24:181487 bool use_shader_translator_;
[email protected]a550584e2010-09-17 18:01:451488 scoped_ptr<ShaderTranslator> vertex_translator_;
1489 scoped_ptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181490
[email protected]e82fb792011-09-22 00:33:291491 DisallowedFeatures disallowed_features_;
[email protected]c410da802011-03-14 19:17:411492
[email protected]915a59a12010-09-30 21:29:111493 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051494 const Validators* validators_;
[email protected]80eb6b52012-01-19 00:14:411495 FeatureInfo::Ref feature_info_;
[email protected]9438b012010-06-15 22:55:051496
[email protected]b493ee622011-04-13 23:52:001497 // This indicates all the following texSubImage2D calls that are part of the
1498 // failed texImage2D call should be ignored.
1499 bool tex_image_2d_failed_;
1500
[email protected]65225772011-05-12 21:10:241501 int frame_number_;
1502
[email protected]38d139d2011-07-14 00:38:431503 bool has_arb_robustness_;
1504 GLenum reset_status_;
1505
[email protected]75c023c2011-08-22 23:54:511506 bool needs_mac_nvidia_driver_workaround_;
[email protected]a2a0fe762011-09-20 00:59:121507 bool needs_glsl_built_in_function_emulation_;
[email protected]75c023c2011-08-22 23:54:511508
[email protected]f0d74742011-10-03 16:31:041509 // These flags are used to override the state of the shared feature_info_
1510 // member. Because the same FeatureInfo instance may be shared among many
1511 // contexts, the assumptions on the availablity of extensions in WebGL
1512 // contexts may be broken. These flags override the shared state to preserve
1513 // WebGL semantics.
1514 bool force_webgl_glsl_validation_;
1515 bool derivatives_explicitly_enabled_;
1516
[email protected]062c38b2012-01-18 03:25:101517 bool compile_shader_always_succeeds_;
1518
[email protected]c892a4e12012-05-08 18:20:191519 bool disable_workarounds_;
1520
[email protected]e51bdf32011-11-23 22:21:461521#if defined(OS_MACOSX)
1522 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1523 TextureToIOSurfaceMap texture_to_io_surface_map_;
1524#endif
1525
[email protected]c826d732012-02-09 04:40:261526 typedef std::vector<GLES2DecoderImpl*> ChildList;
1527 ChildList children_;
1528
[email protected]43410e92012-04-20 17:06:281529 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1530
1531 // Cached values of the currently assigned viewport dimensions.
1532 GLint viewport_x_, viewport_y_;
1533 GLsizei viewport_width_, viewport_height_;
1534 GLsizei viewport_max_width_, viewport_max_height_;
1535
[email protected]96449d2c2009-11-25 00:01:321536 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1537};
1538
[email protected]6217d392010-03-25 22:08:351539ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1540 : decoder_(decoder) {
1541 decoder_->CopyRealGLErrorsToWrapper();
1542}
1543
1544ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1545 decoder_->ClearRealGLErrors();
1546}
1547
1548ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1549 GLuint id)
1550 : decoder_(decoder) {
1551 ScopedGLErrorSuppressor suppressor(decoder_);
1552
1553 // TODO(apatrick): Check if there are any other states that need to be reset
1554 // before binding a new texture.
1555 glActiveTexture(GL_TEXTURE0);
1556 glBindTexture(GL_TEXTURE_2D, id);
1557}
1558
1559ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1560 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301561 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351562}
1563
1564ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1565 GLuint id)
1566 : decoder_(decoder) {
1567 ScopedGLErrorSuppressor suppressor(decoder_);
1568 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1569}
1570
1571ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1572 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301573 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351574}
1575
1576ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1577 GLuint id)
1578 : decoder_(decoder) {
1579 ScopedGLErrorSuppressor suppressor(decoder_);
1580 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1581}
1582
1583ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1584 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301585 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351586}
1587
[email protected]34ff8b0c2010-10-01 20:06:021588ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271589 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521590 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021591 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1592 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]c0701082011-04-20 00:34:521593 (!decoder_->bound_read_framebuffer_.get() ||
1594 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021595 if (!resolve_and_bind_)
1596 return;
1597
1598 ScopedGLErrorSuppressor suppressor(decoder_);
1599 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1600 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271601 GLuint targetid;
1602 if (internal) {
1603 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1604 decoder_->offscreen_resolved_frame_buffer_.reset(
1605 new FrameBuffer(decoder_));
1606 decoder_->offscreen_resolved_frame_buffer_->Create();
1607 decoder_->offscreen_resolved_color_texture_.reset(new Texture(decoder_));
1608 decoder_->offscreen_resolved_color_texture_->Create();
1609
1610 DCHECK(decoder_->offscreen_saved_color_format_);
1611 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1612 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_);
[email protected]de26b3c2011-08-03 21:54:271613 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1614 decoder_->offscreen_resolved_color_texture_.get());
1615 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1616 GL_FRAMEBUFFER_COMPLETE) {
1617 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1618 << "because offscreen resolved FBO was incomplete.";
1619 return;
1620 }
1621 }
1622 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1623 } else {
1624 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1625 }
1626 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021627 const int width = decoder_->offscreen_size_.width();
1628 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181629 glDisable(GL_SCISSOR_TEST);
[email protected]57edfdad2012-02-07 04:57:151630 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021631 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1632 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1633 } else {
1634 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1635 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1636 }
[email protected]de26b3c2011-08-03 21:54:271637 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021638}
1639
1640ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1641 if (!resolve_and_bind_)
1642 return;
1643
1644 ScopedGLErrorSuppressor suppressor(decoder_);
1645 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181646 if (decoder_->enable_scissor_test_) {
1647 glEnable(GL_SCISSOR_TEST);
1648 }
[email protected]34ff8b0c2010-10-01 20:06:021649}
1650
[email protected]6217d392010-03-25 22:08:351651Texture::Texture(GLES2DecoderImpl* decoder)
1652 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141653 id_(0),
1654 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351655}
1656
1657Texture::~Texture() {
1658 // This does not destroy the render texture because that would require that
1659 // the associated GL context was current. Just check that it was explicitly
1660 // destroyed.
1661 DCHECK_EQ(id_, 0u);
1662}
1663
1664void Texture::Create() {
1665 ScopedGLErrorSuppressor suppressor(decoder_);
1666 Destroy();
1667 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581668 ScopedTexture2DBinder binder(decoder_, id_);
1669 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1670 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1671 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1672 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]62788802011-10-03 17:57:161673
1674 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1675 // never called on an offscreen context, no data will ever be uploaded to the
1676 // saved offscreen color texture (it is deferred until to when SwapBuffers
1677 // is called). My idea is that some nvidia drivers might have a bug where
1678 // deleting a texture that has never been populated might cause a
1679 // crash.
1680 glTexImage2D(
1681 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
[email protected]1078f912011-12-23 13:12:141682 estimated_size_ = 16u * 16u * 4u;
1683 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351684}
1685
[email protected]34ff8b0c2010-10-01 20:06:021686bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351687 DCHECK_NE(id_, 0u);
1688 ScopedGLErrorSuppressor suppressor(decoder_);
1689 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]6217d392010-03-25 22:08:351690
[email protected]f0e6a34f2012-01-04 20:53:401691 WrappedTexImage2D(GL_TEXTURE_2D,
1692 0, // mip level
1693 format,
1694 size.width(),
1695 size.height(),
1696 0, // border
1697 format,
1698 GL_UNSIGNED_BYTE,
1699 NULL);
[email protected]6217d392010-03-25 22:08:351700
[email protected]d37231fa2010-04-09 21:16:021701 size_ = size;
1702
[email protected]1078f912011-12-23 13:12:141703 bool success = glGetError() == GL_NO_ERROR;
1704 if (success) {
1705 uint32 image_size = 0;
[email protected]3458a64a2012-04-10 17:39:341706 GLES2Util::ComputeImageDataSizes(
1707 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 4, &image_size,
1708 NULL, NULL);
[email protected]1078f912011-12-23 13:12:141709 estimated_size_ = image_size;
1710 decoder_->UpdateBackbufferMemoryAccounting();
1711 }
1712 return success;
[email protected]6217d392010-03-25 22:08:351713}
1714
[email protected]3a4d0c52011-06-29 23:11:581715void Texture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351716 DCHECK_NE(id_, 0u);
1717 ScopedGLErrorSuppressor suppressor(decoder_);
1718 ScopedTexture2DBinder binder(decoder_, id_);
1719 glCopyTexImage2D(GL_TEXTURE_2D,
1720 0, // level
[email protected]3a4d0c52011-06-29 23:11:581721 format,
[email protected]6217d392010-03-25 22:08:351722 0, 0,
1723 size.width(),
1724 size.height(),
1725 0); // border
1726}
1727
1728void Texture::Destroy() {
1729 if (id_ != 0) {
1730 ScopedGLErrorSuppressor suppressor(decoder_);
1731 glDeleteTextures(1, &id_);
1732 id_ = 0;
[email protected]1078f912011-12-23 13:12:141733 estimated_size_ = 0;
1734 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351735 }
1736}
1737
[email protected]97872062010-11-03 19:07:051738void Texture::Invalidate() {
1739 id_ = 0;
1740}
1741
[email protected]6217d392010-03-25 22:08:351742RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1743 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141744 id_(0),
1745 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351746}
1747
1748RenderBuffer::~RenderBuffer() {
1749 // This does not destroy the render buffer because that would require that
1750 // the associated GL context was current. Just check that it was explicitly
1751 // destroyed.
1752 DCHECK_EQ(id_, 0u);
1753}
1754
1755void RenderBuffer::Create() {
1756 ScopedGLErrorSuppressor suppressor(decoder_);
1757 Destroy();
1758 glGenRenderbuffersEXT(1, &id_);
1759}
1760
[email protected]34ff8b0c2010-10-01 20:06:021761bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1762 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351763 ScopedGLErrorSuppressor suppressor(decoder_);
1764 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021765 if (samples <= 1) {
1766 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1767 format,
1768 size.width(),
1769 size.height());
1770 } else {
[email protected]57edfdad2012-02-07 04:57:151771 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021772 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1773 samples,
1774 format,
1775 size.width(),
1776 size.height());
1777 } else {
1778 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1779 samples,
1780 format,
1781 size.width(),
1782 size.height());
1783 }
1784 }
[email protected]1078f912011-12-23 13:12:141785 bool success = glGetError() == GL_NO_ERROR;
1786 if (success) {
1787 estimated_size_ = size.width() * size.height() * samples *
1788 GLES2Util::RenderbufferBytesPerPixel(format);
1789 decoder_->UpdateBackbufferMemoryAccounting();
1790 }
1791 return success;
[email protected]6217d392010-03-25 22:08:351792}
1793
1794void RenderBuffer::Destroy() {
1795 if (id_ != 0) {
1796 ScopedGLErrorSuppressor suppressor(decoder_);
1797 glDeleteRenderbuffersEXT(1, &id_);
1798 id_ = 0;
[email protected]1078f912011-12-23 13:12:141799 estimated_size_ = 0;
1800 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351801 }
1802}
1803
[email protected]97872062010-11-03 19:07:051804void RenderBuffer::Invalidate() {
1805 id_ = 0;
1806}
1807
[email protected]6217d392010-03-25 22:08:351808FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1809 : decoder_(decoder),
1810 id_(0) {
1811}
1812
1813FrameBuffer::~FrameBuffer() {
1814 // This does not destroy the frame buffer because that would require that
1815 // the associated GL context was current. Just check that it was explicitly
1816 // destroyed.
1817 DCHECK_EQ(id_, 0u);
1818}
1819
1820void FrameBuffer::Create() {
1821 ScopedGLErrorSuppressor suppressor(decoder_);
1822 Destroy();
1823 glGenFramebuffersEXT(1, &id_);
1824}
1825
1826void FrameBuffer::AttachRenderTexture(Texture* texture) {
1827 DCHECK_NE(id_, 0u);
1828 ScopedGLErrorSuppressor suppressor(decoder_);
1829 ScopedFrameBufferBinder binder(decoder_, id_);
1830 GLuint attach_id = texture ? texture->id() : 0;
1831 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1832 GL_COLOR_ATTACHMENT0,
1833 GL_TEXTURE_2D,
1834 attach_id,
1835 0);
1836}
1837
[email protected]b9363b22010-06-09 22:06:151838void FrameBuffer::AttachRenderBuffer(GLenum target,
1839 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351840 DCHECK_NE(id_, 0u);
1841 ScopedGLErrorSuppressor suppressor(decoder_);
1842 ScopedFrameBufferBinder binder(decoder_, id_);
1843 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1844 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151845 target,
[email protected]6217d392010-03-25 22:08:351846 GL_RENDERBUFFER,
1847 attach_id);
1848}
1849
[email protected]6217d392010-03-25 22:08:351850void FrameBuffer::Destroy() {
1851 if (id_ != 0) {
1852 ScopedGLErrorSuppressor suppressor(decoder_);
1853 glDeleteFramebuffersEXT(1, &id_);
1854 id_ = 0;
1855 }
1856}
1857
[email protected]97872062010-11-03 19:07:051858void FrameBuffer::Invalidate() {
1859 id_ = 0;
1860}
1861
[email protected]6217d392010-03-25 22:08:351862GLenum FrameBuffer::CheckStatus() {
1863 DCHECK_NE(id_, 0u);
1864 ScopedGLErrorSuppressor suppressor(decoder_);
1865 ScopedFrameBufferBinder binder(decoder_, id_);
1866 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1867}
1868
[email protected]aa7666122011-09-02 19:45:521869GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1870 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321871}
1872
[email protected]aa7666122011-09-02 19:45:521873GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391874 : GLES2Decoder(),
[email protected]3b1ecc262011-08-03 22:49:571875 group_(group),
[email protected]96449d2c2009-11-25 00:01:321876 error_bits_(0),
[email protected]96449d2c2009-11-25 00:01:321877 pack_alignment_(4),
1878 unpack_alignment_(4),
[email protected]43410e92012-04-20 17:06:281879 unpack_flip_y_(false),
1880 unpack_premultiply_alpha_(false),
[email protected]b1122982010-05-17 23:04:241881 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491882 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241883 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401884 fixed_attrib_buffer_id_(0),
1885 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501886 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281887 clear_red_(0),
1888 clear_green_(0),
1889 clear_blue_(0),
1890 clear_alpha_(0),
1891 mask_red_(true),
1892 mask_green_(true),
1893 mask_blue_(true),
1894 mask_alpha_(true),
1895 clear_stencil_(0),
1896 mask_stencil_front_(-1),
1897 mask_stencil_back_(-1),
1898 clear_depth_(1.0f),
1899 mask_depth_(true),
[email protected]0a1e9ad2012-05-04 21:13:031900 enable_blend_(false),
[email protected]43410e92012-04-20 17:06:281901 enable_cull_face_(false),
[email protected]3a2e7c7b2010-08-06 01:12:281902 enable_scissor_test_(false),
[email protected]297ca1c2011-06-20 23:08:461903 enable_depth_test_(false),
1904 enable_stencil_test_(false),
1905 state_dirty_(true),
[email protected]34ff8b0c2010-10-01 20:06:021906 offscreen_target_color_format_(0),
1907 offscreen_target_depth_format_(0),
1908 offscreen_target_stencil_format_(0),
1909 offscreen_target_samples_(0),
[email protected]8a61d872012-01-20 12:43:561910 offscreen_target_buffer_preserved_(true),
[email protected]97872062010-11-03 19:07:051911 offscreen_saved_color_format_(0),
[email protected]b0af4f52011-09-28 22:04:421912 stream_texture_manager_(NULL),
[email protected]32fe9aa2011-01-21 23:47:131913 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:461914 back_buffer_has_depth_(false),
1915 back_buffer_has_stencil_(false),
[email protected]473c01ccb2011-06-07 01:33:301916 teximage2d_faster_than_texsubimage2d_(true),
1917 bufferdata_faster_than_buffersubdata_(true),
[email protected]fa20ec82012-05-04 04:02:481918 error_count_(0),
[email protected]a3a93e7b2010-08-28 00:48:561919 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051920 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111921 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001922 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241923 tex_image_2d_failed_(false),
[email protected]38d139d2011-07-14 00:38:431924 frame_number_(0),
1925 has_arb_robustness_(false),
[email protected]75c023c2011-08-22 23:54:511926 reset_status_(GL_NO_ERROR),
[email protected]a2a0fe762011-09-20 00:59:121927 needs_mac_nvidia_driver_workaround_(false),
[email protected]f0d74742011-10-03 16:31:041928 needs_glsl_built_in_function_emulation_(false),
1929 force_webgl_glsl_validation_(false),
[email protected]062c38b2012-01-18 03:25:101930 derivatives_explicitly_enabled_(false),
[email protected]43410e92012-04-20 17:06:281931 compile_shader_always_succeeds_(false),
[email protected]c892a4e12012-05-08 18:20:191932 disable_workarounds_(
1933 CommandLine::ForCurrentProcess()->HasSwitch(
1934 switches::kDisableGpuDriverBugWorkarounds)),
[email protected]43410e92012-04-20 17:06:281935 viewport_x_(0),
1936 viewport_y_(0),
1937 viewport_width_(0),
1938 viewport_height_(0),
1939 viewport_max_width_(0),
1940 viewport_max_height_(0) {
[email protected]3b1ecc262011-08-03 22:49:571941 DCHECK(group);
1942
[email protected]b1122982010-05-17 23:04:241943 attrib_0_value_.v[0] = 0.0f;
1944 attrib_0_value_.v[1] = 0.0f;
1945 attrib_0_value_.v[2] = 0.0f;
1946 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151947
[email protected]c2f8c8402010-12-06 18:07:241948 // The shader translator is used for WebGL even when running on EGL
1949 // because additional restrictions are needed (like only enabling
1950 // GL_OES_standard_derivatives on demand). It is used for the unit
1951 // tests because
1952 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1953 // empty string to CompileShader and this is not a valid shader.
1954 // TODO(apatrick): fix this test.
1955 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:041956 !feature_info_->feature_flags().chromium_webglsl &&
1957 !force_webgl_glsl_validation_) ||
[email protected]39ba4f02012-03-26 01:16:001958 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
1959 CommandLine::ForCurrentProcess()->HasSwitch(
1960 switches::kDisableGLSLTranslator)) {
[email protected]b9363b22010-06-09 22:06:151961 use_shader_translator_ = false;
1962 }
[email protected]473c01ccb2011-06-07 01:33:301963
1964 // TODO(gman): Consider setting these based on GPU and/or driver.
1965 if (IsAngle()) {
1966 teximage2d_faster_than_texsubimage2d_ = false;
1967 bufferdata_faster_than_buffersubdata_ = false;
1968 }
[email protected]96449d2c2009-11-25 00:01:321969}
1970
[email protected]80eb6b52012-01-19 00:14:411971GLES2DecoderImpl::~GLES2DecoderImpl() {
1972}
1973
[email protected]c410da802011-03-14 19:17:411974bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:381975 const scoped_refptr<gfx::GLSurface>& surface,
1976 const scoped_refptr<gfx::GLContext>& context,
[email protected]069944672012-04-25 20:52:231977 bool offscreen,
[email protected]c410da802011-03-14 19:17:411978 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:291979 const DisallowedFeatures& disallowed_features,
[email protected]c410da802011-03-14 19:17:411980 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:241981 const std::vector<int32>& attribs) {
[email protected]4bedba72010-04-20 22:08:541982 DCHECK(context);
[email protected]66791e382010-07-14 20:48:301983 DCHECK(!context_.get());
1984
[email protected]e844ae22012-01-14 03:36:261985 if (CommandLine::ForCurrentProcess()->HasSwitch(
1986 switches::kEnableGPUDebugging)) {
1987 set_debug(true);
1988 }
1989
[email protected]39ba4f02012-03-26 01:16:001990 if (CommandLine::ForCurrentProcess()->HasSwitch(
1991 switches::kEnableGPUCommandLogging)) {
1992 set_log_commands(true);
1993 }
1994
[email protected]062c38b2012-01-18 03:25:101995 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
1996 switches::kCompileShaderAlwaysSucceeds);
1997
[email protected]fbe20372011-06-01 01:46:381998 // Take ownership of the GLSurface. TODO(apatrick): once the parent / child
1999 // context is retired, the decoder should not take an initial surface as
2000 // an argument to this function.
2001 // Maybe create a short lived offscreen GLSurface for the purpose of
2002 // initializing the decoder's GLContext.
2003 surface_ = surface;
[email protected]f62a5ab2011-05-23 20:34:152004
[email protected]66791e382010-07-14 20:48:302005 // Take ownership of the GLContext.
[email protected]fbe20372011-06-01 01:46:382006 context_ = context;
[email protected]d37231fa2010-04-09 21:16:022007
[email protected]246a70452010-03-05 21:53:502008 if (!MakeCurrent()) {
[email protected]d0498742010-09-20 20:27:012009 LOG(ERROR) << "GLES2DecoderImpl::Initialize failed because "
2010 << "MakeCurrent failed.";
[email protected]1871a092011-10-10 21:46:422011 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]246a70452010-03-05 21:53:502012 Destroy();
2013 return false;
[email protected]eb54a562010-01-20 21:55:182014 }
2015
[email protected]e82fb792011-09-22 00:33:292016 if (!group_->Initialize(disallowed_features, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:222017 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:392018 << "failed to initialize.";
[email protected]1871a092011-10-10 21:46:422019 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]a3ded6d2010-10-19 06:44:392020 Destroy();
[email protected]ae1741092010-11-17 19:16:032021 return false;
[email protected]a3ded6d2010-10-19 06:44:392022 }
[email protected]b64c24952012-04-19 03:20:272023 CHECK_GL_ERROR();
[email protected]43410e92012-04-20 17:06:282024
2025 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
2026 copy_texture_CHROMIUM_->Initialize();
2027 CHECK_GL_ERROR();
2028
[email protected]e82fb792011-09-22 00:33:292029 disallowed_features_ = disallowed_features;
[email protected]246a70452010-03-05 21:53:502030
[email protected]3757a372012-01-19 05:20:442031 vertex_attrib_manager_.reset(new VertexAttribManager());
2032 vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:322033
[email protected]c45f1972012-03-14 07:27:362034 query_manager_.reset(new QueryManager(this, feature_info_->feature_flags(
2035 ).use_arb_occlusion_query2_for_occlusion_query_boolean));
[email protected]882ba1e22012-03-08 19:02:532036
[email protected]302ce6d2011-07-07 23:28:112037 util_.set_num_compressed_texture_formats(
2038 validators_->compressed_texture_format.GetValues().size());
2039
[email protected]1071e572011-02-09 20:00:122040 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2041 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2042 // OpenGL ES 2.0 does not have this issue.
2043 glEnableVertexAttribArray(0);
2044 }
[email protected]b1122982010-05-17 23:04:242045 glGenBuffersARB(1, &attrib_0_buffer_id_);
2046 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2047 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2048 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:402049 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:082050
[email protected]246a70452010-03-05 21:53:502051 texture_units_.reset(
2052 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:152053 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:492054 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:312055 // We want the last bind to be 2D.
2056 TextureManager::TextureInfo* info;
2057 if (feature_info_->feature_flags().oes_egl_image_external) {
2058 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_EXTERNAL_OES);
2059 texture_units_[tt].bound_texture_external_oes = info;
2060 glBindTexture(GL_TEXTURE_EXTERNAL_OES, info->service_id());
2061 }
[email protected]e51bdf32011-11-23 22:21:462062 if (feature_info_->feature_flags().arb_texture_rectangle) {
2063 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_RECTANGLE_ARB);
2064 texture_units_[tt].bound_texture_rectangle_arb = info;
2065 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, info->service_id());
2066 }
[email protected]61eeb33f2011-07-26 15:30:312067 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:492068 texture_units_[tt].bound_texture_cube_map = info;
2069 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
2070 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2071 texture_units_[tt].bound_texture_2d = info;
2072 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:152073 }
[email protected]00f893d2010-08-24 18:55:492074 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:502075 CHECK_GL_ERROR();
2076
[email protected]297ca1c2011-06-20 23:08:462077 ContextCreationAttribParser attrib_parser;
2078 if (!attrib_parser.Parse(attribs))
2079 return false;
[email protected]41c56362011-06-14 16:47:432080
[email protected]297ca1c2011-06-20 23:08:462081 // These are NOT if the back buffer has these proprorties. They are
2082 // if we want the command buffer to enforce them regardless of what
2083 // the real backbuffer is assuming the real back buffer gives us more than
2084 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2085 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2086 // can't do anything about that.
2087
2088 GLint v = 0;
2089 glGetIntegerv(GL_ALPHA_BITS, &v);
2090 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2091 // user requested RGB then RGB. If the user did not specify a preference than
2092 // use whatever we were given. Same for DEPTH and STENCIL.
2093 back_buffer_color_format_ =
2094 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2095 glGetIntegerv(GL_DEPTH_BITS, &v);
2096 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2097 glGetIntegerv(GL_STENCIL_BITS, &v);
2098 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2099
[email protected]069944672012-04-25 20:52:232100 if (offscreen) {
[email protected]34ff8b0c2010-10-01 20:06:022101 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:542102 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:022103 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
2104 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:432105 // max_sample_count must be initialized to a sane value. If
2106 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2107 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:022108 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2109 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2110 max_sample_count);
2111 } else {
2112 offscreen_target_samples_ = 1;
2113 }
[email protected]8a61d872012-01-20 12:43:562114 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
[email protected]34ff8b0c2010-10-01 20:06:022115
2116 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2117 const bool rgb8_supported =
2118 context_->HasExtension("GL_OES_rgb8_rgba8");
2119 // The only available default render buffer formats in GLES2 have very
2120 // little precision. Don't enable multisampling unless 8-bit render
2121 // buffer formats are available--instead fall back to 8-bit textures.
2122 if (rgb8_supported && offscreen_target_samples_ > 1) {
2123 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2124 GL_RGBA8 : GL_RGB8;
2125 } else {
2126 offscreen_target_samples_ = 1;
2127 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2128 GL_RGBA : GL_RGB;
2129 }
2130
2131 // ANGLE only supports packed depth/stencil formats, so use it if it is
2132 // available.
2133 const bool depth24_stencil8_supported =
2134 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272135 VLOG(1) << "GL_OES_packed_depth_stencil "
2136 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:002137 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2138 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022139 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2140 offscreen_target_stencil_format_ = 0;
2141 } else {
2142 // It may be the case that this depth/stencil combination is not
2143 // supported, but this will be checked later by CheckFramebufferStatus.
2144 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2145 GL_DEPTH_COMPONENT16 : 0;
2146 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2147 GL_STENCIL_INDEX8 : 0;
2148 }
2149 } else {
2150 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2151 GL_RGBA : GL_RGB;
2152
2153 // If depth is requested at all, use the packed depth stencil format if
2154 // it's available, as some desktop GL drivers don't support any non-packed
2155 // formats for depth attachments.
2156 const bool depth24_stencil8_supported =
2157 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272158 VLOG(1) << "GL_EXT_packed_depth_stencil "
2159 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:022160
[email protected]71ee3642010-10-14 18:08:002161 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2162 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022163 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2164 offscreen_target_stencil_format_ = 0;
2165 } else {
2166 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2167 GL_DEPTH_COMPONENT : 0;
2168 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2169 GL_STENCIL_INDEX : 0;
2170 }
2171 }
2172
[email protected]97872062010-11-03 19:07:052173 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2174 GL_RGBA : GL_RGB;
2175
[email protected]6217d392010-03-25 22:08:352176 // Create the target frame buffer. This is the one that the client renders
2177 // directly to.
2178 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
2179 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022180 // Due to GLES2 format limitations, either the color texture (for
2181 // non-multisampling) or the color render buffer (for multisampling) will be
2182 // attached to the offscreen frame buffer. The render buffer has more
2183 // limited formats available to it, but the texture can't do multisampling.
2184 if (IsOffscreenBufferMultisampled()) {
2185 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
2186 offscreen_target_color_render_buffer_->Create();
2187 } else {
2188 offscreen_target_color_texture_.reset(new Texture(this));
2189 offscreen_target_color_texture_->Create();
2190 }
2191 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152192 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022193 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152194 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:352195
2196 // Create the saved offscreen texture. The target frame buffer is copied
2197 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:022198 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
2199 offscreen_saved_frame_buffer_->Create();
2200 //
[email protected]6217d392010-03-25 22:08:352201 offscreen_saved_color_texture_.reset(new Texture(this));
2202 offscreen_saved_color_texture_->Create();
2203
[email protected]6217d392010-03-25 22:08:352204 // Allocate the render buffers at their initial size and check the status
2205 // of the frame buffers is okay.
[email protected]799b4b22011-08-22 17:09:592206 if (!ResizeOffscreenFrameBuffer(size)) {
[email protected]d0498742010-09-20 20:27:012207 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]6217d392010-03-25 22:08:352208 Destroy();
2209 return false;
2210 }
2211
2212 // Bind to the new default frame buffer (the offscreen target frame buffer).
2213 // This should now be associated with ID zero.
2214 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2215 }
2216
[email protected]295faf4b2012-01-25 23:31:412217 // Clear the backbuffer.
2218 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2219
[email protected]76a0ee102010-04-07 21:03:042220 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2221 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2222 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372223 // mailing list archives. It also implicitly enables the desktop GL
2224 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2225 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152226 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2227 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372228 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152229 }
[email protected]de17df392010-04-23 21:09:412230
[email protected]38d139d2011-07-14 00:38:432231 has_arb_robustness_ = context->HasExtension("GL_ARB_robustness");
2232
[email protected]c892a4e12012-05-08 18:20:192233 if (!disable_workarounds_) {
[email protected]75c023c2011-08-22 23:54:512234#if defined(OS_MACOSX)
[email protected]a2a0fe762011-09-20 00:59:122235 const char* vendor_str = reinterpret_cast<const char*>(
2236 glGetString(GL_VENDOR));
2237 needs_mac_nvidia_driver_workaround_ =
2238 vendor_str && strstr(vendor_str, "NVIDIA");
2239 needs_glsl_built_in_function_emulation_ =
2240 vendor_str && (strstr(vendor_str, "ATI") || strstr(vendor_str, "AMD"));
[email protected]75c023c2011-08-22 23:54:512241#endif
[email protected]a2a0fe762011-09-20 00:59:122242 }
[email protected]75c023c2011-08-22 23:54:512243
[email protected]c2f8c8402010-12-06 18:07:242244 if (!InitializeShaderTranslator()) {
2245 return false;
[email protected]de17df392010-04-23 21:09:412246 }
[email protected]76a0ee102010-04-07 21:03:042247
[email protected]5904806b2012-05-08 18:10:222248 viewport_width_ = size.width();
2249 viewport_height_ = size.height();
2250 glViewport(viewport_x_, viewport_y_, viewport_width_, viewport_height_);
[email protected]43410e92012-04-20 17:06:282251
[email protected]5904806b2012-05-08 18:10:222252 GLint viewport_params[4] = { 0 };
[email protected]43410e92012-04-20 17:06:282253 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2254 viewport_max_width_ = viewport_params[0];
[email protected]5904806b2012-05-08 18:10:222255 viewport_max_height_ = viewport_params[1];
[email protected]43410e92012-04-20 17:06:282256
[email protected]246a70452010-03-05 21:53:502257 return true;
[email protected]96449d2c2009-11-25 00:01:322258}
2259
[email protected]302ce6d2011-07-07 23:28:112260void GLES2DecoderImpl::UpdateCapabilities() {
2261 util_.set_num_compressed_texture_formats(
2262 validators_->compressed_texture_format.GetValues().size());
2263 util_.set_num_shader_binary_formats(
2264 validators_->shader_binary_format.GetValues().size());
2265}
2266
[email protected]c2f8c8402010-12-06 18:07:242267bool GLES2DecoderImpl::InitializeShaderTranslator() {
2268 // Re-check the state of use_shader_translator_ each time this is called.
2269 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:042270 (feature_info_->feature_flags().chromium_webglsl ||
2271 force_webgl_glsl_validation_) &&
[email protected]c2f8c8402010-12-06 18:07:242272 !use_shader_translator_) {
2273 use_shader_translator_ = true;
2274 }
2275 if (!use_shader_translator_) {
2276 return true;
2277 }
2278 ShBuiltInResources resources;
2279 ShInitBuiltInResources(&resources);
2280 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2281 resources.MaxVertexUniformVectors =
2282 group_->max_vertex_uniform_vectors();
2283 resources.MaxVaryingVectors = group_->max_varying_vectors();
2284 resources.MaxVertexTextureImageUnits =
2285 group_->max_vertex_texture_image_units();
2286 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2287 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2288 resources.MaxFragmentUniformVectors =
2289 group_->max_fragment_uniform_vectors();
2290 resources.MaxDrawBuffers = 1;
[email protected]f0d74742011-10-03 16:31:042291
2292 if (force_webgl_glsl_validation_) {
2293 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2294 } else {
2295 resources.OES_standard_derivatives =
2296 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
[email protected]e51bdf32011-11-23 22:21:462297 resources.ARB_texture_rectangle =
2298 feature_info_->feature_flags().arb_texture_rectangle ? 1 : 0;
[email protected]f0d74742011-10-03 16:31:042299 }
2300
[email protected]c2f8c8402010-12-06 18:07:242301 vertex_translator_.reset(new ShaderTranslator);
[email protected]f0d74742011-10-03 16:31:042302 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ||
2303 feature_info_->feature_flags().chromium_webglsl ?
2304 SH_WEBGL_SPEC : SH_GLES2_SPEC;
[email protected]a2a0fe762011-09-20 00:59:122305 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2306 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2307 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2308 ShaderTranslatorInterface::GlslBuiltInFunctionBehavior function_behavior =
2309 needs_glsl_built_in_function_emulation_ ?
2310 ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated :
2311 ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal;
[email protected]c2f8c8402010-12-06 18:07:242312 if (!vertex_translator_->Init(
[email protected]a2a0fe762011-09-20 00:59:122313 SH_VERTEX_SHADER, shader_spec, &resources,
2314 implementation_type, function_behavior)) {
[email protected]c2f8c8402010-12-06 18:07:242315 LOG(ERROR) << "Could not initialize vertex shader translator.";
2316 Destroy();
2317 return false;
2318 }
2319 fragment_translator_.reset(new ShaderTranslator);
2320 if (!fragment_translator_->Init(
[email protected]a2a0fe762011-09-20 00:59:122321 SH_FRAGMENT_SHADER, shader_spec, &resources,
2322 implementation_type, function_behavior)) {
[email protected]c2f8c8402010-12-06 18:07:242323 LOG(ERROR) << "Could not initialize fragment shader translator.";
2324 Destroy();
2325 return false;
2326 }
2327 return true;
2328}
2329
[email protected]ae51d192010-04-27 00:48:032330bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472331 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032332 if (GetBufferInfo(client_ids[ii])) {
2333 return false;
2334 }
2335 }
2336 scoped_array<GLuint> service_ids(new GLuint[n]);
2337 glGenBuffersARB(n, service_ids.get());
2338 for (GLsizei ii = 0; ii < n; ++ii) {
2339 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2340 }
2341 return true;
2342}
2343
2344bool GLES2DecoderImpl::GenFramebuffersHelper(
2345 GLsizei n, const GLuint* client_ids) {
2346 for (GLsizei ii = 0; ii < n; ++ii) {
2347 if (GetFramebufferInfo(client_ids[ii])) {
2348 return false;
2349 }
2350 }
2351 scoped_array<GLuint> service_ids(new GLuint[n]);
2352 glGenFramebuffersEXT(n, service_ids.get());
2353 for (GLsizei ii = 0; ii < n; ++ii) {
2354 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2355 }
2356 return true;
2357}
2358
2359bool GLES2DecoderImpl::GenRenderbuffersHelper(
2360 GLsizei n, const GLuint* client_ids) {
2361 for (GLsizei ii = 0; ii < n; ++ii) {
2362 if (GetRenderbufferInfo(client_ids[ii])) {
2363 return false;
2364 }
2365 }
2366 scoped_array<GLuint> service_ids(new GLuint[n]);
2367 glGenRenderbuffersEXT(n, service_ids.get());
2368 for (GLsizei ii = 0; ii < n; ++ii) {
2369 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2370 }
2371 return true;
2372}
2373
2374bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2375 for (GLsizei ii = 0; ii < n; ++ii) {
2376 if (GetTextureInfo(client_ids[ii])) {
2377 return false;
2378 }
2379 }
2380 scoped_array<GLuint> service_ids(new GLuint[n]);
2381 glGenTextures(n, service_ids.get());
2382 for (GLsizei ii = 0; ii < n; ++ii) {
2383 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2384 }
2385 return true;
2386}
2387
2388void GLES2DecoderImpl::DeleteBuffersHelper(
2389 GLsizei n, const GLuint* client_ids) {
2390 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102391 BufferManager::BufferInfo* buffer = GetBufferInfo(client_ids[ii]);
2392 if (buffer && !buffer->IsDeleted()) {
[email protected]3757a372012-01-19 05:20:442393 vertex_attrib_manager_->Unbind(buffer);
[email protected]a0b78dc2011-11-11 10:43:102394 if (bound_array_buffer_ == buffer) {
2395 bound_array_buffer_ = NULL;
2396 }
2397 if (bound_element_array_buffer_ == buffer) {
2398 bound_element_array_buffer_ = NULL;
2399 }
[email protected]ae51d192010-04-27 00:48:032400 RemoveBufferInfo(client_ids[ii]);
2401 }
[email protected]a93bb842010-02-16 23:03:472402 }
[email protected]07f54fcc2009-12-22 02:46:302403}
2404
[email protected]ae51d192010-04-27 00:48:032405void GLES2DecoderImpl::DeleteFramebuffersHelper(
2406 GLsizei n, const GLuint* client_ids) {
[email protected]b177ae22011-11-01 03:29:112407 bool supports_seperate_framebuffer_binds =
2408 feature_info_->feature_flags().chromium_framebuffer_multisample;
2409
[email protected]a25fa872010-03-25 02:57:582410 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102411 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ae51d192010-04-27 00:48:032412 GetFramebufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102413 if (framebuffer && !framebuffer->IsDeleted()) {
2414 if (framebuffer == bound_draw_framebuffer_) {
[email protected]297ca1c2011-06-20 23:08:462415 bound_draw_framebuffer_ = NULL;
2416 state_dirty_ = true;
[email protected]b177ae22011-11-01 03:29:112417 GLenum target = supports_seperate_framebuffer_binds ?
2418 GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER;
2419 glBindFramebufferEXT(target, GetBackbufferServiceId());
2420 }
[email protected]a0b78dc2011-11-11 10:43:102421 if (framebuffer == bound_read_framebuffer_) {
[email protected]b177ae22011-11-01 03:29:112422 bound_read_framebuffer_ = NULL;
2423 GLenum target = supports_seperate_framebuffer_binds ?
2424 GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER;
2425 glBindFramebufferEXT(target, GetBackbufferServiceId());
[email protected]297ca1c2011-06-20 23:08:462426 }
[email protected]ae51d192010-04-27 00:48:032427 RemoveFramebufferInfo(client_ids[ii]);
2428 }
[email protected]a25fa872010-03-25 02:57:582429 }
[email protected]07f54fcc2009-12-22 02:46:302430}
2431
[email protected]ae51d192010-04-27 00:48:032432void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2433 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102434 bool supports_seperate_framebuffer_binds =
2435 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a25fa872010-03-25 02:57:582436 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102437 RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]ae51d192010-04-27 00:48:032438 GetRenderbufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102439 if (renderbuffer && !renderbuffer->IsDeleted()) {
2440 if (bound_renderbuffer_ == renderbuffer) {
2441 bound_renderbuffer_ = NULL;
2442 }
2443 // Unbind from current framebuffers.
2444 if (supports_seperate_framebuffer_binds) {
2445 if (bound_read_framebuffer_) {
2446 bound_read_framebuffer_->UnbindRenderbuffer(
2447 GL_READ_FRAMEBUFFER, renderbuffer);
2448 }
2449 if (bound_draw_framebuffer_) {
2450 bound_draw_framebuffer_->UnbindRenderbuffer(
2451 GL_DRAW_FRAMEBUFFER, renderbuffer);
2452 }
2453 } else {
2454 if (bound_draw_framebuffer_) {
2455 bound_draw_framebuffer_->UnbindRenderbuffer(
2456 GL_FRAMEBUFFER, renderbuffer);
2457 }
2458 }
[email protected]297ca1c2011-06-20 23:08:462459 state_dirty_ = true;
[email protected]ae51d192010-04-27 00:48:032460 RemoveRenderbufferInfo(client_ids[ii]);
2461 }
[email protected]a25fa872010-03-25 02:57:582462 }
[email protected]07f54fcc2009-12-22 02:46:302463}
2464
[email protected]ae51d192010-04-27 00:48:032465void GLES2DecoderImpl::DeleteTexturesHelper(
2466 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102467 bool supports_seperate_framebuffer_binds =
2468 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a93bb842010-02-16 23:03:472469 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102470 TextureManager::TextureInfo* texture = GetTextureInfo(client_ids[ii]);
2471 if (texture && !texture->IsDeleted()) {
2472 if (texture->IsAttachedToFramebuffer()) {
[email protected]297ca1c2011-06-20 23:08:462473 state_dirty_ = true;
2474 }
[email protected]a0b78dc2011-11-11 10:43:102475 // Unbind texture from texture units.
2476 for (size_t jj = 0; jj < group_->max_texture_units(); ++jj) {
2477 texture_units_[ii].Unbind(texture);
2478 }
2479 // Unbind from current framebuffers.
2480 if (supports_seperate_framebuffer_binds) {
2481 if (bound_read_framebuffer_) {
2482 bound_read_framebuffer_->UnbindTexture(GL_READ_FRAMEBUFFER, texture);
2483 }
2484 if (bound_draw_framebuffer_) {
2485 bound_draw_framebuffer_->UnbindTexture(GL_DRAW_FRAMEBUFFER, texture);
2486 }
2487 } else {
2488 if (bound_draw_framebuffer_) {
2489 bound_draw_framebuffer_->UnbindTexture(GL_FRAMEBUFFER, texture);
2490 }
2491 }
2492 GLuint service_id = texture->service_id();
2493 if (texture->IsStreamTexture() && stream_texture_manager_) {
[email protected]b0af4f52011-09-28 22:04:422494 stream_texture_manager_->DestroyStreamTexture(service_id);
2495 }
[email protected]e51bdf32011-11-23 22:21:462496#if defined(OS_MACOSX)
2497 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2498 ReleaseIOSurfaceForTexture(service_id);
2499 }
2500#endif
[email protected]ae51d192010-04-27 00:48:032501 RemoveTextureInfo(client_ids[ii]);
2502 }
[email protected]a93bb842010-02-16 23:03:472503 }
[email protected]07f54fcc2009-12-22 02:46:302504}
2505
[email protected]43f28f832010-02-03 02:28:482506// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322507
[email protected]eb54a562010-01-20 21:55:182508bool GLES2DecoderImpl::MakeCurrent() {
[email protected]38d139d2011-07-14 00:38:432509 bool result = context_.get() ? context_->MakeCurrent(surface_.get()) : false;
2510 if (result && WasContextLost()) {
2511 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
2512 result = false;
2513 }
2514
2515 return result;
[email protected]eb54a562010-01-20 21:55:182516}
2517
[email protected]a96a6022011-11-04 00:58:122518void GLES2DecoderImpl::ReleaseCurrent() {
2519 if (context_.get())
2520 context_->ReleaseCurrent(surface_.get());
2521}
2522
[email protected]8e3e0662010-08-23 18:46:302523void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
[email protected]0d6bfdc2011-11-02 01:32:202524 RenderbufferManager::RenderbufferInfo* renderbuffer =
2525 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
[email protected]8e3e0662010-08-23 18:46:302526 glBindRenderbufferEXT(
[email protected]0d6bfdc2011-11-02 01:32:202527 GL_RENDERBUFFER, renderbuffer ? renderbuffer->service_id() : 0);
[email protected]8e3e0662010-08-23 18:46:302528}
2529
2530static void RebindCurrentFramebuffer(
2531 GLenum target,
2532 FramebufferManager::FramebufferInfo* info,
[email protected]a3783712012-01-20 22:18:242533 GLuint back_buffer_service_id) {
[email protected]8e3e0662010-08-23 18:46:302534 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462535
[email protected]a3783712012-01-20 22:18:242536 if (framebuffer_id == 0) {
2537 framebuffer_id = back_buffer_service_id;
[email protected]8e3e0662010-08-23 18:46:302538 }
[email protected]297ca1c2011-06-20 23:08:462539
[email protected]8e3e0662010-08-23 18:46:302540 glBindFramebufferEXT(target, framebuffer_id);
2541}
2542
2543void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]297ca1c2011-06-20 23:08:462544 state_dirty_ = true;
2545
[email protected]a3ded6d2010-10-19 06:44:392546 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302547 RebindCurrentFramebuffer(
2548 GL_FRAMEBUFFER,
2549 bound_draw_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242550 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302551 } else {
2552 RebindCurrentFramebuffer(
2553 GL_READ_FRAMEBUFFER_EXT,
2554 bound_read_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242555 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302556 RebindCurrentFramebuffer(
2557 GL_DRAW_FRAMEBUFFER_EXT,
2558 bound_draw_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242559 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302560 }
2561}
2562
2563void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2564 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2565 GLuint last_id;
2566 if (info.bound_texture_2d) {
2567 last_id = info.bound_texture_2d->service_id();
2568 } else {
2569 last_id = 0;
2570 }
2571
2572 glBindTexture(GL_TEXTURE_2D, last_id);
2573 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2574}
2575
[email protected]0d6bfdc2011-11-02 01:32:202576bool GLES2DecoderImpl::CheckFramebufferValid(
2577 FramebufferManager::FramebufferInfo* framebuffer,
2578 GLenum target, const char* func_name) {
[email protected]a0b78dc2011-11-11 10:43:102579 if (!framebuffer) {
[email protected]0d6bfdc2011-11-02 01:32:202580 return true;
2581 }
2582
[email protected]968351b2011-12-20 08:26:512583 if (framebuffer_manager()->IsComplete(framebuffer)) {
2584 return true;
2585 }
2586
[email protected]0d6bfdc2011-11-02 01:32:202587 GLenum completeness = framebuffer->IsPossiblyComplete();
2588 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
2589 SetGLError(
2590 GL_INVALID_FRAMEBUFFER_OPERATION,
2591 (std::string(func_name) + " framebuffer incomplete").c_str());
[email protected]3a03a8f2011-03-19 00:51:272592 return false;
2593 }
[email protected]0d6bfdc2011-11-02 01:32:202594
2595 // Are all the attachments cleared?
2596 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2597 texture_manager()->HaveUnclearedMips()) {
2598 if (!framebuffer->IsCleared()) {
2599 // Can we clear them?
2600 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2601 SetGLError(
2602 GL_INVALID_FRAMEBUFFER_OPERATION,
2603 (std::string(func_name) +
2604 " framebuffer incomplete (clear)").c_str());
2605 return false;
2606 }
2607 ClearUnclearedAttachments(target, framebuffer);
2608 }
2609 }
2610
[email protected]968351b2011-12-20 08:26:512611 if (!framebuffer_manager()->IsComplete(framebuffer)) {
2612 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2613 SetGLError(
2614 GL_INVALID_FRAMEBUFFER_OPERATION,
2615 (std::string(func_name) +
2616 " framebuffer incomplete (check)").c_str());
2617 return false;
2618 }
2619 framebuffer_manager()->MarkAsComplete(framebuffer);
2620 }
2621
[email protected]0d6bfdc2011-11-02 01:32:202622 // NOTE: At this point we don't know if the framebuffer is complete but
2623 // we DO know that everything that needs to be cleared has been cleared.
[email protected]3a03a8f2011-03-19 00:51:272624 return true;
2625}
2626
[email protected]0d6bfdc2011-11-02 01:32:202627bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
2628 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
2629 return CheckFramebufferValid(
2630 bound_draw_framebuffer_, GL_FRAMEBUFFER_EXT, func_name);
2631 }
2632 return CheckFramebufferValid(
2633 bound_draw_framebuffer_, GL_DRAW_FRAMEBUFFER_EXT, func_name) &&
2634 CheckFramebufferValid(
2635 bound_read_framebuffer_, GL_READ_FRAMEBUFFER_EXT, func_name);
2636}
2637
[email protected]8e3e0662010-08-23 18:46:302638gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
[email protected]0d6bfdc2011-11-02 01:32:202639 FramebufferManager::FramebufferInfo* framebuffer =
2640 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2641 if (framebuffer != NULL) {
[email protected]9edc6b22010-12-23 02:00:262642 const FramebufferManager::FramebufferInfo::Attachment* attachment =
[email protected]0d6bfdc2011-11-02 01:32:202643 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
[email protected]9edc6b22010-12-23 02:00:262644 if (attachment) {
2645 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502646 }
[email protected]9edc6b22010-12-23 02:00:262647 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022648 } else if (offscreen_target_frame_buffer_.get()) {
2649 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352650 } else {
[email protected]f62a5ab2011-05-23 20:34:152651 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022652 }
[email protected]246a70452010-03-05 21:53:502653}
2654
[email protected]9edc6b22010-12-23 02:00:262655GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202656 FramebufferManager::FramebufferInfo* framebuffer =
2657 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2658 if (framebuffer != NULL) {
2659 return framebuffer->GetColorAttachmentFormat();
[email protected]297ca1c2011-06-20 23:08:462660 } else if (offscreen_target_frame_buffer_.get()) {
2661 return offscreen_target_color_format_;
2662 } else {
2663 return back_buffer_color_format_;
2664 }
2665}
2666
2667GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202668 FramebufferManager::FramebufferInfo* framebuffer =
2669 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
2670 if (framebuffer != NULL) {
2671 return framebuffer->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262672 } else if (offscreen_target_frame_buffer_.get()) {
2673 return offscreen_target_color_format_;
2674 } else {
[email protected]32fe9aa2011-01-21 23:47:132675 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262676 }
2677}
2678
[email protected]9a5afa432011-07-22 18:16:392679void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]34ff8b0c2010-10-01 20:06:022680 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582681 // Update the info about the offscreen saved color texture in the parent.
2682 // The reference to the parent is a weak pointer and will become null if the
2683 // parent is later destroyed.
[email protected]262d7aa2010-12-03 22:07:292684 TextureManager* parent_texture_manager = parent_->texture_manager();
[email protected]262d7aa2010-12-03 22:07:292685 parent_texture_manager->SetLevelInfo(
[email protected]8a61d872012-01-20 12:43:562686 offscreen_saved_color_texture_info_,
[email protected]ef526492010-06-02 23:12:252687 GL_TEXTURE_2D,
2688 0, // level
2689 GL_RGBA,
[email protected]799b4b22011-08-22 17:09:592690 offscreen_size_.width(),
2691 offscreen_size_.height(),
[email protected]ef526492010-06-02 23:12:252692 1, // depth
2693 0, // border
2694 GL_RGBA,
[email protected]0d6bfdc2011-11-02 01:32:202695 GL_UNSIGNED_BYTE,
2696 true);
[email protected]262d7aa2010-12-03 22:07:292697 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562698 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042699 GL_TEXTURE_MAG_FILTER,
2700 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292701 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562702 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042703 GL_TEXTURE_MIN_FILTER,
2704 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292705 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562706 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042707 GL_TEXTURE_WRAP_S,
2708 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292709 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562710 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042711 GL_TEXTURE_WRAP_T,
2712 GL_CLAMP_TO_EDGE);
[email protected]8a61d872012-01-20 12:43:562713 } else {
2714 offscreen_saved_color_texture_info_ = NULL;
[email protected]0c8c9d22010-06-25 17:36:392715 }
[email protected]6217d392010-03-25 22:08:352716}
2717
[email protected]799b4b22011-08-22 17:09:592718void GLES2DecoderImpl::SetResizeCallback(
[email protected]9d37f062011-11-22 01:24:522719 const base::Callback<void(gfx::Size)>& callback) {
2720 resize_callback_ = callback;
[email protected]7ff86b92010-11-25 17:50:002721}
2722
[email protected]6b6e7ee2011-12-13 08:04:522723void GLES2DecoderImpl::SetMsgCallback(const MsgCallback& callback) {
2724 msg_callback_ = callback;
2725}
2726
[email protected]b0af4f52011-09-28 22:04:422727void GLES2DecoderImpl::SetStreamTextureManager(StreamTextureManager* manager) {
2728 stream_texture_manager_ = manager;
2729}
2730
[email protected]1318e922010-09-17 22:03:162731bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2732 uint32* service_texture_id) {
2733 TextureManager::TextureInfo* texture =
2734 texture_manager()->GetTextureInfo(client_texture_id);
2735 if (texture) {
2736 *service_texture_id = texture->service_id();
2737 return true;
2738 }
2739 return false;
2740}
2741
[email protected]96449d2c2009-11-25 00:01:322742void GLES2DecoderImpl::Destroy() {
[email protected]eadc96792010-10-27 19:39:392743 bool have_context = context_.get() && MakeCurrent();
[email protected]97872062010-11-03 19:07:052744
[email protected]c826d732012-02-09 04:40:262745 ChildList children = children_;
2746 for (ChildList::iterator it = children.begin(); it != children.end(); ++it)
2747 (*it)->SetParent(NULL, 0);
2748 DCHECK(children_.empty());
[email protected]3c644d82011-06-20 19:58:242749 SetParent(NULL, 0);
2750
[email protected]80eb6b52012-01-19 00:14:412751 // Unbind everything.
[email protected]3757a372012-01-19 05:20:442752 vertex_attrib_manager_.reset();
[email protected]80eb6b52012-01-19 00:14:412753 texture_units_.reset();
2754 bound_array_buffer_ = NULL;
2755 bound_element_array_buffer_ = NULL;
[email protected]882ba1e22012-03-08 19:02:532756 current_query_ = NULL;
[email protected]80eb6b52012-01-19 00:14:412757 current_program_ = NULL;
2758 bound_read_framebuffer_ = NULL;
2759 bound_draw_framebuffer_ = NULL;
2760 bound_renderbuffer_ = NULL;
2761
[email protected]eadc96792010-10-27 19:39:392762 if (have_context) {
[email protected]43410e92012-04-20 17:06:282763 copy_texture_CHROMIUM_->Destroy();
2764
[email protected]ca488e12010-12-13 20:06:142765 if (current_program_) {
2766 program_manager()->UnuseProgram(shader_manager(), current_program_);
2767 current_program_ = NULL;
2768 }
2769
[email protected]b1122982010-05-17 23:04:242770 if (attrib_0_buffer_id_) {
2771 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2772 }
[email protected]8fbedc02010-11-18 18:43:402773 if (fixed_attrib_buffer_id_) {
2774 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2775 }
[email protected]b1122982010-05-17 23:04:242776
[email protected]97872062010-11-03 19:07:052777 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542778 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052779 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542780 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052781 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022782 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052783 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152784 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052785 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152786 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052787 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022788 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052789 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542790 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:272791 if (offscreen_resolved_frame_buffer_.get())
2792 offscreen_resolved_frame_buffer_->Destroy();
2793 if (offscreen_resolved_color_texture_.get())
2794 offscreen_resolved_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052795 } else {
2796 if (offscreen_target_frame_buffer_.get())
2797 offscreen_target_frame_buffer_->Invalidate();
2798 if (offscreen_target_color_texture_.get())
2799 offscreen_target_color_texture_->Invalidate();
2800 if (offscreen_target_color_render_buffer_.get())
2801 offscreen_target_color_render_buffer_->Invalidate();
2802 if (offscreen_target_depth_render_buffer_.get())
2803 offscreen_target_depth_render_buffer_->Invalidate();
2804 if (offscreen_target_stencil_render_buffer_.get())
2805 offscreen_target_stencil_render_buffer_->Invalidate();
2806 if (offscreen_saved_frame_buffer_.get())
2807 offscreen_saved_frame_buffer_->Invalidate();
2808 if (offscreen_saved_color_texture_.get())
2809 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:272810 if (offscreen_resolved_frame_buffer_.get())
2811 offscreen_resolved_frame_buffer_->Invalidate();
2812 if (offscreen_resolved_color_texture_.get())
2813 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022814 }
[email protected]43410e92012-04-20 17:06:282815 copy_texture_CHROMIUM_.reset();
[email protected]97872062010-11-03 19:07:052816
[email protected]882ba1e22012-03-08 19:02:532817 if (query_manager_.get()) {
2818 query_manager_->Destroy(have_context);
2819 query_manager_.reset();
2820 }
2821
[email protected]1871a092011-10-10 21:46:422822 if (group_) {
2823 group_->Destroy(have_context);
2824 group_ = NULL;
2825 }
[email protected]3ae019382011-10-05 19:42:412826
[email protected]fe871662011-06-16 20:43:052827 if (context_.get()) {
2828 context_->ReleaseCurrent(NULL);
[email protected]79311e82011-09-20 00:40:502829 context_ = NULL;
[email protected]fe871662011-06-16 20:43:052830 }
[email protected]0fc35742011-04-13 17:57:542831
[email protected]97872062010-11-03 19:07:052832 offscreen_target_frame_buffer_.reset();
2833 offscreen_target_color_texture_.reset();
2834 offscreen_target_color_render_buffer_.reset();
2835 offscreen_target_depth_render_buffer_.reset();
2836 offscreen_target_stencil_render_buffer_.reset();
2837 offscreen_saved_frame_buffer_.reset();
2838 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:272839 offscreen_resolved_frame_buffer_.reset();
2840 offscreen_resolved_color_texture_.reset();
[email protected]e51bdf32011-11-23 22:21:462841
2842#if defined(OS_MACOSX)
2843 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
2844 it != texture_to_io_surface_map_.end(); ++it) {
2845 CFRelease(it->second);
2846 }
2847 texture_to_io_surface_map_.clear();
2848#endif
[email protected]96449d2c2009-11-25 00:01:322849}
2850
[email protected]3c644d82011-06-20 19:58:242851bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
2852 uint32 new_parent_texture_id) {
[email protected]9a5afa432011-07-22 18:16:392853 if (!offscreen_saved_color_texture_.get())
2854 return false;
2855
[email protected]3c644d82011-06-20 19:58:242856 // Remove the saved frame buffer mapping from the parent decoder. The
2857 // parent pointer is a weak pointer so it will be null if the parent has
2858 // already been destroyed.
2859 if (parent_) {
[email protected]c826d732012-02-09 04:40:262860 ChildList::iterator it = std::find(
2861 parent_->children_.begin(),
2862 parent_->children_.end(),
2863 this);
2864 DCHECK(it != parent_->children_.end());
2865 parent_->children_.erase(it);
[email protected]3c644d82011-06-20 19:58:242866 // First check the texture has been mapped into the parent. This might not
2867 // be the case if initialization failed midway through.
2868 GLuint service_id = offscreen_saved_color_texture_->id();
2869 GLuint client_id = 0;
2870 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
[email protected]80eb6b52012-01-19 00:14:412871 parent_->texture_manager()->RemoveTextureInfo(client_id);
[email protected]3c644d82011-06-20 19:58:242872 }
2873 }
2874
2875 GLES2DecoderImpl* new_parent_impl = static_cast<GLES2DecoderImpl*>(
2876 new_parent);
2877 if (new_parent_impl) {
[email protected]c826d732012-02-09 04:40:262878#ifndef NDEBUG
2879 ChildList::iterator it = std::find(
2880 new_parent_impl->children_.begin(),
2881 new_parent_impl->children_.end(),
2882 this);
2883 DCHECK(it == new_parent_impl->children_.end());
2884#endif
2885 new_parent_impl->children_.push_back(this);
[email protected]3c644d82011-06-20 19:58:242886 // Map the ID of the saved offscreen texture into the parent so that
2887 // it can reference it.
2888 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]98687862011-07-11 23:31:302889
2890 // Replace texture info when ID is already in use by parent.
2891 if (new_parent_impl->texture_manager()->GetTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412892 new_parent_texture_id))
[email protected]98687862011-07-11 23:31:302893 new_parent_impl->texture_manager()->RemoveTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412894 new_parent_texture_id);
[email protected]98687862011-07-11 23:31:302895
[email protected]8a61d872012-01-20 12:43:562896 offscreen_saved_color_texture_info_ =
[email protected]5f4f2a732011-07-30 00:47:552897 new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id);
[email protected]8a61d872012-01-20 12:43:562898 offscreen_saved_color_texture_info_->SetNotOwned();
2899 new_parent_impl->texture_manager()->
2900 SetInfoTarget(offscreen_saved_color_texture_info_, GL_TEXTURE_2D);
[email protected]3c644d82011-06-20 19:58:242901
2902 parent_ = new_parent_impl->AsWeakPtr();
[email protected]9a5afa432011-07-22 18:16:392903
2904 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:242905 } else {
2906 parent_.reset();
[email protected]8a61d872012-01-20 12:43:562907 offscreen_saved_color_texture_info_ = NULL;
[email protected]3c644d82011-06-20 19:58:242908 }
2909
2910 return true;
2911}
2912
[email protected]1078f912011-12-23 13:12:142913void GLES2DecoderImpl::UpdateBackbufferMemoryAccounting() {
2914 size_t total = 0;
2915 if (offscreen_target_frame_buffer_.get()) {
2916 if (offscreen_target_color_texture_.get()) {
2917 total += offscreen_target_color_texture_->estimated_size();
2918 }
2919 if (offscreen_target_color_render_buffer_.get()) {
2920 total += offscreen_target_color_render_buffer_->estimated_size();
2921 }
2922 if (offscreen_target_depth_render_buffer_.get()) {
2923 total += offscreen_target_depth_render_buffer_->estimated_size();
2924 }
2925 if (offscreen_target_stencil_render_buffer_.get()) {
2926 total += offscreen_target_stencil_render_buffer_->estimated_size();
2927 }
2928 if (offscreen_saved_color_texture_.get()) {
2929 total += offscreen_saved_color_texture_->estimated_size();
2930 }
2931 if (offscreen_resolved_color_texture_.get()) {
2932 total += offscreen_resolved_color_texture_->estimated_size();
2933 }
2934 } else {
2935 gfx::Size size = surface_->GetSize();
2936 total += size.width() * size.height() *
2937 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_);
2938 }
2939 TRACE_COUNTER_ID1(
2940 "GLES2DecoderImpl", "BackbufferMemory", this, total);
2941}
2942
[email protected]799b4b22011-08-22 17:09:592943bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2944 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
2945 if (!is_offscreen) {
2946 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
2947 << " with an onscreen framebuffer.";
2948 return false;
2949 }
2950
2951 if (offscreen_size_ == size)
2952 return true;
2953
2954 offscreen_size_ = size;
2955 int w = offscreen_size_.width();
2956 int h = offscreen_size_.height();
2957 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
2958 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2959 << "to allocate storage due to excessive dimensions.";
2960 return false;
2961 }
2962
2963 // Reallocate the offscreen target buffers.
2964 DCHECK(offscreen_target_color_format_);
2965 if (IsOffscreenBufferMultisampled()) {
2966 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2967 offscreen_size_, offscreen_target_color_format_,
2968 offscreen_target_samples_)) {
2969 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2970 << "to allocate storage for offscreen target color buffer.";
2971 return false;
2972 }
2973 } else {
2974 if (!offscreen_target_color_texture_->AllocateStorage(
2975 offscreen_size_, offscreen_target_color_format_)) {
2976 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2977 << "to allocate storage for offscreen target color texture.";
2978 return false;
2979 }
2980 }
2981 if (offscreen_target_depth_format_ &&
2982 !offscreen_target_depth_render_buffer_->AllocateStorage(
2983 offscreen_size_, offscreen_target_depth_format_,
2984 offscreen_target_samples_)) {
2985 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2986 << "to allocate storage for offscreen target depth buffer.";
2987 return false;
2988 }
2989 if (offscreen_target_stencil_format_ &&
2990 !offscreen_target_stencil_render_buffer_->AllocateStorage(
2991 offscreen_size_, offscreen_target_stencil_format_,
2992 offscreen_target_samples_)) {
2993 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2994 << "to allocate storage for offscreen target stencil buffer.";
2995 return false;
2996 }
[email protected]1078f912011-12-23 13:12:142997 UpdateBackbufferMemoryAccounting();
[email protected]799b4b22011-08-22 17:09:592998
2999 // Attach the offscreen target buffers to the target frame buffer.
3000 if (IsOffscreenBufferMultisampled()) {
3001 offscreen_target_frame_buffer_->AttachRenderBuffer(
3002 GL_COLOR_ATTACHMENT0,
3003 offscreen_target_color_render_buffer_.get());
3004 } else {
3005 offscreen_target_frame_buffer_->AttachRenderTexture(
3006 offscreen_target_color_texture_.get());
3007 }
3008 if (offscreen_target_depth_format_) {
3009 offscreen_target_frame_buffer_->AttachRenderBuffer(
3010 GL_DEPTH_ATTACHMENT,
3011 offscreen_target_depth_render_buffer_.get());
3012 }
3013 const bool packed_depth_stencil =
3014 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3015 if (packed_depth_stencil) {
3016 offscreen_target_frame_buffer_->AttachRenderBuffer(
3017 GL_STENCIL_ATTACHMENT,
3018 offscreen_target_depth_render_buffer_.get());
3019 } else if (offscreen_target_stencil_format_) {
3020 offscreen_target_frame_buffer_->AttachRenderBuffer(
3021 GL_STENCIL_ATTACHMENT,
3022 offscreen_target_stencil_render_buffer_.get());
3023 }
3024
3025 if (offscreen_target_frame_buffer_->CheckStatus() !=
3026 GL_FRAMEBUFFER_COMPLETE) {
3027 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3028 << "because offscreen FBO was incomplete.";
3029 return false;
3030 }
3031
3032 // Clear the target frame buffer.
3033 {
3034 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3035 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3036 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3037 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3038 glClearStencil(0);
3039 glStencilMaskSeparate(GL_FRONT, -1);
3040 glStencilMaskSeparate(GL_BACK, -1);
3041 glClearDepth(0);
3042 glDepthMask(GL_TRUE);
3043 glDisable(GL_SCISSOR_TEST);
3044 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3045 RestoreClearState();
3046 }
[email protected]d85ef76d2011-09-08 22:21:433047
3048 // Destroy the offscreen resolved framebuffers.
3049 if (offscreen_resolved_frame_buffer_.get())
3050 offscreen_resolved_frame_buffer_->Destroy();
3051 if (offscreen_resolved_color_texture_.get())
3052 offscreen_resolved_color_texture_->Destroy();
3053 offscreen_resolved_color_texture_.reset();
3054 offscreen_resolved_frame_buffer_.reset();
3055
[email protected]799b4b22011-08-22 17:09:593056 return true;
[email protected]6217d392010-03-25 22:08:353057}
3058
[email protected]799b4b22011-08-22 17:09:593059error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3060 uint32 immediate_data_size, const gles2::ResizeCHROMIUM& c) {
3061 GLuint width = static_cast<GLuint>(c.width);
3062 GLuint height = static_cast<GLuint>(c.height);
3063 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
[email protected]a0d989162011-11-22 13:15:073064#if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3065 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
[email protected]7ff86b92010-11-25 17:50:003066 // Make sure that we are done drawing to the back buffer before resizing.
3067 glFinish();
3068#endif
[email protected]799b4b22011-08-22 17:09:593069 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3070 if (is_offscreen) {
[email protected]7794d512012-04-17 20:36:493071 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3072 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3073 << "ResizeOffscreenFrameBuffer failed.";
[email protected]799b4b22011-08-22 17:09:593074 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:493075 }
[email protected]7ff86b92010-11-25 17:50:003076 }
[email protected]799b4b22011-08-22 17:09:593077
[email protected]9d37f062011-11-22 01:24:523078 if (!resize_callback_.is_null()) {
3079 resize_callback_.Run(gfx::Size(width, height));
[email protected]c777de52011-09-09 23:08:563080 DCHECK(context_->IsCurrent(surface_.get()));
[email protected]7794d512012-04-17 20:36:493081 if (!context_->IsCurrent(surface_.get())) {
3082 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3083 << "current after resize callback.";
[email protected]658f7562011-09-09 05:24:053084 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:493085 }
[email protected]658f7562011-09-09 05:24:053086 }
[email protected]799b4b22011-08-22 17:09:593087
[email protected]1078f912011-12-23 13:12:143088 UpdateBackbufferMemoryAccounting();
3089
[email protected]799b4b22011-08-22 17:09:593090 return error::kNoError;
[email protected]43ecf372010-11-16 19:19:393091}
3092
[email protected]96449d2c2009-11-25 00:01:323093const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3094 if (command_id > kStartPoint && command_id < kNumCommands) {
3095 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3096 }
3097 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3098}
3099
3100// Decode command with its arguments, and call the corresponding GL function.
3101// Note: args is a pointer to the command buffer. As such, it could be changed
3102// by a (malicious) client at any time, so if validation has to happen, it
3103// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:143104error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:323105 unsigned int command,
3106 unsigned int arg_count,
3107 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:143108 error::Error result = error::kNoError;
[email protected]e844ae22012-01-14 03:36:263109 if (log_commands()) {
[email protected]39ba4f02012-03-26 01:16:003110 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3111 // LOG(INFO), tried VLOG(1), no luck.
3112 LOG(ERROR) << "[" << this << "]" << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193113 }
[email protected]96449d2c2009-11-25 00:01:323114 unsigned int command_index = command - kStartPoint - 1;
3115 if (command_index < arraysize(g_command_info)) {
3116 const CommandInfo& info = g_command_info[command_index];
3117 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3118 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3119 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:193120 uint32 immediate_data_size =
3121 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:323122 switch (command) {
3123 #define GLES2_CMD_OP(name) \
3124 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:193125 result = Handle ## name( \
3126 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:323127 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:193128 break; \
[email protected]96449d2c2009-11-25 00:01:323129
3130 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:323131 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:383132 }
3133 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:303134 GLenum error;
3135 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]39ba4f02012-03-26 01:16:003136 LOG(ERROR) << "[" << this << "] "
3137 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3138 << GetCommandName(command);
[email protected]e844ae22012-01-14 03:36:263139 SetGLError(error, "GL error from driver");
[email protected]b9849abf2009-11-25 19:13:193140 }
[email protected]96449d2c2009-11-25 00:01:323141 }
3142 } else {
[email protected]f7a64ee2010-02-01 22:24:143143 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:323144 }
[email protected]b9849abf2009-11-25 19:13:193145 } else {
3146 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:323147 }
[email protected]a3a93e7b2010-08-28 00:48:563148 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3149 result = current_decoder_error_;
3150 current_decoder_error_ = error::kNoError;
3151 }
[email protected]b9849abf2009-11-25 19:13:193152 return result;
[email protected]96449d2c2009-11-25 00:01:323153}
3154
[email protected]ae51d192010-04-27 00:48:033155void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
3156 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:503157}
3158
[email protected]ae51d192010-04-27 00:48:033159bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3160 if (GetProgramInfo(client_id)) {
3161 return false;
3162 }
[email protected]96449d2c2009-11-25 00:01:323163 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:033164 if (service_id != 0) {
3165 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:323166 }
[email protected]ae51d192010-04-27 00:48:033167 return true;
[email protected]96449d2c2009-11-25 00:01:323168}
3169
[email protected]ae51d192010-04-27 00:48:033170bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3171 if (GetShaderInfo(client_id)) {
3172 return false;
[email protected]96449d2c2009-11-25 00:01:323173 }
[email protected]ae51d192010-04-27 00:48:033174 GLuint service_id = glCreateShader(type);
3175 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:383176 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:033177 }
3178 return true;
[email protected]96449d2c2009-11-25 00:01:323179}
3180
[email protected]882ba1e22012-03-08 19:02:533181void GLES2DecoderImpl::DoFinish() {
3182 glFinish();
[email protected]22e3f552012-03-13 01:54:193183 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533184}
3185
3186void GLES2DecoderImpl::DoFlush() {
3187 glFlush();
[email protected]22e3f552012-03-13 01:54:193188 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533189}
3190
[email protected]3916c97e2010-02-25 03:20:503191void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:453192 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]660858b2011-07-13 23:16:143193 if (texture_index >= group_->max_texture_units()) {
[email protected]8eee29c2010-04-29 03:38:293194 SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:503195 return;
3196 }
[email protected]36cef8ce2010-03-16 07:34:453197 active_texture_unit_ = texture_index;
3198 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:503199}
3200
[email protected]051b1372010-04-12 02:42:083201void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:503202 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083203 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033204 if (client_id != 0) {
3205 info = GetBufferInfo(client_id);
3206 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353207 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153208 LOG(ERROR) << "glBindBuffer: id not generated by glGenBuffers";
3209 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353210 return;
3211 }
3212
[email protected]ae51d192010-04-27 00:48:033213 // It's a new id so make a buffer info for it.
3214 glGenBuffersARB(1, &service_id);
3215 CreateBufferInfo(client_id, service_id);
3216 info = GetBufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573217 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103218 group_->GetIdAllocator(id_namespaces::kBuffers);
3219 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033220 }
[email protected]051b1372010-04-12 02:42:083221 }
[email protected]ae51d192010-04-27 00:48:033222 if (info) {
[email protected]4e8a5b122010-05-08 22:00:103223 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:293224 SetGLError(GL_INVALID_OPERATION,
3225 "glBindBuffer: buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:473226 return;
3227 }
[email protected]ae51d192010-04-27 00:48:033228 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:473229 }
[email protected]96449d2c2009-11-25 00:01:323230 switch (target) {
3231 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503232 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323233 break;
3234 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503235 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323236 break;
3237 default:
[email protected]a93bb842010-02-16 23:03:473238 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:323239 break;
3240 }
[email protected]051b1372010-04-12 02:42:083241 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:323242}
3243
[email protected]297ca1c2011-06-20 23:08:463244bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
3245 return (GLES2Util::GetChannelsForFormat(
3246 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3247}
3248
3249bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203250 FramebufferManager::FramebufferInfo* framebuffer =
3251 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3252 if (framebuffer) {
3253 return framebuffer->HasDepthAttachment();
[email protected]297ca1c2011-06-20 23:08:463254 }
3255 if (offscreen_target_frame_buffer_.get()) {
3256 return offscreen_target_depth_format_ != 0;
3257 }
3258 return back_buffer_has_depth_;
3259}
3260
3261bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203262 FramebufferManager::FramebufferInfo* framebuffer =
3263 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3264 if (framebuffer) {
3265 return framebuffer->HasStencilAttachment();
[email protected]297ca1c2011-06-20 23:08:463266 }
3267 if (offscreen_target_frame_buffer_.get()) {
3268 return offscreen_target_stencil_format_ != 0 ||
3269 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3270 }
3271 return back_buffer_has_stencil_;
3272}
3273
3274void GLES2DecoderImpl::ApplyDirtyState() {
3275 if (state_dirty_) {
3276 glColorMask(
3277 mask_red_, mask_green_, mask_blue_,
3278 mask_alpha_ && BoundFramebufferHasColorAttachmentWithAlpha());
3279 bool have_depth = BoundFramebufferHasDepthAttachment();
3280 glDepthMask(mask_depth_ && have_depth);
3281 EnableDisable(GL_DEPTH_TEST, enable_depth_test_ && have_depth);
3282 bool have_stencil = BoundFramebufferHasStencilAttachment();
3283 glStencilMaskSeparate(GL_FRONT, have_stencil ? mask_stencil_front_ : 0);
3284 glStencilMaskSeparate(GL_BACK, have_stencil ? mask_stencil_back_ : 0);
3285 EnableDisable(GL_STENCIL_TEST, enable_stencil_test_ && have_stencil);
[email protected]43410e92012-04-20 17:06:283286 EnableDisable(GL_CULL_FACE, enable_cull_face_);
3287 EnableDisable(GL_SCISSOR_TEST, enable_scissor_test_);
[email protected]0a1e9ad2012-05-04 21:13:033288 EnableDisable(GL_BLEND, enable_blend_);
[email protected]297ca1c2011-06-20 23:08:463289 state_dirty_ = false;
3290 }
3291}
3292
[email protected]78b514b2012-05-01 21:50:593293void GLES2DecoderImpl::BindAndApplyTextureParameters(
3294 TextureManager::TextureInfo* info) {
3295 glBindTexture(info->target(), info->service_id());
3296 glTexParameteri(info->target(), GL_TEXTURE_MIN_FILTER, info->min_filter());
3297 glTexParameteri(info->target(), GL_TEXTURE_MAG_FILTER, info->mag_filter());
3298 glTexParameteri(info->target(), GL_TEXTURE_WRAP_S, info->wrap_s());
3299 glTexParameteri(info->target(), GL_TEXTURE_WRAP_T, info->wrap_t());
3300}
3301
[email protected]b177ae22011-11-01 03:29:113302GLuint GLES2DecoderImpl::GetBackbufferServiceId() {
3303 return (offscreen_target_frame_buffer_.get()) ?
3304 offscreen_target_frame_buffer_->id() :
3305 surface_->GetBackingFrameBufferObject();
3306}
3307
[email protected]051b1372010-04-12 02:42:083308void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3309 FramebufferManager::FramebufferInfo* info = NULL;
3310 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033311 if (client_id != 0) {
3312 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083313 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353314 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153315 LOG(ERROR)
3316 << "glBindFramebuffer: id not generated by glGenFramebuffers";
3317 current_decoder_error_ = error::kGenericError;
3318 return;
[email protected]bf5a8d132011-08-16 08:39:353319 }
3320
[email protected]ae51d192010-04-27 00:48:033321 // It's a new id so make a framebuffer info for it.
3322 glGenFramebuffersEXT(1, &service_id);
3323 CreateFramebufferInfo(client_id, service_id);
3324 info = GetFramebufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573325 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103326 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3327 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033328 } else {
3329 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083330 }
[email protected]06c8b082011-01-05 18:00:363331 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083332 }
[email protected]8e3e0662010-08-23 18:46:303333
3334 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
3335 bound_draw_framebuffer_ = info;
3336 }
3337 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
3338 bound_read_framebuffer_ = info;
3339 }
[email protected]6217d392010-03-25 22:08:353340
[email protected]297ca1c2011-06-20 23:08:463341 state_dirty_ = true;
3342
[email protected]b177ae22011-11-01 03:29:113343 // If we are rendering to the backbuffer get the FBO id for any simulated
3344 // backbuffer.
3345 if (info == NULL) {
3346 service_id = GetBackbufferServiceId();
[email protected]297ca1c2011-06-20 23:08:463347 }
[email protected]6217d392010-03-25 22:08:353348
[email protected]051b1372010-04-12 02:42:083349 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563350}
3351
[email protected]051b1372010-04-12 02:42:083352void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
3353 RenderbufferManager::RenderbufferInfo* info = NULL;
3354 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033355 if (client_id != 0) {
3356 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083357 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353358 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153359 LOG(ERROR)
3360 << "glBindRenderbuffer: id not generated by glGenRenderbuffers";
3361 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353362 return;
3363 }
3364
[email protected]ae51d192010-04-27 00:48:033365 // It's a new id so make a renderbuffer info for it.
3366 glGenRenderbuffersEXT(1, &service_id);
3367 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:103368 info = GetRenderbufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573369 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103370 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3371 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033372 } else {
3373 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083374 }
[email protected]06c8b082011-01-05 18:00:363375 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083376 }
3377 bound_renderbuffer_ = info;
3378 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563379}
3380
[email protected]051b1372010-04-12 02:42:083381void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033382 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083383 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033384 if (client_id != 0) {
3385 info = GetTextureInfo(client_id);
3386 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353387 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153388 LOG(ERROR) << "glBindTexture: id not generated by glGenTextures";
3389 current_decoder_error_ = error::kGenericError;
3390 return;
[email protected]bf5a8d132011-08-16 08:39:353391 }
3392
[email protected]ae51d192010-04-27 00:48:033393 // It's a new id so make a texture info for it.
3394 glGenTextures(1, &service_id);
[email protected]80eb6b52012-01-19 00:14:413395 DCHECK_NE(0u, service_id);
[email protected]ae51d192010-04-27 00:48:033396 CreateTextureInfo(client_id, service_id);
3397 info = GetTextureInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573398 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103399 group_->GetIdAllocator(id_namespaces::kTextures);
3400 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033401 }
3402 } else {
3403 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:083404 }
[email protected]ae51d192010-04-27 00:48:033405
[email protected]1958e0e2010-04-22 05:17:153406 // Check the texture exists
3407 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:033408 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:293409 SetGLError(GL_INVALID_OPERATION,
3410 "glBindTexture: texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:153411 return;
3412 }
[email protected]b0af4f52011-09-28 22:04:423413 if (info->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
3414 SetGLError(GL_INVALID_OPERATION,
3415 "glBindTexture: illegal target for stream texture.");
3416 return;
3417 }
[email protected]1958e0e2010-04-22 05:17:153418 if (info->target() == 0) {
[email protected]80eb6b52012-01-19 00:14:413419 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:473420 }
[email protected]ae51d192010-04-27 00:48:033421 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:503422 TextureUnit& unit = texture_units_[active_texture_unit_];
3423 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:473424 switch (target) {
3425 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:503426 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:473427 break;
3428 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:503429 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:473430 break;
[email protected]61eeb33f2011-07-26 15:30:313431 case GL_TEXTURE_EXTERNAL_OES:
3432 unit.bound_texture_external_oes = info;
[email protected]b0af4f52011-09-28 22:04:423433 if (info->IsStreamTexture()) {
3434 DCHECK(stream_texture_manager_);
3435 StreamTexture* stream_tex =
3436 stream_texture_manager_->LookupStreamTexture(info->service_id());
3437 if (stream_tex)
3438 stream_tex->Update();
3439 }
[email protected]61eeb33f2011-07-26 15:30:313440 break;
[email protected]e51bdf32011-11-23 22:21:463441 case GL_TEXTURE_RECTANGLE_ARB:
3442 unit.bound_texture_rectangle_arb = info;
3443 break;
[email protected]a93bb842010-02-16 23:03:473444 default:
3445 NOTREACHED(); // Validation should prevent us getting here.
3446 break;
3447 }
3448}
3449
[email protected]07f54fcc2009-12-22 02:46:303450void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443451 if (vertex_attrib_manager_->Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:123452 if (index != 0 ||
3453 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:243454 glDisableVertexAttribArray(index);
3455 }
[email protected]07f54fcc2009-12-22 02:46:303456 } else {
[email protected]8eee29c2010-04-29 03:38:293457 SetGLError(GL_INVALID_VALUE,
3458 "glDisableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:303459 }
3460}
3461
3462void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443463 if (vertex_attrib_manager_->Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:303464 glEnableVertexAttribArray(index);
3465 } else {
[email protected]8eee29c2010-04-29 03:38:293466 SetGLError(GL_INVALID_VALUE,
3467 "glEnableVertexAttribArray: index out of range");
[email protected]07f54fcc2009-12-22 02:46:303468 }
3469}
3470
[email protected]a93bb842010-02-16 23:03:473471void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:503472 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]97dc7cbe2011-12-06 17:26:173473 if (!info ||
[email protected]38c0a972012-05-12 00:48:023474 !texture_manager()->CanGenerateMipmaps(info)) {
[email protected]8eee29c2010-04-29 03:38:293475 SetGLError(GL_INVALID_OPERATION,
[email protected]237bad712012-04-05 20:04:023476 "glGenerateMipmaps: Can not generate mips");
[email protected]a93bb842010-02-16 23:03:473477 return;
3478 }
[email protected]38c0a972012-05-12 00:48:023479
3480 CopyRealGLErrorsToWrapper();
[email protected]59f3ca02011-03-26 22:24:193481 // Workaround for Mac driver bug. In the large scheme of things setting
3482 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
[email protected]a8bad262011-10-21 18:28:563483 // hit so there's probably no need to make this conditional. The bug appears
3484 // to be that if the filtering mode is set to something that doesn't require
3485 // mipmaps for rendering, or is never set to something other than the default,
3486 // then glGenerateMipmap misbehaves.
[email protected]c892a4e12012-05-08 18:20:193487 if (!disable_workarounds_) {
3488 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3489 }
[email protected]a93bb842010-02-16 23:03:473490 glGenerateMipmapEXT(target);
[email protected]c892a4e12012-05-08 18:20:193491 if (!disable_workarounds_) {
3492 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
3493 }
[email protected]38c0a972012-05-12 00:48:023494 GLenum error = PeekGLError();
3495 if (error == GL_NO_ERROR) {
3496 texture_manager()->MarkMipmapsGenerated(info);
3497 }
[email protected]a93bb842010-02-16 23:03:473498}
3499
[email protected]b273e432010-04-12 17:23:583500bool GLES2DecoderImpl::GetHelper(
3501 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:583502 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:153503 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
3504 switch (pname) {
[email protected]b273e432010-04-12 17:23:583505 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
3506 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103507 if (params) {
[email protected]5094b0f2010-11-09 19:45:243508 *params = GL_RGBA; // We don't support other formats.
[email protected]4e8a5b122010-05-08 22:00:103509 }
[email protected]b273e432010-04-12 17:23:583510 return true;
3511 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3512 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103513 if (params) {
[email protected]5094b0f2010-11-09 19:45:243514 *params = GL_UNSIGNED_BYTE; // We don't support other types.
[email protected]4e8a5b122010-05-08 22:00:103515 }
[email protected]b273e432010-04-12 17:23:583516 return true;
3517 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
3518 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103519 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483520 *params = group_->max_fragment_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:103521 }
[email protected]b273e432010-04-12 17:23:583522 return true;
3523 case GL_MAX_VARYING_VECTORS:
3524 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103525 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483526 *params = group_->max_varying_vectors();
[email protected]4e8a5b122010-05-08 22:00:103527 }
[email protected]b273e432010-04-12 17:23:583528 return true;
3529 case GL_MAX_VERTEX_UNIFORM_VECTORS:
3530 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103531 if (params) {
[email protected]8f1ccdac2010-05-19 21:01:483532 *params = group_->max_vertex_uniform_vectors();
[email protected]4e8a5b122010-05-08 22:00:103533 }
[email protected]b273e432010-04-12 17:23:583534 return true;
[email protected]5cb735d2011-10-13 01:37:233535 }
3536 }
3537 switch (pname) {
[email protected]5094b0f2010-11-09 19:45:243538 case GL_MAX_VIEWPORT_DIMS:
3539 if (offscreen_target_frame_buffer_.get()) {
3540 *num_written = 2;
3541 if (params) {
3542 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3543 params[1] = renderbuffer_manager()->max_renderbuffer_size();
3544 }
3545 return true;
3546 }
[email protected]5cb735d2011-10-13 01:37:233547 return false;
[email protected]84afefa2011-10-19 21:45:533548 case GL_MAX_SAMPLES:
3549 *num_written = 1;
3550 if (params) {
3551 params[0] = renderbuffer_manager()->max_samples();
3552 }
3553 return true;
3554 case GL_MAX_RENDERBUFFER_SIZE:
3555 *num_written = 1;
3556 if (params) {
3557 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3558 }
3559 return true;
[email protected]5cb735d2011-10-13 01:37:233560 case GL_MAX_TEXTURE_SIZE:
3561 *num_written = 1;
3562 if (params) {
3563 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
3564 }
3565 return true;
3566 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
3567 *num_written = 1;
3568 if (params) {
3569 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
3570 }
3571 return true;
[email protected]297ca1c2011-06-20 23:08:463572 case GL_COLOR_WRITEMASK:
3573 *num_written = 4;
3574 if (params) {
3575 params[0] = mask_red_;
3576 params[1] = mask_green_;
3577 params[2] = mask_blue_;
3578 params[3] = mask_alpha_;
3579 }
3580 return true;
3581 case GL_DEPTH_WRITEMASK:
3582 *num_written = 1;
3583 if (params) {
3584 params[0] = mask_depth_;
3585 }
3586 return true;
3587 case GL_STENCIL_BACK_WRITEMASK:
3588 *num_written = 1;
3589 if (params) {
3590 params[0] = mask_stencil_back_;
3591 }
3592 return true;
3593 case GL_STENCIL_WRITEMASK:
3594 *num_written = 1;
3595 if (params) {
3596 params[0] = mask_stencil_front_;
3597 }
3598 return true;
3599 case GL_DEPTH_TEST:
3600 *num_written = 1;
3601 if (params) {
3602 params[0] = enable_depth_test_;
3603 }
3604 return true;
3605 case GL_STENCIL_TEST:
3606 *num_written = 1;
3607 if (params) {
3608 params[0] = enable_stencil_test_;
3609 }
3610 return true;
3611 case GL_ALPHA_BITS:
3612 *num_written = 1;
3613 if (params) {
3614 GLint v = 0;
3615 glGetIntegerv(GL_ALPHA_BITS, &v);
3616 params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0;
3617 }
3618 return true;
3619 case GL_DEPTH_BITS:
3620 *num_written = 1;
3621 if (params) {
3622 GLint v = 0;
3623 glGetIntegerv(GL_DEPTH_BITS, &v);
3624 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
3625 }
3626 return true;
3627 case GL_STENCIL_BITS:
3628 *num_written = 1;
3629 if (params) {
3630 GLint v = 0;
3631 glGetIntegerv(GL_STENCIL_BITS, &v);
3632 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
3633 }
3634 return true;
[email protected]656dcaad2010-05-07 17:18:373635 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113636 *num_written = validators_->compressed_texture_format.GetValues().size();
3637 if (params) {
3638 for (GLint ii = 0; ii < *num_written; ++ii) {
3639 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
3640 }
3641 }
[email protected]656dcaad2010-05-07 17:18:373642 return true;
[email protected]b273e432010-04-12 17:23:583643 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
3644 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103645 if (params) {
[email protected]302ce6d2011-07-07 23:28:113646 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103647 }
[email protected]b273e432010-04-12 17:23:583648 return true;
3649 case GL_NUM_SHADER_BINARY_FORMATS:
3650 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103651 if (params) {
[email protected]302ce6d2011-07-07 23:28:113652 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103653 }
[email protected]b273e432010-04-12 17:23:583654 return true;
3655 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113656 *num_written = validators_->shader_binary_format.GetValues().size();
3657 if (params) {
3658 for (GLint ii = 0; ii < *num_written; ++ii) {
3659 params[ii] = validators_->shader_binary_format.GetValues()[ii];
3660 }
3661 }
3662 return true;
[email protected]b273e432010-04-12 17:23:583663 case GL_SHADER_COMPILER:
3664 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103665 if (params) {
3666 *params = GL_TRUE;
3667 }
[email protected]b273e432010-04-12 17:23:583668 return true;
[email protected]6b8cf1a2010-05-06 16:13:583669 case GL_ARRAY_BUFFER_BINDING:
3670 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103671 if (params) {
3672 if (bound_array_buffer_) {
3673 GLuint client_id = 0;
3674 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
3675 &client_id);
3676 *params = client_id;
3677 } else {
3678 *params = 0;
3679 }
[email protected]6b8cf1a2010-05-06 16:13:583680 }
3681 return true;
3682 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3683 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103684 if (params) {
3685 if (bound_element_array_buffer_) {
3686 GLuint client_id = 0;
3687 buffer_manager()->GetClientId(
3688 bound_element_array_buffer_->service_id(),
3689 &client_id);
3690 *params = client_id;
3691 } else {
3692 *params = 0;
3693 }
[email protected]6b8cf1a2010-05-06 16:13:583694 }
3695 return true;
3696 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:303697 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:583698 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103699 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203700 FramebufferManager::FramebufferInfo* framebuffer =
3701 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3702 if (framebuffer) {
[email protected]4e8a5b122010-05-08 22:00:103703 GLuint client_id = 0;
3704 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203705 framebuffer->service_id(), &client_id);
[email protected]8e3e0662010-08-23 18:46:303706 *params = client_id;
3707 } else {
3708 *params = 0;
3709 }
3710 }
3711 return true;
3712 case GL_READ_FRAMEBUFFER_BINDING:
3713 *num_written = 1;
3714 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203715 FramebufferManager::FramebufferInfo* framebuffer =
3716 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
3717 if (framebuffer) {
[email protected]8e3e0662010-08-23 18:46:303718 GLuint client_id = 0;
3719 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203720 framebuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103721 *params = client_id;
3722 } else {
3723 *params = 0;
3724 }
[email protected]6b8cf1a2010-05-06 16:13:583725 }
3726 return true;
3727 case GL_RENDERBUFFER_BINDING:
3728 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103729 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203730 RenderbufferManager::RenderbufferInfo* renderbuffer =
3731 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
3732 if (renderbuffer) {
[email protected]4e8a5b122010-05-08 22:00:103733 GLuint client_id = 0;
3734 renderbuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203735 renderbuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103736 *params = client_id;
3737 } else {
3738 *params = 0;
3739 }
[email protected]6b8cf1a2010-05-06 16:13:583740 }
3741 return true;
3742 case GL_CURRENT_PROGRAM:
3743 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103744 if (params) {
3745 if (current_program_) {
3746 GLuint client_id = 0;
3747 program_manager()->GetClientId(
3748 current_program_->service_id(), &client_id);
3749 *params = client_id;
3750 } else {
3751 *params = 0;
3752 }
[email protected]6b8cf1a2010-05-06 16:13:583753 }
3754 return true;
[email protected]4e8a5b122010-05-08 22:00:103755 case GL_TEXTURE_BINDING_2D:
3756 *num_written = 1;
3757 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583758 TextureUnit& unit = texture_units_[active_texture_unit_];
3759 if (unit.bound_texture_2d) {
3760 GLuint client_id = 0;
3761 texture_manager()->GetClientId(
3762 unit.bound_texture_2d->service_id(), &client_id);
3763 *params = client_id;
3764 } else {
3765 *params = 0;
3766 }
[email protected]6b8cf1a2010-05-06 16:13:583767 }
[email protected]4e8a5b122010-05-08 22:00:103768 return true;
3769 case GL_TEXTURE_BINDING_CUBE_MAP:
3770 *num_written = 1;
3771 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583772 TextureUnit& unit = texture_units_[active_texture_unit_];
3773 if (unit.bound_texture_cube_map) {
3774 GLuint client_id = 0;
3775 texture_manager()->GetClientId(
3776 unit.bound_texture_cube_map->service_id(), &client_id);
3777 *params = client_id;
3778 } else {
3779 *params = 0;
3780 }
[email protected]6b8cf1a2010-05-06 16:13:583781 }
[email protected]4e8a5b122010-05-08 22:00:103782 return true;
[email protected]61eeb33f2011-07-26 15:30:313783 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3784 *num_written = 1;
3785 if (params) {
3786 TextureUnit& unit = texture_units_[active_texture_unit_];
3787 if (unit.bound_texture_external_oes) {
3788 GLuint client_id = 0;
3789 texture_manager()->GetClientId(
3790 unit.bound_texture_external_oes->service_id(), &client_id);
3791 *params = client_id;
3792 } else {
3793 *params = 0;
3794 }
3795 }
3796 return true;
[email protected]e51bdf32011-11-23 22:21:463797 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
3798 *num_written = 1;
3799 if (params) {
3800 TextureUnit& unit = texture_units_[active_texture_unit_];
3801 if (unit.bound_texture_rectangle_arb) {
3802 GLuint client_id = 0;
3803 texture_manager()->GetClientId(
3804 unit.bound_texture_rectangle_arb->service_id(), &client_id);
3805 *params = client_id;
3806 } else {
3807 *params = 0;
3808 }
3809 }
3810 return true;
[email protected]b273e432010-04-12 17:23:583811 default:
[email protected]4e8a5b122010-05-08 22:00:103812 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533813 return false;
[email protected]b273e432010-04-12 17:23:583814 }
3815}
3816
[email protected]4e8a5b122010-05-08 22:00:103817bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3818 GLenum pname, GLsizei* num_values) {
3819 return GetHelper(pname, NULL, num_values);
3820}
3821
[email protected]b273e432010-04-12 17:23:583822void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3823 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103824 GLsizei num_written = 0;
3825 if (GetHelper(pname, NULL, &num_written)) {
3826 scoped_array<GLint> values(new GLint[num_written]);
3827 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583828 for (GLsizei ii = 0; ii < num_written; ++ii) {
3829 params[ii] = static_cast<GLboolean>(values[ii]);
3830 }
3831 } else {
3832 glGetBooleanv(pname, params);
3833 }
3834}
3835
3836void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3837 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103838 GLsizei num_written = 0;
3839 if (GetHelper(pname, NULL, &num_written)) {
3840 scoped_array<GLint> values(new GLint[num_written]);
3841 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583842 for (GLsizei ii = 0; ii < num_written; ++ii) {
3843 params[ii] = static_cast<GLfloat>(values[ii]);
3844 }
3845 } else {
3846 glGetFloatv(pname, params);
3847 }
3848}
3849
3850void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3851 DCHECK(params);
3852 GLsizei num_written;
3853 if (!GetHelper(pname, params, &num_written)) {
3854 glGetIntegerv(pname, params);
3855 }
3856}
3857
[email protected]a0c3e972010-04-21 00:49:133858void GLES2DecoderImpl::DoGetProgramiv(
3859 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583860 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3861 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133862 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133863 return;
3864 }
3865 info->GetProgramiv(pname, params);
3866}
3867
[email protected]258a3313f2011-10-18 20:13:573868void GLES2DecoderImpl::DoBindAttribLocation(
3869 GLuint program, GLuint index, const char* name) {
3870 if (!StringIsValidForGLES(name)) {
3871 SetGLError(GL_INVALID_VALUE, "glBindAttribLocation: Invalid character");
3872 return;
3873 }
[email protected]68dcb1f2012-04-07 00:14:563874 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
3875 SetGLError(GL_INVALID_OPERATION, "glBindAttribLocation: reserved prefix");
3876 return;
3877 }
3878 if (index >= group_->max_vertex_attribs()) {
3879 SetGLError(GL_INVALID_VALUE, "glBindAttribLocation: index out of range");
3880 return;
3881 }
[email protected]6b8cf1a2010-05-06 16:13:583882 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3883 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033884 if (!info) {
[email protected]258a3313f2011-10-18 20:13:573885 return;
[email protected]558847a2010-03-24 07:02:543886 }
[email protected]c3e4c4e2012-03-02 19:23:243887 info->SetAttribLocationBinding(name, static_cast<GLint>(index));
[email protected]258a3313f2011-10-18 20:13:573888 glBindAttribLocation(info->service_id(), index, name);
3889}
3890
3891error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3892 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
3893 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543894 GLuint index = static_cast<GLuint>(c.index);
3895 uint32 name_size = c.data_size;
3896 const char* name = GetSharedMemoryAs<const char*>(
3897 c.name_shm_id, c.name_shm_offset, name_size);
3898 if (name == NULL) {
3899 return error::kOutOfBounds;
3900 }
3901 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573902 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543903 return error::kNoError;
3904}
3905
3906error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3907 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583908 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543909 GLuint index = static_cast<GLuint>(c.index);
3910 uint32 name_size = c.data_size;
3911 const char* name = GetImmediateDataAs<const char*>(
3912 c, name_size, immediate_data_size);
3913 if (name == NULL) {
3914 return error::kOutOfBounds;
3915 }
3916 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573917 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543918 return error::kNoError;
3919}
3920
3921error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3922 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583923 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543924 GLuint index = static_cast<GLuint>(c.index);
3925 Bucket* bucket = GetBucket(c.name_bucket_id);
3926 if (!bucket || bucket->size() == 0) {
3927 return error::kInvalidArguments;
3928 }
3929 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183930 if (!bucket->GetAsString(&name_str)) {
3931 return error::kInvalidArguments;
3932 }
[email protected]258a3313f2011-10-18 20:13:573933 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543934 return error::kNoError;
3935}
3936
[email protected]f7a64ee2010-02-01 22:24:143937error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463938 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033939 GLuint client_id = c.shader;
3940 if (client_id) {
3941 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3942 if (info) {
[email protected]ca488e12010-12-13 20:06:143943 if (!info->IsDeleted()) {
3944 glDeleteShader(info->service_id());
3945 shader_manager()->MarkAsDeleted(info);
3946 }
[email protected]ae51d192010-04-27 00:48:033947 } else {
[email protected]8eee29c2010-04-29 03:38:293948 SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
[email protected]ae51d192010-04-27 00:48:033949 }
[email protected]96449d2c2009-11-25 00:01:323950 }
[email protected]f7a64ee2010-02-01 22:24:143951 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323952}
3953
[email protected]f7a64ee2010-02-01 22:24:143954error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:463955 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:033956 GLuint client_id = c.program;
3957 if (client_id) {
3958 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
3959 if (info) {
[email protected]ca488e12010-12-13 20:06:143960 if (!info->IsDeleted()) {
[email protected]ca488e12010-12-13 20:06:143961 program_manager()->MarkAsDeleted(shader_manager(), info);
3962 }
[email protected]ae51d192010-04-27 00:48:033963 } else {
[email protected]8eee29c2010-04-29 03:38:293964 SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
[email protected]ae51d192010-04-27 00:48:033965 }
[email protected]96449d2c2009-11-25 00:01:323966 }
[email protected]f7a64ee2010-02-01 22:24:143967 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:323968}
3969
[email protected]269200b12010-11-18 22:53:063970void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:103971 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:573972 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:103973 for (GLsizei ii = 0; ii < n; ++ii) {
3974 id_allocator->FreeID(ids[ii]);
3975 }
3976}
3977
[email protected]269200b12010-11-18 22:53:063978error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
3979 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:103980 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
3981 GLsizei n = static_cast<GLsizei>(c.n);
3982 uint32 data_size;
3983 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
3984 return error::kOutOfBounds;
3985 }
3986 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
3987 c.ids_shm_id, c.ids_shm_offset, data_size);
3988 if (n < 0) {
[email protected]269200b12010-11-18 22:53:063989 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:103990 return error::kNoError;
3991 }
3992 if (ids == NULL) {
3993 return error::kOutOfBounds;
3994 }
[email protected]269200b12010-11-18 22:53:063995 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:103996 return error::kNoError;
3997}
3998
[email protected]269200b12010-11-18 22:53:063999void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104000 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574001 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104002 if (id_offset == 0) {
4003 for (GLsizei ii = 0; ii < n; ++ii) {
4004 ids[ii] = id_allocator->AllocateID();
4005 }
4006 } else {
4007 for (GLsizei ii = 0; ii < n; ++ii) {
4008 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4009 id_offset = ids[ii] + 1;
4010 }
4011 }
4012}
4013
[email protected]269200b12010-11-18 22:53:064014error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4015 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104016 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4017 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4018 GLsizei n = static_cast<GLsizei>(c.n);
4019 uint32 data_size;
4020 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4021 return error::kOutOfBounds;
4022 }
4023 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4024 c.ids_shm_id, c.ids_shm_offset, data_size);
4025 if (n < 0) {
[email protected]269200b12010-11-18 22:53:064026 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:104027 return error::kNoError;
4028 }
4029 if (ids == NULL) {
4030 return error::kOutOfBounds;
4031 }
[email protected]269200b12010-11-18 22:53:064032 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:104033 return error::kNoError;
4034}
4035
[email protected]269200b12010-11-18 22:53:064036void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104037 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574038 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104039 for (GLsizei ii = 0; ii < n; ++ii) {
4040 if (!id_allocator->MarkAsUsed(ids[ii])) {
4041 for (GLsizei jj = 0; jj < ii; ++jj) {
4042 id_allocator->FreeID(ids[jj]);
4043 }
4044 SetGLError(
4045 GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:064046 "RegisterSharedIdsCHROMIUM: attempt to register "
4047 "id that already exists");
[email protected]066849e32010-05-03 19:14:104048 return;
4049 }
4050 }
4051}
4052
[email protected]269200b12010-11-18 22:53:064053error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4054 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104055 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4056 GLsizei n = static_cast<GLsizei>(c.n);
4057 uint32 data_size;
4058 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4059 return error::kOutOfBounds;
4060 }
4061 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4062 c.ids_shm_id, c.ids_shm_offset, data_size);
4063 if (n < 0) {
[email protected]269200b12010-11-18 22:53:064064 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM: n < 0");
[email protected]066849e32010-05-03 19:14:104065 return error::kNoError;
4066 }
4067 if (ids == NULL) {
4068 return error::kOutOfBounds;
4069 }
[email protected]269200b12010-11-18 22:53:064070 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:104071 return error::kNoError;
4072}
4073
[email protected]3a03a8f2011-03-19 00:51:274074void GLES2DecoderImpl::DoClear(GLbitfield mask) {
[email protected]0d6bfdc2011-11-02 01:32:204075 if (CheckBoundFramebuffersValid("glClear")) {
[email protected]529c6672012-01-04 02:18:264076 UNSHIPPED_TRACE_EVENT_INSTANT2("test_gpu", "DoClear", "red", clear_red_,
4077 "green", clear_green_);
[email protected]297ca1c2011-06-20 23:08:464078 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:274079 glClear(mask);
4080 }
4081}
4082
[email protected]36cef8ce2010-03-16 07:34:454083void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4084 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:034085 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:304086 FramebufferManager::FramebufferInfo* framebuffer_info =
4087 GetFramebufferInfoForTarget(target);
4088 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294089 SetGLError(GL_INVALID_OPERATION,
4090 "glFramebufferRenderbuffer: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454091 return;
4092 }
[email protected]ae51d192010-04-27 00:48:034093 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:284094 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:034095 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:284096 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:034097 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294098 SetGLError(GL_INVALID_OPERATION,
4099 "glFramebufferRenderbuffer: unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:034100 return;
4101 }
4102 service_id = info->service_id();
4103 }
[email protected]9edc6b22010-12-23 02:00:264104 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034105 glFramebufferRenderbufferEXT(
4106 target, attachment, renderbuffertarget, service_id);
[email protected]1002c2d2011-06-28 22:39:044107 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264108 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:304109 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]3a2e7c7b2010-08-06 01:12:284110 }
[email protected]297ca1c2011-06-20 23:08:464111 if (framebuffer_info == bound_draw_framebuffer_) {
4112 state_dirty_ = true;
4113 }
[email protected]3a2e7c7b2010-08-06 01:12:284114}
4115
[email protected]297ca1c2011-06-20 23:08:464116bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
[email protected]3a2e7c7b2010-08-06 01:12:284117 switch (cap) {
[email protected]0a1e9ad2012-05-04 21:13:034118 case GL_BLEND:
4119 enable_blend_ = enabled;
4120 return true;
[email protected]43410e92012-04-20 17:06:284121 case GL_CULL_FACE:
4122 enable_cull_face_ = enabled;
4123 return true;
[email protected]3a2e7c7b2010-08-06 01:12:284124 case GL_SCISSOR_TEST:
4125 enable_scissor_test_ = enabled;
[email protected]297ca1c2011-06-20 23:08:464126 return true;
4127 case GL_DEPTH_TEST: {
4128 if (enable_depth_test_ != enabled) {
4129 enable_depth_test_ = enabled;
4130 state_dirty_ = true;
4131 }
4132 return false;
4133 }
4134 case GL_STENCIL_TEST:
4135 if (enable_stencil_test_ != enabled) {
4136 enable_stencil_test_ = enabled;
4137 state_dirty_ = true;
4138 }
4139 return false;
[email protected]3a2e7c7b2010-08-06 01:12:284140 default:
[email protected]297ca1c2011-06-20 23:08:464141 return true;
[email protected]3a2e7c7b2010-08-06 01:12:284142 }
4143}
4144
4145void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464146 if (SetCapabilityState(cap, false)) {
4147 glDisable(cap);
4148 }
[email protected]3a2e7c7b2010-08-06 01:12:284149}
4150
4151void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464152 if (SetCapabilityState(cap, true)) {
4153 glEnable(cap);
4154 }
[email protected]3a2e7c7b2010-08-06 01:12:284155}
4156
[email protected]3dc69c42012-05-12 02:29:244157bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
4158 switch (cap) {
4159 case GL_BLEND:
4160 return enable_blend_;
4161 case GL_CULL_FACE:
4162 return enable_cull_face_;
4163 case GL_SCISSOR_TEST:
4164 return enable_scissor_test_;
4165 case GL_DEPTH_TEST:
4166 return enable_depth_test_;
4167 case GL_STENCIL_TEST:
4168 return enable_stencil_test_;
4169 default:
4170 return glIsEnabled(cap) != 0;
4171 }
4172}
4173
[email protected]3a2e7c7b2010-08-06 01:12:284174void GLES2DecoderImpl::DoClearColor(
4175 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
4176 clear_red_ = red;
4177 clear_green_ = green;
4178 clear_blue_ = blue;
4179 clear_alpha_ = alpha;
4180 glClearColor(red, green, blue, alpha);
4181}
4182
4183void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
4184 clear_depth_ = depth;
4185 glClearDepth(depth);
4186}
4187
4188void GLES2DecoderImpl::DoClearStencil(GLint s) {
4189 clear_stencil_ = s;
4190 glClearStencil(s);
4191}
4192
4193void GLES2DecoderImpl::DoColorMask(
4194 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
4195 mask_red_ = red;
4196 mask_green_ = green;
4197 mask_blue_ = blue;
4198 mask_alpha_ = alpha;
[email protected]297ca1c2011-06-20 23:08:464199 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284200}
4201
4202void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
4203 mask_depth_ = depth;
[email protected]297ca1c2011-06-20 23:08:464204 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284205}
4206
4207void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
4208 mask_stencil_front_ = mask;
4209 mask_stencil_back_ = mask;
[email protected]297ca1c2011-06-20 23:08:464210 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284211}
4212
4213void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
[email protected]297ca1c2011-06-20 23:08:464214 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284215 mask_stencil_front_ = mask;
[email protected]297ca1c2011-06-20 23:08:464216 }
4217 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284218 mask_stencil_back_ = mask;
4219 }
[email protected]297ca1c2011-06-20 23:08:464220 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284221}
4222
[email protected]0d6bfdc2011-11-02 01:32:204223// Assumes framebuffer is complete.
4224void GLES2DecoderImpl::ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:304225 GLenum target, FramebufferManager::FramebufferInfo* info) {
4226 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204227 // bind this to the DRAW point, clear then bind back to READ
4228 // TODO(gman): I don't think there is any guarantee that an FBO that
4229 // is complete on the READ attachment will be complete as a DRAW
4230 // attachment.
4231 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
4232 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, info->service_id());
[email protected]8e3e0662010-08-23 18:46:304233 }
[email protected]3a2e7c7b2010-08-06 01:12:284234 GLbitfield clear_bits = 0;
4235 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:464236 glClearColor(
[email protected]0d6bfdc2011-11-02 01:32:204237 0.0f, 0.0f, 0.0f,
[email protected]297ca1c2011-06-20 23:08:464238 (GLES2Util::GetChannelsForFormat(
[email protected]0d6bfdc2011-11-02 01:32:204239 info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f : 1.0f);
[email protected]3a2e7c7b2010-08-06 01:12:284240 glColorMask(true, true, true, true);
4241 clear_bits |= GL_COLOR_BUFFER_BIT;
4242 }
4243
4244 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4245 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4246 glClearStencil(0);
4247 glStencilMask(-1);
4248 clear_bits |= GL_STENCIL_BUFFER_BIT;
4249 }
4250
4251 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4252 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4253 glClearDepth(1.0f);
4254 glDepthMask(true);
4255 clear_bits |= GL_DEPTH_BUFFER_BIT;
4256 }
4257
4258 glDisable(GL_SCISSOR_TEST);
4259 glClear(clear_bits);
4260
[email protected]968351b2011-12-20 08:26:514261 framebuffer_manager()->MarkAttachmentsAsCleared(
4262 info, renderbuffer_manager(), texture_manager());
[email protected]3a2e7c7b2010-08-06 01:12:284263
[email protected]c007aa02010-09-02 22:22:404264 RestoreClearState();
4265
4266 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204267 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, info->service_id());
[email protected]87d1a3fe2011-12-01 04:25:484268 FramebufferManager::FramebufferInfo* framebuffer =
4269 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4270 GLuint service_id =
4271 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
4272 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
[email protected]c007aa02010-09-02 22:22:404273 }
4274}
4275
4276void GLES2DecoderImpl::RestoreClearState() {
[email protected]297ca1c2011-06-20 23:08:464277 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284278 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
[email protected]3a2e7c7b2010-08-06 01:12:284279 glClearStencil(clear_stencil_);
[email protected]3a2e7c7b2010-08-06 01:12:284280 glClearDepth(clear_depth_);
[email protected]3a2e7c7b2010-08-06 01:12:284281 if (enable_scissor_test_) {
4282 glEnable(GL_SCISSOR_TEST);
4283 }
[email protected]36cef8ce2010-03-16 07:34:454284}
4285
4286GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]0d6bfdc2011-11-02 01:32:204287 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]8e3e0662010-08-23 18:46:304288 GetFramebufferInfoForTarget(target);
[email protected]0d6bfdc2011-11-02 01:32:204289 if (!framebuffer) {
[email protected]36cef8ce2010-03-16 07:34:454290 return GL_FRAMEBUFFER_COMPLETE;
4291 }
[email protected]0d6bfdc2011-11-02 01:32:204292 GLenum completeness = framebuffer->IsPossiblyComplete();
4293 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4294 return completeness;
4295 }
[email protected]36cef8ce2010-03-16 07:34:454296 return glCheckFramebufferStatusEXT(target);
4297}
4298
4299void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:034300 GLenum target, GLenum attachment, GLenum textarget,
4301 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:304302 FramebufferManager::FramebufferInfo* framebuffer_info =
4303 GetFramebufferInfoForTarget(target);
4304 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294305 SetGLError(GL_INVALID_OPERATION,
4306 "glFramebufferTexture2D: no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:454307 return;
4308 }
[email protected]ae51d192010-04-27 00:48:034309 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:284310 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:034311 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:284312 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:034313 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294314 SetGLError(GL_INVALID_OPERATION,
4315 "glFramebufferTexture2D: unknown texture");
[email protected]ae51d192010-04-27 00:48:034316 return;
4317 }
4318 service_id = info->service_id();
4319 }
[email protected]0d6bfdc2011-11-02 01:32:204320
[email protected]80eb6b52012-01-19 00:14:414321 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
[email protected]0d6bfdc2011-11-02 01:32:204322 SetGLError(GL_INVALID_VALUE,
4323 "glFramebufferTexture2D: level out of range");
4324 return;
4325 }
4326
[email protected]9edc6b22010-12-23 02:00:264327 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034328 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]1002c2d2011-06-28 22:39:044329 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264330 if (error == GL_NO_ERROR) {
4331 framebuffer_info->AttachTexture(attachment, info, textarget, level);
[email protected]3a2e7c7b2010-08-06 01:12:284332 }
[email protected]297ca1c2011-06-20 23:08:464333 if (framebuffer_info == bound_draw_framebuffer_) {
4334 state_dirty_ = true;
4335 }
[email protected]36cef8ce2010-03-16 07:34:454336}
4337
4338void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4339 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:304340 FramebufferManager::FramebufferInfo* framebuffer_info =
4341 GetFramebufferInfoForTarget(target);
4342 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294343 SetGLError(GL_INVALID_OPERATION,
4344 "glFramebufferAttachmentParameteriv: no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454345 return;
4346 }
4347 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:574348 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4349 GLint type = 0;
4350 GLuint client_id = 0;
4351 glGetFramebufferAttachmentParameterivEXT(
4352 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
4353 switch (type) {
4354 case GL_RENDERBUFFER: {
4355 renderbuffer_manager()->GetClientId(*params, &client_id);
4356 break;
4357 }
4358 case GL_TEXTURE: {
4359 texture_manager()->GetClientId(*params, &client_id);
4360 break;
4361 }
4362 default:
4363 break;
4364 }
4365 *params = client_id;
4366 }
[email protected]36cef8ce2010-03-16 07:34:454367}
4368
4369void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4370 GLenum target, GLenum pname, GLint* params) {
[email protected]0d6bfdc2011-11-02 01:32:204371 RenderbufferManager::RenderbufferInfo* renderbuffer =
4372 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4373 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294374 SetGLError(GL_INVALID_OPERATION,
4375 "glGetRenderbufferParameteriv: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454376 return;
4377 }
[email protected]3a03a8f2011-03-19 00:51:274378 switch (pname) {
4379 case GL_RENDERBUFFER_INTERNAL_FORMAT:
[email protected]0d6bfdc2011-11-02 01:32:204380 *params = renderbuffer->internal_format();
[email protected]3a03a8f2011-03-19 00:51:274381 break;
4382 case GL_RENDERBUFFER_WIDTH:
[email protected]0d6bfdc2011-11-02 01:32:204383 *params = renderbuffer->width();
[email protected]3a03a8f2011-03-19 00:51:274384 break;
4385 case GL_RENDERBUFFER_HEIGHT:
[email protected]0d6bfdc2011-11-02 01:32:204386 *params = renderbuffer->height();
[email protected]3a03a8f2011-03-19 00:51:274387 break;
4388 default:
4389 glGetRenderbufferParameterivEXT(target, pname, params);
4390 break;
[email protected]b71f52c2010-06-18 22:20:204391 }
[email protected]36cef8ce2010-03-16 07:34:454392}
4393
[email protected]8e3e0662010-08-23 18:46:304394void GLES2DecoderImpl::DoBlitFramebufferEXT(
4395 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
4396 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
4397 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:394398 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304399 SetGLError(GL_INVALID_OPERATION,
4400 "glBlitFramebufferEXT: function not available");
4401 }
[email protected]5094b0f2010-11-09 19:45:244402 if (IsAngle()) {
4403 glBlitFramebufferANGLE(
4404 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4405 } else {
4406 glBlitFramebufferEXT(
4407 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4408 }
[email protected]529c6672012-01-04 02:18:264409 UNSHIPPED_TRACE_EVENT_INSTANT1("test_gpu", "DoBlit", "width", srcX1 - srcX0);
[email protected]8e3e0662010-08-23 18:46:304410}
4411
4412void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
4413 GLenum target, GLsizei samples, GLenum internalformat,
4414 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:394415 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304416 SetGLError(GL_INVALID_OPERATION,
4417 "glRenderbufferStorageMultisampleEXT: function not available");
4418 return;
4419 }
[email protected]8e3e0662010-08-23 18:46:304420
[email protected]0d6bfdc2011-11-02 01:32:204421 RenderbufferManager::RenderbufferInfo* renderbuffer =
4422 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4423 if (!renderbuffer) {
4424 SetGLError(GL_INVALID_OPERATION,
4425 "glGetRenderbufferStorageMultisample: no renderbuffer bound");
4426 return;
4427 }
4428
[email protected]84afefa2011-10-19 21:45:534429 if (samples > renderbuffer_manager()->max_samples()) {
4430 SetGLError(GL_INVALID_VALUE,
4431 "glGetRenderbufferStorageMultisample: samples too large");
4432 return;
4433 }
4434
4435 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4436 height > renderbuffer_manager()->max_renderbuffer_size()) {
4437 SetGLError(GL_INVALID_VALUE,
4438 "glGetRenderbufferStorageMultisample: size too large");
4439 return;
4440 }
4441
[email protected]9edc6b22010-12-23 02:00:264442 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:304443 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264444 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:304445 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264446 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:304447 break;
4448 case GL_RGBA4:
4449 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264450 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:304451 break;
4452 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264453 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:304454 break;
4455 }
4456 }
4457
[email protected]9edc6b22010-12-23 02:00:264458 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:084459 if (IsAngle()) {
4460 glRenderbufferStorageMultisampleANGLE(
4461 target, samples, impl_format, width, height);
4462 } else {
4463 glRenderbufferStorageMultisampleEXT(
4464 target, samples, impl_format, width, height);
4465 }
[email protected]1002c2d2011-06-28 22:39:044466 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264467 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514468 // TODO(gman): If renderbuffers tracked which framebuffers they were
4469 // attached to we could just mark those framebuffers as not complete.
4470 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204471 renderbuffer_manager()->SetInfo(
4472 renderbuffer, samples, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264473 }
[email protected]8e3e0662010-08-23 18:46:304474}
4475
[email protected]36cef8ce2010-03-16 07:34:454476void GLES2DecoderImpl::DoRenderbufferStorage(
4477 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]0d6bfdc2011-11-02 01:32:204478 RenderbufferManager::RenderbufferInfo* renderbuffer =
4479 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4480 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294481 SetGLError(GL_INVALID_OPERATION,
4482 "glGetRenderbufferStorage: no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454483 return;
4484 }
[email protected]876f6fee2010-08-02 23:10:324485
[email protected]84afefa2011-10-19 21:45:534486 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4487 height > renderbuffer_manager()->max_renderbuffer_size()) {
4488 SetGLError(GL_INVALID_VALUE,
4489 "glGetRenderbufferStorage: size too large");
4490 return;
4491 }
4492
[email protected]9edc6b22010-12-23 02:00:264493 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:324494 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264495 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:324496 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264497 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:324498 break;
4499 case GL_RGBA4:
4500 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264501 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:324502 break;
4503 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264504 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:324505 break;
4506 }
[email protected]b71f52c2010-06-18 22:20:204507 }
[email protected]876f6fee2010-08-02 23:10:324508
[email protected]9edc6b22010-12-23 02:00:264509 CopyRealGLErrorsToWrapper();
4510 glRenderbufferStorageEXT(target, impl_format, width, height);
[email protected]1002c2d2011-06-28 22:39:044511 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264512 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514513 // TODO(gman): If tetxures tracked which framebuffers they were attached to
4514 // we could just mark those framebuffers as not complete.
4515 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204516 renderbuffer_manager()->SetInfo(
4517 renderbuffer, 0, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264518 }
[email protected]36cef8ce2010-03-16 07:34:454519}
4520
[email protected]07f54fcc2009-12-22 02:46:304521void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]0c8fabf2011-06-14 19:35:224522 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]6b8cf1a2010-05-06 16:13:584523 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4524 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:474525 if (!info) {
[email protected]a93bb842010-02-16 23:03:474526 return;
4527 }
[email protected]05afda12011-01-20 00:17:344528
[email protected]2df73892012-04-28 01:09:544529 if (info->Link()) {
4530 if (info == current_program_.get()) {
4531 program_manager()->ClearUniforms(info);
4532 }
4533 }
[email protected]07f54fcc2009-12-22 02:46:304534};
4535
[email protected]3916c97e2010-02-25 03:20:504536void GLES2DecoderImpl::DoTexParameterf(
4537 GLenum target, GLenum pname, GLfloat param) {
4538 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:304539 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294540 SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244541 return;
[email protected]07f54fcc2009-12-22 02:46:304542 }
[email protected]cbb22e42011-05-12 23:36:244543
4544 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414545 info, pname, static_cast<GLint>(param))) {
[email protected]cbb22e42011-05-12 23:36:244546 SetGLError(GL_INVALID_ENUM, "glTexParameterf: param GL_INVALID_ENUM");
4547 return;
4548 }
4549 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:304550}
4551
[email protected]3916c97e2010-02-25 03:20:504552void GLES2DecoderImpl::DoTexParameteri(
4553 GLenum target, GLenum pname, GLint param) {
4554 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4555 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294556 SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244557 return;
[email protected]3916c97e2010-02-25 03:20:504558 }
[email protected]cbb22e42011-05-12 23:36:244559
[email protected]80eb6b52012-01-19 00:14:414560 if (!texture_manager()->SetParameter(info, pname, param)) {
[email protected]cbb22e42011-05-12 23:36:244561 SetGLError(GL_INVALID_ENUM, "glTexParameteri: param GL_INVALID_ENUM");
4562 return;
4563 }
4564 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:504565}
4566
4567void GLES2DecoderImpl::DoTexParameterfv(
4568 GLenum target, GLenum pname, const GLfloat* params) {
4569 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4570 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294571 SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244572 return;
[email protected]3916c97e2010-02-25 03:20:504573 }
[email protected]cbb22e42011-05-12 23:36:244574
4575 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414576 info, pname, static_cast<GLint>(params[0]))) {
[email protected]cbb22e42011-05-12 23:36:244577 SetGLError(GL_INVALID_ENUM, "glTexParameterfv: param GL_INVALID_ENUM");
4578 return;
4579 }
4580 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504581}
4582
4583void GLES2DecoderImpl::DoTexParameteriv(
4584 GLenum target, GLenum pname, const GLint* params) {
4585 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4586 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294587 SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
[email protected]cbb22e42011-05-12 23:36:244588 return;
[email protected]3916c97e2010-02-25 03:20:504589 }
[email protected]cbb22e42011-05-12 23:36:244590
[email protected]80eb6b52012-01-19 00:14:414591 if (!texture_manager()->SetParameter(info, pname, *params)) {
[email protected]cbb22e42011-05-12 23:36:244592 SetGLError(GL_INVALID_ENUM, "glTexParameteriv: param GL_INVALID_ENUM");
4593 return;
4594 }
4595 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504596}
4597
[email protected]939e7362010-05-13 20:49:104598bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:144599 if (!current_program_) {
[email protected]939e7362010-05-13 20:49:104600 // The program does not exist.
4601 SetGLError(GL_INVALID_OPERATION,
4602 (std::string(function_name) + ": no program in use").c_str());
4603 return false;
4604 }
[email protected]ca488e12010-12-13 20:06:144605 if (!current_program_->InUse()) {
[email protected]939e7362010-05-13 20:49:104606 SetGLError(GL_INVALID_OPERATION,
4607 (std::string(function_name) + ": program not linked").c_str());
4608 return false;
4609 }
4610 return true;
4611}
4612
4613bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
4614 GLint location, const char* function_name) {
4615 if (!CheckCurrentProgram(function_name)) {
4616 return false;
4617 }
4618 return location != -1;
4619}
4620
[email protected]43c2f1f2011-03-25 18:35:364621bool GLES2DecoderImpl::PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124622 GLint fake_location, const char* function_name,
4623 GLint* real_location, GLenum* type, GLsizei* count) {
[email protected]43c2f1f2011-03-25 18:35:364624 DCHECK(type);
4625 DCHECK(count);
[email protected]1b0a6752012-02-22 03:44:124626 DCHECK(real_location);
4627 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
[email protected]939e7362010-05-13 20:49:104628 return false;
4629 }
[email protected]43c2f1f2011-03-25 18:35:364630 GLint array_index = -1;
4631 const ProgramManager::ProgramInfo::UniformInfo* info =
[email protected]1b0a6752012-02-22 03:44:124632 current_program_->GetUniformInfoByFakeLocation(
4633 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:364634 if (!info) {
[email protected]939e7362010-05-13 20:49:104635 SetGLError(GL_INVALID_OPERATION,
[email protected]43c2f1f2011-03-25 18:35:364636 (std::string(function_name) + ": unknown location").c_str());
[email protected]939e7362010-05-13 20:49:104637 return false;
4638 }
[email protected]43c2f1f2011-03-25 18:35:364639 if (*count > 1 && !info->is_array) {
4640 SetGLError(
4641 GL_INVALID_OPERATION,
4642 (std::string(function_name) + ": count > 1 for non-array").c_str());
4643 return false;
4644 }
4645 *count = std::min(info->size - array_index, *count);
4646 if (*count <= 0) {
4647 return false;
4648 }
4649 *type = info->type;
[email protected]939e7362010-05-13 20:49:104650 return true;
4651}
4652
[email protected]1b0a6752012-02-22 03:44:124653void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
4654 GLenum type = 0;
4655 GLsizei count = 1;
4656 GLint real_location = -1;
4657 if (!PrepForSetUniformByLocation(
4658 fake_location, "glUniform1iv", &real_location, &type, &count)) {
[email protected]3916c97e2010-02-25 03:20:504659 return;
4660 }
[email protected]d20a6512012-05-02 20:17:464661 if (!current_program_->SetSamplers(
4662 group_->max_texture_units(), fake_location, 1, &v0)) {
4663 SetGLError(GL_INVALID_VALUE, "glUniform1i: texture unit out of range");
4664 return;
4665 }
[email protected]1b0a6752012-02-22 03:44:124666 glUniform1i(real_location, v0);
[email protected]3916c97e2010-02-25 03:20:504667}
4668
4669void GLES2DecoderImpl::DoUniform1iv(
[email protected]1b0a6752012-02-22 03:44:124670 GLint fake_location, GLsizei count, const GLint *value) {
[email protected]43c2f1f2011-03-25 18:35:364671 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124672 GLint real_location = -1;
4673 if (!PrepForSetUniformByLocation(
4674 fake_location, "glUniform1iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364675 return;
4676 }
[email protected]61eeb33f2011-07-26 15:30:314677 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
4678 type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]d20a6512012-05-02 20:17:464679 if (!current_program_->SetSamplers(
4680 group_->max_texture_units(), fake_location, count, value)) {
4681 SetGLError(GL_INVALID_VALUE, "glUniform1iv: texture unit out of range");
4682 return;
4683 }
[email protected]43c2f1f2011-03-25 18:35:364684 }
[email protected]1b0a6752012-02-22 03:44:124685 glUniform1iv(real_location, count, value);
[email protected]3916c97e2010-02-25 03:20:504686}
4687
[email protected]939e7362010-05-13 20:49:104688void GLES2DecoderImpl::DoUniform1fv(
[email protected]1b0a6752012-02-22 03:44:124689 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364690 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124691 GLint real_location = -1;
4692 if (!PrepForSetUniformByLocation(
4693 fake_location, "glUniform1fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104694 return;
4695 }
4696 if (type == GL_BOOL) {
4697 scoped_array<GLint> temp(new GLint[count]);
4698 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:534699 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104700 }
[email protected]1b0a6752012-02-22 03:44:124701 DoUniform1iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104702 } else {
[email protected]1b0a6752012-02-22 03:44:124703 glUniform1fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104704 }
4705}
4706
4707void GLES2DecoderImpl::DoUniform2fv(
[email protected]1b0a6752012-02-22 03:44:124708 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364709 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124710 GLint real_location = -1;
4711 if (!PrepForSetUniformByLocation(
4712 fake_location, "glUniform2fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104713 return;
4714 }
4715 if (type == GL_BOOL_VEC2) {
4716 GLsizei num_values = count * 2;
4717 scoped_array<GLint> temp(new GLint[num_values]);
4718 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534719 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104720 }
[email protected]1b0a6752012-02-22 03:44:124721 glUniform2iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104722 } else {
[email protected]1b0a6752012-02-22 03:44:124723 glUniform2fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104724 }
4725}
4726
4727void GLES2DecoderImpl::DoUniform3fv(
[email protected]1b0a6752012-02-22 03:44:124728 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364729 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124730 GLint real_location = -1;
4731 if (!PrepForSetUniformByLocation(
4732 fake_location, "glUniform3fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104733 return;
4734 }
4735 if (type == GL_BOOL_VEC3) {
4736 GLsizei num_values = count * 3;
4737 scoped_array<GLint> temp(new GLint[num_values]);
4738 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534739 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104740 }
[email protected]1b0a6752012-02-22 03:44:124741 glUniform3iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104742 } else {
[email protected]1b0a6752012-02-22 03:44:124743 glUniform3fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104744 }
4745}
4746
4747void GLES2DecoderImpl::DoUniform4fv(
[email protected]1b0a6752012-02-22 03:44:124748 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364749 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124750 GLint real_location = -1;
4751 if (!PrepForSetUniformByLocation(
4752 fake_location, "glUniform4fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104753 return;
4754 }
4755 if (type == GL_BOOL_VEC4) {
4756 GLsizei num_values = count * 4;
4757 scoped_array<GLint> temp(new GLint[num_values]);
4758 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534759 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104760 }
[email protected]1b0a6752012-02-22 03:44:124761 glUniform4iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104762 } else {
[email protected]1b0a6752012-02-22 03:44:124763 glUniform4fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104764 }
4765}
4766
[email protected]43c2f1f2011-03-25 18:35:364767void GLES2DecoderImpl::DoUniform2iv(
[email protected]1b0a6752012-02-22 03:44:124768 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364769 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124770 GLint real_location = -1;
4771 if (!PrepForSetUniformByLocation(
4772 fake_location, "glUniform2iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364773 return;
4774 }
[email protected]1b0a6752012-02-22 03:44:124775 glUniform2iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364776}
4777
4778void GLES2DecoderImpl::DoUniform3iv(
[email protected]1b0a6752012-02-22 03:44:124779 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364780 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124781 GLint real_location = -1;
4782 if (!PrepForSetUniformByLocation(
4783 fake_location, "glUniform3iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364784 return;
4785 }
[email protected]1b0a6752012-02-22 03:44:124786 glUniform3iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364787}
4788
4789void GLES2DecoderImpl::DoUniform4iv(
[email protected]1b0a6752012-02-22 03:44:124790 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364791 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124792 GLint real_location = -1;
4793 if (!PrepForSetUniformByLocation(
4794 fake_location, "glUniform4iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364795 return;
4796 }
[email protected]1b0a6752012-02-22 03:44:124797 glUniform4iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364798}
4799
4800void GLES2DecoderImpl::DoUniformMatrix2fv(
[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, "glUniformMatrix2fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364807 return;
4808 }
[email protected]1b0a6752012-02-22 03:44:124809 glUniformMatrix2fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364810}
4811
4812void GLES2DecoderImpl::DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:124813 GLint fake_location, GLsizei count, GLboolean transpose,
4814 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364815 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124816 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364817 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124818 fake_location, "glUniformMatrix3fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364819 return;
4820 }
[email protected]1b0a6752012-02-22 03:44:124821 glUniformMatrix3fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364822}
4823
4824void GLES2DecoderImpl::DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:124825 GLint fake_location, GLsizei count, GLboolean transpose,
4826 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364827 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124828 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364829 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124830 fake_location, "glUniformMatrix4fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364831 return;
4832 }
[email protected]1b0a6752012-02-22 03:44:124833 glUniformMatrix4fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364834}
4835
[email protected]3916c97e2010-02-25 03:20:504836void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:034837 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:504838 ProgramManager::ProgramInfo* info = NULL;
4839 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:584840 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:504841 if (!info) {
[email protected]ae51d192010-04-27 00:48:034842 return;
4843 }
4844 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:504845 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:294846 SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
[email protected]3916c97e2010-02-25 03:20:504847 return;
4848 }
[email protected]ae51d192010-04-27 00:48:034849 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:504850 }
[email protected]ca488e12010-12-13 20:06:144851 if (current_program_) {
4852 program_manager()->UnuseProgram(shader_manager(), current_program_);
4853 }
[email protected]3916c97e2010-02-25 03:20:504854 current_program_ = info;
[email protected]2df73892012-04-28 01:09:544855 glUseProgram(service_id);
[email protected]ca488e12010-12-13 20:06:144856 if (current_program_) {
4857 program_manager()->UseProgram(current_program_);
4858 }
[email protected]3916c97e2010-02-25 03:20:504859}
4860
[email protected]96449d2c2009-11-25 00:01:324861GLenum GLES2DecoderImpl::GetGLError() {
4862 // Check the GL error first, then our wrapped error.
4863 GLenum error = glGetError();
4864 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:374865 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:324866 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:294867 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:324868 break;
4869 }
4870 }
4871 }
4872
4873 if (error != GL_NO_ERROR) {
4874 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:294875 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324876 }
4877 return error;
4878}
4879
[email protected]1002c2d2011-06-28 22:39:044880GLenum GLES2DecoderImpl::PeekGLError() {
4881 GLenum error = glGetError();
4882 if (error != GL_NO_ERROR) {
4883 SetGLError(error, "");
4884 }
4885 return error;
4886}
4887
[email protected]8eee29c2010-04-29 03:38:294888void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
4889 if (msg) {
4890 last_error_ = msg;
[email protected]fa20ec82012-05-04 04:02:484891 if (error_count_ < kMaxLogErrors ||
4892 CommandLine::ForCurrentProcess()->HasSwitch(
4893 switches::kDisableGLErrorLimit)) {
4894 ++error_count_;
4895 // LOG this unless logging is turned off as any chromium code that
4896 // generates these errors probably has a bug.
4897 if (log_synthesized_gl_errors()) {
4898 LOG(ERROR) << last_error_;
4899 }
4900 if (!msg_callback_.is_null()) {
4901 msg_callback_.Run(0, GLES2Util::GetStringEnum(error) + " : " + msg);
4902 }
4903 } else {
4904 if (error_count_ == kMaxLogErrors) {
4905 ++error_count_;
4906 LOG(ERROR)
4907 << "Too many GL errors, not reporting any more for this context."
4908 << " use --disable-gl-error-limit to see all errors.";
4909 }
[email protected]6b6e7ee2011-12-13 08:04:524910 }
[email protected]8eee29c2010-04-29 03:38:294911 }
[email protected]ddd968b82010-03-02 00:44:294912 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324913}
4914
[email protected]07f54fcc2009-12-22 02:46:304915void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
4916 GLenum error;
4917 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]8eee29c2010-04-29 03:38:294918 SetGLError(error, NULL);
[email protected]07f54fcc2009-12-22 02:46:304919 }
4920}
4921
[email protected]6217d392010-03-25 22:08:354922void GLES2DecoderImpl::ClearRealGLErrors() {
4923 GLenum error;
4924 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]3ed14d112011-12-13 22:05:514925 if (error != GL_OUT_OF_MEMORY) {
4926 // GL_OUT_OF_MEMORY can legally happen on lost device.
4927 NOTREACHED() << "GL error " << error << " was unhandled.";
4928 }
[email protected]6217d392010-03-25 22:08:354929 }
4930}
4931
[email protected]ef526492010-06-02 23:12:254932bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:504933 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:254934 // Only check if there are some unrenderable textures.
4935 if (!texture_manager()->HaveUnrenderableTextures()) {
4936 return false;
4937 }
4938 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:504939 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4940 current_program_->sampler_indices();
4941 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4942 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4943 current_program_->GetUniformInfo(sampler_indices[ii]);
4944 DCHECK(uniform_info);
4945 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4946 GLuint texture_unit_index = uniform_info->texture_units[jj];
4947 if (texture_unit_index < group_->max_texture_units()) {
4948 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4949 TextureManager::TextureInfo* texture_info =
[email protected]61eeb33f2011-07-26 15:30:314950 texture_unit.GetInfoForSamplerType(uniform_info->type);
[email protected]80eb6b52012-01-19 00:14:414951 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]ef526492010-06-02 23:12:254952 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:504953 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4954 glBindTexture(
[email protected]61eeb33f2011-07-26 15:30:314955 GetBindTargetForSamplerType(uniform_info->type),
[email protected]00f893d2010-08-24 18:55:494956 texture_manager()->black_texture_id(uniform_info->type));
[email protected]3916c97e2010-02-25 03:20:504957 }
4958 }
4959 // else: should this be an error?
4960 }
4961 }
[email protected]ef526492010-06-02 23:12:254962 return textures_set;
[email protected]3916c97e2010-02-25 03:20:504963}
4964
4965void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
4966 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:504967 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
4968 current_program_->sampler_indices();
4969 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
4970 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
4971 current_program_->GetUniformInfo(sampler_indices[ii]);
4972 DCHECK(uniform_info);
4973 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
4974 GLuint texture_unit_index = uniform_info->texture_units[jj];
4975 if (texture_unit_index < group_->max_texture_units()) {
4976 TextureUnit& texture_unit = texture_units_[texture_unit_index];
4977 TextureManager::TextureInfo* texture_info =
4978 uniform_info->type == GL_SAMPLER_2D ?
4979 texture_unit.bound_texture_2d :
4980 texture_unit.bound_texture_cube_map;
[email protected]80eb6b52012-01-19 00:14:414981 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]3916c97e2010-02-25 03:20:504982 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
4983 // Get the texture info that was previously bound here.
4984 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
4985 texture_unit.bound_texture_2d :
4986 texture_unit.bound_texture_cube_map;
4987 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:034988 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:504989 }
4990 }
4991 }
4992 }
4993 // Set the active texture back to whatever the user had it as.
4994 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:304995}
4996
[email protected]0d6bfdc2011-11-02 01:32:204997bool GLES2DecoderImpl::ClearUnclearedTextures() {
4998 // Only check if there are some uncleared textures.
4999 if (!texture_manager()->HaveUnsafeTextures()) {
5000 return true;
5001 }
5002
5003 // 1: Check all textures we are about to render with.
5004 if (current_program_) {
5005 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
5006 current_program_->sampler_indices();
5007 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5008 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
5009 current_program_->GetUniformInfo(sampler_indices[ii]);
5010 DCHECK(uniform_info);
5011 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5012 GLuint texture_unit_index = uniform_info->texture_units[jj];
5013 if (texture_unit_index < group_->max_texture_units()) {
5014 TextureUnit& texture_unit = texture_units_[texture_unit_index];
5015 TextureManager::TextureInfo* texture_info =
5016 texture_unit.GetInfoForSamplerType(uniform_info->type);
5017 if (texture_info && !texture_info->SafeToRenderFrom()) {
5018 if (!texture_manager()->ClearRenderableLevels(this, texture_info)) {
5019 return false;
5020 }
5021 }
5022 }
5023 }
5024 }
5025 }
5026 return true;
5027}
5028
[email protected]c6aef902012-02-14 03:31:425029bool GLES2DecoderImpl::IsDrawValid(
5030 GLuint max_vertex_accessed, GLsizei primcount) {
[email protected]689fa1c52010-06-09 18:35:035031 // NOTE: We specifically do not check current_program->IsValid() because
5032 // it could never be invalid since glUseProgram would have failed. While
5033 // glLinkProgram could later mark the program as invalid the previous
5034 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:145035 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:505036 // The program does not exist.
5037 // But GL says no ERROR.
5038 return false;
5039 }
[email protected]c6aef902012-02-14 03:31:425040
5041 // true if any enabled, used divisor is zero
5042 bool divisor0 = false;
[email protected]f39f4b3f2010-05-12 17:04:085043 // Validate all attribs currently enabled. If they are used by the current
5044 // program then check that they have enough elements to handle the draw call.
5045 // If they are not used by the current program check that they have a buffer
5046 // assigned.
5047 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:445048 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]f39f4b3f2010-05-12 17:04:085049 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:405050 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:085051 const VertexAttribManager::VertexAttribInfo* info = *it;
5052 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5053 current_program_->GetAttribInfoByLocation(info->index());
5054 if (attrib_info) {
[email protected]c6aef902012-02-14 03:31:425055 divisor0 |= (info->divisor() == 0);
5056 GLuint count = info->MaxVertexAccessed(primcount, max_vertex_accessed);
[email protected]f39f4b3f2010-05-12 17:04:085057 // This attrib is used in the current program.
[email protected]c6aef902012-02-14 03:31:425058 if (!info->CanAccess(count)) {
[email protected]f39f4b3f2010-05-12 17:04:085059 SetGLError(GL_INVALID_OPERATION,
5060 "glDrawXXX: attempt to access out of range vertices");
5061 return false;
5062 }
5063 } else {
5064 // This attrib is not used in the current program.
[email protected]a0b78dc2011-11-11 10:43:105065 if (!info->buffer()) {
[email protected]f39f4b3f2010-05-12 17:04:085066 SetGLError(
5067 GL_INVALID_OPERATION,
5068 "glDrawXXX: attempt to render with no buffer attached to enabled "
5069 "attrib");
5070 return false;
5071 }
[email protected]1d32bc82010-01-13 22:06:465072 }
[email protected]07f54fcc2009-12-22 02:46:305073 }
[email protected]c6aef902012-02-14 03:31:425074
5075 if (primcount && !divisor0) {
5076 SetGLError(
5077 GL_INVALID_OPERATION,
5078 "glDrawXXX: attempt instanced render with all attributes having "
5079 "non-zero divisors");
5080 return false;
5081 }
5082
[email protected]3916c97e2010-02-25 03:20:505083 return true;
[email protected]b1122982010-05-17 23:04:245084}
5085
[email protected]c13e1da62011-09-09 21:48:305086bool GLES2DecoderImpl::SimulateAttrib0(
5087 GLuint max_vertex_accessed, bool* simulated) {
5088 DCHECK(simulated);
5089 *simulated = false;
5090
[email protected]876f6fee2010-08-02 23:10:325091 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
[email protected]c13e1da62011-09-09 21:48:305092 return true;
[email protected]876f6fee2010-08-02 23:10:325093
[email protected]b1122982010-05-17 23:04:245094 const VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445095 vertex_attrib_manager_->GetVertexAttribInfo(0);
[email protected]b1122982010-05-17 23:04:245096 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:495097 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
5098 if (info->enabled() && attrib_0_used) {
[email protected]c13e1da62011-09-09 21:48:305099 return true;
[email protected]b1122982010-05-17 23:04:245100 }
5101
[email protected]b1122982010-05-17 23:04:245102 // Make a buffer with a single repeated vec4 value enough to
5103 // simulate the constant value that is supposed to be here.
5104 // This is required to emulate GLES2 on GL.
[email protected]c13e1da62011-09-09 21:48:305105 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
5106
5107 GLuint num_vertices = max_vertex_accessed + 1;
5108 GLuint size_needed = 0;
5109
5110 if (num_vertices == 0 ||
5111 !SafeMultiply(num_vertices, static_cast<GLuint>(sizeof(Vec4)),
5112 &size_needed) ||
5113 size_needed > 0x7FFFFFFFU) {
5114 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
5115 return false;
5116 }
5117
5118 CopyRealGLErrorsToWrapper();
5119 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
5120
[email protected]8f0b86c2f2012-04-10 05:48:285121 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
5122 if (new_buffer) {
[email protected]fc753442011-02-04 19:49:495123 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305124 GLenum error = glGetError();
5125 if (error != GL_NO_ERROR) {
5126 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
5127 return false;
5128 }
[email protected]fc753442011-02-04 19:49:495129 }
[email protected]8f0b86c2f2012-04-10 05:48:285130 if (new_buffer ||
5131 (attrib_0_used &&
5132 (!attrib_0_buffer_matches_value_ ||
5133 (info->value().v[0] != attrib_0_value_.v[0] ||
5134 info->value().v[1] != attrib_0_value_.v[1] ||
5135 info->value().v[2] != attrib_0_value_.v[2] ||
5136 info->value().v[3] != attrib_0_value_.v[3])))) {
[email protected]fc753442011-02-04 19:49:495137 std::vector<Vec4> temp(num_vertices, info->value());
5138 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
5139 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:245140 attrib_0_value_ = info->value();
5141 attrib_0_size_ = size_needed;
5142 }
5143
5144 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5145
[email protected]c6aef902012-02-14 03:31:425146 if (info->divisor())
5147 glVertexAttribDivisorANGLE(0, 0);
5148
[email protected]c13e1da62011-09-09 21:48:305149 *simulated = true;
[email protected]b1122982010-05-17 23:04:245150 return true;
[email protected]b1122982010-05-17 23:04:245151}
5152
[email protected]43410e92012-04-20 17:06:285153void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib) {
[email protected]b1122982010-05-17 23:04:245154 const VertexAttribManager::VertexAttribInfo* info =
[email protected]43410e92012-04-20 17:06:285155 vertex_attrib_manager_->GetVertexAttribInfo(attrib);
[email protected]b1122982010-05-17 23:04:245156 const void* ptr = reinterpret_cast<const void*>(info->offset());
5157 BufferManager::BufferInfo* buffer_info = info->buffer();
5158 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
5159 glVertexAttribPointer(
[email protected]43410e92012-04-20 17:06:285160 attrib, info->size(), info->type(), info->normalized(), info->gl_stride(),
[email protected]b1122982010-05-17 23:04:245161 ptr);
[email protected]c6aef902012-02-14 03:31:425162 if (info->divisor())
[email protected]43410e92012-04-20 17:06:285163 glVertexAttribDivisorANGLE(attrib, info->divisor());
[email protected]b1122982010-05-17 23:04:245164 glBindBuffer(GL_ARRAY_BUFFER,
5165 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
[email protected]43410e92012-04-20 17:06:285166
5167 if (info->enabled()) {
5168 glEnableVertexAttribArray(attrib);
5169 } else {
5170 glDisableVertexAttribArray(attrib);
5171 }
[email protected]b1122982010-05-17 23:04:245172}
[email protected]07f54fcc2009-12-22 02:46:305173
[email protected]8fbedc02010-11-18 18:43:405174bool GLES2DecoderImpl::SimulateFixedAttribs(
[email protected]c6aef902012-02-14 03:31:425175 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
[email protected]8fbedc02010-11-18 18:43:405176 DCHECK(simulated);
5177 *simulated = false;
5178 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
5179 return true;
5180
[email protected]3757a372012-01-19 05:20:445181 if (!vertex_attrib_manager_->HaveFixedAttribs()) {
[email protected]8fbedc02010-11-18 18:43:405182 return true;
5183 }
5184
5185 // NOTE: we could be smart and try to check if a buffer is used
5186 // twice in 2 different attribs, find the overlapping parts and therefore
5187 // duplicate the minimum amount of data but this whole code path is not meant
5188 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
5189 // tests so we just add to the buffer attrib used.
5190
[email protected]c13e1da62011-09-09 21:48:305191 GLuint elements_needed = 0;
[email protected]8fbedc02010-11-18 18:43:405192 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:445193 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]8fbedc02010-11-18 18:43:405194 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5195 infos.begin(); it != infos.end(); ++it) {
5196 const VertexAttribManager::VertexAttribInfo* info = *it;
5197 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5198 current_program_->GetAttribInfoByLocation(info->index());
[email protected]c6aef902012-02-14 03:31:425199 GLuint max_accessed = info->MaxVertexAccessed(primcount,
5200 max_vertex_accessed);
5201 GLuint num_vertices = max_accessed + 1;
5202 if (num_vertices == 0) {
5203 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
5204 return false;
5205 }
[email protected]8fbedc02010-11-18 18:43:405206 if (attrib_info &&
[email protected]c6aef902012-02-14 03:31:425207 info->CanAccess(max_accessed) &&
[email protected]8fbedc02010-11-18 18:43:405208 info->type() == GL_FIXED) {
[email protected]c13e1da62011-09-09 21:48:305209 GLuint elements_used = 0;
5210 if (!SafeMultiply(num_vertices,
5211 static_cast<GLuint>(info->size()), &elements_used) ||
[email protected]8fbedc02010-11-18 18:43:405212 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
5213 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5214 return false;
5215 }
5216 }
5217 }
5218
[email protected]c13e1da62011-09-09 21:48:305219 const GLuint kSizeOfFloat = sizeof(float); // NOLINT
5220 GLuint size_needed = 0;
5221 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed) ||
5222 size_needed > 0x7FFFFFFFU) {
[email protected]8fbedc02010-11-18 18:43:405223 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5224 return false;
5225 }
5226
[email protected]c13e1da62011-09-09 21:48:305227 CopyRealGLErrorsToWrapper();
[email protected]8fbedc02010-11-18 18:43:405228
5229 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
[email protected]c13e1da62011-09-09 21:48:305230 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
[email protected]8fbedc02010-11-18 18:43:405231 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305232 GLenum error = glGetError();
5233 if (error != GL_NO_ERROR) {
5234 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
5235 return false;
5236 }
[email protected]8fbedc02010-11-18 18:43:405237 }
5238
5239 // Copy the elements and convert to float
5240 GLintptr offset = 0;
5241 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5242 infos.begin(); it != infos.end(); ++it) {
5243 const VertexAttribManager::VertexAttribInfo* info = *it;
5244 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5245 current_program_->GetAttribInfoByLocation(info->index());
[email protected]c6aef902012-02-14 03:31:425246 GLuint max_accessed = info->MaxVertexAccessed(primcount,
5247 max_vertex_accessed);
5248 GLuint num_vertices = max_accessed + 1;
5249 if (num_vertices == 0) {
5250 SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: Simulating attrib 0");
5251 return false;
5252 }
[email protected]8fbedc02010-11-18 18:43:405253 if (attrib_info &&
[email protected]c6aef902012-02-14 03:31:425254 info->CanAccess(max_accessed) &&
[email protected]8fbedc02010-11-18 18:43:405255 info->type() == GL_FIXED) {
5256 int num_elements = info->size() * kSizeOfFloat;
5257 int size = num_elements * num_vertices;
5258 scoped_array<float> data(new float[size]);
5259 const int32* src = reinterpret_cast<const int32 *>(
5260 info->buffer()->GetRange(info->offset(), size));
5261 const int32* end = src + num_elements;
5262 float* dst = data.get();
5263 while (src != end) {
5264 *dst++ = static_cast<float>(*src++) / 65536.0f;
5265 }
5266 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
5267 glVertexAttribPointer(
5268 info->index(), info->size(), GL_FLOAT, false, 0,
5269 reinterpret_cast<GLvoid*>(offset));
5270 offset += size;
5271 }
5272 }
5273 *simulated = true;
5274 return true;
5275}
5276
5277void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
5278 // There's no need to call glVertexAttribPointer because we shadow all the
5279 // settings and passing GL_FIXED to it will not work.
5280 glBindBuffer(GL_ARRAY_BUFFER,
5281 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
5282}
5283
[email protected]c6aef902012-02-14 03:31:425284error::Error GLES2DecoderImpl::DoDrawArrays(bool instanced,
5285 GLenum mode,
5286 GLint first,
5287 GLsizei count,
5288 GLsizei primcount) {
[email protected]38d139d2011-07-14 00:38:435289 if (!validators_->draw_mode.IsValid(mode)) {
5290 SetGLError(GL_INVALID_ENUM, "glDrawArrays: mode GL_INVALID_ENUM");
5291 return error::kNoError;
5292 }
5293 if (count < 0) {
5294 SetGLError(GL_INVALID_VALUE, "glDrawArrays: count < 0");
5295 return error::kNoError;
5296 }
[email protected]c6aef902012-02-14 03:31:425297 if (primcount < 0) {
5298 SetGLError(GL_INVALID_VALUE, "glDrawArrays: primcount < 0");
5299 return error::kNoError;
5300 }
[email protected]0d6bfdc2011-11-02 01:32:205301 if (!CheckBoundFramebuffersValid("glDrawArrays")) {
[email protected]38d139d2011-07-14 00:38:435302 return error::kNoError;
5303 }
5304 // We have to check this here because the prototype for glDrawArrays
5305 // is GLint not GLsizei.
5306 if (first < 0) {
5307 SetGLError(GL_INVALID_VALUE, "glDrawArrays: first < 0");
5308 return error::kNoError;
5309 }
5310
[email protected]c6aef902012-02-14 03:31:425311 if (count == 0 || (instanced && primcount == 0)) {
[email protected]38d139d2011-07-14 00:38:435312 return error::kNoError;
5313 }
5314
5315 GLuint max_vertex_accessed = first + count - 1;
[email protected]c6aef902012-02-14 03:31:425316 if (IsDrawValid(max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:205317 if (!ClearUnclearedTextures()) {
5318 SetGLError(GL_INVALID_VALUE, "glDrawArrays: out of memory");
5319 return error::kNoError;
5320 }
[email protected]c13e1da62011-09-09 21:48:305321 bool simulated_attrib_0 = false;
5322 if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
5323 return error::kNoError;
5324 }
[email protected]38d139d2011-07-14 00:38:435325 bool simulated_fixed_attribs = false;
[email protected]c6aef902012-02-14 03:31:425326 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs,
5327 primcount)) {
[email protected]38d139d2011-07-14 00:38:435328 bool textures_set = SetBlackTextureForNonRenderableTextures();
5329 ApplyDirtyState();
[email protected]c6aef902012-02-14 03:31:425330 if (!instanced) {
5331 glDrawArrays(mode, first, count);
5332 } else {
5333 glDrawArraysInstancedANGLE(mode, first, count, primcount);
5334 }
[email protected]22e3f552012-03-13 01:54:195335 ProcessPendingQueries();
[email protected]38d139d2011-07-14 00:38:435336 if (textures_set) {
5337 RestoreStateForNonRenderableTextures();
5338 }
5339 if (simulated_fixed_attribs) {
5340 RestoreStateForSimulatedFixedAttribs();
5341 }
5342 }
5343 if (simulated_attrib_0) {
[email protected]43410e92012-04-20 17:06:285344 RestoreStateForAttrib(0);
[email protected]38d139d2011-07-14 00:38:435345 }
5346 if (WasContextLost()) {
5347 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawArrays.";
5348 return error::kLostContext;
5349 }
5350 }
5351 return error::kNoError;
5352}
5353
[email protected]c6aef902012-02-14 03:31:425354error::Error GLES2DecoderImpl::HandleDrawArrays(
5355 uint32 immediate_data_size, const gles2::DrawArrays& c) {
5356 return DoDrawArrays(false,
5357 static_cast<GLenum>(c.mode),
5358 static_cast<GLint>(c.first),
5359 static_cast<GLsizei>(c.count),
5360 0);
5361}
5362
5363error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
5364 uint32 immediate_data_size, const gles2::DrawArraysInstancedANGLE& c) {
5365 if (!feature_info_->feature_flags().angle_instanced_arrays) {
5366 SetGLError(GL_INVALID_OPERATION,
5367 "glDrawArraysInstancedANGLE: function not available");
5368 return error::kNoError;
5369 }
5370 return DoDrawArrays(true,
5371 static_cast<GLenum>(c.mode),
5372 static_cast<GLint>(c.first),
5373 static_cast<GLsizei>(c.count),
5374 static_cast<GLsizei>(c.primcount));
5375}
5376
5377error::Error GLES2DecoderImpl::DoDrawElements(bool instanced,
5378 GLenum mode,
5379 GLsizei count,
5380 GLenum type,
5381 int32 offset,
5382 GLsizei primcount) {
[email protected]a0b78dc2011-11-11 10:43:105383 if (!bound_element_array_buffer_) {
[email protected]8eee29c2010-04-29 03:38:295384 SetGLError(GL_INVALID_OPERATION,
5385 "glDrawElements: No element array buffer bound");
5386 return error::kNoError;
5387 }
5388
[email protected]8eee29c2010-04-29 03:38:295389 if (count < 0) {
5390 SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
5391 return error::kNoError;
5392 }
5393 if (offset < 0) {
5394 SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
5395 return error::kNoError;
5396 }
[email protected]9438b012010-06-15 22:55:055397 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]8eee29c2010-04-29 03:38:295398 SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
5399 return error::kNoError;
5400 }
[email protected]9438b012010-06-15 22:55:055401 if (!validators_->index_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:295402 SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
5403 return error::kNoError;
5404 }
[email protected]c6aef902012-02-14 03:31:425405 if (primcount < 0) {
5406 SetGLError(GL_INVALID_VALUE, "glDrawElements: primcount < 0");
5407 return error::kNoError;
5408 }
[email protected]8eee29c2010-04-29 03:38:295409
[email protected]0d6bfdc2011-11-02 01:32:205410 if (!CheckBoundFramebuffersValid("glDrawElements")) {
[email protected]3a03a8f2011-03-19 00:51:275411 return error::kNoError;
5412 }
5413
[email protected]c6aef902012-02-14 03:31:425414 if (count == 0 || (instanced && primcount == 0)) {
[email protected]6c788fb72010-08-26 02:16:315415 return error::kNoError;
5416 }
5417
[email protected]8eee29c2010-04-29 03:38:295418 GLuint max_vertex_accessed;
5419 if (!bound_element_array_buffer_->GetMaxValueForRange(
5420 offset, count, type, &max_vertex_accessed)) {
5421 SetGLError(GL_INVALID_OPERATION,
5422 "glDrawElements: range out of bounds for buffer");
5423 return error::kNoError;
5424 }
5425
[email protected]c6aef902012-02-14 03:31:425426 if (IsDrawValid(max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:205427 if (!ClearUnclearedTextures()) {
5428 SetGLError(GL_INVALID_VALUE, "glDrawElements: out of memory");
5429 return error::kNoError;
5430 }
[email protected]c13e1da62011-09-09 21:48:305431 bool simulated_attrib_0 = false;
5432 if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
5433 return error::kNoError;
5434 }
[email protected]8fbedc02010-11-18 18:43:405435 bool simulated_fixed_attribs = false;
[email protected]c6aef902012-02-14 03:31:425436 if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs,
5437 primcount)) {
[email protected]8fbedc02010-11-18 18:43:405438 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:465439 ApplyDirtyState();
[email protected]8fbedc02010-11-18 18:43:405440 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
[email protected]c6aef902012-02-14 03:31:425441 if (!instanced) {
5442 glDrawElements(mode, count, type, indices);
5443 } else {
5444 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
5445 }
[email protected]22e3f552012-03-13 01:54:195446 ProcessPendingQueries();
[email protected]8fbedc02010-11-18 18:43:405447 if (textures_set) {
5448 RestoreStateForNonRenderableTextures();
5449 }
5450 if (simulated_fixed_attribs) {
5451 RestoreStateForSimulatedFixedAttribs();
5452 }
[email protected]ba3176a2009-12-16 18:19:465453 }
[email protected]b1122982010-05-17 23:04:245454 if (simulated_attrib_0) {
[email protected]43410e92012-04-20 17:06:285455 RestoreStateForAttrib(0);
[email protected]b1122982010-05-17 23:04:245456 }
[email protected]38d139d2011-07-14 00:38:435457 if (WasContextLost()) {
5458 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawElements.";
5459 return error::kLostContext;
5460 }
[email protected]96449d2c2009-11-25 00:01:325461 }
[email protected]f7a64ee2010-02-01 22:24:145462 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325463}
5464
[email protected]c6aef902012-02-14 03:31:425465error::Error GLES2DecoderImpl::HandleDrawElements(
5466 uint32 immediate_data_size, const gles2::DrawElements& c) {
5467 return DoDrawElements(false,
5468 static_cast<GLenum>(c.mode),
5469 static_cast<GLsizei>(c.count),
5470 static_cast<GLenum>(c.type),
5471 static_cast<int32>(c.index_offset),
5472 0);
5473}
5474
5475error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
5476 uint32 immediate_data_size, const gles2::DrawElementsInstancedANGLE& c) {
5477 if (!feature_info_->feature_flags().angle_instanced_arrays) {
5478 SetGLError(GL_INVALID_OPERATION,
5479 "glDrawElementsInstancedANGLE: function not available");
5480 return error::kNoError;
5481 }
5482 return DoDrawElements(true,
5483 static_cast<GLenum>(c.mode),
5484 static_cast<GLsizei>(c.count),
5485 static_cast<GLenum>(c.type),
5486 static_cast<int32>(c.index_offset),
5487 static_cast<GLsizei>(c.primcount));
5488}
5489
[email protected]269200b12010-11-18 22:53:065490GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:235491 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
5492 GLuint max_vertex_accessed = 0;
5493 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:295494 if (!info) {
[email protected]ae51d192010-04-27 00:48:035495 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:295496 SetGLError(GL_INVALID_VALUE,
[email protected]269200b12010-11-18 22:53:065497 "GetMaxValueInBufferCHROMIUM: unknown buffer");
[email protected]29a9eb52010-04-13 09:04:235498 } else {
5499 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:035500 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:065501 SetGLError(
5502 GL_INVALID_OPERATION,
5503 "GetMaxValueInBufferCHROMIUM: range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:235504 }
5505 }
5506 return max_vertex_accessed;
5507}
5508
[email protected]96449d2c2009-11-25 00:01:325509// Calls glShaderSource for the various versions of the ShaderSource command.
5510// Assumes that data / data_size points to a piece of memory that is in range
5511// of whatever context it came from (shared memory, immediate memory, bucket
5512// memory.)
[email protected]45bf5152010-02-12 00:11:315513error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035514 GLuint client_id, const char* data, uint32 data_size) {
[email protected]258a3313f2011-10-18 20:13:575515 std::string str(data, data + data_size);
[email protected]6b8cf1a2010-05-06 16:13:585516 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5517 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:315518 if (!info) {
[email protected]45bf5152010-02-12 00:11:315519 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325520 }
[email protected]45bf5152010-02-12 00:11:315521 // Note: We don't actually call glShaderSource here. We wait until
5522 // the call to glCompileShader.
[email protected]258a3313f2011-10-18 20:13:575523 info->UpdateSource(str.c_str());
[email protected]f7a64ee2010-02-01 22:24:145524 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325525}
5526
[email protected]f7a64ee2010-02-01 22:24:145527error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:195528 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:325529 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315530 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:325531 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:465532 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145533 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325534 }
[email protected]ae51d192010-04-27 00:48:035535 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:325536}
5537
[email protected]f7a64ee2010-02-01 22:24:145538error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:195539 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:325540 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315541 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:305542 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465543 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145544 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325545 }
[email protected]ae51d192010-04-27 00:48:035546 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:315547}
5548
[email protected]558847a2010-03-24 07:02:545549error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
5550 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:545551 Bucket* bucket = GetBucket(c.data_bucket_id);
5552 if (!bucket || bucket->size() == 0) {
5553 return error::kInvalidArguments;
5554 }
5555 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035556 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:545557 bucket->size() - 1);
5558}
5559
[email protected]ae51d192010-04-27 00:48:035560void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]0c8fabf2011-06-14 19:35:225561 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]6b8cf1a2010-05-06 16:13:585562 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5563 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:315564 if (!info) {
[email protected]45bf5152010-02-12 00:11:315565 return;
5566 }
[email protected]de17df392010-04-23 21:09:415567 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
5568 // glShaderSource and then glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:525569 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:345570 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:185571 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:345572 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:455573 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:235574
[email protected]a550584e2010-09-17 18:01:455575 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:345576 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:185577 return;
5578 }
[email protected]a550584e2010-09-17 18:01:455579 shader_src = translator->translated_shader();
[email protected]93297702011-11-05 05:09:465580 if (!feature_info_->feature_flags().angle_translated_shader_source)
[email protected]d6a53e42011-10-05 00:09:365581 info->UpdateTranslatedSource(shader_src);
[email protected]de17df392010-04-23 21:09:415582 }
[email protected]de17df392010-04-23 21:09:415583
[email protected]ae51d192010-04-27 00:48:035584 glShaderSource(info->service_id(), 1, &shader_src, NULL);
5585 glCompileShader(info->service_id());
[email protected]93297702011-11-05 05:09:465586 if (feature_info_->feature_flags().angle_translated_shader_source) {
[email protected]d6a53e42011-10-05 00:09:365587 GLint max_len = 0;
5588 glGetShaderiv(info->service_id(),
5589 GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
5590 &max_len);
5591 scoped_array<char> temp(new char[max_len]);
5592 GLint len = 0;
5593 glGetTranslatedShaderSourceANGLE(
5594 info->service_id(), max_len, &len, temp.get());
5595 DCHECK(max_len == 0 || len < max_len);
5596 DCHECK(len == 0 || temp[len] == '\0');
5597 info->UpdateTranslatedSource(temp.get());
5598 }
5599
[email protected]e5186162010-06-14 18:54:415600 GLint status = GL_FALSE;
5601 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
5602 if (status) {
[email protected]f57bb282010-11-12 00:51:345603 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:415604 } else {
[email protected]d9977d42010-09-01 20:27:025605 // We cannot reach here if we are using the shader translator.
5606 // All invalid shaders must be rejected by the translator.
5607 // All translated shaders must compile.
5608 LOG_IF(ERROR, use_shader_translator_)
5609 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:335610 GLint max_len = 0;
5611 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
5612 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:415613 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:335614 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
5615 DCHECK(max_len == 0 || len < max_len);
[email protected]d6a53e42011-10-05 00:09:365616 DCHECK(len == 0 || temp[len] == '\0');
[email protected]df6cf1ad2011-01-29 01:20:525617 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
[email protected]e5186162010-06-14 18:54:415618 }
[email protected]45bf5152010-02-12 00:11:315619};
5620
[email protected]ddd968b82010-03-02 00:44:295621void GLES2DecoderImpl::DoGetShaderiv(
5622 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:585623 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5624 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:295625 if (!info) {
[email protected]ddd968b82010-03-02 00:44:295626 return;
5627 }
[email protected]8f1ccdac2010-05-19 21:01:485628 switch (pname) {
5629 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525630 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:485631 return;
5632 case GL_COMPILE_STATUS:
[email protected]062c38b2012-01-18 03:25:105633 *params = compile_shader_always_succeeds_ ? true : info->IsValid();
[email protected]e5186162010-06-14 18:54:415634 return;
[email protected]8f1ccdac2010-05-19 21:01:485635 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525636 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:415637 return;
[email protected]d6a53e42011-10-05 00:09:365638 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5639 *params = info->translated_source() ?
5640 info->translated_source()->size() + 1 : 0;
5641 return;
[email protected]8f1ccdac2010-05-19 21:01:485642 default:
5643 break;
[email protected]ddd968b82010-03-02 00:44:295644 }
[email protected]8f1ccdac2010-05-19 21:01:485645 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:295646}
5647
[email protected]ae51d192010-04-27 00:48:035648error::Error GLES2DecoderImpl::HandleGetShaderSource(
5649 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
5650 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:035651 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5652 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:585653 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5654 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:525655 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:295656 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:295657 return error::kNoError;
5658 }
[email protected]df6cf1ad2011-01-29 01:20:525659 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:035660 return error::kNoError;
5661}
5662
[email protected]d6a53e42011-10-05 00:09:365663error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
5664 uint32 immediate_data_size,
5665 const gles2::GetTranslatedShaderSourceANGLE& c) {
5666 GLuint shader = c.shader;
5667
5668 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5669 Bucket* bucket = CreateBucket(bucket_id);
5670 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5671 shader, "glTranslatedGetShaderSourceANGLE");
5672 if (!info) {
5673 bucket->SetSize(0);
5674 return error::kNoError;
5675 }
5676
5677 bucket->SetFromString(info->translated_source() ?
5678 info->translated_source()->c_str() : NULL);
5679 return error::kNoError;
5680}
5681
[email protected]ae51d192010-04-27 00:48:035682error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
5683 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
5684 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:585685 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5686 Bucket* bucket = CreateBucket(bucket_id);
5687 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5688 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525689 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465690 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035691 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:315692 }
[email protected]df6cf1ad2011-01-29 01:20:525693 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035694 return error::kNoError;
5695}
5696
5697error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
5698 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
5699 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:585700 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5701 Bucket* bucket = CreateBucket(bucket_id);
5702 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5703 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525704 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465705 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035706 return error::kNoError;
5707 }
[email protected]df6cf1ad2011-01-29 01:20:525708 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035709 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325710}
5711
[email protected]1958e0e2010-04-22 05:17:155712bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105713 const BufferManager::BufferInfo* buffer = GetBufferInfo(client_id);
5714 return buffer && buffer->IsValid() && !buffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155715}
5716
5717bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105718 const FramebufferManager::FramebufferInfo* framebuffer =
[email protected]06c8b082011-01-05 18:00:365719 GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105720 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155721}
5722
5723bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365724 // IsProgram is true for programs as soon as they are created, until they are
5725 // deleted and no longer in use.
[email protected]a0b78dc2011-11-11 10:43:105726 const ProgramManager::ProgramInfo* program = GetProgramInfo(client_id);
5727 return program != NULL && !program->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155728}
5729
5730bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105731 const RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]06c8b082011-01-05 18:00:365732 GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105733 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155734}
5735
5736bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365737 // IsShader is true for shaders as soon as they are created, until they
5738 // are deleted and not attached to any programs.
[email protected]a0b78dc2011-11-11 10:43:105739 const ShaderManager::ShaderInfo* shader = GetShaderInfo(client_id);
5740 return shader != NULL && !shader->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155741}
5742
5743bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105744 const TextureManager::TextureInfo* texture = GetTextureInfo(client_id);
5745 return texture && texture->IsValid() && !texture->IsDeleted();
[email protected]ae51d192010-04-27 00:48:035746}
5747
5748void GLES2DecoderImpl::DoAttachShader(
5749 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585750 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5751 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035752 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035753 return;
[email protected]1958e0e2010-04-22 05:17:155754 }
[email protected]6b8cf1a2010-05-06 16:13:585755 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5756 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035757 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035758 return;
5759 }
[email protected]ca488e12010-12-13 20:06:145760 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:315761 SetGLError(GL_INVALID_OPERATION,
5762 "glAttachShader: can not attach more than"
5763 " one shader of the same type.");
5764 return;
5765 }
[email protected]ae51d192010-04-27 00:48:035766 glAttachShader(program_info->service_id(), shader_info->service_id());
5767}
5768
5769void GLES2DecoderImpl::DoDetachShader(
5770 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585771 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5772 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035773 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035774 return;
5775 }
[email protected]6b8cf1a2010-05-06 16:13:585776 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5777 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035778 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035779 return;
5780 }
[email protected]9a0ccd42011-03-16 23:58:225781 if (!program_info->DetachShader(shader_manager(), shader_info)) {
5782 SetGLError(GL_INVALID_OPERATION,
5783 "glDetachShader: shader not attached to program");
5784 return;
5785 }
[email protected]ae51d192010-04-27 00:48:035786 glDetachShader(program_info->service_id(), shader_info->service_id());
5787}
5788
5789void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585790 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5791 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:035792 if (!info) {
[email protected]ae51d192010-04-27 00:48:035793 return;
5794 }
[email protected]d685a682011-04-29 16:19:575795 info->Validate();
[email protected]1958e0e2010-04-22 05:17:155796}
5797
[email protected]b1122982010-05-17 23:04:245798void GLES2DecoderImpl::DoGetVertexAttribfv(
5799 GLuint index, GLenum pname, GLfloat* params) {
5800 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445801 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245802 if (!info) {
5803 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
5804 return;
5805 }
5806 switch (pname) {
5807 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5808 BufferManager::BufferInfo* buffer = info->buffer();
5809 if (buffer && !buffer->IsDeleted()) {
5810 GLuint client_id;
5811 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5812 *params = static_cast<GLfloat>(client_id);
5813 }
5814 break;
5815 }
5816 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5817 *params = static_cast<GLfloat>(info->enabled());
5818 break;
5819 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5820 *params = static_cast<GLfloat>(info->size());
5821 break;
5822 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5823 *params = static_cast<GLfloat>(info->gl_stride());
5824 break;
5825 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5826 *params = static_cast<GLfloat>(info->type());
5827 break;
5828 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5829 *params = static_cast<GLfloat>(info->normalized());
5830 break;
5831 case GL_CURRENT_VERTEX_ATTRIB:
5832 params[0] = info->value().v[0];
5833 params[1] = info->value().v[1];
5834 params[2] = info->value().v[2];
5835 params[3] = info->value().v[3];
5836 break;
[email protected]c6aef902012-02-14 03:31:425837 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
5838 *params = static_cast<GLfloat>(info->divisor());
5839 break;
[email protected]b1122982010-05-17 23:04:245840 default:
5841 NOTREACHED();
5842 break;
5843 }
5844}
5845
5846void GLES2DecoderImpl::DoGetVertexAttribiv(
5847 GLuint index, GLenum pname, GLint* params) {
5848 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445849 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245850 if (!info) {
5851 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
5852 return;
5853 }
5854 switch (pname) {
5855 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5856 BufferManager::BufferInfo* buffer = info->buffer();
5857 if (buffer && !buffer->IsDeleted()) {
5858 GLuint client_id;
5859 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5860 *params = client_id;
5861 }
5862 break;
5863 }
5864 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5865 *params = info->enabled();
5866 break;
5867 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5868 *params = info->size();
5869 break;
5870 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5871 *params = info->gl_stride();
5872 break;
5873 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5874 *params = info->type();
5875 break;
5876 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5877 *params = static_cast<GLint>(info->normalized());
5878 break;
[email protected]c6aef902012-02-14 03:31:425879 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
5880 *params = info->divisor();
5881 break;
[email protected]b1122982010-05-17 23:04:245882 case GL_CURRENT_VERTEX_ATTRIB:
5883 params[0] = static_cast<GLint>(info->value().v[0]);
5884 params[1] = static_cast<GLint>(info->value().v[1]);
5885 params[2] = static_cast<GLint>(info->value().v[2]);
5886 params[3] = static_cast<GLint>(info->value().v[3]);
5887 break;
5888 default:
5889 NOTREACHED();
5890 break;
5891 }
5892}
5893
5894void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
5895 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445896 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245897 if (!info) {
5898 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
5899 return;
5900 }
5901 VertexAttribManager::VertexAttribInfo::Vec4 value;
5902 value.v[0] = v0;
5903 value.v[1] = 0.0f;
5904 value.v[2] = 0.0f;
5905 value.v[3] = 1.0f;
5906 info->set_value(value);
5907 glVertexAttrib1f(index, v0);
5908}
5909
5910void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
5911 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445912 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245913 if (!info) {
5914 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
5915 return;
5916 }
5917 VertexAttribManager::VertexAttribInfo::Vec4 value;
5918 value.v[0] = v0;
5919 value.v[1] = v1;
5920 value.v[2] = 0.0f;
5921 value.v[3] = 1.0f;
5922 info->set_value(value);
5923 glVertexAttrib2f(index, v0, v1);
5924}
5925
5926void GLES2DecoderImpl::DoVertexAttrib3f(
5927 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
5928 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445929 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245930 if (!info) {
5931 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
5932 return;
5933 }
5934 VertexAttribManager::VertexAttribInfo::Vec4 value;
5935 value.v[0] = v0;
5936 value.v[1] = v1;
5937 value.v[2] = v2;
5938 value.v[3] = 1.0f;
5939 info->set_value(value);
5940 glVertexAttrib3f(index, v0, v1, v2);
5941}
5942
5943void GLES2DecoderImpl::DoVertexAttrib4f(
5944 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
5945 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445946 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245947 if (!info) {
5948 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
5949 return;
5950 }
5951 VertexAttribManager::VertexAttribInfo::Vec4 value;
5952 value.v[0] = v0;
5953 value.v[1] = v1;
5954 value.v[2] = v2;
5955 value.v[3] = v3;
5956 info->set_value(value);
5957 glVertexAttrib4f(index, v0, v1, v2, v3);
5958}
5959
5960void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
5961 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445962 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245963 if (!info) {
5964 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
5965 return;
5966 }
5967 VertexAttribManager::VertexAttribInfo::Vec4 value;
5968 value.v[0] = v[0];
5969 value.v[1] = 0.0f;
5970 value.v[2] = 0.0f;
5971 value.v[3] = 1.0f;
5972 info->set_value(value);
5973 glVertexAttrib1fv(index, v);
5974}
5975
5976void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
5977 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445978 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245979 if (!info) {
5980 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
5981 return;
5982 }
5983 VertexAttribManager::VertexAttribInfo::Vec4 value;
5984 value.v[0] = v[0];
5985 value.v[1] = v[1];
5986 value.v[2] = 0.0f;
5987 value.v[3] = 1.0f;
5988 info->set_value(value);
5989 glVertexAttrib2fv(index, v);
5990}
5991
5992void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
5993 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445994 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245995 if (!info) {
5996 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
5997 return;
5998 }
5999 VertexAttribManager::VertexAttribInfo::Vec4 value;
6000 value.v[0] = v[0];
6001 value.v[1] = v[1];
6002 value.v[2] = v[2];
6003 value.v[3] = 1.0f;
6004 info->set_value(value);
6005 glVertexAttrib3fv(index, v);
6006}
6007
6008void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
6009 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:446010 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246011 if (!info) {
6012 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
6013 return;
6014 }
6015 VertexAttribManager::VertexAttribInfo::Vec4 value;
6016 value.v[0] = v[0];
6017 value.v[1] = v[1];
6018 value.v[2] = v[2];
6019 value.v[3] = v[3];
6020 info->set_value(value);
6021 glVertexAttrib4fv(index, v);
6022}
6023
[email protected]f7a64ee2010-02-01 22:24:146024error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:196025 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:296026 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
6027 SetGLError(GL_INVALID_VALUE,
6028 "glVertexAttribPointer: no array buffer bound");
6029 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326030 }
[email protected]8eee29c2010-04-29 03:38:296031
6032 GLuint indx = c.indx;
6033 GLint size = c.size;
6034 GLenum type = c.type;
6035 GLboolean normalized = c.normalized;
6036 GLsizei stride = c.stride;
6037 GLsizei offset = c.offset;
6038 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:056039 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:296040 SetGLError(GL_INVALID_ENUM,
6041 "glVertexAttribPointer: type GL_INVALID_ENUM");
6042 return error::kNoError;
6043 }
[email protected]9438b012010-06-15 22:55:056044 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:316045 SetGLError(GL_INVALID_VALUE,
[email protected]8eee29c2010-04-29 03:38:296046 "glVertexAttribPointer: size GL_INVALID_VALUE");
6047 return error::kNoError;
6048 }
6049 if (indx >= group_->max_vertex_attribs()) {
6050 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
6051 return error::kNoError;
6052 }
6053 if (stride < 0) {
6054 SetGLError(GL_INVALID_VALUE,
6055 "glVertexAttribPointer: stride < 0");
6056 return error::kNoError;
6057 }
6058 if (stride > 255) {
6059 SetGLError(GL_INVALID_VALUE,
6060 "glVertexAttribPointer: stride > 255");
6061 return error::kNoError;
6062 }
6063 if (offset < 0) {
6064 SetGLError(GL_INVALID_VALUE,
6065 "glVertexAttribPointer: offset < 0");
6066 return error::kNoError;
6067 }
6068 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:316069 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:296070 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:316071 SetGLError(GL_INVALID_OPERATION,
6072 "glVertexAttribPointer: offset not valid for type");
6073 return error::kNoError;
6074 }
6075 if (stride % component_size > 0) {
6076 SetGLError(GL_INVALID_OPERATION,
[email protected]8eee29c2010-04-29 03:38:296077 "glVertexAttribPointer: stride not valid for type");
6078 return error::kNoError;
6079 }
[email protected]3757a372012-01-19 05:20:446080 vertex_attrib_manager_->SetAttribInfo(
[email protected]8fbedc02010-11-18 18:43:406081 indx,
[email protected]8eee29c2010-04-29 03:38:296082 bound_array_buffer_,
6083 size,
6084 type,
[email protected]b1122982010-05-17 23:04:246085 normalized,
6086 stride,
6087 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:296088 offset);
[email protected]8fbedc02010-11-18 18:43:406089 if (type != GL_FIXED) {
6090 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
6091 }
[email protected]f7a64ee2010-02-01 22:24:146092 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326093}
6094
[email protected]43410e92012-04-20 17:06:286095void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
6096 GLsizei height) {
6097 viewport_x_ = x;
6098 viewport_y_ = y;
6099 viewport_width_ = std::min(width, viewport_max_width_);
6100 viewport_height_ = std::min(height, viewport_max_height_);
6101 glViewport(x, y, width, height);
6102}
6103
[email protected]c6aef902012-02-14 03:31:426104error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
6105 uint32 immediate_data_size, const gles2::VertexAttribDivisorANGLE& c) {
6106 if (!feature_info_->feature_flags().angle_instanced_arrays) {
6107 SetGLError(GL_INVALID_OPERATION,
6108 "glVertexAttribDivisorANGLE: function not available");
6109 }
6110 GLuint index = c.index;
6111 GLuint divisor = c.divisor;
6112 if (index >= group_->max_vertex_attribs()) {
6113 SetGLError(GL_INVALID_VALUE,
6114 "glVertexAttribDivisorANGLE: index out of range");
6115 return error::kNoError;
6116 }
6117
6118 vertex_attrib_manager_->SetDivisor(
6119 index,
6120 divisor);
6121 glVertexAttribDivisorANGLE(index, divisor);
6122 return error::kNoError;
6123}
6124
[email protected]f7a64ee2010-02-01 22:24:146125error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:196126 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:316127 GLint x = c.x;
6128 GLint y = c.y;
6129 GLsizei width = c.width;
6130 GLsizei height = c.height;
6131 GLenum format = c.format;
6132 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:566133 if (width < 0 || height < 0) {
[email protected]8eee29c2010-04-29 03:38:296134 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
[email protected]57f223832010-03-19 01:57:566135 return error::kNoError;
6136 }
[email protected]a51788e2010-02-24 21:54:256137 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:186138 uint32 pixels_size;
[email protected]3458a64a2012-04-10 17:39:346139 if (!GLES2Util::ComputeImageDataSizes(
6140 width, height, format, type, pack_alignment_, &pixels_size, NULL, NULL)) {
[email protected]a76b0052010-03-05 00:33:186141 return error::kOutOfBounds;
6142 }
[email protected]612d2f82009-12-08 20:49:316143 void* pixels = GetSharedMemoryAs<void*>(
6144 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:256145 Result* result = GetSharedMemoryAs<Result*>(
6146 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6147 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:146148 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466149 }
[email protected]a51788e2010-02-24 21:54:256150
[email protected]9438b012010-06-15 22:55:056151 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:296152 SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
6153 return error::kNoError;
6154 }
[email protected]9438b012010-06-15 22:55:056155 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:296156 SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:126157 return error::kNoError;
6158 }
[email protected]57f223832010-03-19 01:57:566159 if (width == 0 || height == 0) {
6160 return error::kNoError;
6161 }
6162
[email protected]57f223832010-03-19 01:57:566163 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:306164 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:566165
6166 GLint max_x;
6167 GLint max_y;
6168 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]8eee29c2010-04-29 03:38:296169 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:146170 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:316171 }
[email protected]57f223832010-03-19 01:57:566172
[email protected]0d6bfdc2011-11-02 01:32:206173 if (!CheckBoundFramebuffersValid("glReadPixels")) {
6174 return error::kNoError;
6175 }
6176
[email protected]a0b78dc2011-11-11 10:43:106177 CopyRealGLErrorsToWrapper();
6178
6179 ScopedResolvedFrameBufferBinder binder(this, false, true);
6180
[email protected]d37231fa2010-04-09 21:16:026181 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:566182 // The user requested an out of range area. Get the results 1 line
6183 // at a time.
6184 uint32 temp_size;
[email protected]3458a64a2012-04-10 17:39:346185 uint32 unpadded_row_size;
6186 uint32 padded_row_size;
6187 if (!GLES2Util::ComputeImageDataSizes(
6188 width, 2, format, type, pack_alignment_, &temp_size,
6189 &unpadded_row_size, &padded_row_size)) {
[email protected]8eee29c2010-04-29 03:38:296190 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:566191 return error::kNoError;
6192 }
6193
6194 GLint dest_x_offset = std::max(-x, 0);
6195 uint32 dest_row_offset;
[email protected]3458a64a2012-04-10 17:39:346196 if (!GLES2Util::ComputeImageDataSizes(
6197 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset, NULL,
6198 NULL)) {
[email protected]8eee29c2010-04-29 03:38:296199 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
[email protected]57f223832010-03-19 01:57:566200 return error::kNoError;
6201 }
6202
6203 // Copy each row into the larger dest rect.
6204 int8* dst = static_cast<int8*>(pixels);
6205 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:026206 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:566207 GLint read_width = read_end_x - read_x;
6208 for (GLint yy = 0; yy < height; ++yy) {
6209 GLint ry = y + yy;
6210
6211 // Clear the row.
6212 memset(dst, 0, unpadded_row_size);
6213
6214 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:026215 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:566216 glReadPixels(
6217 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
6218 }
6219 dst += padded_row_size;
6220 }
6221 } else {
6222 glReadPixels(x, y, width, height, format, type, pixels);
6223 }
[email protected]1002c2d2011-06-28 22:39:046224 GLenum error = PeekGLError();
[email protected]a51788e2010-02-24 21:54:256225 if (error == GL_NO_ERROR) {
6226 *result = true;
[email protected]4848b9f82011-03-10 18:37:566227
6228 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6229 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
[email protected]c892a4e12012-05-08 18:20:196230 if ((channels_exist & 0x0008) == 0 && !disable_workarounds_) {
[email protected]4848b9f82011-03-10 18:37:566231 // Set the alpha to 255 because some drivers are buggy in this regard.
6232 uint32 temp_size;
[email protected]3458a64a2012-04-10 17:39:346233
6234 uint32 unpadded_row_size;
6235 uint32 padded_row_size;
6236 if (!GLES2Util::ComputeImageDataSizes(
6237 width, 2, format, type, pack_alignment_, &temp_size,
6238 &unpadded_row_size, &padded_row_size)) {
[email protected]4848b9f82011-03-10 18:37:566239 SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
6240 return error::kNoError;
6241 }
6242 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
6243 // of this implementation.
6244 if (type != GL_UNSIGNED_BYTE) {
6245 SetGLError(GL_INVALID_OPERATION, "unsupported readPixel format");
6246 return error::kNoError;
6247 }
6248 switch (format) {
6249 case GL_RGBA:
[email protected]297ca1c2011-06-20 23:08:466250 case GL_BGRA_EXT:
[email protected]4848b9f82011-03-10 18:37:566251 case GL_ALPHA: {
6252 int offset = (format == GL_ALPHA) ? 0 : 3;
6253 int step = (format == GL_ALPHA) ? 1 : 4;
6254 uint8* dst = static_cast<uint8*>(pixels) + offset;
6255 for (GLint yy = 0; yy < height; ++yy) {
6256 uint8* end = dst + unpadded_row_size;
6257 for (uint8* d = dst; d < end; d += step) {
6258 *d = 255;
6259 }
6260 dst += padded_row_size;
6261 }
6262 break;
6263 }
6264 default:
6265 break;
6266 }
6267 }
[email protected]a51788e2010-02-24 21:54:256268 }
[email protected]4848b9f82011-03-10 18:37:566269
[email protected]f7a64ee2010-02-01 22:24:146270 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326271}
6272
[email protected]f7a64ee2010-02-01 22:24:146273error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:196274 uint32 immediate_data_size, const gles2::PixelStorei& c) {
6275 GLenum pname = c.pname;
6276 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:056277 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:296278 SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:126279 return error::kNoError;
6280 }
[email protected]222471d2011-11-30 18:06:396281 switch (pname) {
6282 case GL_PACK_ALIGNMENT:
6283 case GL_UNPACK_ALIGNMENT:
6284 if (!validators_->pixel_store_alignment.IsValid(param)) {
6285 SetGLError(GL_INVALID_VALUE,
6286 "glPixelSTore: param GL_INVALID_VALUE");
6287 return error::kNoError;
6288 }
[email protected]164d6d52012-05-05 00:55:036289 break;
[email protected]0a1e9ad2012-05-04 21:13:036290 case GL_UNPACK_FLIP_Y_CHROMIUM:
6291 unpack_flip_y_ = (param != 0);
6292 return error::kNoError;
6293 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
6294 unpack_premultiply_alpha_ = (param != 0);
6295 return error::kNoError;
[email protected]222471d2011-11-30 18:06:396296 default:
6297 break;
[email protected]b9849abf2009-11-25 19:13:196298 }
6299 glPixelStorei(pname, param);
6300 switch (pname) {
6301 case GL_PACK_ALIGNMENT:
6302 pack_alignment_ = param;
6303 break;
[email protected]222471d2011-11-30 18:06:396304 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
6305 break;
[email protected]b9849abf2009-11-25 19:13:196306 case GL_UNPACK_ALIGNMENT:
6307 unpack_alignment_ = param;
6308 break;
[email protected]b9849abf2009-11-25 19:13:196309 default:
6310 // Validation should have prevented us from getting here.
[email protected]656dcaad2010-05-07 17:18:376311 NOTREACHED();
[email protected]b9849abf2009-11-25 19:13:196312 break;
6313 }
[email protected]f7a64ee2010-02-01 22:24:146314 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196315}
6316
[email protected]1c75a3702011-11-11 14:15:286317error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
6318 uint32 immediate_data_size, const gles2::PostSubBufferCHROMIUM& c) {
6319 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
[email protected]aa258822011-11-22 13:52:256320 if (!context_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
[email protected]1c75a3702011-11-11 14:15:286321 SetGLError(GL_INVALID_OPERATION,
6322 "glPostSubBufferCHROMIUM: command not supported by surface");
6323 return error::kNoError;
6324 }
[email protected]7794d512012-04-17 20:36:496325 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
[email protected]1c75a3702011-11-11 14:15:286326 return error::kNoError;
[email protected]7794d512012-04-17 20:36:496327 } else {
6328 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
[email protected]1c75a3702011-11-11 14:15:286329 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:496330 }
[email protected]1c75a3702011-11-11 14:15:286331}
6332
[email protected]558847a2010-03-24 07:02:546333error::Error GLES2DecoderImpl::GetAttribLocationHelper(
6334 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6335 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576336 if (!StringIsValidForGLES(name_str.c_str())) {
6337 SetGLError(GL_INVALID_VALUE, "glGetAttribLocation: Invalid character");
6338 return error::kNoError;
6339 }
[email protected]6b8cf1a2010-05-06 16:13:586340 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6341 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:036342 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146343 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196344 }
[email protected]ae51d192010-04-27 00:48:036345 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:296346 SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:256347 return error::kNoError;
6348 }
[email protected]b9849abf2009-11-25 19:13:196349 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546350 location_shm_id, location_shm_offset, sizeof(GLint));
6351 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146352 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196353 }
[email protected]558847a2010-03-24 07:02:546354 // Require the client to init this incase the context is lost and we are no
6355 // longer executing commands.
6356 if (*location != -1) {
6357 return error::kGenericError;
6358 }
[email protected]0bfd9882010-02-05 23:02:256359 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:146360 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196361}
6362
[email protected]558847a2010-03-24 07:02:546363error::Error GLES2DecoderImpl::HandleGetAttribLocation(
6364 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
6365 uint32 name_size = c.data_size;
6366 const char* name = GetSharedMemoryAs<const char*>(
6367 c.name_shm_id, c.name_shm_offset, name_size);
6368 if (!name) {
6369 return error::kOutOfBounds;
6370 }
6371 String name_str(name, name_size);
6372 return GetAttribLocationHelper(
6373 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6374}
6375
[email protected]f7a64ee2010-02-01 22:24:146376error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196377 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:546378 uint32 name_size = c.data_size;
6379 const char* name = GetImmediateDataAs<const char*>(
6380 c, name_size, immediate_data_size);
6381 if (!name) {
6382 return error::kOutOfBounds;
6383 }
6384 String name_str(name, name_size);
6385 return GetAttribLocationHelper(
6386 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6387}
6388
6389error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
6390 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
6391 Bucket* bucket = GetBucket(c.name_bucket_id);
6392 if (!bucket) {
6393 return error::kInvalidArguments;
6394 }
6395 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186396 if (!bucket->GetAsString(&name_str)) {
6397 return error::kInvalidArguments;
6398 }
[email protected]558847a2010-03-24 07:02:546399 return GetAttribLocationHelper(
6400 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6401}
6402
6403error::Error GLES2DecoderImpl::GetUniformLocationHelper(
6404 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6405 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576406 if (!StringIsValidForGLES(name_str.c_str())) {
6407 SetGLError(GL_INVALID_VALUE, "glGetUniformLocation: Invalid character");
6408 return error::kNoError;
6409 }
[email protected]6b8cf1a2010-05-06 16:13:586410 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6411 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:036412 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146413 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196414 }
[email protected]ae51d192010-04-27 00:48:036415 if (!info->IsValid()) {
[email protected]8eee29c2010-04-29 03:38:296416 SetGLError(GL_INVALID_OPERATION,
6417 "glGetUniformLocation: program not linked");
[email protected]0bfd9882010-02-05 23:02:256418 return error::kNoError;
6419 }
[email protected]b9849abf2009-11-25 19:13:196420 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546421 location_shm_id, location_shm_offset, sizeof(GLint));
6422 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146423 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196424 }
[email protected]558847a2010-03-24 07:02:546425 // Require the client to init this incase the context is lost an we are no
6426 // longer executing commands.
6427 if (*location != -1) {
6428 return error::kGenericError;
6429 }
[email protected]5d4c6b22012-02-07 08:22:286430 *location = program_manager()->SwizzleLocation(
[email protected]1b0a6752012-02-22 03:44:126431 info->GetUniformFakeLocation(name_str));
[email protected]f7a64ee2010-02-01 22:24:146432 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196433}
6434
[email protected]f7a64ee2010-02-01 22:24:146435error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:196436 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:196437 uint32 name_size = c.data_size;
6438 const char* name = GetSharedMemoryAs<const char*>(
6439 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:546440 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146441 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196442 }
6443 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546444 return GetUniformLocationHelper(
6445 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196446}
6447
[email protected]f7a64ee2010-02-01 22:24:146448error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196449 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:196450 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:306451 const char* name = GetImmediateDataAs<const char*>(
6452 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:546453 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146454 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196455 }
6456 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546457 return GetUniformLocationHelper(
6458 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6459}
6460
6461error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
6462 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
6463 Bucket* bucket = GetBucket(c.name_bucket_id);
6464 if (!bucket) {
6465 return error::kInvalidArguments;
6466 }
6467 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186468 if (!bucket->GetAsString(&name_str)) {
6469 return error::kInvalidArguments;
6470 }
[email protected]558847a2010-03-24 07:02:546471 return GetUniformLocationHelper(
6472 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196473}
6474
[email protected]ddd968b82010-03-02 00:44:296475error::Error GLES2DecoderImpl::HandleGetString(
6476 uint32 immediate_data_size, const gles2::GetString& c) {
6477 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:056478 if (!validators_->string_type.IsValid(name)) {
[email protected]8eee29c2010-04-29 03:38:296479 SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:296480 return error::kNoError;
6481 }
[email protected]1958e0e2010-04-22 05:17:156482 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
6483 const char* str = NULL;
[email protected]f0d74742011-10-03 16:31:046484 std::string extensions;
[email protected]1958e0e2010-04-22 05:17:156485 switch (name) {
6486 case GL_VERSION:
6487 str = "OpenGL ES 2.0 Chromium";
6488 break;
6489 case GL_SHADING_LANGUAGE_VERSION:
6490 str = "OpenGL ES GLSL ES 1.0 Chromium";
6491 break;
[email protected]32939602012-05-09 06:25:166492 case GL_RENDERER:
6493 str = "Chromium";
6494 break;
6495 case GL_VENDOR:
6496 str = "Chromium";
6497 break;
[email protected]1958e0e2010-04-22 05:17:156498 case GL_EXTENSIONS:
[email protected]f0d74742011-10-03 16:31:046499 {
6500 // For WebGL contexts, strip out the OES derivatives extension if it has
6501 // not been enabled.
6502 if (force_webgl_glsl_validation_ &&
6503 !derivatives_explicitly_enabled_) {
6504 extensions = feature_info_->extensions();
6505 size_t offset = extensions.find(kOESDerivativeExtension);
6506 if (std::string::npos != offset) {
6507 extensions.replace(offset,
6508 offset + arraysize(kOESDerivativeExtension),
6509 std::string());
6510 }
6511 str = extensions.c_str();
6512 } else {
6513 str = feature_info_->extensions().c_str();
6514 }
[email protected]f0d74742011-10-03 16:31:046515 }
[email protected]1958e0e2010-04-22 05:17:156516 break;
6517 default:
6518 str = gl_str;
6519 break;
6520 }
[email protected]ddd968b82010-03-02 00:44:296521 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:156522 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:296523 return error::kNoError;
6524}
6525
[email protected]0c86dbf2010-03-05 08:14:116526void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:156527 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:056528 if (!validators_->buffer_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296529 SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
6530 return;
6531 }
[email protected]9438b012010-06-15 22:55:056532 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]8eee29c2010-04-29 03:38:296533 SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:116534 return;
[email protected]3b6ec202010-03-05 05:16:236535 }
6536 if (size < 0) {
[email protected]8eee29c2010-04-29 03:38:296537 SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
[email protected]037896bd2010-04-21 19:07:286538 return;
[email protected]3b6ec202010-03-05 05:16:236539 }
6540 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
6541 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296542 SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:286543 return;
[email protected]3b6ec202010-03-05 05:16:236544 }
6545 // Clear the buffer to 0 if no initial data was passed in.
6546 scoped_array<int8> zero;
6547 if (!data) {
6548 zero.reset(new int8[size]);
6549 memset(zero.get(), 0, size);
6550 data = zero.get();
6551 }
[email protected]473c01ccb2011-06-07 01:33:306552
6553 if (!bufferdata_faster_than_buffersubdata_ &&
6554 size == info->size() && usage == info->usage()) {
6555 glBufferSubData(target, 0, size, data);
6556 info->SetRange(0, size, data);
6557 return;
6558 }
6559
[email protected]3b6ec202010-03-05 05:16:236560 CopyRealGLErrorsToWrapper();
6561 glBufferData(target, size, data, usage);
[email protected]1002c2d2011-06-28 22:39:046562 GLenum error = PeekGLError();
6563 if (error == GL_NO_ERROR) {
[email protected]473c01ccb2011-06-07 01:33:306564 buffer_manager()->SetInfo(info, size, usage);
[email protected]0c86dbf2010-03-05 08:14:116565 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:236566 }
[email protected]0c86dbf2010-03-05 08:14:116567}
6568
6569error::Error GLES2DecoderImpl::HandleBufferData(
6570 uint32 immediate_data_size, const gles2::BufferData& c) {
6571 GLenum target = static_cast<GLenum>(c.target);
6572 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
6573 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6574 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6575 GLenum usage = static_cast<GLenum>(c.usage);
6576 const void* data = NULL;
6577 if (data_shm_id != 0 || data_shm_offset != 0) {
6578 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
6579 if (!data) {
6580 return error::kOutOfBounds;
6581 }
6582 }
6583 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:146584 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196585}
6586
[email protected]f7a64ee2010-02-01 22:24:146587error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:196588 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
6589 GLenum target = static_cast<GLenum>(c.target);
6590 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:306591 const void* data = GetImmediateDataAs<const void*>(
6592 c, size, immediate_data_size);
6593 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146594 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:306595 }
[email protected]b9849abf2009-11-25 19:13:196596 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:116597 DoBufferData(target, size, data, usage);
6598 return error::kNoError;
6599}
6600
6601void GLES2DecoderImpl::DoBufferSubData(
6602 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:506603 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476604 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296605 SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
[email protected]037896bd2010-04-21 19:07:286606 return;
[email protected]a93bb842010-02-16 23:03:476607 }
[email protected]0c86dbf2010-03-05 08:14:116608 if (!info->SetRange(offset, size, data)) {
[email protected]8eee29c2010-04-29 03:38:296609 SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
[email protected]473c01ccb2011-06-07 01:33:306610 return;
[email protected]07f54fcc2009-12-22 02:46:306611 }
[email protected]473c01ccb2011-06-07 01:33:306612 if (bufferdata_faster_than_buffersubdata_ &&
6613 offset == 0 && size == info->size()) {
6614 glBufferData(target, size, data, info->usage());
6615 return;
6616 }
6617 glBufferSubData(target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:196618}
6619
[email protected]0d6bfdc2011-11-02 01:32:206620bool GLES2DecoderImpl::ClearLevel(
6621 unsigned service_id,
6622 unsigned bind_target,
6623 unsigned target,
6624 int level,
6625 unsigned format,
6626 unsigned type,
6627 int width,
[email protected]4502e6492011-12-14 19:39:156628 int height,
6629 bool is_texture_immutable) {
[email protected]45d15a62012-04-18 14:33:176630 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
6631
6632 uint32 size;
6633 uint32 padded_row_size;
[email protected]3458a64a2012-04-10 17:39:346634 if (!GLES2Util::ComputeImageDataSizes(
[email protected]45d15a62012-04-18 14:33:176635 width, height, format, type, unpack_alignment_, &size,
6636 NULL, &padded_row_size)) {
[email protected]0d6bfdc2011-11-02 01:32:206637 return false;
6638 }
[email protected]45d15a62012-04-18 14:33:176639
6640 int tile_height;
6641
6642 if (size > kMaxZeroSize) {
6643 if (kMaxZeroSize < padded_row_size) {
6644 // That'd be an awfully large texture.
6645 return false;
6646 }
6647 // We should never have a large total size with a zero row size.
6648 DCHECK_GT(padded_row_size, 0U);
6649 tile_height = kMaxZeroSize / padded_row_size;
6650 if (!GLES2Util::ComputeImageDataSizes(
6651 width, tile_height, format, type, unpack_alignment_, &size, NULL,
6652 NULL)) {
6653 return false;
6654 }
[email protected]4502e6492011-12-14 19:39:156655 } else {
[email protected]45d15a62012-04-18 14:33:176656 tile_height = height;
6657 }
6658
6659 // Assumes the size has already been checked.
6660 scoped_array<char> zero(new char[size]);
6661 memset(zero.get(), 0, size);
6662 glBindTexture(bind_target, service_id);
6663
6664 GLint y = 0;
6665 while (y < height) {
6666 GLint h = y + tile_height > height ? height - y : tile_height;
6667 if (is_texture_immutable || h != height) {
6668 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
6669 } else {
6670 WrappedTexImage2D(
6671 target, level, format, width, h, 0, format, type, zero.get());
6672 }
6673 y += tile_height;
[email protected]4502e6492011-12-14 19:39:156674 }
[email protected]0d6bfdc2011-11-02 01:32:206675 TextureManager::TextureInfo* info = GetTextureInfoForTarget(bind_target);
6676 glBindTexture(bind_target, info ? info->service_id() : 0);
6677 return true;
6678}
6679
[email protected]a93bb842010-02-16 23:03:476680error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
6681 GLenum target,
6682 GLint level,
6683 GLenum internal_format,
6684 GLsizei width,
6685 GLsizei height,
6686 GLint border,
6687 GLsizei image_size,
6688 const void* data) {
[email protected]a93bb842010-02-16 23:03:476689 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:056690 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296691 SetGLError(GL_INVALID_ENUM,
6692 "glCompressedTexImage2D: target GL_INVALID_ENUM");
6693 return error::kNoError;
6694 }
[email protected]9438b012010-06-15 22:55:056695 if (!validators_->compressed_texture_format.IsValid(
6696 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296697 SetGLError(GL_INVALID_ENUM,
6698 "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:476699 return error::kNoError;
6700 }
[email protected]80eb6b52012-01-19 00:14:416701 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476702 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296703 SetGLError(GL_INVALID_VALUE,
6704 "glCompressedTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476705 return error::kNoError;
6706 }
[email protected]3916c97e2010-02-25 03:20:506707 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476708 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296709 SetGLError(GL_INVALID_VALUE,
6710 "glCompressedTexImage2D: unknown texture target");
[email protected]a93bb842010-02-16 23:03:476711 return error::kNoError;
6712 }
[email protected]97dc7cbe2011-12-06 17:26:176713 if (info->IsImmutable()) {
6714 SetGLError(GL_INVALID_OPERATION,
6715 "glCompressedTexImage2D: texture is immutable");
6716 return error::kNoError;
6717 }
[email protected]968351b2011-12-20 08:26:516718
6719 if (info->IsAttachedToFramebuffer()) {
6720 state_dirty_ = true;
6721 // TODO(gman): If textures tracked which framebuffers they were attached to
6722 // we could just mark those framebuffers as not complete.
6723 framebuffer_manager()->IncFramebufferStateChangeCount();
6724 }
6725
[email protected]a93bb842010-02-16 23:03:476726 scoped_array<int8> zero;
6727 if (!data) {
6728 zero.reset(new int8[image_size]);
6729 memset(zero.get(), 0, image_size);
6730 data = zero.get();
6731 }
[email protected]cadde4a2010-07-31 17:10:436732 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:476733 glCompressedTexImage2D(
6734 target, level, internal_format, width, height, border, image_size, data);
[email protected]1002c2d2011-06-28 22:39:046735 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436736 if (error == GL_NO_ERROR) {
6737 texture_manager()->SetLevelInfo(
[email protected]0d6bfdc2011-11-02 01:32:206738 info, target, level, internal_format, width, height, 1, border, 0, 0,
6739 true);
[email protected]cadde4a2010-07-31 17:10:436740 }
[email protected]a93bb842010-02-16 23:03:476741 return error::kNoError;
6742}
6743
[email protected]f7a64ee2010-02-01 22:24:146744error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196745 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
6746 GLenum target = static_cast<GLenum>(c.target);
6747 GLint level = static_cast<GLint>(c.level);
6748 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6749 GLsizei width = static_cast<GLsizei>(c.width);
6750 GLsizei height = static_cast<GLsizei>(c.height);
6751 GLint border = static_cast<GLint>(c.border);
6752 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
6753 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6754 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6755 const void* data = NULL;
6756 if (data_shm_id != 0 || data_shm_offset != 0) {
6757 data = GetSharedMemoryAs<const void*>(
6758 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:466759 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146760 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196761 }
6762 }
[email protected]a93bb842010-02-16 23:03:476763 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196764 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:196765}
6766
[email protected]f7a64ee2010-02-01 22:24:146767error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:196768 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
6769 GLenum target = static_cast<GLenum>(c.target);
6770 GLint level = static_cast<GLint>(c.level);
6771 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6772 GLsizei width = static_cast<GLsizei>(c.width);
6773 GLsizei height = static_cast<GLsizei>(c.height);
6774 GLint border = static_cast<GLint>(c.border);
6775 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:306776 const void* data = GetImmediateDataAs<const void*>(
6777 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466778 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146779 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466780 }
[email protected]a93bb842010-02-16 23:03:476781 return DoCompressedTexImage2D(
6782 target, level, internal_format, width, height, border, image_size, data);
6783}
6784
[email protected]b6140d02010-05-17 14:47:166785error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
6786 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
6787 GLenum target = static_cast<GLenum>(c.target);
6788 GLint level = static_cast<GLint>(c.level);
6789 GLenum internal_format = static_cast<GLenum>(c.internalformat);
6790 GLsizei width = static_cast<GLsizei>(c.width);
6791 GLsizei height = static_cast<GLsizei>(c.height);
6792 GLint border = static_cast<GLint>(c.border);
6793 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:286794 if (!bucket) {
6795 return error::kInvalidArguments;
6796 }
6797 uint32 data_size = bucket->size();
6798 GLsizei imageSize = data_size;
6799 const void* data = bucket->GetData(0, data_size);
6800 if (!data) {
6801 return error::kInvalidArguments;
6802 }
[email protected]b6140d02010-05-17 14:47:166803 return DoCompressedTexImage2D(
6804 target, level, internal_format, width, height, border,
[email protected]12f93d82011-10-17 21:16:286805 imageSize, data);
[email protected]b6140d02010-05-17 14:47:166806}
6807
6808error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
6809 uint32 immediate_data_size,
6810 const gles2::CompressedTexSubImage2DBucket& c) {
6811 GLenum target = static_cast<GLenum>(c.target);
6812 GLint level = static_cast<GLint>(c.level);
6813 GLint xoffset = static_cast<GLint>(c.xoffset);
6814 GLint yoffset = static_cast<GLint>(c.yoffset);
6815 GLsizei width = static_cast<GLsizei>(c.width);
6816 GLsizei height = static_cast<GLsizei>(c.height);
6817 GLenum format = static_cast<GLenum>(c.format);
6818 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:286819 if (!bucket) {
6820 return error::kInvalidArguments;
6821 }
[email protected]b6140d02010-05-17 14:47:166822 uint32 data_size = bucket->size();
6823 GLsizei imageSize = data_size;
6824 const void* data = bucket->GetData(0, data_size);
[email protected]12f93d82011-10-17 21:16:286825 if (!data) {
6826 return error::kInvalidArguments;
6827 }
[email protected]9438b012010-06-15 22:55:056828 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:166829 SetGLError(
6830 GL_INVALID_ENUM, "glCompressedTexSubImage2D: target GL_INVALID_ENUM");
6831 return error::kNoError;
6832 }
[email protected]9438b012010-06-15 22:55:056833 if (!validators_->compressed_texture_format.IsValid(format)) {
6834 SetGLError(GL_INVALID_ENUM,
6835 "glCompressedTexSubImage2D: format GL_INVALID_ENUM");
6836 return error::kNoError;
6837 }
[email protected]b6140d02010-05-17 14:47:166838 if (width < 0) {
6839 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: width < 0");
6840 return error::kNoError;
6841 }
6842 if (height < 0) {
6843 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: height < 0");
6844 return error::kNoError;
6845 }
6846 if (imageSize < 0) {
6847 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D: imageSize < 0");
6848 return error::kNoError;
6849 }
[email protected]cadde4a2010-07-31 17:10:436850 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:166851 target, level, xoffset, yoffset, width, height, format, imageSize, data);
6852 return error::kNoError;
6853}
6854
[email protected]a93bb842010-02-16 23:03:476855error::Error GLES2DecoderImpl::DoTexImage2D(
6856 GLenum target,
6857 GLint level,
6858 GLenum internal_format,
6859 GLsizei width,
6860 GLsizei height,
6861 GLint border,
6862 GLenum format,
6863 GLenum type,
6864 const void* pixels,
6865 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:056866 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296867 SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
6868 return error::kNoError;
6869 }
[email protected]9438b012010-06-15 22:55:056870 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296871 SetGLError(GL_INVALID_ENUM,
6872 "glTexImage2D: internal_format GL_INVALID_ENUM");
6873 return error::kNoError;
6874 }
[email protected]9438b012010-06-15 22:55:056875 if (!validators_->texture_format.IsValid(format)) {
[email protected]8eee29c2010-04-29 03:38:296876 SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
6877 return error::kNoError;
6878 }
[email protected]9438b012010-06-15 22:55:056879 if (!validators_->pixel_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:296880 SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:146881 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196882 }
[email protected]7b92c412010-07-20 17:48:256883 if (format != internal_format) {
6884 SetGLError(GL_INVALID_OPERATION, "glTexImage2D: format != internalFormat");
6885 return error::kNoError;
6886 }
[email protected]80eb6b52012-01-19 00:14:416887 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476888 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296889 SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476890 return error::kNoError;
6891 }
[email protected]3916c97e2010-02-25 03:20:506892 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476893 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296894 SetGLError(GL_INVALID_OPERATION,
6895 "glTexImage2D: unknown texture for target");
[email protected]a93bb842010-02-16 23:03:476896 return error::kNoError;
6897 }
[email protected]0226c112011-07-22 03:25:076898
[email protected]97dc7cbe2011-12-06 17:26:176899 if (info->IsImmutable()) {
6900 SetGLError(GL_INVALID_OPERATION,
6901 "glTexImage2D: texture is immutable");
6902 return error::kNoError;
6903 }
6904
[email protected]0226c112011-07-22 03:25:076905 GLsizei tex_width = 0;
6906 GLsizei tex_height = 0;
6907 GLenum tex_type = 0;
6908 GLenum tex_format = 0;
6909 bool level_is_same =
6910 info->GetLevelSize(target, level, &tex_width, &tex_height) &&
6911 info->GetLevelType(target, level, &tex_type, &tex_format) &&
6912 width == tex_width && height == tex_height &&
6913 type == tex_type && format == tex_format;
6914
6915 if (level_is_same && !pixels) {
[email protected]1bed6222011-12-21 11:21:396916 // Just set the level info but mark the texture as uncleared.
6917 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416918 info,
[email protected]1bed6222011-12-21 11:21:396919 target, level, internal_format, width, height, 1, border, format, type,
6920 false);
[email protected]ea72ed222011-08-17 18:58:436921 tex_image_2d_failed_ = false;
[email protected]0226c112011-07-22 03:25:076922 return error::kNoError;
6923 }
6924
[email protected]297ca1c2011-06-20 23:08:466925 if (info->IsAttachedToFramebuffer()) {
6926 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:516927 // TODO(gman): If textures tracked which framebuffers they were attached to
6928 // we could just mark those framebuffers as not complete.
6929 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:466930 }
6931
[email protected]1bed6222011-12-21 11:21:396932 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same && pixels) {
[email protected]0226c112011-07-22 03:25:076933 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
[email protected]57edfdad2012-02-07 04:57:156934 texture_manager()->SetLevelCleared(info, target, level);
[email protected]0226c112011-07-22 03:25:076935 tex_image_2d_failed_ = false;
6936 return error::kNoError;
[email protected]7488d962010-07-16 02:41:586937 }
[email protected]876f6fee2010-08-02 23:10:326938
[email protected]cadde4a2010-07-31 17:10:436939 CopyRealGLErrorsToWrapper();
[email protected]473c01ccb2011-06-07 01:33:306940 WrappedTexImage2D(
6941 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476942 pixels);
[email protected]1002c2d2011-06-28 22:39:046943 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436944 if (error == GL_NO_ERROR) {
[email protected]0d6bfdc2011-11-02 01:32:206945 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:416946 info,
[email protected]0d6bfdc2011-11-02 01:32:206947 target, level, internal_format, width, height, 1, border, format, type,
6948 pixels != NULL);
[email protected]b493ee622011-04-13 23:52:006949 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:436950 }
[email protected]f7a64ee2010-02-01 22:24:146951 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196952}
6953
[email protected]f7a64ee2010-02-01 22:24:146954error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196955 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]366ae242011-05-10 02:23:586956 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:006957 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:196958 GLenum target = static_cast<GLenum>(c.target);
6959 GLint level = static_cast<GLint>(c.level);
6960 GLint internal_format = static_cast<GLint>(c.internalformat);
6961 GLsizei width = static_cast<GLsizei>(c.width);
6962 GLsizei height = static_cast<GLsizei>(c.height);
6963 GLint border = static_cast<GLint>(c.border);
6964 GLenum format = static_cast<GLenum>(c.format);
6965 GLenum type = static_cast<GLenum>(c.type);
6966 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
6967 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:186968 uint32 pixels_size;
[email protected]3458a64a2012-04-10 17:39:346969 if (!GLES2Util::ComputeImageDataSizes(
6970 width, height, format, type, unpack_alignment_, &pixels_size, NULL,
6971 NULL)) {
[email protected]a76b0052010-03-05 00:33:186972 return error::kOutOfBounds;
6973 }
[email protected]b9849abf2009-11-25 19:13:196974 const void* pixels = NULL;
6975 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
6976 pixels = GetSharedMemoryAs<const void*>(
6977 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:466978 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146979 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196980 }
6981 }
[email protected]a93bb842010-02-16 23:03:476982 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:196983 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:476984 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:196985}
6986
[email protected]f7a64ee2010-02-01 22:24:146987error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:196988 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
6989 GLenum target = static_cast<GLenum>(c.target);
6990 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:466991 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:196992 GLsizei width = static_cast<GLsizei>(c.width);
6993 GLsizei height = static_cast<GLsizei>(c.height);
6994 GLint border = static_cast<GLint>(c.border);
6995 GLenum format = static_cast<GLenum>(c.format);
6996 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:186997 uint32 size;
[email protected]3458a64a2012-04-10 17:39:346998 if (!GLES2Util::ComputeImageDataSizes(
6999 width, height, format, type, unpack_alignment_, &size, NULL, NULL)) {
[email protected]a76b0052010-03-05 00:33:187000 return error::kOutOfBounds;
7001 }
[email protected]07f54fcc2009-12-22 02:46:307002 const void* pixels = GetImmediateDataAs<const void*>(
7003 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:467004 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:147005 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:467006 }
[email protected]a93bb842010-02-16 23:03:477007 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:467008 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:477009 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:147010 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327011}
7012
[email protected]cadde4a2010-07-31 17:10:437013void GLES2DecoderImpl::DoCompressedTexSubImage2D(
7014 GLenum target,
7015 GLint level,
7016 GLint xoffset,
7017 GLint yoffset,
7018 GLsizei width,
7019 GLsizei height,
7020 GLenum format,
7021 GLsizei image_size,
7022 const void * data) {
7023 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7024 if (!info) {
7025 SetGLError(GL_INVALID_OPERATION,
7026 "glCompressedTexSubImage2D: unknown texture for target");
7027 return;
7028 }
7029 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:527030 GLenum internal_format = 0;
7031 if (!info->GetLevelType(target, level, &type, &internal_format)) {
7032 SetGLError(
7033 GL_INVALID_OPERATION,
[email protected]4502e6492011-12-14 19:39:157034 "glCompressedTexSubImage2D: level does not exist.");
[email protected]df6cf1ad2011-01-29 01:20:527035 return;
7036 }
7037 if (internal_format != format) {
7038 SetGLError(
7039 GL_INVALID_OPERATION,
[email protected]4502e6492011-12-14 19:39:157040 "glCompressedTexSubImage2D: format does not match internal format.");
[email protected]df6cf1ad2011-01-29 01:20:527041 return;
7042 }
7043 if (!info->ValidForTexture(
7044 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:437045 SetGLError(GL_INVALID_VALUE,
[email protected]4502e6492011-12-14 19:39:157046 "glCompressedTexSubImage2D: bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:437047 return;
7048 }
[email protected]0d6bfdc2011-11-02 01:32:207049 // Note: There is no need to deal with texture cleared tracking here
7050 // because the validation above means you can only get here if the level
7051 // is already a matching compressed format and in that case
7052 // CompressedTexImage2D already cleared the texture.
[email protected]cadde4a2010-07-31 17:10:437053 glCompressedTexSubImage2D(
7054 target, level, xoffset, yoffset, width, height, format, image_size, data);
7055}
7056
[email protected]6e288612010-12-21 20:45:037057static void Clip(
7058 GLint start, GLint range, GLint sourceRange,
7059 GLint* out_start, GLint* out_range) {
7060 DCHECK(out_start);
7061 DCHECK(out_range);
7062 if (start < 0) {
7063 range += start;
7064 start = 0;
7065 }
7066 GLint end = start + range;
7067 if (end > sourceRange) {
7068 range -= end - sourceRange;
7069 }
7070 *out_start = start;
7071 *out_range = range;
7072}
7073
[email protected]cadde4a2010-07-31 17:10:437074void GLES2DecoderImpl::DoCopyTexImage2D(
7075 GLenum target,
7076 GLint level,
7077 GLenum internal_format,
7078 GLint x,
7079 GLint y,
7080 GLsizei width,
7081 GLsizei height,
7082 GLint border) {
7083 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7084 if (!info) {
7085 SetGLError(GL_INVALID_OPERATION,
7086 "glCopyTexImage2D: unknown texture for target");
7087 return;
7088 }
[email protected]97dc7cbe2011-12-06 17:26:177089 if (info->IsImmutable()) {
7090 SetGLError(GL_INVALID_OPERATION,
7091 "glCopyTexImage2D: texture is immutable");
7092 }
[email protected]80eb6b52012-01-19 00:14:417093 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:187094 border != 0) {
7095 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions out of range");
7096 return;
7097 }
7098
[email protected]9edc6b22010-12-23 02:00:267099 // Check we have compatible formats.
7100 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7101 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7102 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
7103
7104 if ((channels_needed & channels_exist) != channels_needed) {
7105 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D: incompatible format");
7106 return;
7107 }
7108
[email protected]a0b78dc2011-11-11 10:43:107109 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
7110 return;
7111 }
7112
[email protected]cadde4a2010-07-31 17:10:437113 CopyRealGLErrorsToWrapper();
[email protected]de26b3c2011-08-03 21:54:277114 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:037115 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:267116
[email protected]297ca1c2011-06-20 23:08:467117 if (info->IsAttachedToFramebuffer()) {
7118 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:517119 // TODO(gman): If textures tracked which framebuffers they were attached to
7120 // we could just mark those framebuffers as not complete.
7121 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:467122 }
7123
[email protected]9edc6b22010-12-23 02:00:267124 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:037125 GLint copyX = 0;
7126 GLint copyY = 0;
7127 GLint copyWidth = 0;
7128 GLint copyHeight = 0;
7129 Clip(x, width, size.width(), &copyX, &copyWidth);
7130 Clip(y, height, size.height(), &copyY, &copyHeight);
7131
7132 if (copyX != x ||
7133 copyY != y ||
7134 copyWidth != width ||
7135 copyHeight != height) {
7136 // some part was clipped so clear the texture.
[email protected]0d6bfdc2011-11-02 01:32:207137 if (!ClearLevel(
7138 info->service_id(), info->target(),
[email protected]4502e6492011-12-14 19:39:157139 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
7140 info->IsImmutable())) {
[email protected]0d6bfdc2011-11-02 01:32:207141 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexImage2D: dimensions too big");
[email protected]6e288612010-12-21 20:45:037142 return;
7143 }
[email protected]6e288612010-12-21 20:45:037144 if (copyHeight > 0 && copyWidth > 0) {
7145 GLint dx = copyX - x;
7146 GLint dy = copyY - y;
7147 GLint destX = dx;
7148 GLint destY = dy;
7149 glCopyTexSubImage2D(target, level,
7150 destX, destY, copyX, copyY,
7151 copyWidth, copyHeight);
7152 }
7153 } else {
7154 glCopyTexImage2D(target, level, internal_format,
7155 copyX, copyY, copyWidth, copyHeight, border);
7156 }
[email protected]1002c2d2011-06-28 22:39:047157 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:437158 if (error == GL_NO_ERROR) {
7159 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:417160 info, target, level, internal_format, width, height, 1,
[email protected]0d6bfdc2011-11-02 01:32:207161 border, internal_format, GL_UNSIGNED_BYTE, true);
[email protected]cadde4a2010-07-31 17:10:437162 }
7163}
7164
7165void GLES2DecoderImpl::DoCopyTexSubImage2D(
7166 GLenum target,
7167 GLint level,
7168 GLint xoffset,
7169 GLint yoffset,
7170 GLint x,
7171 GLint y,
7172 GLsizei width,
7173 GLsizei height) {
7174 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7175 if (!info) {
7176 SetGLError(GL_INVALID_OPERATION,
7177 "glCopyTexSubImage2D: unknown texture for target");
7178 return;
7179 }
7180 GLenum type = 0;
7181 GLenum format = 0;
7182 if (!info->GetLevelType(target, level, &type, &format) ||
7183 !info->ValidForTexture(
7184 target, level, xoffset, yoffset, width, height, format, type)) {
7185 SetGLError(GL_INVALID_VALUE,
7186 "glCopyTexSubImage2D: bad dimensions.");
7187 return;
7188 }
[email protected]9edc6b22010-12-23 02:00:267189
7190 // Check we have compatible formats.
7191 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7192 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7193 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
7194
7195 if ((channels_needed & channels_exist) != channels_needed) {
7196 SetGLError(
7197 GL_INVALID_OPERATION, "glCopyTexSubImage2D: incompatible format");
7198 return;
7199 }
7200
[email protected]a0b78dc2011-11-11 10:43:107201 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
7202 return;
7203 }
7204
[email protected]de26b3c2011-08-03 21:54:277205 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:037206 gfx::Size size = GetBoundReadFrameBufferSize();
7207 GLint copyX = 0;
7208 GLint copyY = 0;
7209 GLint copyWidth = 0;
7210 GLint copyHeight = 0;
7211 Clip(x, width, size.width(), &copyX, &copyWidth);
7212 Clip(y, height, size.height(), &copyY, &copyHeight);
[email protected]0d6bfdc2011-11-02 01:32:207213
7214 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
7215 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D: dimensions too big");
7216 return;
7217 }
7218
[email protected]6e288612010-12-21 20:45:037219 if (copyX != x ||
7220 copyY != y ||
7221 copyWidth != width ||
7222 copyHeight != height) {
[email protected]0d6bfdc2011-11-02 01:32:207223 // some part was clipped so clear the sub rect.
[email protected]6e288612010-12-21 20:45:037224 uint32 pixels_size = 0;
[email protected]3458a64a2012-04-10 17:39:347225 if (!GLES2Util::ComputeImageDataSizes(
7226 width, height, format, type, unpack_alignment_, &pixels_size, NULL,
7227 NULL)) {
[email protected]6e288612010-12-21 20:45:037228 SetGLError(GL_INVALID_VALUE, "glCopyTexSubImage2D: dimensions too large");
7229 return;
7230 }
7231 scoped_array<char> zero(new char[pixels_size]);
7232 memset(zero.get(), 0, pixels_size);
7233 glTexSubImage2D(
7234 target, level, xoffset, yoffset, width, height,
7235 format, type, zero.get());
7236 }
[email protected]0d6bfdc2011-11-02 01:32:207237
[email protected]6e288612010-12-21 20:45:037238 if (copyHeight > 0 && copyWidth > 0) {
7239 GLint dx = copyX - x;
7240 GLint dy = copyY - y;
7241 GLint destX = xoffset + dx;
7242 GLint destY = yoffset + dy;
7243 glCopyTexSubImage2D(target, level,
7244 destX, destY, copyX, copyY,
7245 copyWidth, copyHeight);
7246 }
[email protected]cadde4a2010-07-31 17:10:437247}
7248
7249void GLES2DecoderImpl::DoTexSubImage2D(
7250 GLenum target,
7251 GLint level,
7252 GLint xoffset,
7253 GLint yoffset,
7254 GLsizei width,
7255 GLsizei height,
7256 GLenum format,
7257 GLenum type,
7258 const void * data) {
7259 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7260 if (!info) {
7261 SetGLError(GL_INVALID_OPERATION,
7262 "glTexSubImage2D: unknown texture for target");
7263 return;
7264 }
[email protected]df6cf1ad2011-01-29 01:20:527265 GLenum current_type = 0;
7266 GLenum internal_format = 0;
7267 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
7268 SetGLError(
7269 GL_INVALID_OPERATION,
7270 "glTexSubImage2D: level does not exist.");
7271 return;
7272 }
7273 if (format != internal_format) {
7274 SetGLError(GL_INVALID_OPERATION,
7275 "glTexSubImage2D: format does not match internal format.");
7276 return;
7277 }
7278 if (type != current_type) {
7279 SetGLError(GL_INVALID_OPERATION,
7280 "glTexSubImage2D: type does not match type of texture.");
7281 return;
7282 }
7283
[email protected]cadde4a2010-07-31 17:10:437284 if (!info->ValidForTexture(
7285 target, level, xoffset, yoffset, width, height, format, type)) {
7286 SetGLError(GL_INVALID_VALUE,
7287 "glTexSubImage2D: bad dimensions.");
7288 return;
7289 }
[email protected]473c01ccb2011-06-07 01:33:307290
[email protected]4502e6492011-12-14 19:39:157291 GLsizei tex_width = 0;
7292 GLsizei tex_height = 0;
7293 bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height);
7294 DCHECK(ok);
7295 if (xoffset != 0 || yoffset != 0 ||
7296 width != tex_width || height != tex_height) {
7297 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
7298 SetGLError(GL_OUT_OF_MEMORY, "glTexSubImage2D: dimensions too big");
[email protected]473c01ccb2011-06-07 01:33:307299 return;
7300 }
[email protected]4502e6492011-12-14 19:39:157301 glTexSubImage2D(
7302 target, level, xoffset, yoffset, width, height, format, type, data);
[email protected]0d6bfdc2011-11-02 01:32:207303 return;
7304 }
[email protected]4502e6492011-12-14 19:39:157305
7306 if (teximage2d_faster_than_texsubimage2d_ && !info->IsImmutable()) {
7307 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
7308 // same as internal_foramt. If that changes we'll need to look them up.
7309 WrappedTexImage2D(
7310 target, level, format, width, height, 0, format, type, data);
7311 } else {
7312 glTexSubImage2D(
7313 target, level, xoffset, yoffset, width, height, format, type, data);
7314 }
7315 texture_manager()->SetLevelCleared(info, target, level);
[email protected]cadde4a2010-07-31 17:10:437316}
7317
[email protected]b493ee622011-04-13 23:52:007318error::Error GLES2DecoderImpl::HandleTexSubImage2D(
7319 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]366ae242011-05-10 02:23:587320 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:007321 GLboolean internal = static_cast<GLboolean>(c.internal);
7322 if (internal == GL_TRUE && tex_image_2d_failed_)
7323 return error::kNoError;
7324
7325 GLenum target = static_cast<GLenum>(c.target);
7326 GLint level = static_cast<GLint>(c.level);
7327 GLint xoffset = static_cast<GLint>(c.xoffset);
7328 GLint yoffset = static_cast<GLint>(c.yoffset);
7329 GLsizei width = static_cast<GLsizei>(c.width);
7330 GLsizei height = static_cast<GLsizei>(c.height);
7331 GLenum format = static_cast<GLenum>(c.format);
7332 GLenum type = static_cast<GLenum>(c.type);
7333 uint32 data_size;
[email protected]3458a64a2012-04-10 17:39:347334 if (!GLES2Util::ComputeImageDataSizes(
7335 width, height, format, type, unpack_alignment_, &data_size, NULL, NULL)) {
[email protected]b493ee622011-04-13 23:52:007336 return error::kOutOfBounds;
7337 }
7338 const void* pixels = GetSharedMemoryAs<const void*>(
7339 c.pixels_shm_id, c.pixels_shm_offset, data_size);
7340 if (!validators_->texture_target.IsValid(target)) {
7341 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
7342 return error::kNoError;
7343 }
7344 if (width < 0) {
7345 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
7346 return error::kNoError;
7347 }
7348 if (height < 0) {
7349 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
7350 return error::kNoError;
7351 }
7352 if (!validators_->texture_format.IsValid(format)) {
7353 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
7354 return error::kNoError;
7355 }
7356 if (!validators_->pixel_type.IsValid(type)) {
7357 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
7358 return error::kNoError;
7359 }
7360 if (pixels == NULL) {
7361 return error::kOutOfBounds;
7362 }
7363 DoTexSubImage2D(
7364 target, level, xoffset, yoffset, width, height, format, type, pixels);
7365 return error::kNoError;
7366}
7367
7368error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
7369 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
7370 GLboolean internal = static_cast<GLboolean>(c.internal);
7371 if (internal == GL_TRUE && tex_image_2d_failed_)
7372 return error::kNoError;
7373
7374 GLenum target = static_cast<GLenum>(c.target);
7375 GLint level = static_cast<GLint>(c.level);
7376 GLint xoffset = static_cast<GLint>(c.xoffset);
7377 GLint yoffset = static_cast<GLint>(c.yoffset);
7378 GLsizei width = static_cast<GLsizei>(c.width);
7379 GLsizei height = static_cast<GLsizei>(c.height);
7380 GLenum format = static_cast<GLenum>(c.format);
7381 GLenum type = static_cast<GLenum>(c.type);
7382 uint32 data_size;
[email protected]3458a64a2012-04-10 17:39:347383 if (!GLES2Util::ComputeImageDataSizes(
7384 width, height, format, type, unpack_alignment_, &data_size, NULL, NULL)) {
[email protected]b493ee622011-04-13 23:52:007385 return error::kOutOfBounds;
7386 }
7387 const void* pixels = GetImmediateDataAs<const void*>(
7388 c, data_size, immediate_data_size);
7389 if (!validators_->texture_target.IsValid(target)) {
7390 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: target GL_INVALID_ENUM");
7391 return error::kNoError;
7392 }
7393 if (width < 0) {
7394 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: width < 0");
7395 return error::kNoError;
7396 }
7397 if (height < 0) {
7398 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D: height < 0");
7399 return error::kNoError;
7400 }
7401 if (!validators_->texture_format.IsValid(format)) {
7402 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: format GL_INVALID_ENUM");
7403 return error::kNoError;
7404 }
7405 if (!validators_->pixel_type.IsValid(type)) {
7406 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D: type GL_INVALID_ENUM");
7407 return error::kNoError;
7408 }
7409 if (pixels == NULL) {
7410 return error::kOutOfBounds;
7411 }
7412 DoTexSubImage2D(
7413 target, level, xoffset, yoffset, width, height, format, type, pixels);
7414 return error::kNoError;
7415}
7416
[email protected]f7a64ee2010-02-01 22:24:147417error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:197418 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:367419 GLuint index = static_cast<GLuint>(c.index);
7420 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:257421 typedef gles2::GetVertexAttribPointerv::Result Result;
7422 Result* result = GetSharedMemoryAs<Result*>(
7423 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:367424 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:147425 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:367426 }
[email protected]07d0cc82010-02-17 04:51:407427 // Check that the client initialized the result.
7428 if (result->size != 0) {
7429 return error::kInvalidArguments;
7430 }
[email protected]9438b012010-06-15 22:55:057431 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:297432 SetGLError(GL_INVALID_ENUM,
7433 "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:147434 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367435 }
[email protected]3916c97e2010-02-25 03:20:507436 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:297437 SetGLError(GL_INVALID_VALUE,
7438 "glGetVertexAttribPointerv: index out of range.");
[email protected]f7a64ee2010-02-01 22:24:147439 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367440 }
[email protected]0bfd9882010-02-05 23:02:257441 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:087442 *result->GetData() =
[email protected]3757a372012-01-19 05:20:447443 vertex_attrib_manager_->GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:147444 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327445}
7446
[email protected]f7b85372010-02-03 01:11:377447bool GLES2DecoderImpl::GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127448 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:377449 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:127450 error::Error* error, GLint* real_location,
7451 GLuint* service_id, void** result_pointer, GLenum* result_type) {
[email protected]939e7362010-05-13 20:49:107452 DCHECK(error);
7453 DCHECK(service_id);
7454 DCHECK(result_pointer);
7455 DCHECK(result_type);
[email protected]1b0a6752012-02-22 03:44:127456 DCHECK(real_location);
[email protected]f7b85372010-02-03 01:11:377457 *error = error::kNoError;
7458 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:257459 SizedResult<GLint>* result;
7460 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7461 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
7462 if (!result) {
[email protected]f7b85372010-02-03 01:11:377463 *error = error::kOutOfBounds;
7464 return false;
7465 }
[email protected]0bfd9882010-02-05 23:02:257466 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:377467 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:257468 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:587469 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7470 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:377471 if (!info) {
[email protected]ae51d192010-04-27 00:48:037472 return false;
7473 }
7474 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:377475 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]8eee29c2010-04-29 03:38:297476 SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
[email protected]f7b85372010-02-03 01:11:377477 return false;
7478 }
[email protected]ae51d192010-04-27 00:48:037479 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:367480 GLint array_index = -1;
7481 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
[email protected]1b0a6752012-02-22 03:44:127482 info->GetUniformInfoByFakeLocation(
7483 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:367484 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:377485 // No such location.
[email protected]8eee29c2010-04-29 03:38:297486 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
[email protected]f7b85372010-02-03 01:11:377487 return false;
7488 }
[email protected]43c2f1f2011-03-25 18:35:367489 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:507490 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:377491 if (size == 0) {
[email protected]8eee29c2010-04-29 03:38:297492 SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
[email protected]f7b85372010-02-03 01:11:377493 return false;
7494 }
[email protected]0bfd9882010-02-05 23:02:257495 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7496 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
7497 if (!result) {
[email protected]f7b85372010-02-03 01:11:377498 *error = error::kOutOfBounds;
7499 return false;
7500 }
[email protected]0bfd9882010-02-05 23:02:257501 result->size = size;
[email protected]939e7362010-05-13 20:49:107502 *result_type = type;
[email protected]f7b85372010-02-03 01:11:377503 return true;
7504}
7505
[email protected]f7a64ee2010-02-01 22:24:147506error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:197507 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:377508 GLuint program = c.program;
[email protected]1b0a6752012-02-22 03:44:127509 GLint fake_location = program_manager()->UnswizzleLocation(c.location);
[email protected]f7b85372010-02-03 01:11:377510 GLuint service_id;
[email protected]939e7362010-05-13 20:49:107511 GLenum result_type;
[email protected]1b0a6752012-02-22 03:44:127512 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:377513 Error error;
[email protected]0bfd9882010-02-05 23:02:257514 void* result;
[email protected]f7b85372010-02-03 01:11:377515 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127516 program, fake_location, c.params_shm_id, c.params_shm_offset,
7517 &error, &real_location, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:257518 glGetUniformiv(
[email protected]1b0a6752012-02-22 03:44:127519 service_id, real_location,
[email protected]0bfd9882010-02-05 23:02:257520 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[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::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:197526 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:377527 GLuint program = c.program;
[email protected]1b0a6752012-02-22 03:44:127528 GLint fake_location = program_manager()->UnswizzleLocation(c.location);
[email protected]f7b85372010-02-03 01:11:377529 GLuint service_id;
[email protected]1b0a6752012-02-22 03:44:127530 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:377531 Error error;
[email protected]0bfd9882010-02-05 23:02:257532 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:107533 Result* result;
7534 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:377535 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127536 program, fake_location, c.params_shm_id, c.params_shm_offset,
7537 &error, &real_location, &service_id,
7538 reinterpret_cast<void**>(&result), &result_type)) {
[email protected]939e7362010-05-13 20:49:107539 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
7540 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
7541 GLsizei num_values = result->GetNumResults();
7542 scoped_array<GLint> temp(new GLint[num_values]);
[email protected]1b0a6752012-02-22 03:44:127543 glGetUniformiv(service_id, real_location, temp.get());
[email protected]939e7362010-05-13 20:49:107544 GLfloat* dst = result->GetData();
7545 for (GLsizei ii = 0; ii < num_values; ++ii) {
7546 dst[ii] = (temp[ii] != 0);
7547 }
7548 } else {
[email protected]1b0a6752012-02-22 03:44:127549 glGetUniformfv(service_id, real_location, result->GetData());
[email protected]939e7362010-05-13 20:49:107550 }
[email protected]f7b85372010-02-03 01:11:377551 }
7552 return error;
[email protected]96449d2c2009-11-25 00:01:327553}
7554
[email protected]f7a64ee2010-02-01 22:24:147555error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:197556 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:257557 GLenum shader_type = static_cast<GLenum>(c.shadertype);
7558 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
7559 typedef gles2::GetShaderPrecisionFormat::Result Result;
7560 Result* result = GetSharedMemoryAs<Result*>(
7561 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7562 if (!result) {
7563 return error::kOutOfBounds;
7564 }
[email protected]07d0cc82010-02-17 04:51:407565 // Check that the client initialized the result.
7566 if (result->success != 0) {
7567 return error::kInvalidArguments;
7568 }
[email protected]9438b012010-06-15 22:55:057569 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:297570 SetGLError(GL_INVALID_ENUM,
7571 "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
7572 return error::kNoError;
7573 }
[email protected]9438b012010-06-15 22:55:057574 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:297575 SetGLError(GL_INVALID_ENUM,
7576 "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
7577 return error::kNoError;
7578 }
7579
7580 result->success = 1; // true
7581 switch (precision_type) {
7582 case GL_LOW_INT:
7583 case GL_MEDIUM_INT:
7584 case GL_HIGH_INT:
[email protected]0a34b582012-04-09 22:42:567585 // These values are for a 32-bit twos-complement integer format.
7586 result->min_range = 31;
7587 result->max_range = 30;
[email protected]8eee29c2010-04-29 03:38:297588 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:107589 break;
[email protected]8eee29c2010-04-29 03:38:297590 case GL_LOW_FLOAT:
7591 case GL_MEDIUM_FLOAT:
7592 case GL_HIGH_FLOAT:
[email protected]0a34b582012-04-09 22:42:567593 // These values are for an IEEE single-precision floating-point format.
7594 result->min_range = 127;
7595 result->max_range = 127;
7596 result->precision = 23;
[email protected]8eee29c2010-04-29 03:38:297597 break;
7598 default:
7599 NOTREACHED();
7600 break;
[email protected]0bfd9882010-02-05 23:02:257601 }
[email protected]f7a64ee2010-02-01 22:24:147602 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327603}
7604
[email protected]f7a64ee2010-02-01 22:24:147605error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:197606 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:257607 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:587608 GLuint program = static_cast<GLuint>(c.program);
7609 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7610 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:037611 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257612 return error::kNoError;
7613 }
7614 typedef gles2::GetAttachedShaders::Result Result;
7615 uint32 max_count = Result::ComputeMaxResults(result_size);
7616 Result* result = GetSharedMemoryAs<Result*>(
7617 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
7618 if (!result) {
7619 return error::kOutOfBounds;
7620 }
[email protected]07d0cc82010-02-17 04:51:407621 // Check that the client initialized the result.
7622 if (result->size != 0) {
7623 return error::kInvalidArguments;
7624 }
[email protected]0bfd9882010-02-05 23:02:257625 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:037626 glGetAttachedShaders(
7627 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:257628 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:037629 if (!shader_manager()->GetClientId(result->GetData()[ii],
7630 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:257631 NOTREACHED();
7632 return error::kGenericError;
7633 }
7634 }
7635 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:147636 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327637}
7638
[email protected]f7a64ee2010-02-01 22:24:147639error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:197640 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:257641 GLuint program = c.program;
7642 GLuint index = c.index;
7643 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:257644 typedef gles2::GetActiveUniform::Result Result;
7645 Result* result = GetSharedMemoryAs<Result*>(
7646 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7647 if (!result) {
7648 return error::kOutOfBounds;
7649 }
[email protected]07d0cc82010-02-17 04:51:407650 // Check that the client initialized the result.
7651 if (result->success != 0) {
7652 return error::kInvalidArguments;
7653 }
[email protected]6b8cf1a2010-05-06 16:13:587654 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7655 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:037656 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257657 return error::kNoError;
7658 }
7659 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
7660 info->GetUniformInfo(index);
7661 if (!uniform_info) {
[email protected]8eee29c2010-04-29 03:38:297662 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
[email protected]0bfd9882010-02-05 23:02:257663 return error::kNoError;
7664 }
7665 result->success = 1; // true.
7666 result->size = uniform_info->size;
7667 result->type = uniform_info->type;
7668 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297669 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:147670 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327671}
7672
[email protected]f7a64ee2010-02-01 22:24:147673error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:197674 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:257675 GLuint program = c.program;
7676 GLuint index = c.index;
7677 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:257678 typedef gles2::GetActiveAttrib::Result Result;
7679 Result* result = GetSharedMemoryAs<Result*>(
7680 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7681 if (!result) {
7682 return error::kOutOfBounds;
7683 }
[email protected]07d0cc82010-02-17 04:51:407684 // Check that the client initialized the result.
7685 if (result->success != 0) {
7686 return error::kInvalidArguments;
7687 }
[email protected]6b8cf1a2010-05-06 16:13:587688 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7689 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:037690 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257691 return error::kNoError;
7692 }
7693 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
7694 info->GetAttribInfo(index);
7695 if (!attrib_info) {
[email protected]8eee29c2010-04-29 03:38:297696 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
[email protected]0bfd9882010-02-05 23:02:257697 return error::kNoError;
7698 }
7699 result->success = 1; // true.
7700 result->size = attrib_info->size;
7701 result->type = attrib_info->type;
7702 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297703 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:147704 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327705}
7706
[email protected]b273e432010-04-12 17:23:587707error::Error GLES2DecoderImpl::HandleShaderBinary(
7708 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
7709#if 1 // No binary shader support.
[email protected]8eee29c2010-04-29 03:38:297710 SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
[email protected]b273e432010-04-12 17:23:587711 return error::kNoError;
7712#else
7713 GLsizei n = static_cast<GLsizei>(c.n);
7714 if (n < 0) {
[email protected]8eee29c2010-04-29 03:38:297715 SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
[email protected]b273e432010-04-12 17:23:587716 return error::kNoError;
7717 }
7718 GLsizei length = static_cast<GLsizei>(c.length);
7719 if (length < 0) {
[email protected]8eee29c2010-04-29 03:38:297720 SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
[email protected]b273e432010-04-12 17:23:587721 return error::kNoError;
7722 }
7723 uint32 data_size;
7724 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
7725 return error::kOutOfBounds;
7726 }
7727 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
7728 c.shaders_shm_id, c.shaders_shm_offset, data_size);
7729 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
7730 const void* binary = GetSharedMemoryAs<const void*>(
7731 c.binary_shm_id, c.binary_shm_offset, length);
7732 if (shaders == NULL || binary == NULL) {
7733 return error::kOutOfBounds;
7734 }
7735 scoped_array<GLuint> service_ids(new GLuint[n]);
7736 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:037737 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
7738 if (!info) {
[email protected]8eee29c2010-04-29 03:38:297739 SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
[email protected]b273e432010-04-12 17:23:587740 return error::kNoError;
7741 }
[email protected]ae51d192010-04-27 00:48:037742 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:587743 }
7744 // TODO(gman): call glShaderBinary
7745 return error::kNoError;
7746#endif
7747}
7748
[email protected]6217d392010-03-25 22:08:357749error::Error GLES2DecoderImpl::HandleSwapBuffers(
7750 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:497751 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
7752 int this_frame_number = frame_number_++;
[email protected]da151512011-11-11 23:27:387753 // TRACE_EVENT for gpu tests:
[email protected]529c6672012-01-04 02:18:267754 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers",
7755 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
7756 "width", (is_offscreen ? offscreen_size_.width() :
7757 surface_->GetSize().width()));
[email protected]64ace852011-05-19 21:49:497758 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
7759 "offscreen", is_offscreen,
7760 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:357761 // If offscreen then don't actually SwapBuffers to the display. Just copy
7762 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:497763 if (is_offscreen) {
[email protected]1fb8c482011-08-31 01:01:537764 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
7765 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
7766 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
7767 // fix this.
7768 if (needs_mac_nvidia_driver_workaround_) {
7769 offscreen_saved_frame_buffer_->Create();
7770 glFinish();
7771 }
7772
7773 // Allocate the offscreen saved color texture.
7774 DCHECK(offscreen_saved_color_format_);
7775 offscreen_saved_color_texture_->AllocateStorage(
7776 offscreen_size_, offscreen_saved_color_format_);
[email protected]1078f912011-12-23 13:12:147777 UpdateBackbufferMemoryAccounting();
[email protected]1fb8c482011-08-31 01:01:537778
7779 offscreen_saved_frame_buffer_->AttachRenderTexture(
7780 offscreen_saved_color_texture_.get());
7781 if (offscreen_saved_frame_buffer_->CheckStatus() !=
7782 GL_FRAMEBUFFER_COMPLETE) {
7783 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
7784 << "because offscreen saved FBO was incomplete.";
7785 return error::kLostContext;
7786 }
7787
[email protected]1fb8c482011-08-31 01:01:537788 // Clear the offscreen color texture.
7789 // TODO(piman): Is this still necessary?
7790 {
7791 ScopedFrameBufferBinder binder(this,
7792 offscreen_saved_frame_buffer_->id());
7793 glClearColor(0, 0, 0, 0);
7794 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
7795 glDisable(GL_SCISSOR_TEST);
7796 glClear(GL_COLOR_BUFFER_BIT);
7797 RestoreClearState();
7798 }
7799
7800 UpdateParentTextureInfo();
7801 }
7802
[email protected]6217d392010-03-25 22:08:357803 ScopedGLErrorSuppressor suppressor(this);
7804
[email protected]34ff8b0c2010-10-01 20:06:027805 if (IsOffscreenBufferMultisampled()) {
[email protected]51411e32012-01-19 20:21:137806 // For multisampled buffers, resolve the frame buffer.
[email protected]de26b3c2011-08-03 21:54:277807 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]89d6ed02011-04-20 00:23:237808 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:487809 } else {
[email protected]069944672012-04-25 20:52:237810 ScopedFrameBufferBinder binder(this,
7811 offscreen_target_frame_buffer_->id());
[email protected]51411e32012-01-19 20:21:137812
[email protected]069944672012-04-25 20:52:237813 if (offscreen_target_buffer_preserved_) {
7814 // Copy the target frame buffer to the saved offscreen texture.
7815 offscreen_saved_color_texture_->Copy(
7816 offscreen_saved_color_texture_->size(),
7817 offscreen_saved_color_format_);
7818 } else {
7819 // Flip the textures in the parent context via the texture manager.
7820 if (!!offscreen_saved_color_texture_info_.get())
7821 offscreen_saved_color_texture_info_->
7822 SetServiceId(offscreen_target_color_texture_->id());
[email protected]8a61d872012-01-20 12:43:567823
[email protected]069944672012-04-25 20:52:237824 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
7825 offscreen_target_frame_buffer_->AttachRenderTexture(
7826 offscreen_target_color_texture_.get());
[email protected]b86b14982010-10-11 18:45:487827 }
[email protected]069944672012-04-25 20:52:237828
7829 // Ensure the side effects of the copy are visible to the parent
7830 // context. There is no need to do this for ANGLE because it uses a
7831 // single D3D device for all contexts.
7832 if (!IsAngle())
7833 glFlush();
[email protected]89d6ed02011-04-20 00:23:237834 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:397835 }
[email protected]6217d392010-03-25 22:08:357836 } else {
[email protected]64ace852011-05-19 21:49:497837 TRACE_EVENT1("gpu", "GLContext::SwapBuffers", "frame", this_frame_number);
[email protected]f62a5ab2011-05-23 20:34:157838 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:017839 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:027840 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:017841 }
[email protected]6217d392010-03-25 22:08:357842 }
7843
[email protected]89d6ed02011-04-20 00:23:237844 return error::kNoError;
[email protected]6217d392010-03-25 22:08:357845}
7846
[email protected]d4239852011-08-12 04:51:227847error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
7848 uint32 immediate_data_size, const gles2::EnableFeatureCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:187849 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287850 if (!bucket || bucket->size() == 0) {
7851 return error::kInvalidArguments;
7852 }
[email protected]d4239852011-08-12 04:51:227853 typedef gles2::EnableFeatureCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:187854 Result* result = GetSharedMemoryAs<Result*>(
7855 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7856 if (!result) {
7857 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:107858 }
[email protected]b1d2dcb2010-05-17 19:24:187859 // Check that the client initialized the result.
7860 if (*result != 0) {
7861 return error::kInvalidArguments;
7862 }
7863 std::string feature_str;
7864 if (!bucket->GetAsString(&feature_str)) {
7865 return error::kInvalidArguments;
7866 }
7867
7868 // TODO(gman): make this some kind of table to function pointer thingy.
[email protected]d4239852011-08-12 04:51:227869 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
[email protected]b1d2dcb2010-05-17 19:24:187870 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]d4239852011-08-12 04:51:227871 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
[email protected]8fbedc02010-11-18 18:43:407872 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
7873 // TODO(gman): decide how to remove the need for this const_cast.
7874 // I could make validators_ non const but that seems bad as this is the only
7875 // place it is needed. I could make some special friend class of validators
7876 // just to allow this to set them. That seems silly. I could refactor this
7877 // code to use the extension mechanism or the initialization attributes to
7878 // turn this feature on. Given that the only real point of this is to make
7879 // the conformance tests pass and given that there is lots of real work that
7880 // needs to be done it seems like refactoring for one to one of those
7881 // methods is a very low priority.
7882 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]f0d74742011-10-03 16:31:047883 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
7884 force_webgl_glsl_validation_ = true;
7885 InitializeShaderTranslator();
[email protected]b1d2dcb2010-05-17 19:24:187886 } else {
7887 return error::kNoError;
7888 }
7889
7890 *result = 1; // true.
7891 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:107892}
7893
[email protected]c2f8c8402010-12-06 18:07:247894error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
7895 uint32 immediate_data_size,
7896 const gles2::GetRequestableExtensionsCHROMIUM& c) {
7897 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]80eb6b52012-01-19 00:14:417898 FeatureInfo::Ref info(new FeatureInfo());
[email protected]e82fb792011-09-22 00:33:297899 info->Initialize(disallowed_features_, NULL);
[email protected]c2f8c8402010-12-06 18:07:247900 bucket->SetFromString(info->extensions().c_str());
7901 return error::kNoError;
7902}
7903
7904error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
7905 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
7906 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287907 if (!bucket || bucket->size() == 0) {
7908 return error::kInvalidArguments;
7909 }
[email protected]c2f8c8402010-12-06 18:07:247910 std::string feature_str;
7911 if (!bucket->GetAsString(&feature_str)) {
7912 return error::kInvalidArguments;
7913 }
7914
7915 bool std_derivatives_enabled =
7916 feature_info_->feature_flags().oes_standard_derivatives;
7917 bool webglsl_enabled =
7918 feature_info_->feature_flags().chromium_webglsl;
7919
7920 feature_info_->AddFeatures(feature_str.c_str());
7921
[email protected]f0d74742011-10-03 16:31:047922 bool initialization_required = false;
7923 if (force_webgl_glsl_validation_ && !derivatives_explicitly_enabled_) {
7924 size_t derivatives_offset = feature_str.find(kOESDerivativeExtension);
7925 if (std::string::npos != derivatives_offset) {
7926 derivatives_explicitly_enabled_ = true;
7927 initialization_required = true;
7928 }
7929 }
7930
[email protected]c2f8c8402010-12-06 18:07:247931 // If we just enabled a feature which affects the shader translator,
7932 // we may need to re-initialize it.
7933 if (std_derivatives_enabled !=
7934 feature_info_->feature_flags().oes_standard_derivatives ||
7935 webglsl_enabled !=
[email protected]f0d74742011-10-03 16:31:047936 feature_info_->feature_flags().chromium_webglsl ||
7937 initialization_required) {
[email protected]c2f8c8402010-12-06 18:07:247938 InitializeShaderTranslator();
7939 }
7940
[email protected]302ce6d2011-07-07 23:28:117941 UpdateCapabilities();
7942
[email protected]c2f8c8402010-12-06 18:07:247943 return error::kNoError;
7944}
7945
[email protected]372e0412011-06-28 16:08:567946error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
7947 uint32 immediate_data_size, const gles2::GetMultipleIntegervCHROMIUM& c) {
7948 GLuint count = c.count;
7949 uint32 pnames_size;
7950 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
7951 return error::kOutOfBounds;
7952 }
7953 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
7954 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
7955 if (pnames == NULL) {
7956 return error::kOutOfBounds;
7957 }
7958
7959 // We have to copy them since we use them twice so the client
7960 // can't change them between the time we validate them and the time we use
7961 // them.
7962 scoped_array<GLenum> enums(new GLenum[count]);
7963 memcpy(enums.get(), pnames, pnames_size);
7964
7965 // Count up the space needed for the result.
7966 uint32 num_results = 0;
7967 for (GLuint ii = 0; ii < count; ++ii) {
7968 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
7969 if (num == 0) {
7970 SetGLError(GL_INVALID_ENUM,
7971 "glGetMulitpleCHROMIUM: pname GL_INVALID_ENUM");
7972 return error::kNoError;
7973 }
7974 // Num will never be more than 4.
7975 DCHECK_LE(num, 4u);
7976 if (!SafeAdd(num_results, num, &num_results)) {
7977 return error::kOutOfBounds;
7978 }
7979 }
7980
7981 uint32 result_size = 0;
7982 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
7983 return error::kOutOfBounds;
7984 }
7985
7986 if (result_size != static_cast<uint32>(c.size)) {
7987 SetGLError(GL_INVALID_VALUE,
7988 "glGetMulitpleCHROMIUM: bad size GL_INVALID_VALUE");
7989 return error::kNoError;
7990 }
7991
7992 GLint* results = GetSharedMemoryAs<GLint*>(
7993 c.results_shm_id, c.results_shm_offset, result_size);
7994 if (results == NULL) {
7995 return error::kOutOfBounds;
7996 }
7997
7998 // Check the results have been cleared in case the context was lost.
7999 for (uint32 ii = 0; ii < num_results; ++ii) {
8000 if (results[ii]) {
8001 return error::kInvalidArguments;
8002 }
8003 }
8004
8005 // Get each result.
8006 GLint* start = results;
8007 for (GLuint ii = 0; ii < count; ++ii) {
8008 GLsizei num_written = 0;
8009 if (!GetHelper(enums[ii], results, &num_written)) {
8010 glGetIntegerv(enums[ii], results);
8011 }
8012 results += num_written;
8013 }
8014
8015 // Just to verify. Should this be a DCHECK?
8016 if (static_cast<uint32>(results - start) != num_results) {
8017 return error::kOutOfBounds;
8018 }
8019
8020 return error::kNoError;
8021}
8022
[email protected]2318d342011-07-11 22:27:428023error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
8024 uint32 immediate_data_size, const gles2::GetProgramInfoCHROMIUM& c) {
8025 GLuint program = static_cast<GLuint>(c.program);
8026 uint32 bucket_id = c.bucket_id;
8027 Bucket* bucket = CreateBucket(bucket_id);
8028 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
8029 ProgramManager::ProgramInfo* info = NULL;
[email protected]9a14ae612011-08-08 17:51:468030 info = GetProgramInfo(program);
8031 if (!info || !info->IsValid()) {
8032 return error::kNoError;
[email protected]2318d342011-07-11 22:27:428033 }
[email protected]5d4c6b22012-02-07 08:22:288034 info->GetProgramInfo(program_manager(), bucket);
[email protected]2318d342011-07-11 22:27:428035 return error::kNoError;
8036}
8037
[email protected]38d139d2011-07-14 00:38:438038error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
8039 switch (reset_status_) {
8040 case GL_NO_ERROR:
8041 // TODO(kbr): improve the precision of the error code in this case.
8042 // Consider delegating to context for error code if MakeCurrent fails.
8043 return error::kUnknown;
8044 case GL_GUILTY_CONTEXT_RESET_ARB:
8045 return error::kGuilty;
8046 case GL_INNOCENT_CONTEXT_RESET_ARB:
8047 return error::kInnocent;
8048 case GL_UNKNOWN_CONTEXT_RESET_ARB:
8049 return error::kUnknown;
8050 }
8051
8052 NOTREACHED();
8053 return error::kUnknown;
8054}
8055
8056bool GLES2DecoderImpl::WasContextLost() {
8057 if (context_->WasAllocatedUsingARBRobustness() && has_arb_robustness_) {
8058 GLenum status = glGetGraphicsResetStatusARB();
8059 if (status != GL_NO_ERROR) {
8060 // The graphics card was reset. Signal a lost context to the application.
8061 reset_status_ = status;
8062 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
8063 << " context lost via ARB_robustness. Reset status = 0x"
8064 << std::hex << status << std::dec;
8065 return true;
8066 }
8067 }
8068 return false;
8069}
8070
[email protected]882ba1e22012-03-08 19:02:538071bool GLES2DecoderImpl::GenQueriesEXTHelper(
8072 GLsizei n, const GLuint* client_ids) {
8073 for (GLsizei ii = 0; ii < n; ++ii) {
8074 if (query_manager_->GetQuery(client_ids[ii])) {
8075 return false;
8076 }
8077 }
[email protected]c45f1972012-03-14 07:27:368078 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
[email protected]882ba1e22012-03-08 19:02:538079 return true;
8080}
8081
8082void GLES2DecoderImpl::DeleteQueriesEXTHelper(
8083 GLsizei n, const GLuint* client_ids) {
8084 for (GLsizei ii = 0; ii < n; ++ii) {
8085 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
8086 if (query && !query->IsDeleted()) {
8087 if (query == current_query_) {
8088 current_query_ = NULL;
8089 }
[email protected]c45f1972012-03-14 07:27:368090 query->Destroy(true);
[email protected]882ba1e22012-03-08 19:02:538091 query_manager_->RemoveQuery(client_ids[ii]);
8092 }
8093 }
8094}
8095
[email protected]22e3f552012-03-13 01:54:198096bool GLES2DecoderImpl::ProcessPendingQueries() {
8097 if (query_manager_.get() == NULL) {
8098 return false;
8099 }
[email protected]c45f1972012-03-14 07:27:368100 if (!query_manager_->ProcessPendingQueries()) {
[email protected]22e3f552012-03-13 01:54:198101 current_decoder_error_ = error::kOutOfBounds;
8102 }
8103 return query_manager_->HavePendingQueries();
8104}
8105
[email protected]882ba1e22012-03-08 19:02:538106error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
8107 uint32 immediate_data_size, const gles2::BeginQueryEXT& c) {
8108 GLenum target = static_cast<GLenum>(c.target);
8109 GLuint client_id = static_cast<GLuint>(c.id);
8110 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
8111 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
8112
[email protected]c45f1972012-03-14 07:27:368113 switch (target) {
8114 case GL_COMMANDS_ISSUED_CHROMIUM:
8115 break;
8116 default:
8117 if (!feature_info_->feature_flags().occlusion_query_boolean) {
8118 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT: not enabled");
8119 return error::kNoError;
8120 }
8121 break;
[email protected]882ba1e22012-03-08 19:02:538122 }
8123
8124 if (current_query_) {
8125 SetGLError(
8126 GL_INVALID_OPERATION, "glBeginQueryEXT: query already in progress");
8127 return error::kNoError;
8128 }
8129
8130 if (client_id == 0) {
8131 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT: id is 0");
8132 return error::kNoError;
8133 }
8134
8135 QueryManager::Query* query = query_manager_->GetQuery(client_id);
8136 if (!query) {
[email protected]c45f1972012-03-14 07:27:368137 // TODO(gman): Decide if we need this check.
8138 //
[email protected]882ba1e22012-03-08 19:02:538139 // Checks id was made by glGenQueries
[email protected]c45f1972012-03-14 07:27:368140 //
8141 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
8142 // for all Query ids but from the POV of the command buffer service maybe
8143 // you don't.
8144 //
8145 // The client can enforce this. I don't think the service cares.
8146 //
8147 // IdAllocatorInterface* id_allocator =
8148 // group_->GetIdAllocator(id_namespaces::kQueries);
8149 // if (!id_allocator->InUse(client_id)) {
8150 // SetGLError(GL_INVALID_OPERATION,
8151 // "glBeginQueryEXT: id not made by glGenQueriesEXT");
8152 // return error::kNoError;
8153 // }
8154 query = query_manager_->CreateQuery(
8155 target, client_id, sync_shm_id, sync_shm_offset);
[email protected]882ba1e22012-03-08 19:02:538156 }
8157
[email protected]c45f1972012-03-14 07:27:368158 if (query->target() != target) {
[email protected]882ba1e22012-03-08 19:02:538159 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT: target does not match");
8160 return error::kNoError;
8161 } else if (query->shm_id() != sync_shm_id ||
8162 query->shm_offset() != sync_shm_offset) {
8163 DLOG(ERROR) << "Shared memory used by query not the same as before";
8164 return error::kInvalidArguments;
8165 }
8166
[email protected]c45f1972012-03-14 07:27:368167 if (!query_manager_->BeginQuery(query)) {
8168 return error::kOutOfBounds;
8169 }
[email protected]882ba1e22012-03-08 19:02:538170
[email protected]882ba1e22012-03-08 19:02:538171 current_query_ = query;
[email protected]882ba1e22012-03-08 19:02:538172 return error::kNoError;
8173}
8174
8175error::Error GLES2DecoderImpl::HandleEndQueryEXT(
8176 uint32 immediate_data_size, const gles2::EndQueryEXT& c) {
8177 GLenum target = static_cast<GLenum>(c.target);
8178 uint32 submit_count = static_cast<GLuint>(c.submit_count);
8179
8180 if (!current_query_) {
8181 SetGLError(GL_INVALID_OPERATION, "glEndQueryEXT: No active query");
8182 return error::kNoError;
8183 }
8184 if (current_query_->target() != target) {
8185 SetGLError(GL_INVALID_OPERATION,
8186 "glEndQueryEXT: target does not match active query");
8187 return error::kNoError;
8188 }
[email protected]882ba1e22012-03-08 19:02:538189
[email protected]c45f1972012-03-14 07:27:368190 if (!query_manager_->EndQuery(current_query_, submit_count)) {
8191 return error::kOutOfBounds;
8192 }
8193
8194 current_query_ = NULL;
[email protected]882ba1e22012-03-08 19:02:538195 return error::kNoError;
8196}
8197
[email protected]b0af4f52011-09-28 22:04:428198error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
8199 uint32 immediate_data_size,
8200 const gles2::CreateStreamTextureCHROMIUM& c) {
8201 if (!feature_info_->feature_flags().chromium_stream_texture) {
8202 SetGLError(GL_INVALID_OPERATION,
8203 "glOpenStreamTextureCHROMIUM: "
8204 "not supported.");
8205 return error::kNoError;
8206 }
8207
8208 uint32 client_id = c.client_id;
8209 typedef gles2::CreateStreamTextureCHROMIUM::Result Result;
8210 Result* result = GetSharedMemoryAs<Result*>(
8211 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8212
[email protected]e5081262012-01-05 23:09:038213 if (!result)
8214 return error::kOutOfBounds;
[email protected]b0af4f52011-09-28 22:04:428215 *result = GL_ZERO;
8216 TextureManager::TextureInfo* info =
8217 texture_manager()->GetTextureInfo(client_id);
8218 if (!info) {
8219 SetGLError(GL_INVALID_VALUE,
8220 "glCreateStreamTextureCHROMIUM: "
8221 "bad texture id.");
8222 return error::kNoError;
8223 }
8224
8225 if (info->IsStreamTexture()) {
8226 SetGLError(GL_INVALID_OPERATION,
8227 "glCreateStreamTextureCHROMIUM: "
8228 "is already a stream texture.");
8229 return error::kNoError;
8230 }
8231
8232 if (info->target() && info->target() != GL_TEXTURE_EXTERNAL_OES) {
8233 SetGLError(GL_INVALID_OPERATION,
8234 "glCreateStreamTextureCHROMIUM: "
8235 "is already bound to incompatible target.");
8236 return error::kNoError;
8237 }
8238
8239 if (!stream_texture_manager_)
8240 return error::kInvalidArguments;
8241
8242 GLuint object_id = stream_texture_manager_->CreateStreamTexture(
8243 info->service_id(), client_id);
8244
8245 if (object_id) {
8246 info->SetStreamTexture(true);
8247 } else {
8248 SetGLError(GL_OUT_OF_MEMORY,
8249 "glCreateStreamTextureCHROMIUM: "
8250 "failed to create platform texture.");
8251 }
8252
8253 *result = object_id;
8254 return error::kNoError;
8255}
8256
8257error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
8258 uint32 immediate_data_size,
8259 const gles2::DestroyStreamTextureCHROMIUM& c) {
8260 GLuint client_id = c.texture;
8261 TextureManager::TextureInfo* info =
8262 texture_manager()->GetTextureInfo(client_id);
8263 if (info && info->IsStreamTexture()) {
8264 if (!stream_texture_manager_)
8265 return error::kInvalidArguments;
8266
8267 stream_texture_manager_->DestroyStreamTexture(info->service_id());
8268 info->SetStreamTexture(false);
[email protected]80eb6b52012-01-19 00:14:418269 texture_manager()->SetInfoTarget(info, 0);
[email protected]b0af4f52011-09-28 22:04:428270 } else {
8271 SetGLError(GL_INVALID_VALUE,
8272 "glDestroyStreamTextureCHROMIUM: bad texture id.");
8273 }
8274
8275 return error::kNoError;
8276}
8277
[email protected]e51bdf32011-11-23 22:21:468278#if defined(OS_MACOSX)
8279void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
8280 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
8281 texture_id);
8282 if (it != texture_to_io_surface_map_.end()) {
8283 // Found a previous IOSurface bound to this texture; release it.
8284 CFTypeRef surface = it->second;
8285 CFRelease(surface);
8286 texture_to_io_surface_map_.erase(it);
8287 }
8288}
8289#endif
8290
8291void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
8292 GLenum target, GLsizei width, GLsizei height,
8293 GLuint io_surface_id, GLuint plane) {
8294#if defined(OS_MACOSX)
8295 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
8296 SetGLError(GL_INVALID_OPERATION,
8297 "glTexImageIOSurface2DCHROMIUM: only supported on desktop GL.");
8298 return;
8299 }
8300
8301 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
8302 if (!surface_support) {
8303 SetGLError(GL_INVALID_OPERATION,
8304 "glTexImageIOSurface2DCHROMIUM: only supported on 10.6.");
8305 return;
8306 }
8307
8308 if (target != GL_TEXTURE_RECTANGLE_ARB) {
8309 // This might be supported in the future, and if we could require
8310 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
8311 // could delete a lot of code. For now, perform strict validation so we
8312 // know what's going on.
8313 SetGLError(
8314 GL_INVALID_OPERATION,
8315 "glTexImageIOSurface2DCHROMIUM: requires TEXTURE_RECTANGLE_ARB target");
8316 return;
8317 }
8318
8319 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8320 if (!info) {
8321 SetGLError(GL_INVALID_OPERATION,
8322 "glTexImageIOSurface2DCHROMIUM: no rectangle texture bound");
8323 return;
8324 }
8325 if (info == texture_manager()->GetDefaultTextureInfo(target)) {
8326 // Maybe this is conceptually valid, but disallow it to avoid accidents.
8327 SetGLError(GL_INVALID_OPERATION,
8328 "glTexImageIOSurface2DCHROMIUM: can't bind default texture");
8329 return;
8330 }
8331
8332 // Look up the new IOSurface. Note that because of asynchrony
8333 // between processes this might fail; during live resizing the
8334 // plugin process might allocate and release an IOSurface before
8335 // this process gets a chance to look it up. Hold on to any old
8336 // IOSurface in this case.
8337 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
8338 if (!surface) {
8339 SetGLError(GL_INVALID_OPERATION,
8340 "glTexImageIOSurface2DCHROMIUM: no IOSurface with the given ID");
8341 return;
8342 }
8343
8344 // Release any IOSurface previously bound to this texture.
8345 ReleaseIOSurfaceForTexture(info->service_id());
8346
8347 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
8348 texture_to_io_surface_map_.insert(
8349 std::make_pair(info->service_id(), surface));
8350
8351 CGLContextObj context =
8352 static_cast<CGLContextObj>(context_->GetHandle());
8353
8354 CGLError err = surface_support->CGLTexImageIOSurface2D(
8355 context,
8356 target,
8357 GL_RGBA,
8358 width,
8359 height,
8360 GL_BGRA,
8361 GL_UNSIGNED_INT_8_8_8_8_REV,
8362 surface,
8363 plane);
8364
8365 if (err != kCGLNoError) {
8366 SetGLError(
8367 GL_INVALID_OPERATION,
8368 "glTexImageIOSurface2DCHROMIUM: error in CGLTexImageIOSurface2D");
8369 return;
8370 }
8371
8372 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:418373 info, target, 0, GL_RGBA, width, height, 1, 0,
[email protected]e51bdf32011-11-23 22:21:468374 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
8375
8376#else
8377 SetGLError(GL_INVALID_OPERATION,
8378 "glTexImageIOSurface2DCHROMIUM: not supported.");
8379#endif
8380}
8381
[email protected]97dc7cbe2011-12-06 17:26:178382static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
8383 switch (internalformat) {
8384 case GL_RGB565:
8385 return GL_RGB;
8386 case GL_RGBA4:
8387 return GL_RGBA;
8388 case GL_RGB5_A1:
8389 return GL_RGBA;
8390 case GL_RGB8_OES:
8391 return GL_RGB;
8392 case GL_RGBA8_OES:
8393 return GL_RGBA;
8394 case GL_LUMINANCE8_ALPHA8_EXT:
8395 return GL_LUMINANCE_ALPHA;
8396 case GL_LUMINANCE8_EXT:
8397 return GL_LUMINANCE;
8398 case GL_ALPHA8_EXT:
8399 return GL_ALPHA;
8400 case GL_RGBA32F_EXT:
8401 return GL_RGBA;
8402 case GL_RGB32F_EXT:
8403 return GL_RGB;
8404 case GL_ALPHA32F_EXT:
8405 return GL_ALPHA;
8406 case GL_LUMINANCE32F_EXT:
8407 return GL_LUMINANCE;
8408 case GL_LUMINANCE_ALPHA32F_EXT:
8409 return GL_LUMINANCE_ALPHA;
8410 case GL_RGBA16F_EXT:
8411 return GL_RGBA;
8412 case GL_RGB16F_EXT:
8413 return GL_RGB;
8414 case GL_ALPHA16F_EXT:
8415 return GL_ALPHA;
8416 case GL_LUMINANCE16F_EXT:
8417 return GL_LUMINANCE;
8418 case GL_LUMINANCE_ALPHA16F_EXT:
8419 return GL_LUMINANCE_ALPHA;
8420 case GL_BGRA8_EXT:
8421 return GL_BGRA_EXT;
8422 default:
8423 return GL_NONE;
8424 }
8425}
8426
[email protected]43410e92012-04-20 17:06:288427void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
[email protected]0a1e9ad2012-05-04 21:13:038428 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
8429 GLenum internal_format) {
[email protected]43410e92012-04-20 17:06:288430 TextureManager::TextureInfo* dest_info = GetTextureInfo(dest_id);
8431 TextureManager::TextureInfo* source_info = GetTextureInfo(source_id);
8432
8433 if (!source_info || !dest_info) {
8434 SetGLError(GL_INVALID_VALUE, "glCopyTextureCHROMIUM: unknown texture id");
8435 return;
8436 }
8437
8438 if (GL_TEXTURE_2D != target) {
8439 SetGLError(GL_INVALID_VALUE,
8440 "glCopyTextureCHROMIUM: invalid texture target");
8441 return;
8442 }
8443
[email protected]0a1e9ad2012-05-04 21:13:038444 if (dest_info->target() != GL_TEXTURE_2D ||
8445 source_info->target() != GL_TEXTURE_2D) {
8446 SetGLError(GL_INVALID_VALUE,
8447 "glCopyTextureCHROMIUM: invalid texture target binding");
8448 return;
8449 }
8450
[email protected]43410e92012-04-20 17:06:288451 int source_width, source_height, dest_width, dest_height;
8452 if (!source_info->GetLevelSize(GL_TEXTURE_2D, 0, &source_width,
8453 &source_height)) {
8454 SetGLError(GL_INVALID_VALUE,
8455 "glCopyTextureChromium: source texture has no level 0");
8456 return;
8457 }
8458
[email protected]43410e92012-04-20 17:06:288459 // Check that this type of texture is allowed.
8460 if (!texture_manager()->ValidForTarget(GL_TEXTURE_2D, level, source_width,
8461 source_height, 1)) {
8462 SetGLError(GL_INVALID_VALUE,
8463 "glCopyTextureCHROMIUM: Bad dimensions");
8464 return;
8465 }
8466
[email protected]0a1e9ad2012-05-04 21:13:038467 GLenum dest_type;
8468 GLenum dest_internal_format;
8469 bool dest_level_defined = dest_info->GetLevelSize(GL_TEXTURE_2D, level,
8470 &dest_width,
8471 &dest_height);
[email protected]43410e92012-04-20 17:06:288472
[email protected]0a1e9ad2012-05-04 21:13:038473 if (dest_level_defined) {
8474 dest_info->GetLevelType(GL_TEXTURE_2D, level, &dest_type,
8475 &dest_internal_format);
8476 } else {
8477 GLenum source_internal_format;
8478 source_info->GetLevelType(GL_TEXTURE_2D, 0, &dest_type,
8479 &source_internal_format);
8480 }
8481
8482 // Resize the destination texture to the dimensions of the source texture.
8483 if (!dest_level_defined || dest_width != source_width ||
8484 dest_height != source_height ||
8485 dest_internal_format != internal_format) {
[email protected]43410e92012-04-20 17:06:288486 // Ensure that the glTexImage2D succeeds.
8487 CopyRealGLErrorsToWrapper();
[email protected]0a1e9ad2012-05-04 21:13:038488 glBindTexture(GL_TEXTURE_2D, dest_info->service_id());
[email protected]43410e92012-04-20 17:06:288489 WrappedTexImage2D(
8490 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
[email protected]0a1e9ad2012-05-04 21:13:038491 0, internal_format, dest_type, NULL);
[email protected]43410e92012-04-20 17:06:288492 GLenum error = PeekGLError();
[email protected]0a1e9ad2012-05-04 21:13:038493 if (error != GL_NO_ERROR) {
8494 RestoreCurrentTexture2DBindings();
[email protected]43410e92012-04-20 17:06:288495 return;
[email protected]0a1e9ad2012-05-04 21:13:038496 }
[email protected]43410e92012-04-20 17:06:288497
8498 texture_manager()->SetLevelInfo(
8499 dest_info, GL_TEXTURE_2D, level, internal_format, source_width,
[email protected]0a1e9ad2012-05-04 21:13:038500 source_height, 1, 0, internal_format, dest_type, true);
[email protected]43410e92012-04-20 17:06:288501 }
8502
8503 state_dirty_ = true;
[email protected]0a1e9ad2012-05-04 21:13:038504 glViewport(0, 0, source_width, source_height);
[email protected]43410e92012-04-20 17:06:288505 copy_texture_CHROMIUM_->DoCopyTexture(target, source_info->service_id(),
8506 dest_info->service_id(), level,
8507 unpack_flip_y_,
8508 unpack_premultiply_alpha_);
8509 glViewport(viewport_x_, viewport_y_, viewport_width_, viewport_height_);
8510
8511 // Restore all of the state touched by the extension.
8512 if (current_program_)
8513 glUseProgram(current_program_->service_id());
8514 else
8515 glUseProgram(0);
8516
8517 RestoreCurrentFramebufferBindings();
8518 RestoreCurrentTexture2DBindings();
8519 RestoreStateForAttrib(
8520 CopyTextureCHROMIUMResourceManager::kVertexPositionAttrib);
8521 RestoreStateForAttrib(
8522 CopyTextureCHROMIUMResourceManager::kVertexTextureAttrib);
8523
8524 ApplyDirtyState();
8525}
8526
[email protected]97dc7cbe2011-12-06 17:26:178527static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
8528 switch (internalformat) {
8529 case GL_RGB565:
8530 return GL_UNSIGNED_SHORT_5_6_5;
8531 case GL_RGBA4:
8532 return GL_UNSIGNED_SHORT_4_4_4_4;
8533 case GL_RGB5_A1:
8534 return GL_UNSIGNED_SHORT_5_5_5_1;
8535 case GL_RGB8_OES:
8536 return GL_UNSIGNED_BYTE;
8537 case GL_RGBA8_OES:
8538 return GL_UNSIGNED_BYTE;
8539 case GL_LUMINANCE8_ALPHA8_EXT:
8540 return GL_UNSIGNED_BYTE;
8541 case GL_LUMINANCE8_EXT:
8542 return GL_UNSIGNED_BYTE;
8543 case GL_ALPHA8_EXT:
8544 return GL_UNSIGNED_BYTE;
8545 case GL_RGBA32F_EXT:
8546 return GL_FLOAT;
8547 case GL_RGB32F_EXT:
8548 return GL_FLOAT;
8549 case GL_ALPHA32F_EXT:
8550 return GL_FLOAT;
8551 case GL_LUMINANCE32F_EXT:
8552 return GL_FLOAT;
8553 case GL_LUMINANCE_ALPHA32F_EXT:
8554 return GL_FLOAT;
8555 case GL_RGBA16F_EXT:
8556 return GL_HALF_FLOAT_OES;
8557 case GL_RGB16F_EXT:
8558 return GL_HALF_FLOAT_OES;
8559 case GL_ALPHA16F_EXT:
8560 return GL_HALF_FLOAT_OES;
8561 case GL_LUMINANCE16F_EXT:
8562 return GL_HALF_FLOAT_OES;
8563 case GL_LUMINANCE_ALPHA16F_EXT:
8564 return GL_HALF_FLOAT_OES;
8565 case GL_BGRA8_EXT:
8566 return GL_UNSIGNED_BYTE;
8567 default:
8568 return GL_NONE;
8569 }
8570}
8571
8572void GLES2DecoderImpl::DoTexStorage2DEXT(
8573 GLenum target,
8574 GLint levels,
8575 GLenum internal_format,
8576 GLsizei width,
8577 GLsizei height) {
[email protected]cf57fbc2012-04-26 22:18:418578 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
[email protected]80eb6b52012-01-19 00:14:418579 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
[email protected]97dc7cbe2011-12-06 17:26:178580 TextureManager::ComputeMipMapCount(width, height, 1) < levels) {
8581 SetGLError(GL_INVALID_VALUE, "glTexStorage2DEXT: dimensions out of range");
8582 return;
8583 }
8584 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8585 if (!info) {
8586 SetGLError(GL_INVALID_OPERATION,
8587 "glTexStorage2DEXT: unknown texture for target");
8588 return;
8589 }
8590 if (info->IsAttachedToFramebuffer()) {
8591 state_dirty_ = true;
8592 }
8593 if (info->IsImmutable()) {
8594 SetGLError(GL_INVALID_OPERATION,
8595 "glTexStorage2DEXT: texture is immutable");
8596 return;
8597 }
8598 CopyRealGLErrorsToWrapper();
[email protected]f0e6a34f2012-01-04 20:53:408599 glTexStorage2DEXT(target, levels, GetTexInternalFormat(internal_format),
8600 width, height);
[email protected]97dc7cbe2011-12-06 17:26:178601 GLenum error = PeekGLError();
8602 if (error == GL_NO_ERROR) {
8603 GLenum format = ExtractFormatFromStorageFormat(internal_format);
8604 GLenum type = ExtractTypeFromStorageFormat(internal_format);
[email protected]4502e6492011-12-14 19:39:158605 GLsizei level_width = width;
8606 GLsizei level_height = height;
8607 for (int ii = 0; ii < levels; ++ii) {
8608 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:418609 info, target, 0, format, level_width, level_height, 1, 0, format,
8610 type, false);
[email protected]4502e6492011-12-14 19:39:158611 level_width = std::max(1, level_width >> 1);
8612 level_height = std::max(1, level_height >> 1);
8613 }
[email protected]97dc7cbe2011-12-06 17:26:178614 info->SetImmutable(true);
8615 }
[email protected]97dc7cbe2011-12-06 17:26:178616}
[email protected]e51bdf32011-11-23 22:21:468617
[email protected]78b514b2012-05-01 21:50:598618error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
8619 uint32 immediate_data_size, const gles2::GenMailboxCHROMIUM& c) {
8620 MailboxName name;
8621 mailbox_manager()->GenerateMailboxName(&name);
8622 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
8623 Bucket* bucket = CreateBucket(bucket_id);
8624
8625 bucket->SetSize(GL_MAILBOX_SIZE_CHROMIUM);
8626 bucket->SetData(&name, 0, GL_MAILBOX_SIZE_CHROMIUM);
8627
8628 return error::kNoError;
8629}
8630
8631void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
8632 const GLbyte* mailbox) {
8633 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8634 if (!info) {
8635 SetGLError(GL_INVALID_OPERATION,
8636 "glProduceTextureCHROMIUM: unknown texture for target");
8637 return;
8638 }
8639
8640 TextureDefinition* definition = texture_manager()->Save(info);
8641 if (!definition) {
8642 SetGLError(GL_INVALID_OPERATION,
8643 "glProduceTextureCHROMIUM: invalid texture");
8644 return;
8645 }
8646
8647 if (!group_->mailbox_manager()->ProduceTexture(
8648 target,
8649 *reinterpret_cast<const MailboxName*>(mailbox),
8650 definition,
8651 texture_manager())) {
8652 bool success = texture_manager()->Restore(info, definition);
8653 DCHECK(success);
8654 SetGLError(GL_INVALID_OPERATION,
8655 "glProduceTextureCHROMIUM: invalid mailbox name");
8656 return;
8657 }
8658
8659 BindAndApplyTextureParameters(info);
8660}
8661
8662void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
8663 const GLbyte* mailbox) {
8664 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8665 if (!info) {
8666 SetGLError(GL_INVALID_OPERATION,
8667 "glConsumeTextureCHROMIUM: unknown texture for target");
8668 return;
8669 }
8670
8671 scoped_ptr<TextureDefinition> definition(
8672 group_->mailbox_manager()->ConsumeTexture(
8673 target,
8674 *reinterpret_cast<const MailboxName*>(mailbox)));
8675 if (!definition.get()) {
8676 SetGLError(GL_INVALID_OPERATION,
8677 "glConsumeTextureCHROMIUM: invalid mailbox name");
8678 return;
8679 }
8680
8681 if (!texture_manager()->Restore(info, definition.release())) {
8682 SetGLError(GL_INVALID_OPERATION,
8683 "glConsumeTextureCHROMIUM: invalid texture");
8684 return;
8685 }
8686
8687 BindAndApplyTextureParameters(info);
8688}
8689
[email protected]96449d2c2009-11-25 00:01:328690// Include the auto-generated part of this file. We split this because it means
8691// we can easily edit the non-auto generated parts right here in this file
8692// instead of having to edit some template or the code generator.
8693#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
8694
8695} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:258696} // namespace gpu