blob: b40198e87554e5fe84c5fc5c63779d68818cc142 [file] [log] [blame]
[email protected]529c6672012-01-04 02:18:261// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]96449d2c2009-11-25 00:01:322// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]8a837bb2010-01-05 00:21:245#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
[email protected]74470702010-01-06 18:51:166
7#include <stdio.h>
8
[email protected]1aef98132010-02-23 18:00:079#include <algorithm>
[email protected]f39f4b3f2010-05-12 17:04:0810#include <list>
[email protected]96449d2c2009-11-25 00:01:3211#include <map>
[email protected]f39f4b3f2010-05-12 17:04:0812#include <string>
13#include <vector>
[email protected]5a6db6c2010-04-22 18:32:0614
[email protected]00eb49a2010-08-12 20:46:5715#include "base/at_exit.h"
[email protected]d353541f2012-05-03 22:45:4116#include "base/atomicops.h"
[email protected]9d37f062011-11-22 01:24:5217#include "base/bind.h"
[email protected]e844ae22012-01-14 03:36:2618#include "base/command_line.h"
[email protected]1078f912011-12-23 13:12:1419#include "base/debug/trace_event.h"
[email protected]e51bdf32011-11-23 22:21:4620#if defined(OS_MACOSX)
21#include "base/mac/scoped_cftyperef.h"
22#endif
[email protected]3b63f8f42011-03-28 01:54:1523#include "base/memory/scoped_ptr.h"
24#include "base/memory/weak_ptr.h"
[email protected]0f8afe82012-05-14 23:43:0125#include "base/string_number_conversions.h"
[email protected]d37231fa2010-04-09 21:16:0226#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3227#define GLES2_GPU_SERVICE 1
28#include "gpu/command_buffer/common/gles2_cmd_format.h"
29#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1030#include "gpu/command_buffer/common/id_allocator.h"
[email protected]3916c97e2010-02-25 03:20:5031#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3232#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5033#include "gpu/command_buffer/service/context_group.h"
[email protected]915a59a12010-09-30 21:29:1134#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5835#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3236#include "gpu/command_buffer/service/gl_utils.h"
[email protected]43410e92012-04-20 17:06:2837#include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
[email protected]ba3176a2009-12-16 18:19:4638#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]e844ae22012-01-14 03:36:2639#include "gpu/command_buffer/service/gpu_switches.h"
[email protected]78b514b2012-05-01 21:50:5940#include "gpu/command_buffer/service/mailbox_manager.h"
[email protected]a93bb842010-02-16 23:03:4741#include "gpu/command_buffer/service/program_manager.h"
[email protected]882ba1e22012-03-08 19:02:5342#include "gpu/command_buffer/service/query_manager.h"
[email protected]a25fa872010-03-25 02:57:5843#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4744#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4545#include "gpu/command_buffer/service/shader_translator.h"
[email protected]87fb6ab2012-06-13 22:28:0446#include "gpu/command_buffer/service/shader_translator_cache.h"
[email protected]b0af4f52011-09-28 22:04:4247#include "gpu/command_buffer/service/stream_texture.h"
48#include "gpu/command_buffer/service/stream_texture_manager.h"
[email protected]78b514b2012-05-01 21:50:5949#include "gpu/command_buffer/service/texture_definition.h"
[email protected]a93bb842010-02-16 23:03:4750#include "gpu/command_buffer/service/texture_manager.h"
[email protected]d8ea9772011-07-11 18:11:4351#include "gpu/command_buffer/service/vertex_attrib_manager.h"
[email protected]c9e2cbbb2012-05-12 21:17:2752#include "ui/gl/gl_context.h"
53#include "ui/gl/gl_implementation.h"
54#include "ui/gl/gl_surface.h"
[email protected]e51bdf32011-11-23 22:21:4655#if defined(OS_MACOSX)
[email protected]d353541f2012-05-03 22:45:4156#include "ui/surface/io_surface_support_mac.h"
[email protected]e51bdf32011-11-23 22:21:4657#endif
[email protected]de17df392010-04-23 21:09:4158
[email protected]6217d392010-03-25 22:08:3559#if !defined(GL_DEPTH24_STENCIL8)
60#define GL_DEPTH24_STENCIL8 0x88F0
61#endif
62
[email protected]a7a27ace2009-12-12 00:11:2563namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3264namespace gles2 {
65
[email protected]f0d74742011-10-03 16:31:0466namespace {
67static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
68}
69
[email protected]6217d392010-03-25 22:08:3570class GLES2DecoderImpl;
71
[email protected]07f54fcc2009-12-22 02:46:3072// Check that certain assumptions the code makes are true. There are places in
73// the code where shared memory is passed direclty to GL. Example, glUniformiv,
74// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
75// a few others) are 32bits. If they are not 32bits the code will have to change
76// to call those GL functions with service side memory and then copy the results
77// to shared memory, converting the sizes.
78COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
79 GLint_not_same_size_as_uint32);
80COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
81 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:3782COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
83 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:3084
[email protected]43f28f832010-02-03 02:28:4885// TODO(kbr): the use of this anonymous namespace core dumps the
86// linker on Mac OS X 10.6 when the symbol ordering file is used
87// namespace {
[email protected]96449d2c2009-11-25 00:01:3288
89// Returns the address of the first byte after a struct.
90template <typename T>
91const void* AddressAfterStruct(const T& pod) {
92 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
93}
94
[email protected]07f54fcc2009-12-22 02:46:3095// Returns the address of the frst byte after the struct or NULL if size >
96// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:3297template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:3098RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
99 uint32 size,
100 uint32 immediate_data_size) {
101 return (size <= immediate_data_size) ?
102 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
103 NULL;
[email protected]96449d2c2009-11-25 00:01:32104}
105
[email protected]07f54fcc2009-12-22 02:46:30106// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:18107bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:32108 GLuint count,
109 size_t size,
[email protected]a76b0052010-03-05 00:33:18110 unsigned int elements_per_unit,
111 uint32* dst) {
112 uint32 value;
113 if (!SafeMultiplyUint32(count, size, &value)) {
114 return false;
115 }
116 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
117 return false;
118 }
119 *dst = value;
120 return true;
[email protected]96449d2c2009-11-25 00:01:32121}
122
123// A struct to hold info about each command.
124struct CommandInfo {
125 int arg_flags; // How to handle the arguments for this command
126 int arg_count; // How many arguments are expected for this command.
127};
128
129// A table of CommandInfo for all the commands.
130const CommandInfo g_command_info[] = {
131 #define GLES2_CMD_OP(name) { \
132 name::kArgFlags, \
133 sizeof(name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
134
135 GLES2_COMMAND_LIST(GLES2_CMD_OP)
136
137 #undef GLES2_CMD_OP
138};
139
[email protected]258a3313f2011-10-18 20:13:57140// Return true if a character belongs to the ASCII subset as defined in
141// GLSL ES 1.0 spec section 3.1.
142static bool CharacterIsValidForGLES(unsigned char c) {
143 // Printing characters are valid except " $ ` @ \ ' DEL.
144 if (c >= 32 && c <= 126 &&
145 c != '"' &&
146 c != '$' &&
147 c != '`' &&
148 c != '@' &&
149 c != '\\' &&
150 c != '\'') {
151 return true;
152 }
153 // Horizontal tab, line feed, vertical tab, form feed, carriage return
154 // are also valid.
155 if (c >= 9 && c <= 13) {
156 return true;
157 }
158
159 return false;
160}
161
162static bool StringIsValidForGLES(const char* str) {
163 for (; *str; ++str) {
164 if (!CharacterIsValidForGLES(*str)) {
165 return false;
166 }
167 }
168 return true;
169}
170
[email protected]f0e6a34f2012-01-04 20:53:40171static inline GLenum GetTexInternalFormat(GLenum internal_format) {
172 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
173 if (internal_format == GL_BGRA_EXT || internal_format == GL_BGRA8_EXT)
174 return GL_RGBA8;
175 }
176 return internal_format;
177}
178
[email protected]297ca1c2011-06-20 23:08:46179static void WrappedTexImage2D(
[email protected]473c01ccb2011-06-07 01:33:30180 GLenum target,
181 GLint level,
182 GLenum internal_format,
183 GLsizei width,
184 GLsizei height,
185 GLint border,
186 GLenum format,
187 GLenum type,
188 const void* pixels) {
[email protected]f0e6a34f2012-01-04 20:53:40189 GLenum gl_internal_format = GetTexInternalFormat(internal_format);
[email protected]473c01ccb2011-06-07 01:33:30190 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]f0e6a34f2012-01-04 20:53:40191 if (type == GL_FLOAT) {
[email protected]58b75f92012-03-20 21:15:43192 switch (format) {
193 case GL_RGBA:
194 gl_internal_format = GL_RGBA32F_ARB;
195 break;
196 case GL_RGB:
197 gl_internal_format = GL_RGB32F_ARB;
198 break;
199 case GL_LUMINANCE_ALPHA:
200 gl_internal_format = GL_LUMINANCE_ALPHA32F_ARB;
201 break;
202 case GL_LUMINANCE:
203 gl_internal_format = GL_LUMINANCE32F_ARB;
204 break;
205 case GL_ALPHA:
206 gl_internal_format = GL_ALPHA32F_ARB;
207 break;
208 default:
209 NOTREACHED();
210 break;
[email protected]473c01ccb2011-06-07 01:33:30211 }
212 } else if (type == GL_HALF_FLOAT_OES) {
[email protected]58b75f92012-03-20 21:15:43213 switch (format) {
214 case GL_RGBA:
215 gl_internal_format = GL_RGBA16F_ARB;
216 break;
217 case GL_RGB:
218 gl_internal_format = GL_RGB16F_ARB;
219 break;
220 case GL_LUMINANCE_ALPHA:
221 gl_internal_format = GL_LUMINANCE_ALPHA16F_ARB;
222 break;
223 case GL_LUMINANCE:
224 gl_internal_format = GL_LUMINANCE16F_ARB;
225 break;
226 case GL_ALPHA:
227 gl_internal_format = GL_ALPHA16F_ARB;
228 break;
229 default:
230 NOTREACHED();
231 break;
[email protected]473c01ccb2011-06-07 01:33:30232 }
233 }
234 }
235 glTexImage2D(
236 target, level, gl_internal_format, width, height, border, format, type,
237 pixels);
238}
239
[email protected]297ca1c2011-06-20 23:08:46240// Wrapper for glEnable/glDisable that doesn't suck.
241static void EnableDisable(GLenum pname, bool enable) {
242 if (enable) {
243 glEnable(pname);
244 } else {
245 glDisable(pname);
246 }
247}
248
[email protected]6217d392010-03-25 22:08:35249// This class prevents any GL errors that occur when it is in scope from
250// being reported to the client.
251class ScopedGLErrorSuppressor {
252 public:
253 explicit ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder);
254 ~ScopedGLErrorSuppressor();
255 private:
256 GLES2DecoderImpl* decoder_;
257 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
258};
259
260// Temporarily changes a decoder's bound 2D texture and restore it when this
261// object goes out of scope. Also temporarily switches to using active texture
262// unit zero in case the client has changed that to something invalid.
263class ScopedTexture2DBinder {
264 public:
265 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
266 ~ScopedTexture2DBinder();
267
268 private:
269 GLES2DecoderImpl* decoder_;
270 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
271};
272
273// Temporarily changes a decoder's bound render buffer and restore it when this
274// object goes out of scope.
275class ScopedRenderBufferBinder {
276 public:
277 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
278 ~ScopedRenderBufferBinder();
279
280 private:
281 GLES2DecoderImpl* decoder_;
282 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
283};
284
285// Temporarily changes a decoder's bound frame buffer and restore it when this
286// object goes out of scope.
287class ScopedFrameBufferBinder {
288 public:
289 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
290 ~ScopedFrameBufferBinder();
291
292 private:
293 GLES2DecoderImpl* decoder_;
294 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
295};
296
[email protected]34ff8b0c2010-10-01 20:06:02297// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52298// the multisampled offscreen render buffer if that buffer is multisampled, and,
[email protected]de26b3c2011-08-03 21:54:27299// if it is bound or enforce_internal_framebuffer is true. If internal is
300// true, the resolved framebuffer is not visible to the parent.
[email protected]34ff8b0c2010-10-01 20:06:02301class ScopedResolvedFrameBufferBinder {
302 public:
[email protected]e7e38032011-07-26 17:25:25303 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
[email protected]de26b3c2011-08-03 21:54:27304 bool enforce_internal_framebuffer,
305 bool internal);
[email protected]34ff8b0c2010-10-01 20:06:02306 ~ScopedResolvedFrameBufferBinder();
307
308 private:
309 GLES2DecoderImpl* decoder_;
310 bool resolve_and_bind_;
311 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
312};
313
[email protected]6217d392010-03-25 22:08:35314// Encapsulates an OpenGL texture.
315class Texture {
316 public:
317 explicit Texture(GLES2DecoderImpl* decoder);
318 ~Texture();
319
320 // Create a new render texture.
321 void Create();
322
323 // Set the initial size and format of a render texture or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02324 bool AllocateStorage(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35325
326 // Copy the contents of the currently bound frame buffer.
[email protected]3a4d0c52011-06-29 23:11:58327 void Copy(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35328
329 // Destroy the render texture. This must be explicitly called before
330 // destroying this object.
331 void Destroy();
332
[email protected]97872062010-11-03 19:07:05333 // Invalidate the texture. This can be used when a context is lost and it is
334 // not possible to make it current in order to free the resource.
335 void Invalidate();
336
[email protected]6217d392010-03-25 22:08:35337 GLuint id() const {
338 return id_;
339 }
340
[email protected]d37231fa2010-04-09 21:16:02341 gfx::Size size() const {
342 return size_;
343 }
344
[email protected]1078f912011-12-23 13:12:14345 size_t estimated_size() const {
346 return estimated_size_;
347 }
348
[email protected]6217d392010-03-25 22:08:35349 private:
350 GLES2DecoderImpl* decoder_;
351 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02352 gfx::Size size_;
[email protected]1078f912011-12-23 13:12:14353 size_t estimated_size_;
[email protected]6217d392010-03-25 22:08:35354 DISALLOW_COPY_AND_ASSIGN(Texture);
355};
356
357// Encapsulates an OpenGL render buffer of any format.
358class RenderBuffer {
359 public:
360 explicit RenderBuffer(GLES2DecoderImpl* decoder);
361 ~RenderBuffer();
362
363 // Create a new render buffer.
364 void Create();
365
366 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02367 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35368
369 // Destroy the render buffer. This must be explicitly called before destroying
370 // this object.
371 void Destroy();
372
[email protected]97872062010-11-03 19:07:05373 // Invalidate the render buffer. This can be used when a context is lost and
374 // it is not possible to make it current in order to free the resource.
375 void Invalidate();
376
[email protected]6217d392010-03-25 22:08:35377 GLuint id() const {
378 return id_;
379 }
380
[email protected]1078f912011-12-23 13:12:14381 size_t estimated_size() const {
382 return estimated_size_;
383 }
384
[email protected]6217d392010-03-25 22:08:35385 private:
386 GLES2DecoderImpl* decoder_;
387 GLuint id_;
[email protected]1078f912011-12-23 13:12:14388 size_t estimated_size_;
[email protected]6217d392010-03-25 22:08:35389 DISALLOW_COPY_AND_ASSIGN(RenderBuffer);
390};
391
392// Encapsulates an OpenGL frame buffer.
393class FrameBuffer {
394 public:
395 explicit FrameBuffer(GLES2DecoderImpl* decoder);
396 ~FrameBuffer();
397
398 // Create a new frame buffer.
399 void Create();
400
401 // Attach a color render buffer to a frame buffer.
402 void AttachRenderTexture(Texture* texture);
403
[email protected]b9363b22010-06-09 22:06:15404 // Attach a render buffer to a frame buffer. Note that this unbinds any
405 // currently bound frame buffer.
406 void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35407
[email protected]6217d392010-03-25 22:08:35408 // Destroy the frame buffer. This must be explicitly called before destroying
409 // this object.
410 void Destroy();
411
[email protected]97872062010-11-03 19:07:05412 // Invalidate the frame buffer. This can be used when a context is lost and it
413 // is not possible to make it current in order to free the resource.
414 void Invalidate();
415
[email protected]6217d392010-03-25 22:08:35416 // See glCheckFramebufferStatusEXT.
417 GLenum CheckStatus();
418
419 GLuint id() const {
420 return id_;
421 }
422
423 private:
424 GLES2DecoderImpl* decoder_;
425 GLuint id_;
426 DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
427};
[email protected]34ff8b0c2010-10-01 20:06:02428
[email protected]43f28f832010-02-03 02:28:48429// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32430
[email protected]ddb1e5a2010-12-13 20:10:45431bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
432 uint32* service_texture_id) {
433 return false;
434}
435
[email protected]a3ded6d2010-10-19 06:44:39436GLES2Decoder::GLES2Decoder()
[email protected]e844ae22012-01-14 03:36:26437 : debug_(false),
[email protected]b5d647c2012-02-10 01:41:32438 log_commands_(false),
439 log_synthesized_gl_errors_(true) {
[email protected]96449d2c2009-11-25 00:01:32440}
441
[email protected]3916c97e2010-02-25 03:20:50442GLES2Decoder::~GLES2Decoder() {
443}
444
[email protected]57edfdad2012-02-07 04:57:15445bool GLES2Decoder::testing_force_is_angle_;
446
447void GLES2Decoder::set_testing_force_is_angle(bool force) {
448 testing_force_is_angle_ = force;
449}
450
451bool GLES2Decoder::IsAngle() {
452#if defined(OS_WIN)
453 return testing_force_is_angle_ ||
454 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
455#else
456 return testing_force_is_angle_;
457#endif
458}
459
[email protected]f39f4b3f2010-05-12 17:04:08460// This class implements GLES2Decoder so we don't have to expose all the GLES2
461// cmd stuff to outside this class.
462class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
463 public GLES2Decoder {
464 public:
[email protected]0f8afe82012-05-14 23:43:01465 static const int kMaxLogMessages = 256;
[email protected]fa20ec82012-05-04 04:02:48466
[email protected]aa7666122011-09-02 19:45:52467 explicit GLES2DecoderImpl(ContextGroup* group);
[email protected]80eb6b52012-01-19 00:14:41468 ~GLES2DecoderImpl();
[email protected]f39f4b3f2010-05-12 17:04:08469
[email protected]96449d2c2009-11-25 00:01:32470 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14471 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50472 unsigned int arg_count,
473 const void* args);
[email protected]96449d2c2009-11-25 00:01:32474
475 // Overridden from AsyncAPIInterface.
476 virtual const char* GetCommandName(unsigned int command_id) const;
477
478 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38479 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
480 const scoped_refptr<gfx::GLContext>& context,
[email protected]069944672012-04-25 20:52:23481 bool offscreen,
[email protected]6217d392010-03-25 22:08:35482 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:29483 const DisallowedFeatures& disallowed_features,
[email protected]a3ded6d2010-10-19 06:44:39484 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:24485 const std::vector<int32>& attribs);
[email protected]63c9b052012-05-17 18:27:38486 virtual void Destroy(bool have_context);
487 virtual void SetSurface(
488 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
[email protected]3c644d82011-06-20 19:58:24489 virtual bool SetParent(GLES2Decoder* parent_decoder,
490 uint32 parent_texture_id);
[email protected]799b4b22011-08-22 17:09:59491 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size);
[email protected]9a5afa432011-07-22 18:16:39492 void UpdateParentTextureInfo();
[email protected]eb54a562010-01-20 21:55:18493 virtual bool MakeCurrent();
[email protected]a96a6022011-11-04 00:58:12494 virtual void ReleaseCurrent();
[email protected]56ac89b2010-03-17 21:16:55495 virtual GLES2Util* GetGLES2Util() { return &util_; }
[email protected]66791e382010-07-14 20:48:30496 virtual gfx::GLContext* GetGLContext() { return context_.get(); }
[email protected]a3ded6d2010-10-19 06:44:39497 virtual ContextGroup* GetContextGroup() { return group_.get(); }
[email protected]882ba1e22012-03-08 19:02:53498 virtual QueryManager* GetQueryManager() { return query_manager_.get(); }
[email protected]22e3f552012-03-13 01:54:19499 virtual bool ProcessPendingQueries();
[email protected]43f28f832010-02-03 02:28:48500
[email protected]ad84a3a2012-06-08 21:42:43501 virtual void SetGLError(
502 GLenum error, const char* function_name, const char* msg);
[email protected]9d37f062011-11-22 01:24:52503 virtual void SetResizeCallback(
504 const base::Callback<void(gfx::Size)>& callback);
[email protected]22f320a2011-08-30 01:17:00505
[email protected]6b6e7ee2011-12-13 08:04:52506 virtual void SetMsgCallback(const MsgCallback& callback);
[email protected]22f320a2011-08-30 01:17:00507
[email protected]b0af4f52011-09-28 22:04:42508 virtual void SetStreamTextureManager(StreamTextureManager* manager);
[email protected]1318e922010-09-17 22:03:16509 virtual bool GetServiceTextureId(uint32 client_texture_id,
510 uint32* service_texture_id);
[email protected]43f28f832010-02-03 02:28:48511
[email protected]8e3e0662010-08-23 18:46:30512 // Restores the current state to the user's settings.
513 void RestoreCurrentFramebufferBindings();
514 void RestoreCurrentRenderbufferBindings();
515 void RestoreCurrentTexture2DBindings();
516
[email protected]297ca1c2011-06-20 23:08:46517 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
518 void ApplyDirtyState();
519
[email protected]78b514b2012-05-01 21:50:59520 // Reapply the texture parameters to the given texture.
521 void BindAndApplyTextureParameters(TextureManager::TextureInfo* info);
522
[email protected]297ca1c2011-06-20 23:08:46523 // These check the state of the currently bound framebuffer or the
524 // backbuffer if no framebuffer is bound.
525 bool BoundFramebufferHasColorAttachmentWithAlpha();
526 bool BoundFramebufferHasDepthAttachment();
527 bool BoundFramebufferHasStencilAttachment();
528
[email protected]38d139d2011-07-14 00:38:43529 virtual error::ContextLostReason GetContextLostReason();
530
[email protected]96449d2c2009-11-25 00:01:32531 private:
[email protected]6217d392010-03-25 22:08:35532 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02533 friend class ScopedResolvedFrameBufferBinder;
[email protected]1078f912011-12-23 13:12:14534 friend class Texture;
[email protected]6217d392010-03-25 22:08:35535 friend class RenderBuffer;
536 friend class FrameBuffer;
537
[email protected]3916c97e2010-02-25 03:20:50538 // State associated with each texture unit.
539 struct TextureUnit {
540 TextureUnit() : bind_target(GL_TEXTURE_2D) { }
541
542 // The last target that was bound to this texture unit.
543 GLenum bind_target;
544
545 // texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
546 TextureManager::TextureInfo::Ref bound_texture_2d;
547
548 // texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
549 // glBindTexture
550 TextureManager::TextureInfo::Ref bound_texture_cube_map;
[email protected]61eeb33f2011-07-26 15:30:31551
552 // texture currently bound to this unit's GL_TEXTURE_EXTERNAL_OES with
553 // glBindTexture
554 TextureManager::TextureInfo::Ref bound_texture_external_oes;
555
[email protected]e51bdf32011-11-23 22:21:46556 // texture currently bound to this unit's GL_TEXTURE_RECTANGLE_ARB with
557 // glBindTexture
558 TextureManager::TextureInfo::Ref bound_texture_rectangle_arb;
559
[email protected]61eeb33f2011-07-26 15:30:31560 TextureManager::TextureInfo::Ref GetInfoForSamplerType(GLenum type) {
561 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:46562 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
563 switch (type) {
564 case GL_SAMPLER_2D:
565 return bound_texture_2d;
566 case GL_SAMPLER_CUBE:
567 return bound_texture_cube_map;
568 case GL_SAMPLER_EXTERNAL_OES:
569 return bound_texture_external_oes;
570 case GL_SAMPLER_2D_RECT_ARB:
571 return bound_texture_rectangle_arb;
572 }
573
574 NOTREACHED();
575 return NULL;
[email protected]61eeb33f2011-07-26 15:30:31576 }
[email protected]a0b78dc2011-11-11 10:43:10577
578 void Unbind(TextureManager::TextureInfo* texture) {
579 if (bound_texture_2d == texture) {
580 bound_texture_2d = NULL;
581 }
582 if (bound_texture_cube_map == texture) {
583 bound_texture_cube_map = NULL;
584 }
585 if (bound_texture_external_oes == texture) {
586 bound_texture_external_oes = NULL;
587 }
588 }
[email protected]3916c97e2010-02-25 03:20:50589 };
590
[email protected]c2f8c8402010-12-06 18:07:24591 // Initialize or re-initialize the shader translator.
592 bool InitializeShaderTranslator();
593
[email protected]302ce6d2011-07-07 23:28:11594 void UpdateCapabilities();
595
[email protected]ae51d192010-04-27 00:48:03596 // Helpers for the glGen and glDelete functions.
597 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
598 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
599 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
600 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
601 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
602 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
603 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
604 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]882ba1e22012-03-08 19:02:53605 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
606 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47607
[email protected]3916c97e2010-02-25 03:20:50608 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50609 BufferManager* buffer_manager() {
610 return group_->buffer_manager();
611 }
612
[email protected]a25fa872010-03-25 02:57:58613 RenderbufferManager* renderbuffer_manager() {
614 return group_->renderbuffer_manager();
615 }
616
617 FramebufferManager* framebuffer_manager() {
618 return group_->framebuffer_manager();
619 }
620
[email protected]3916c97e2010-02-25 03:20:50621 ProgramManager* program_manager() {
622 return group_->program_manager();
623 }
624
625 ShaderManager* shader_manager() {
626 return group_->shader_manager();
627 }
628
629 TextureManager* texture_manager() {
630 return group_->texture_manager();
631 }
632
[email protected]78b514b2012-05-01 21:50:59633 MailboxManager* mailbox_manager() {
634 return group_->mailbox_manager();
635 }
636
[email protected]34ff8b0c2010-10-01 20:06:02637 bool IsOffscreenBufferMultisampled() const {
638 return offscreen_target_samples_ > 1;
639 }
640
[email protected]a93bb842010-02-16 23:03:47641 // Creates a TextureInfo for the given texture.
[email protected]ae51d192010-04-27 00:48:03642 TextureManager::TextureInfo* CreateTextureInfo(
643 GLuint client_id, GLuint service_id) {
[email protected]80eb6b52012-01-19 00:14:41644 return texture_manager()->CreateTextureInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47645 }
646
647 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03648 TextureManager::TextureInfo* GetTextureInfo(GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:50649 TextureManager::TextureInfo* info =
[email protected]ae51d192010-04-27 00:48:03650 texture_manager()->GetTextureInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:10651 return info;
[email protected]a93bb842010-02-16 23:03:47652 }
653
654 // Deletes the texture info for the given texture.
[email protected]ae51d192010-04-27 00:48:03655 void RemoveTextureInfo(GLuint client_id) {
[email protected]80eb6b52012-01-19 00:14:41656 texture_manager()->RemoveTextureInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:50657 }
[email protected]a93bb842010-02-16 23:03:47658
[email protected]d37231fa2010-04-09 21:16:02659 // Get the size (in pixels) of the currently bound frame buffer (either FBO
660 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30661 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02662
[email protected]9edc6b22010-12-23 02:00:26663 // Get the format of the currently bound frame buffer (either FBO or regular
664 // back buffer)
665 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46666 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26667
[email protected]a93bb842010-02-16 23:03:47668 // Wrapper for CompressedTexImage2D commands.
669 error::Error DoCompressedTexImage2D(
670 GLenum target,
671 GLint level,
672 GLenum internal_format,
673 GLsizei width,
674 GLsizei height,
675 GLint border,
676 GLsizei image_size,
677 const void* data);
678
[email protected]cadde4a2010-07-31 17:10:43679 // Wrapper for CompressedTexSubImage2D.
680 void DoCompressedTexSubImage2D(
681 GLenum target,
682 GLint level,
683 GLint xoffset,
684 GLint yoffset,
685 GLsizei width,
686 GLsizei height,
687 GLenum format,
688 GLsizei imageSize,
689 const void * data);
690
691 // Wrapper for CopyTexImage2D.
692 void DoCopyTexImage2D(
693 GLenum target,
694 GLint level,
695 GLenum internal_format,
696 GLint x,
697 GLint y,
698 GLsizei width,
699 GLsizei height,
700 GLint border);
701
702 // Wrapper for CopyTexSubImage2D.
703 void DoCopyTexSubImage2D(
704 GLenum target,
705 GLint level,
706 GLint xoffset,
707 GLint yoffset,
708 GLint x,
709 GLint y,
710 GLsizei width,
711 GLsizei height);
712
[email protected]a93bb842010-02-16 23:03:47713 // Wrapper for TexImage2D commands.
714 error::Error DoTexImage2D(
715 GLenum target,
716 GLint level,
717 GLenum internal_format,
718 GLsizei width,
719 GLsizei height,
720 GLint border,
721 GLenum format,
722 GLenum type,
723 const void* pixels,
724 uint32 pixels_size);
725
[email protected]cadde4a2010-07-31 17:10:43726 // Wrapper for TexSubImage2D.
727 void DoTexSubImage2D(
728 GLenum target,
729 GLint level,
730 GLint xoffset,
731 GLint yoffset,
732 GLsizei width,
733 GLsizei height,
734 GLenum format,
735 GLenum type,
736 const void * data);
737
[email protected]e51bdf32011-11-23 22:21:46738 // Wrapper for TexImageIOSurface2DCHROMIUM.
739 void DoTexImageIOSurface2DCHROMIUM(
740 GLenum target,
741 GLsizei width,
742 GLsizei height,
743 GLuint io_surface_id,
744 GLuint plane);
745
[email protected]43410e92012-04-20 17:06:28746 void DoCopyTextureCHROMIUM(
747 GLenum target,
748 GLuint source_id,
749 GLuint target_id,
[email protected]0a1e9ad2012-05-04 21:13:03750 GLint level,
751 GLenum internal_format);
[email protected]43410e92012-04-20 17:06:28752
[email protected]97dc7cbe2011-12-06 17:26:17753 // Wrapper for TexStorage2DEXT.
754 void DoTexStorage2DEXT(
755 GLenum target,
756 GLint levels,
757 GLenum internal_format,
758 GLsizei width,
759 GLsizei height);
760
[email protected]78b514b2012-05-01 21:50:59761 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
762 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
763
[email protected]a93bb842010-02-16 23:03:47764 // Creates a ProgramInfo for the given program.
[email protected]d685a682011-04-29 16:19:57765 ProgramManager::ProgramInfo* CreateProgramInfo(
766 GLuint client_id, GLuint service_id) {
767 return program_manager()->CreateProgramInfo(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47768 }
769
[email protected]07f54fcc2009-12-22 02:46:30770 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03771 ProgramManager::ProgramInfo* GetProgramInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14772 return program_manager()->GetProgramInfo(client_id);
[email protected]1d32bc82010-01-13 22:06:46773 }
[email protected]07f54fcc2009-12-22 02:46:30774
[email protected]6b8cf1a2010-05-06 16:13:58775 // Gets the program info for the given program. If it's not a program
776 // generates a GL error. Returns NULL if not program.
777 ProgramManager::ProgramInfo* GetProgramInfoNotShader(
778 GLuint client_id, const char* function_name) {
779 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
780 if (!info) {
781 if (GetShaderInfo(client_id)) {
[email protected]ad84a3a2012-06-08 21:42:43782 SetGLError(
783 GL_INVALID_OPERATION, function_name, "shader passed for program");
[email protected]6b8cf1a2010-05-06 16:13:58784 } else {
[email protected]ad84a3a2012-06-08 21:42:43785 SetGLError(GL_INVALID_VALUE, function_name, "unknown program");
[email protected]6b8cf1a2010-05-06 16:13:58786 }
787 }
788 return info;
789 }
790
791
[email protected]45bf5152010-02-12 00:11:31792 // Creates a ShaderInfo for the given shader.
[email protected]d685a682011-04-29 16:19:57793 ShaderManager::ShaderInfo* CreateShaderInfo(
794 GLuint client_id,
795 GLuint service_id,
796 GLenum shader_type) {
797 return shader_manager()->CreateShaderInfo(
798 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31799 }
800
801 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ae51d192010-04-27 00:48:03802 ShaderManager::ShaderInfo* GetShaderInfo(GLuint client_id) {
[email protected]ca488e12010-12-13 20:06:14803 return shader_manager()->GetShaderInfo(client_id);
[email protected]45bf5152010-02-12 00:11:31804 }
805
[email protected]6b8cf1a2010-05-06 16:13:58806 // Gets the shader info for the given shader. If it's not a shader generates a
807 // GL error. Returns NULL if not shader.
808 ShaderManager::ShaderInfo* GetShaderInfoNotProgram(
809 GLuint client_id, const char* function_name) {
810 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
811 if (!info) {
812 if (GetProgramInfo(client_id)) {
813 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:43814 GL_INVALID_OPERATION, function_name, "program passed for shader");
[email protected]6b8cf1a2010-05-06 16:13:58815 } else {
[email protected]ad84a3a2012-06-08 21:42:43816 SetGLError(
817 GL_INVALID_VALUE, function_name, "unknown shader");
[email protected]6b8cf1a2010-05-06 16:13:58818 }
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]ad84a3a2012-06-08 21:42:431190 bool IsDrawValid(
1191 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount);
[email protected]07f54fcc2009-12-22 02:46:301192
[email protected]c13e1da62011-09-09 21:48:301193 // Returns true if successful, simulated will be true if attrib0 was
1194 // simulated.
[email protected]c6aef902012-02-14 03:31:421195 bool SimulateAttrib0(
[email protected]ad84a3a2012-06-08 21:42:431196 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
[email protected]43410e92012-04-20 17:06:281197 void RestoreStateForAttrib(GLuint attrib);
[email protected]b1122982010-05-17 23:04:241198
[email protected]ef526492010-06-02 23:12:251199 // Returns true if textures were set.
1200 bool SetBlackTextureForNonRenderableTextures();
[email protected]3916c97e2010-02-25 03:20:501201 void RestoreStateForNonRenderableTextures();
1202
[email protected]8fbedc02010-11-18 18:43:401203 // Returns true if GL_FIXED attribs were simulated.
[email protected]c6aef902012-02-14 03:31:421204 bool SimulateFixedAttribs(
[email protected]ad84a3a2012-06-08 21:42:431205 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421206 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
[email protected]8fbedc02010-11-18 18:43:401207 void RestoreStateForSimulatedFixedAttribs();
1208
[email protected]c6aef902012-02-14 03:31:421209 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1210 // cases (primcount is 0 for non-instanced).
1211 error::Error DoDrawArrays(
[email protected]ad84a3a2012-06-08 21:42:431212 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421213 bool instanced, GLenum mode, GLint first, GLsizei count,
1214 GLsizei primcount);
1215 error::Error DoDrawElements(
[email protected]ad84a3a2012-06-08 21:42:431216 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421217 bool instanced, GLenum mode, GLsizei count, GLenum type,
1218 int32 offset, GLsizei primcount);
1219
[email protected]07f54fcc2009-12-22 02:46:301220 // Gets the buffer id for a given target.
[email protected]3916c97e2010-02-25 03:20:501221 BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
[email protected]07f54fcc2009-12-22 02:46:301222 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
[email protected]3916c97e2010-02-25 03:20:501223 BufferManager::BufferInfo* info = target == GL_ARRAY_BUFFER ?
1224 bound_array_buffer_ : bound_element_array_buffer_;
[email protected]a0b78dc2011-11-11 10:43:101225 return info;
[email protected]07f54fcc2009-12-22 02:46:301226 }
1227
[email protected]a93bb842010-02-16 23:03:471228 // Gets the texture id for a given target.
[email protected]3916c97e2010-02-25 03:20:501229 TextureManager::TextureInfo* GetTextureInfoForTarget(GLenum target) {
1230 TextureUnit& unit = texture_units_[active_texture_unit_];
1231 TextureManager::TextureInfo* info = NULL;
[email protected]a93bb842010-02-16 23:03:471232 switch (target) {
1233 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:501234 info = unit.bound_texture_2d;
1235 break;
[email protected]a93bb842010-02-16 23:03:471236 case GL_TEXTURE_CUBE_MAP:
1237 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1238 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1239 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1240 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1241 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1242 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
[email protected]3916c97e2010-02-25 03:20:501243 info = unit.bound_texture_cube_map;
1244 break;
[email protected]61eeb33f2011-07-26 15:30:311245 case GL_TEXTURE_EXTERNAL_OES:
1246 info = unit.bound_texture_external_oes;
1247 break;
[email protected]e51bdf32011-11-23 22:21:461248 case GL_TEXTURE_RECTANGLE_ARB:
1249 info = unit.bound_texture_rectangle_arb;
1250 break;
[email protected]a93bb842010-02-16 23:03:471251 default:
1252 NOTREACHED();
[email protected]3916c97e2010-02-25 03:20:501253 return NULL;
[email protected]a93bb842010-02-16 23:03:471254 }
[email protected]a0b78dc2011-11-11 10:43:101255 return info;
[email protected]a93bb842010-02-16 23:03:471256 }
1257
[email protected]61eeb33f2011-07-26 15:30:311258 GLenum GetBindTargetForSamplerType(GLenum type) {
1259 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:461260 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1261 switch (type) {
1262 case GL_SAMPLER_2D:
1263 return GL_TEXTURE_2D;
1264 case GL_SAMPLER_CUBE:
1265 return GL_TEXTURE_CUBE_MAP;
1266 case GL_SAMPLER_EXTERNAL_OES:
1267 return GL_TEXTURE_EXTERNAL_OES;
1268 case GL_SAMPLER_2D_RECT_ARB:
1269 return GL_TEXTURE_RECTANGLE_ARB;
1270 }
1271
1272 NOTREACHED();
1273 return 0;
[email protected]61eeb33f2011-07-26 15:30:311274 }
1275
[email protected]8e3e0662010-08-23 18:46:301276 // Gets the framebuffer info for a particular target.
1277 FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
1278 GLenum target) {
1279 FramebufferManager::FramebufferInfo* info = NULL;
1280 switch (target) {
1281 case GL_FRAMEBUFFER:
1282 case GL_DRAW_FRAMEBUFFER:
1283 info = bound_draw_framebuffer_;
1284 break;
1285 case GL_READ_FRAMEBUFFER:
1286 info = bound_read_framebuffer_;
1287 break;
1288 default:
1289 NOTREACHED();
1290 break;
1291 }
[email protected]a0b78dc2011-11-11 10:43:101292 return info;
[email protected]8e3e0662010-08-23 18:46:301293 }
1294
[email protected]0d6bfdc2011-11-02 01:32:201295 RenderbufferManager::RenderbufferInfo* GetRenderbufferInfoForTarget(
1296 GLenum target) {
1297 RenderbufferManager::RenderbufferInfo* info = NULL;
1298 switch (target) {
1299 case GL_RENDERBUFFER:
1300 info = bound_renderbuffer_;
1301 break;
1302 default:
1303 NOTREACHED();
1304 break;
1305 }
[email protected]a0b78dc2011-11-11 10:43:101306 return info;
[email protected]0d6bfdc2011-11-02 01:32:201307 }
1308
[email protected]f7b85372010-02-03 01:11:371309 // Validates the program and location for a glGetUniform call and returns
1310 // a SizeResult setup to receive the result. Returns true if glGetUniform
1311 // should be called.
1312 bool GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:121313 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:371314 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:121315 error::Error* error, GLint* real_location, GLuint* service_id,
1316 void** result, GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371317
[email protected]1078f912011-12-23 13:12:141318 // Computes the estimated memory used for the backbuffer and passes it to
1319 // the tracing system.
1320 void UpdateBackbufferMemoryAccounting();
1321
[email protected]38d139d2011-07-14 00:38:431322 // Returns true if the context was just lost due to e.g. GL_ARB_robustness.
1323 bool WasContextLost();
1324
[email protected]e51bdf32011-11-23 22:21:461325#if defined(OS_MACOSX)
1326 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1327#endif
1328
[email protected]81375742012-06-08 00:04:001329 // Validates the combination of texture parameters. For example validates that
1330 // for a given format the specific type, level and targets are valid.
1331 // Synthesizes the correct GL error if invalid. Returns true if valid.
1332 bool ValidateTextureParameters(
1333 const char* function_name,
1334 GLenum target, GLenum format, GLenum type, GLint level);
1335
[email protected]ad84a3a2012-06-08 21:42:431336 bool ValidateCompressedTexDimensions(
1337 const char* function_name,
1338 GLint level, GLsizei width, GLsizei height, GLenum format);
1339 bool ValidateCompressedTexFuncData(
1340 const char* function_name,
1341 GLsizei width, GLsizei height, GLenum format, size_t size);
1342 bool ValidateCompressedTexSubDimensions(
1343 const char* function_name,
1344 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1345 GLsizei width, GLsizei height, GLenum format,
1346 TextureManager::TextureInfo* texture);
1347
[email protected]0f8afe82012-05-14 23:43:011348 void LogMessage(const std::string& msg);
1349 void RenderWarning(const std::string& msg);
1350 void PerformanceWarning(const std::string& msg);
1351
[email protected]96449d2c2009-11-25 00:01:321352 // Generate a member function prototype for each command in an automated and
1353 // typesafe way.
1354 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141355 Error Handle ## name( \
[email protected]b9849abf2009-11-25 19:13:191356 uint32 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:321357 const gles2::name& args); \
1358
1359 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1360
1361 #undef GLES2_CMD_OP
1362
[email protected]2f2d7042010-04-14 21:45:581363 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381364 scoped_refptr<gfx::GLSurface> surface_;
1365 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021366
[email protected]a3ded6d2010-10-19 06:44:391367 // The ContextGroup for this decoder uses to track resources.
1368 ContextGroup::Ref group_;
1369
[email protected]6217d392010-03-25 22:08:351370 // A parent decoder can access this decoders saved offscreen frame buffer.
1371 // The parent pointer is reset if the parent is destroyed.
1372 base::WeakPtr<GLES2DecoderImpl> parent_;
1373
[email protected]34ff8b0c2010-10-01 20:06:021374 // Current width and height of the offscreen frame buffer.
1375 gfx::Size offscreen_size_;
1376
[email protected]96449d2c2009-11-25 00:01:321377 // Current GL error bits.
1378 uint32 error_bits_;
1379
[email protected]96449d2c2009-11-25 00:01:321380 // Util to help with GL.
1381 GLES2Util util_;
1382
1383 // pack alignment as last set by glPixelStorei
1384 GLint pack_alignment_;
1385
1386 // unpack alignment as last set by glPixelStorei
1387 GLint unpack_alignment_;
1388
[email protected]43410e92012-04-20 17:06:281389 // unpack flip y as last set by glPixelStorei
1390 bool unpack_flip_y_;
1391
[email protected]6c75c712012-06-19 15:43:171392 // unpack (un)premultiply alpha as last set by glPixelStorei
[email protected]43410e92012-04-20 17:06:281393 bool unpack_premultiply_alpha_;
[email protected]6c75c712012-06-19 15:43:171394 bool unpack_unpremultiply_alpha_;
[email protected]43410e92012-04-20 17:06:281395
[email protected]96449d2c2009-11-25 00:01:321396 // The currently bound array buffer. If this is 0 it is illegal to call
1397 // glVertexAttribPointer.
[email protected]3916c97e2010-02-25 03:20:501398 BufferManager::BufferInfo::Ref bound_array_buffer_;
[email protected]96449d2c2009-11-25 00:01:321399
1400 // The currently bound element array buffer. If this is 0 it is illegal
1401 // to call glDrawElements.
[email protected]3916c97e2010-02-25 03:20:501402 BufferManager::BufferInfo::Ref bound_element_array_buffer_;
[email protected]07f54fcc2009-12-22 02:46:301403
[email protected]f39f4b3f2010-05-12 17:04:081404 // Class that manages vertex attribs.
[email protected]3757a372012-01-19 05:20:441405 scoped_ptr<VertexAttribManager> vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301406
[email protected]b1122982010-05-17 23:04:241407 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1408 GLuint attrib_0_buffer_id_;
1409
1410 // The value currently in attrib_0.
1411 VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
1412
[email protected]fc753442011-02-04 19:49:491413 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1414 bool attrib_0_buffer_matches_value_;
1415
[email protected]b1122982010-05-17 23:04:241416 // The size of attrib 0.
1417 GLsizei attrib_0_size_;
1418
[email protected]8fbedc02010-11-18 18:43:401419 // The buffer used to simulate GL_FIXED attribs.
1420 GLuint fixed_attrib_buffer_id_;
1421
1422 // The size of fiixed attrib buffer.
1423 GLsizei fixed_attrib_buffer_size_;
1424
[email protected]3916c97e2010-02-25 03:20:501425 // Current active texture by 0 - n index.
1426 // In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
1427 // be 2.
1428 GLuint active_texture_unit_;
[email protected]07f54fcc2009-12-22 02:46:301429
[email protected]3916c97e2010-02-25 03:20:501430 // Which textures are bound to texture units through glActiveTexture.
1431 scoped_array<TextureUnit> texture_units_;
[email protected]a93bb842010-02-16 23:03:471432
[email protected]3a2e7c7b2010-08-06 01:12:281433 // state saved for clearing so we can clear render buffers and then
1434 // restore to these values.
1435 GLclampf clear_red_;
1436 GLclampf clear_green_;
1437 GLclampf clear_blue_;
1438 GLclampf clear_alpha_;
1439 GLboolean mask_red_;
1440 GLboolean mask_green_;
1441 GLboolean mask_blue_;
1442 GLboolean mask_alpha_;
1443 GLint clear_stencil_;
1444 GLuint mask_stencil_front_;
1445 GLuint mask_stencil_back_;
1446 GLclampf clear_depth_;
1447 GLboolean mask_depth_;
[email protected]0a1e9ad2012-05-04 21:13:031448 bool enable_blend_;
[email protected]43410e92012-04-20 17:06:281449 bool enable_cull_face_;
[email protected]3a2e7c7b2010-08-06 01:12:281450 bool enable_scissor_test_;
[email protected]297ca1c2011-06-20 23:08:461451 bool enable_depth_test_;
1452 bool enable_stencil_test_;
1453 bool state_dirty_;
[email protected]3a2e7c7b2010-08-06 01:12:281454
[email protected]1d32bc82010-01-13 22:06:461455 // The program in use by glUseProgram
[email protected]3916c97e2010-02-25 03:20:501456 ProgramManager::ProgramInfo::Ref current_program_;
[email protected]07f54fcc2009-12-22 02:46:301457
[email protected]8e3e0662010-08-23 18:46:301458 // The currently bound framebuffers
1459 FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
1460 FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
[email protected]86093972010-03-11 00:13:561461
1462 // The currently bound renderbuffer
[email protected]051b1372010-04-12 02:42:081463 RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
[email protected]86093972010-03-11 00:13:561464
[email protected]b9363b22010-06-09 22:06:151465 // The offscreen frame buffer that the client renders to. With EGL, the
1466 // depth and stencil buffers are separate. With regular GL there is a single
1467 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1468 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]6217d392010-03-25 22:08:351469 scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_;
1470 scoped_ptr<Texture> offscreen_target_color_texture_;
[email protected]34ff8b0c2010-10-01 20:06:021471 scoped_ptr<RenderBuffer> offscreen_target_color_render_buffer_;
[email protected]b9363b22010-06-09 22:06:151472 scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_;
1473 scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021474 GLenum offscreen_target_color_format_;
1475 GLenum offscreen_target_depth_format_;
1476 GLenum offscreen_target_stencil_format_;
1477 GLsizei offscreen_target_samples_;
[email protected]8a61d872012-01-20 12:43:561478 GLboolean offscreen_target_buffer_preserved_;
[email protected]6217d392010-03-25 22:08:351479
[email protected]de26b3c2011-08-03 21:54:271480 // The copy that is saved when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:021481 scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_;
[email protected]6217d392010-03-25 22:08:351482 scoped_ptr<Texture> offscreen_saved_color_texture_;
[email protected]8a61d872012-01-20 12:43:561483 TextureManager::TextureInfo::Ref offscreen_saved_color_texture_info_;
[email protected]de26b3c2011-08-03 21:54:271484
1485 // The copy that is used as the destination for multi-sample resolves.
1486 scoped_ptr<FrameBuffer> offscreen_resolved_frame_buffer_;
1487 scoped_ptr<Texture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051488 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351489
[email protected]882ba1e22012-03-08 19:02:531490 scoped_ptr<QueryManager> query_manager_;
1491 QueryManager::Query::Ref current_query_;
1492
[email protected]9d37f062011-11-22 01:24:521493 base::Callback<void(gfx::Size)> resize_callback_;
[email protected]22f320a2011-08-30 01:17:001494
[email protected]6b6e7ee2011-12-13 08:04:521495 MsgCallback msg_callback_;
[email protected]43f28f832010-02-03 02:28:481496
[email protected]b0af4f52011-09-28 22:04:421497 StreamTextureManager* stream_texture_manager_;
1498
[email protected]32fe9aa2011-01-21 23:47:131499 // The format of the back buffer_
1500 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461501 bool back_buffer_has_depth_;
1502 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131503
[email protected]473c01ccb2011-06-07 01:33:301504 bool teximage2d_faster_than_texsubimage2d_;
1505 bool bufferdata_faster_than_buffersubdata_;
1506
[email protected]8eee29c2010-04-29 03:38:291507 // The last error message set.
1508 std::string last_error_;
1509
[email protected]0f8afe82012-05-14 23:43:011510 int log_message_count_;
[email protected]fa20ec82012-05-04 04:02:481511
[email protected]a3a93e7b2010-08-28 00:48:561512 // The current decoder error.
1513 error::Error current_decoder_error_;
1514
[email protected]b1d2dcb2010-05-17 19:24:181515 bool use_shader_translator_;
[email protected]87fb6ab2012-06-13 22:28:041516 scoped_refptr<ShaderTranslator> vertex_translator_;
1517 scoped_refptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181518
[email protected]e82fb792011-09-22 00:33:291519 DisallowedFeatures disallowed_features_;
[email protected]c410da802011-03-14 19:17:411520
[email protected]915a59a12010-09-30 21:29:111521 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051522 const Validators* validators_;
[email protected]80eb6b52012-01-19 00:14:411523 FeatureInfo::Ref feature_info_;
[email protected]9438b012010-06-15 22:55:051524
[email protected]b493ee622011-04-13 23:52:001525 // This indicates all the following texSubImage2D calls that are part of the
1526 // failed texImage2D call should be ignored.
1527 bool tex_image_2d_failed_;
1528
[email protected]65225772011-05-12 21:10:241529 int frame_number_;
1530
[email protected]38d139d2011-07-14 00:38:431531 bool has_arb_robustness_;
1532 GLenum reset_status_;
1533
[email protected]75c023c2011-08-22 23:54:511534 bool needs_mac_nvidia_driver_workaround_;
[email protected]a2a0fe762011-09-20 00:59:121535 bool needs_glsl_built_in_function_emulation_;
[email protected]75c023c2011-08-22 23:54:511536
[email protected]f0d74742011-10-03 16:31:041537 // These flags are used to override the state of the shared feature_info_
1538 // member. Because the same FeatureInfo instance may be shared among many
1539 // contexts, the assumptions on the availablity of extensions in WebGL
1540 // contexts may be broken. These flags override the shared state to preserve
1541 // WebGL semantics.
1542 bool force_webgl_glsl_validation_;
1543 bool derivatives_explicitly_enabled_;
1544
[email protected]062c38b2012-01-18 03:25:101545 bool compile_shader_always_succeeds_;
1546
[email protected]c892a4e12012-05-08 18:20:191547 bool disable_workarounds_;
1548
[email protected]e51bdf32011-11-23 22:21:461549#if defined(OS_MACOSX)
1550 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1551 TextureToIOSurfaceMap texture_to_io_surface_map_;
1552#endif
1553
[email protected]c826d732012-02-09 04:40:261554 typedef std::vector<GLES2DecoderImpl*> ChildList;
1555 ChildList children_;
1556
[email protected]43410e92012-04-20 17:06:281557 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1558
1559 // Cached values of the currently assigned viewport dimensions.
1560 GLint viewport_x_, viewport_y_;
1561 GLsizei viewport_width_, viewport_height_;
1562 GLsizei viewport_max_width_, viewport_max_height_;
1563
[email protected]96449d2c2009-11-25 00:01:321564 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1565};
1566
[email protected]6217d392010-03-25 22:08:351567ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(GLES2DecoderImpl* decoder)
1568 : decoder_(decoder) {
1569 decoder_->CopyRealGLErrorsToWrapper();
1570}
1571
1572ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
1573 decoder_->ClearRealGLErrors();
1574}
1575
1576ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1577 GLuint id)
1578 : decoder_(decoder) {
1579 ScopedGLErrorSuppressor suppressor(decoder_);
1580
1581 // TODO(apatrick): Check if there are any other states that need to be reset
1582 // before binding a new texture.
1583 glActiveTexture(GL_TEXTURE0);
1584 glBindTexture(GL_TEXTURE_2D, id);
1585}
1586
1587ScopedTexture2DBinder::~ScopedTexture2DBinder() {
1588 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301589 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351590}
1591
1592ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1593 GLuint id)
1594 : decoder_(decoder) {
1595 ScopedGLErrorSuppressor suppressor(decoder_);
1596 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1597}
1598
1599ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
1600 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301601 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351602}
1603
1604ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1605 GLuint id)
1606 : decoder_(decoder) {
1607 ScopedGLErrorSuppressor suppressor(decoder_);
1608 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
1609}
1610
1611ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
1612 ScopedGLErrorSuppressor suppressor(decoder_);
[email protected]8e3e0662010-08-23 18:46:301613 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351614}
1615
[email protected]34ff8b0c2010-10-01 20:06:021616ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271617 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521618 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021619 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1620 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]c0701082011-04-20 00:34:521621 (!decoder_->bound_read_framebuffer_.get() ||
1622 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021623 if (!resolve_and_bind_)
1624 return;
1625
1626 ScopedGLErrorSuppressor suppressor(decoder_);
1627 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1628 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271629 GLuint targetid;
1630 if (internal) {
1631 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1632 decoder_->offscreen_resolved_frame_buffer_.reset(
1633 new FrameBuffer(decoder_));
1634 decoder_->offscreen_resolved_frame_buffer_->Create();
1635 decoder_->offscreen_resolved_color_texture_.reset(new Texture(decoder_));
1636 decoder_->offscreen_resolved_color_texture_->Create();
1637
1638 DCHECK(decoder_->offscreen_saved_color_format_);
1639 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
1640 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_);
[email protected]de26b3c2011-08-03 21:54:271641 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1642 decoder_->offscreen_resolved_color_texture_.get());
1643 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1644 GL_FRAMEBUFFER_COMPLETE) {
1645 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1646 << "because offscreen resolved FBO was incomplete.";
1647 return;
1648 }
1649 }
1650 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1651 } else {
1652 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1653 }
1654 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021655 const int width = decoder_->offscreen_size_.width();
1656 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181657 glDisable(GL_SCISSOR_TEST);
[email protected]57edfdad2012-02-07 04:57:151658 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021659 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1660 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1661 } else {
1662 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1663 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1664 }
[email protected]de26b3c2011-08-03 21:54:271665 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021666}
1667
1668ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1669 if (!resolve_and_bind_)
1670 return;
1671
1672 ScopedGLErrorSuppressor suppressor(decoder_);
1673 decoder_->RestoreCurrentFramebufferBindings();
[email protected]8c3e68782010-10-27 16:41:181674 if (decoder_->enable_scissor_test_) {
1675 glEnable(GL_SCISSOR_TEST);
1676 }
[email protected]34ff8b0c2010-10-01 20:06:021677}
1678
[email protected]6217d392010-03-25 22:08:351679Texture::Texture(GLES2DecoderImpl* decoder)
1680 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141681 id_(0),
1682 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351683}
1684
1685Texture::~Texture() {
1686 // This does not destroy the render texture because that would require that
1687 // the associated GL context was current. Just check that it was explicitly
1688 // destroyed.
1689 DCHECK_EQ(id_, 0u);
1690}
1691
1692void Texture::Create() {
1693 ScopedGLErrorSuppressor suppressor(decoder_);
1694 Destroy();
1695 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581696 ScopedTexture2DBinder binder(decoder_, id_);
1697 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1698 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1699 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1700 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]62788802011-10-03 17:57:161701
1702 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1703 // never called on an offscreen context, no data will ever be uploaded to the
1704 // saved offscreen color texture (it is deferred until to when SwapBuffers
1705 // is called). My idea is that some nvidia drivers might have a bug where
1706 // deleting a texture that has never been populated might cause a
1707 // crash.
1708 glTexImage2D(
1709 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
[email protected]1078f912011-12-23 13:12:141710 estimated_size_ = 16u * 16u * 4u;
1711 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351712}
1713
[email protected]34ff8b0c2010-10-01 20:06:021714bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351715 DCHECK_NE(id_, 0u);
1716 ScopedGLErrorSuppressor suppressor(decoder_);
1717 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]6217d392010-03-25 22:08:351718
[email protected]f0e6a34f2012-01-04 20:53:401719 WrappedTexImage2D(GL_TEXTURE_2D,
1720 0, // mip level
1721 format,
1722 size.width(),
1723 size.height(),
1724 0, // border
1725 format,
1726 GL_UNSIGNED_BYTE,
1727 NULL);
[email protected]6217d392010-03-25 22:08:351728
[email protected]d37231fa2010-04-09 21:16:021729 size_ = size;
1730
[email protected]1078f912011-12-23 13:12:141731 bool success = glGetError() == GL_NO_ERROR;
1732 if (success) {
1733 uint32 image_size = 0;
[email protected]3458a64a2012-04-10 17:39:341734 GLES2Util::ComputeImageDataSizes(
1735 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 4, &image_size,
1736 NULL, NULL);
[email protected]1078f912011-12-23 13:12:141737 estimated_size_ = image_size;
1738 decoder_->UpdateBackbufferMemoryAccounting();
1739 }
1740 return success;
[email protected]6217d392010-03-25 22:08:351741}
1742
[email protected]3a4d0c52011-06-29 23:11:581743void Texture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351744 DCHECK_NE(id_, 0u);
1745 ScopedGLErrorSuppressor suppressor(decoder_);
1746 ScopedTexture2DBinder binder(decoder_, id_);
1747 glCopyTexImage2D(GL_TEXTURE_2D,
1748 0, // level
[email protected]3a4d0c52011-06-29 23:11:581749 format,
[email protected]6217d392010-03-25 22:08:351750 0, 0,
1751 size.width(),
1752 size.height(),
1753 0); // border
1754}
1755
1756void Texture::Destroy() {
1757 if (id_ != 0) {
1758 ScopedGLErrorSuppressor suppressor(decoder_);
1759 glDeleteTextures(1, &id_);
1760 id_ = 0;
[email protected]1078f912011-12-23 13:12:141761 estimated_size_ = 0;
1762 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351763 }
1764}
1765
[email protected]97872062010-11-03 19:07:051766void Texture::Invalidate() {
1767 id_ = 0;
1768}
1769
[email protected]6217d392010-03-25 22:08:351770RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder)
1771 : decoder_(decoder),
[email protected]1078f912011-12-23 13:12:141772 id_(0),
1773 estimated_size_(0) {
[email protected]6217d392010-03-25 22:08:351774}
1775
1776RenderBuffer::~RenderBuffer() {
1777 // This does not destroy the render buffer because that would require that
1778 // the associated GL context was current. Just check that it was explicitly
1779 // destroyed.
1780 DCHECK_EQ(id_, 0u);
1781}
1782
1783void RenderBuffer::Create() {
1784 ScopedGLErrorSuppressor suppressor(decoder_);
1785 Destroy();
1786 glGenRenderbuffersEXT(1, &id_);
1787}
1788
[email protected]34ff8b0c2010-10-01 20:06:021789bool RenderBuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1790 GLsizei samples) {
[email protected]6217d392010-03-25 22:08:351791 ScopedGLErrorSuppressor suppressor(decoder_);
1792 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]34ff8b0c2010-10-01 20:06:021793 if (samples <= 1) {
1794 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1795 format,
1796 size.width(),
1797 size.height());
1798 } else {
[email protected]57edfdad2012-02-07 04:57:151799 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021800 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1801 samples,
1802 format,
1803 size.width(),
1804 size.height());
1805 } else {
1806 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1807 samples,
1808 format,
1809 size.width(),
1810 size.height());
1811 }
1812 }
[email protected]1078f912011-12-23 13:12:141813 bool success = glGetError() == GL_NO_ERROR;
1814 if (success) {
1815 estimated_size_ = size.width() * size.height() * samples *
1816 GLES2Util::RenderbufferBytesPerPixel(format);
1817 decoder_->UpdateBackbufferMemoryAccounting();
1818 }
1819 return success;
[email protected]6217d392010-03-25 22:08:351820}
1821
1822void RenderBuffer::Destroy() {
1823 if (id_ != 0) {
1824 ScopedGLErrorSuppressor suppressor(decoder_);
1825 glDeleteRenderbuffersEXT(1, &id_);
1826 id_ = 0;
[email protected]1078f912011-12-23 13:12:141827 estimated_size_ = 0;
1828 decoder_->UpdateBackbufferMemoryAccounting();
[email protected]6217d392010-03-25 22:08:351829 }
1830}
1831
[email protected]97872062010-11-03 19:07:051832void RenderBuffer::Invalidate() {
1833 id_ = 0;
1834}
1835
[email protected]6217d392010-03-25 22:08:351836FrameBuffer::FrameBuffer(GLES2DecoderImpl* decoder)
1837 : decoder_(decoder),
1838 id_(0) {
1839}
1840
1841FrameBuffer::~FrameBuffer() {
1842 // This does not destroy the frame buffer because that would require that
1843 // the associated GL context was current. Just check that it was explicitly
1844 // destroyed.
1845 DCHECK_EQ(id_, 0u);
1846}
1847
1848void FrameBuffer::Create() {
1849 ScopedGLErrorSuppressor suppressor(decoder_);
1850 Destroy();
1851 glGenFramebuffersEXT(1, &id_);
1852}
1853
1854void FrameBuffer::AttachRenderTexture(Texture* texture) {
1855 DCHECK_NE(id_, 0u);
1856 ScopedGLErrorSuppressor suppressor(decoder_);
1857 ScopedFrameBufferBinder binder(decoder_, id_);
1858 GLuint attach_id = texture ? texture->id() : 0;
1859 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
1860 GL_COLOR_ATTACHMENT0,
1861 GL_TEXTURE_2D,
1862 attach_id,
1863 0);
1864}
1865
[email protected]b9363b22010-06-09 22:06:151866void FrameBuffer::AttachRenderBuffer(GLenum target,
1867 RenderBuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:351868 DCHECK_NE(id_, 0u);
1869 ScopedGLErrorSuppressor suppressor(decoder_);
1870 ScopedFrameBufferBinder binder(decoder_, id_);
1871 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
1872 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:151873 target,
[email protected]6217d392010-03-25 22:08:351874 GL_RENDERBUFFER,
1875 attach_id);
1876}
1877
[email protected]6217d392010-03-25 22:08:351878void FrameBuffer::Destroy() {
1879 if (id_ != 0) {
1880 ScopedGLErrorSuppressor suppressor(decoder_);
1881 glDeleteFramebuffersEXT(1, &id_);
1882 id_ = 0;
1883 }
1884}
1885
[email protected]97872062010-11-03 19:07:051886void FrameBuffer::Invalidate() {
1887 id_ = 0;
1888}
1889
[email protected]6217d392010-03-25 22:08:351890GLenum FrameBuffer::CheckStatus() {
1891 DCHECK_NE(id_, 0u);
1892 ScopedGLErrorSuppressor suppressor(decoder_);
1893 ScopedFrameBufferBinder binder(decoder_, id_);
1894 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
1895}
1896
[email protected]aa7666122011-09-02 19:45:521897GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
1898 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:321899}
1900
[email protected]aa7666122011-09-02 19:45:521901GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:391902 : GLES2Decoder(),
[email protected]3b1ecc262011-08-03 22:49:571903 group_(group),
[email protected]96449d2c2009-11-25 00:01:321904 error_bits_(0),
[email protected]96449d2c2009-11-25 00:01:321905 pack_alignment_(4),
1906 unpack_alignment_(4),
[email protected]43410e92012-04-20 17:06:281907 unpack_flip_y_(false),
1908 unpack_premultiply_alpha_(false),
[email protected]6c75c712012-06-19 15:43:171909 unpack_unpremultiply_alpha_(false),
[email protected]b1122982010-05-17 23:04:241910 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:491911 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:241912 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:401913 fixed_attrib_buffer_id_(0),
1914 fixed_attrib_buffer_size_(0),
[email protected]3916c97e2010-02-25 03:20:501915 active_texture_unit_(0),
[email protected]3a2e7c7b2010-08-06 01:12:281916 clear_red_(0),
1917 clear_green_(0),
1918 clear_blue_(0),
1919 clear_alpha_(0),
1920 mask_red_(true),
1921 mask_green_(true),
1922 mask_blue_(true),
1923 mask_alpha_(true),
1924 clear_stencil_(0),
1925 mask_stencil_front_(-1),
1926 mask_stencil_back_(-1),
1927 clear_depth_(1.0f),
1928 mask_depth_(true),
[email protected]0a1e9ad2012-05-04 21:13:031929 enable_blend_(false),
[email protected]43410e92012-04-20 17:06:281930 enable_cull_face_(false),
[email protected]3a2e7c7b2010-08-06 01:12:281931 enable_scissor_test_(false),
[email protected]297ca1c2011-06-20 23:08:461932 enable_depth_test_(false),
1933 enable_stencil_test_(false),
1934 state_dirty_(true),
[email protected]34ff8b0c2010-10-01 20:06:021935 offscreen_target_color_format_(0),
1936 offscreen_target_depth_format_(0),
1937 offscreen_target_stencil_format_(0),
1938 offscreen_target_samples_(0),
[email protected]8a61d872012-01-20 12:43:561939 offscreen_target_buffer_preserved_(true),
[email protected]97872062010-11-03 19:07:051940 offscreen_saved_color_format_(0),
[email protected]b0af4f52011-09-28 22:04:421941 stream_texture_manager_(NULL),
[email protected]32fe9aa2011-01-21 23:47:131942 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:461943 back_buffer_has_depth_(false),
1944 back_buffer_has_stencil_(false),
[email protected]473c01ccb2011-06-07 01:33:301945 teximage2d_faster_than_texsubimage2d_(true),
1946 bufferdata_faster_than_buffersubdata_(true),
[email protected]0f8afe82012-05-14 23:43:011947 log_message_count_(0),
[email protected]a3a93e7b2010-08-28 00:48:561948 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:051949 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:111950 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:001951 feature_info_(group_->feature_info()),
[email protected]65225772011-05-12 21:10:241952 tex_image_2d_failed_(false),
[email protected]38d139d2011-07-14 00:38:431953 frame_number_(0),
1954 has_arb_robustness_(false),
[email protected]75c023c2011-08-22 23:54:511955 reset_status_(GL_NO_ERROR),
[email protected]a2a0fe762011-09-20 00:59:121956 needs_mac_nvidia_driver_workaround_(false),
[email protected]f0d74742011-10-03 16:31:041957 needs_glsl_built_in_function_emulation_(false),
1958 force_webgl_glsl_validation_(false),
[email protected]062c38b2012-01-18 03:25:101959 derivatives_explicitly_enabled_(false),
[email protected]43410e92012-04-20 17:06:281960 compile_shader_always_succeeds_(false),
[email protected]c892a4e12012-05-08 18:20:191961 disable_workarounds_(
1962 CommandLine::ForCurrentProcess()->HasSwitch(
1963 switches::kDisableGpuDriverBugWorkarounds)),
[email protected]43410e92012-04-20 17:06:281964 viewport_x_(0),
1965 viewport_y_(0),
1966 viewport_width_(0),
1967 viewport_height_(0),
1968 viewport_max_width_(0),
1969 viewport_max_height_(0) {
[email protected]3b1ecc262011-08-03 22:49:571970 DCHECK(group);
1971
[email protected]b1122982010-05-17 23:04:241972 attrib_0_value_.v[0] = 0.0f;
1973 attrib_0_value_.v[1] = 0.0f;
1974 attrib_0_value_.v[2] = 0.0f;
1975 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:151976
[email protected]c2f8c8402010-12-06 18:07:241977 // The shader translator is used for WebGL even when running on EGL
1978 // because additional restrictions are needed (like only enabling
1979 // GL_OES_standard_derivatives on demand). It is used for the unit
1980 // tests because
1981 // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the
1982 // empty string to CompileShader and this is not a valid shader.
1983 // TODO(apatrick): fix this test.
1984 if ((gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:041985 !feature_info_->feature_flags().chromium_webglsl &&
1986 !force_webgl_glsl_validation_) ||
[email protected]39ba4f02012-03-26 01:16:001987 gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
1988 CommandLine::ForCurrentProcess()->HasSwitch(
1989 switches::kDisableGLSLTranslator)) {
[email protected]b9363b22010-06-09 22:06:151990 use_shader_translator_ = false;
1991 }
[email protected]473c01ccb2011-06-07 01:33:301992
1993 // TODO(gman): Consider setting these based on GPU and/or driver.
1994 if (IsAngle()) {
1995 teximage2d_faster_than_texsubimage2d_ = false;
1996 bufferdata_faster_than_buffersubdata_ = false;
1997 }
[email protected]96449d2c2009-11-25 00:01:321998}
1999
[email protected]80eb6b52012-01-19 00:14:412000GLES2DecoderImpl::~GLES2DecoderImpl() {
2001}
2002
[email protected]c410da802011-03-14 19:17:412003bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:382004 const scoped_refptr<gfx::GLSurface>& surface,
2005 const scoped_refptr<gfx::GLContext>& context,
[email protected]069944672012-04-25 20:52:232006 bool offscreen,
[email protected]c410da802011-03-14 19:17:412007 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:292008 const DisallowedFeatures& disallowed_features,
[email protected]c410da802011-03-14 19:17:412009 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:242010 const std::vector<int32>& attribs) {
[email protected]3551cb202012-05-24 10:55:322011 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
[email protected]63c9b052012-05-17 18:27:382012 DCHECK(context->IsCurrent(surface.get()));
[email protected]66791e382010-07-14 20:48:302013 DCHECK(!context_.get());
2014
[email protected]e844ae22012-01-14 03:36:262015 if (CommandLine::ForCurrentProcess()->HasSwitch(
2016 switches::kEnableGPUDebugging)) {
2017 set_debug(true);
2018 }
2019
[email protected]39ba4f02012-03-26 01:16:002020 if (CommandLine::ForCurrentProcess()->HasSwitch(
2021 switches::kEnableGPUCommandLogging)) {
2022 set_log_commands(true);
2023 }
2024
[email protected]062c38b2012-01-18 03:25:102025 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2026 switches::kCompileShaderAlwaysSucceeds);
2027
[email protected]f62a5ab2011-05-23 20:34:152028
[email protected]63c9b052012-05-17 18:27:382029 // Take ownership of the context and surface. The surface can be replaced with
2030 // SetSurface.
[email protected]fbe20372011-06-01 01:46:382031 context_ = context;
[email protected]63c9b052012-05-17 18:27:382032 surface_ = surface;
[email protected]eb54a562010-01-20 21:55:182033
[email protected]e82fb792011-09-22 00:33:292034 if (!group_->Initialize(disallowed_features, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:222035 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:392036 << "failed to initialize.";
[email protected]1871a092011-10-10 21:46:422037 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]63c9b052012-05-17 18:27:382038 Destroy(true);
[email protected]ae1741092010-11-17 19:16:032039 return false;
[email protected]a3ded6d2010-10-19 06:44:392040 }
[email protected]b64c24952012-04-19 03:20:272041 CHECK_GL_ERROR();
[email protected]43410e92012-04-20 17:06:282042
[email protected]e82fb792011-09-22 00:33:292043 disallowed_features_ = disallowed_features;
[email protected]246a70452010-03-05 21:53:502044
[email protected]3757a372012-01-19 05:20:442045 vertex_attrib_manager_.reset(new VertexAttribManager());
2046 vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
[email protected]876f6fee2010-08-02 23:10:322047
[email protected]d6ca4792012-05-14 19:24:132048 query_manager_.reset(new QueryManager(this, feature_info_));
[email protected]882ba1e22012-03-08 19:02:532049
[email protected]302ce6d2011-07-07 23:28:112050 util_.set_num_compressed_texture_formats(
2051 validators_->compressed_texture_format.GetValues().size());
2052
[email protected]1071e572011-02-09 20:00:122053 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2054 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2055 // OpenGL ES 2.0 does not have this issue.
2056 glEnableVertexAttribArray(0);
2057 }
[email protected]b1122982010-05-17 23:04:242058 glGenBuffersARB(1, &attrib_0_buffer_id_);
2059 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2060 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2061 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:402062 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:082063
[email protected]246a70452010-03-05 21:53:502064 texture_units_.reset(
2065 new TextureUnit[group_->max_texture_units()]);
[email protected]1958e0e2010-04-22 05:17:152066 for (uint32 tt = 0; tt < group_->max_texture_units(); ++tt) {
[email protected]00f893d2010-08-24 18:55:492067 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:312068 // We want the last bind to be 2D.
2069 TextureManager::TextureInfo* info;
2070 if (feature_info_->feature_flags().oes_egl_image_external) {
2071 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_EXTERNAL_OES);
2072 texture_units_[tt].bound_texture_external_oes = info;
2073 glBindTexture(GL_TEXTURE_EXTERNAL_OES, info->service_id());
2074 }
[email protected]e51bdf32011-11-23 22:21:462075 if (feature_info_->feature_flags().arb_texture_rectangle) {
2076 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_RECTANGLE_ARB);
2077 texture_units_[tt].bound_texture_rectangle_arb = info;
2078 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, info->service_id());
2079 }
[email protected]61eeb33f2011-07-26 15:30:312080 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
[email protected]00f893d2010-08-24 18:55:492081 texture_units_[tt].bound_texture_cube_map = info;
2082 glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id());
2083 info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2084 texture_units_[tt].bound_texture_2d = info;
2085 glBindTexture(GL_TEXTURE_2D, info->service_id());
[email protected]1958e0e2010-04-22 05:17:152086 }
[email protected]00f893d2010-08-24 18:55:492087 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:502088 CHECK_GL_ERROR();
2089
[email protected]297ca1c2011-06-20 23:08:462090 ContextCreationAttribParser attrib_parser;
2091 if (!attrib_parser.Parse(attribs))
2092 return false;
[email protected]41c56362011-06-14 16:47:432093
[email protected]297ca1c2011-06-20 23:08:462094 // These are NOT if the back buffer has these proprorties. They are
2095 // if we want the command buffer to enforce them regardless of what
2096 // the real backbuffer is assuming the real back buffer gives us more than
2097 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2098 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2099 // can't do anything about that.
2100
2101 GLint v = 0;
2102 glGetIntegerv(GL_ALPHA_BITS, &v);
2103 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2104 // user requested RGB then RGB. If the user did not specify a preference than
2105 // use whatever we were given. Same for DEPTH and STENCIL.
2106 back_buffer_color_format_ =
2107 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2108 glGetIntegerv(GL_DEPTH_BITS, &v);
2109 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2110 glGetIntegerv(GL_STENCIL_BITS, &v);
2111 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
2112
[email protected]069944672012-04-25 20:52:232113 if (offscreen) {
[email protected]34ff8b0c2010-10-01 20:06:022114 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]53862ed2010-10-25 19:22:542115 (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
[email protected]34ff8b0c2010-10-01 20:06:022116 context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
2117 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:432118 // max_sample_count must be initialized to a sane value. If
2119 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2120 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:022121 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2122 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2123 max_sample_count);
2124 } else {
2125 offscreen_target_samples_ = 1;
2126 }
[email protected]8a61d872012-01-20 12:43:562127 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
[email protected]34ff8b0c2010-10-01 20:06:022128
2129 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2130 const bool rgb8_supported =
2131 context_->HasExtension("GL_OES_rgb8_rgba8");
2132 // The only available default render buffer formats in GLES2 have very
2133 // little precision. Don't enable multisampling unless 8-bit render
2134 // buffer formats are available--instead fall back to 8-bit textures.
2135 if (rgb8_supported && offscreen_target_samples_ > 1) {
2136 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2137 GL_RGBA8 : GL_RGB8;
2138 } else {
2139 offscreen_target_samples_ = 1;
2140 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2141 GL_RGBA : GL_RGB;
2142 }
2143
2144 // ANGLE only supports packed depth/stencil formats, so use it if it is
2145 // available.
2146 const bool depth24_stencil8_supported =
2147 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272148 VLOG(1) << "GL_OES_packed_depth_stencil "
2149 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:002150 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2151 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022152 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2153 offscreen_target_stencil_format_ = 0;
2154 } else {
2155 // It may be the case that this depth/stencil combination is not
2156 // supported, but this will be checked later by CheckFramebufferStatus.
2157 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2158 GL_DEPTH_COMPONENT16 : 0;
2159 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2160 GL_STENCIL_INDEX8 : 0;
2161 }
2162 } else {
2163 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2164 GL_RGBA : GL_RGB;
2165
2166 // If depth is requested at all, use the packed depth stencil format if
2167 // it's available, as some desktop GL drivers don't support any non-packed
2168 // formats for depth attachments.
2169 const bool depth24_stencil8_supported =
2170 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272171 VLOG(1) << "GL_EXT_packed_depth_stencil "
2172 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:022173
[email protected]71ee3642010-10-14 18:08:002174 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2175 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022176 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2177 offscreen_target_stencil_format_ = 0;
2178 } else {
2179 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2180 GL_DEPTH_COMPONENT : 0;
2181 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2182 GL_STENCIL_INDEX : 0;
2183 }
2184 }
2185
[email protected]97872062010-11-03 19:07:052186 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2187 GL_RGBA : GL_RGB;
2188
[email protected]6217d392010-03-25 22:08:352189 // Create the target frame buffer. This is the one that the client renders
2190 // directly to.
2191 offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
2192 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022193 // Due to GLES2 format limitations, either the color texture (for
2194 // non-multisampling) or the color render buffer (for multisampling) will be
2195 // attached to the offscreen frame buffer. The render buffer has more
2196 // limited formats available to it, but the texture can't do multisampling.
2197 if (IsOffscreenBufferMultisampled()) {
2198 offscreen_target_color_render_buffer_.reset(new RenderBuffer(this));
2199 offscreen_target_color_render_buffer_->Create();
2200 } else {
2201 offscreen_target_color_texture_.reset(new Texture(this));
2202 offscreen_target_color_texture_->Create();
2203 }
2204 offscreen_target_depth_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152205 offscreen_target_depth_render_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022206 offscreen_target_stencil_render_buffer_.reset(new RenderBuffer(this));
[email protected]b9363b22010-06-09 22:06:152207 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:352208
2209 // Create the saved offscreen texture. The target frame buffer is copied
2210 // here when SwapBuffers is called.
[email protected]34ff8b0c2010-10-01 20:06:022211 offscreen_saved_frame_buffer_.reset(new FrameBuffer(this));
2212 offscreen_saved_frame_buffer_->Create();
2213 //
[email protected]6217d392010-03-25 22:08:352214 offscreen_saved_color_texture_.reset(new Texture(this));
2215 offscreen_saved_color_texture_->Create();
2216
[email protected]6217d392010-03-25 22:08:352217 // Allocate the render buffers at their initial size and check the status
2218 // of the frame buffers is okay.
[email protected]799b4b22011-08-22 17:09:592219 if (!ResizeOffscreenFrameBuffer(size)) {
[email protected]d0498742010-09-20 20:27:012220 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]63c9b052012-05-17 18:27:382221 Destroy(true);
[email protected]6217d392010-03-25 22:08:352222 return false;
2223 }
2224
2225 // Bind to the new default frame buffer (the offscreen target frame buffer).
2226 // This should now be associated with ID zero.
2227 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2228 }
2229
[email protected]295faf4b2012-01-25 23:31:412230 // Clear the backbuffer.
2231 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2232
[email protected]76a0ee102010-04-07 21:03:042233 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2234 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2235 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372236 // mailing list archives. It also implicitly enables the desktop GL
2237 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2238 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152239 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2240 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372241 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152242 }
[email protected]de17df392010-04-23 21:09:412243
[email protected]38d139d2011-07-14 00:38:432244 has_arb_robustness_ = context->HasExtension("GL_ARB_robustness");
2245
[email protected]c892a4e12012-05-08 18:20:192246 if (!disable_workarounds_) {
[email protected]75c023c2011-08-22 23:54:512247#if defined(OS_MACOSX)
[email protected]a2a0fe762011-09-20 00:59:122248 needs_mac_nvidia_driver_workaround_ =
[email protected]5c67c7032012-05-15 18:21:222249 feature_info_->feature_flags().is_nvidia;
[email protected]a2a0fe762011-09-20 00:59:122250 needs_glsl_built_in_function_emulation_ =
[email protected]5c67c7032012-05-15 18:21:222251 feature_info_->feature_flags().is_amd;
[email protected]75c023c2011-08-22 23:54:512252#endif
[email protected]a2a0fe762011-09-20 00:59:122253 }
[email protected]75c023c2011-08-22 23:54:512254
[email protected]c2f8c8402010-12-06 18:07:242255 if (!InitializeShaderTranslator()) {
2256 return false;
[email protected]de17df392010-04-23 21:09:412257 }
[email protected]76a0ee102010-04-07 21:03:042258
[email protected]5904806b2012-05-08 18:10:222259 viewport_width_ = size.width();
2260 viewport_height_ = size.height();
2261 glViewport(viewport_x_, viewport_y_, viewport_width_, viewport_height_);
[email protected]43410e92012-04-20 17:06:282262
[email protected]5904806b2012-05-08 18:10:222263 GLint viewport_params[4] = { 0 };
[email protected]43410e92012-04-20 17:06:282264 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2265 viewport_max_width_ = viewport_params[0];
[email protected]5904806b2012-05-08 18:10:222266 viewport_max_height_ = viewport_params[1];
[email protected]43410e92012-04-20 17:06:282267
[email protected]246a70452010-03-05 21:53:502268 return true;
[email protected]96449d2c2009-11-25 00:01:322269}
2270
[email protected]302ce6d2011-07-07 23:28:112271void GLES2DecoderImpl::UpdateCapabilities() {
2272 util_.set_num_compressed_texture_formats(
2273 validators_->compressed_texture_format.GetValues().size());
2274 util_.set_num_shader_binary_formats(
2275 validators_->shader_binary_format.GetValues().size());
2276}
2277
[email protected]c2f8c8402010-12-06 18:07:242278bool GLES2DecoderImpl::InitializeShaderTranslator() {
[email protected]a5d3dad2012-05-26 04:34:442279 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2280
[email protected]c2f8c8402010-12-06 18:07:242281 // Re-check the state of use_shader_translator_ each time this is called.
2282 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
[email protected]f0d74742011-10-03 16:31:042283 (feature_info_->feature_flags().chromium_webglsl ||
2284 force_webgl_glsl_validation_) &&
[email protected]c2f8c8402010-12-06 18:07:242285 !use_shader_translator_) {
2286 use_shader_translator_ = true;
2287 }
2288 if (!use_shader_translator_) {
2289 return true;
2290 }
2291 ShBuiltInResources resources;
2292 ShInitBuiltInResources(&resources);
2293 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2294 resources.MaxVertexUniformVectors =
2295 group_->max_vertex_uniform_vectors();
2296 resources.MaxVaryingVectors = group_->max_varying_vectors();
2297 resources.MaxVertexTextureImageUnits =
2298 group_->max_vertex_texture_image_units();
2299 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2300 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2301 resources.MaxFragmentUniformVectors =
2302 group_->max_fragment_uniform_vectors();
2303 resources.MaxDrawBuffers = 1;
[email protected]f0d74742011-10-03 16:31:042304
2305 if (force_webgl_glsl_validation_) {
2306 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
2307 } else {
2308 resources.OES_standard_derivatives =
2309 feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0;
[email protected]e51bdf32011-11-23 22:21:462310 resources.ARB_texture_rectangle =
2311 feature_info_->feature_flags().arb_texture_rectangle ? 1 : 0;
[email protected]f0d74742011-10-03 16:31:042312 }
2313
[email protected]f0d74742011-10-03 16:31:042314 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ||
2315 feature_info_->feature_flags().chromium_webglsl ?
2316 SH_WEBGL_SPEC : SH_GLES2_SPEC;
[email protected]a2a0fe762011-09-20 00:59:122317 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2318 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2319 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2320 ShaderTranslatorInterface::GlslBuiltInFunctionBehavior function_behavior =
2321 needs_glsl_built_in_function_emulation_ ?
2322 ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated :
2323 ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal;
[email protected]87fb6ab2012-06-13 22:28:042324
2325 ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
2326 vertex_translator_ = cache->GetTranslator(
2327 SH_VERTEX_SHADER, shader_spec, &resources,
2328 implementation_type, function_behavior);
2329 if (!vertex_translator_.get()) {
[email protected]c2f8c8402010-12-06 18:07:242330 LOG(ERROR) << "Could not initialize vertex shader translator.";
[email protected]63c9b052012-05-17 18:27:382331 Destroy(true);
[email protected]c2f8c8402010-12-06 18:07:242332 return false;
2333 }
[email protected]87fb6ab2012-06-13 22:28:042334
2335 fragment_translator_ = cache->GetTranslator(
2336 SH_FRAGMENT_SHADER, shader_spec, &resources,
2337 implementation_type, function_behavior);
2338 if (!fragment_translator_.get()) {
[email protected]c2f8c8402010-12-06 18:07:242339 LOG(ERROR) << "Could not initialize fragment shader translator.";
[email protected]63c9b052012-05-17 18:27:382340 Destroy(true);
[email protected]c2f8c8402010-12-06 18:07:242341 return false;
2342 }
2343 return true;
2344}
2345
[email protected]ae51d192010-04-27 00:48:032346bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472347 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:032348 if (GetBufferInfo(client_ids[ii])) {
2349 return false;
2350 }
2351 }
2352 scoped_array<GLuint> service_ids(new GLuint[n]);
2353 glGenBuffersARB(n, service_ids.get());
2354 for (GLsizei ii = 0; ii < n; ++ii) {
2355 CreateBufferInfo(client_ids[ii], service_ids[ii]);
2356 }
2357 return true;
2358}
2359
2360bool GLES2DecoderImpl::GenFramebuffersHelper(
2361 GLsizei n, const GLuint* client_ids) {
2362 for (GLsizei ii = 0; ii < n; ++ii) {
2363 if (GetFramebufferInfo(client_ids[ii])) {
2364 return false;
2365 }
2366 }
2367 scoped_array<GLuint> service_ids(new GLuint[n]);
2368 glGenFramebuffersEXT(n, service_ids.get());
2369 for (GLsizei ii = 0; ii < n; ++ii) {
2370 CreateFramebufferInfo(client_ids[ii], service_ids[ii]);
2371 }
2372 return true;
2373}
2374
2375bool GLES2DecoderImpl::GenRenderbuffersHelper(
2376 GLsizei n, const GLuint* client_ids) {
2377 for (GLsizei ii = 0; ii < n; ++ii) {
2378 if (GetRenderbufferInfo(client_ids[ii])) {
2379 return false;
2380 }
2381 }
2382 scoped_array<GLuint> service_ids(new GLuint[n]);
2383 glGenRenderbuffersEXT(n, service_ids.get());
2384 for (GLsizei ii = 0; ii < n; ++ii) {
2385 CreateRenderbufferInfo(client_ids[ii], service_ids[ii]);
2386 }
2387 return true;
2388}
2389
2390bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2391 for (GLsizei ii = 0; ii < n; ++ii) {
2392 if (GetTextureInfo(client_ids[ii])) {
2393 return false;
2394 }
2395 }
2396 scoped_array<GLuint> service_ids(new GLuint[n]);
2397 glGenTextures(n, service_ids.get());
2398 for (GLsizei ii = 0; ii < n; ++ii) {
2399 CreateTextureInfo(client_ids[ii], service_ids[ii]);
2400 }
2401 return true;
2402}
2403
2404void GLES2DecoderImpl::DeleteBuffersHelper(
2405 GLsizei n, const GLuint* client_ids) {
2406 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102407 BufferManager::BufferInfo* buffer = GetBufferInfo(client_ids[ii]);
2408 if (buffer && !buffer->IsDeleted()) {
[email protected]3757a372012-01-19 05:20:442409 vertex_attrib_manager_->Unbind(buffer);
[email protected]a0b78dc2011-11-11 10:43:102410 if (bound_array_buffer_ == buffer) {
2411 bound_array_buffer_ = NULL;
2412 }
2413 if (bound_element_array_buffer_ == buffer) {
2414 bound_element_array_buffer_ = NULL;
2415 }
[email protected]ae51d192010-04-27 00:48:032416 RemoveBufferInfo(client_ids[ii]);
2417 }
[email protected]a93bb842010-02-16 23:03:472418 }
[email protected]07f54fcc2009-12-22 02:46:302419}
2420
[email protected]ae51d192010-04-27 00:48:032421void GLES2DecoderImpl::DeleteFramebuffersHelper(
2422 GLsizei n, const GLuint* client_ids) {
[email protected]b177ae22011-11-01 03:29:112423 bool supports_seperate_framebuffer_binds =
2424 feature_info_->feature_flags().chromium_framebuffer_multisample;
2425
[email protected]a25fa872010-03-25 02:57:582426 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102427 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]ae51d192010-04-27 00:48:032428 GetFramebufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102429 if (framebuffer && !framebuffer->IsDeleted()) {
2430 if (framebuffer == bound_draw_framebuffer_) {
[email protected]297ca1c2011-06-20 23:08:462431 bound_draw_framebuffer_ = NULL;
2432 state_dirty_ = true;
[email protected]b177ae22011-11-01 03:29:112433 GLenum target = supports_seperate_framebuffer_binds ?
2434 GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER;
2435 glBindFramebufferEXT(target, GetBackbufferServiceId());
2436 }
[email protected]a0b78dc2011-11-11 10:43:102437 if (framebuffer == bound_read_framebuffer_) {
[email protected]b177ae22011-11-01 03:29:112438 bound_read_framebuffer_ = NULL;
2439 GLenum target = supports_seperate_framebuffer_binds ?
2440 GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER;
2441 glBindFramebufferEXT(target, GetBackbufferServiceId());
[email protected]297ca1c2011-06-20 23:08:462442 }
[email protected]ae51d192010-04-27 00:48:032443 RemoveFramebufferInfo(client_ids[ii]);
2444 }
[email protected]a25fa872010-03-25 02:57:582445 }
[email protected]07f54fcc2009-12-22 02:46:302446}
2447
[email protected]ae51d192010-04-27 00:48:032448void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2449 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102450 bool supports_seperate_framebuffer_binds =
2451 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a25fa872010-03-25 02:57:582452 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102453 RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]ae51d192010-04-27 00:48:032454 GetRenderbufferInfo(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102455 if (renderbuffer && !renderbuffer->IsDeleted()) {
2456 if (bound_renderbuffer_ == renderbuffer) {
2457 bound_renderbuffer_ = NULL;
2458 }
2459 // Unbind from current framebuffers.
2460 if (supports_seperate_framebuffer_binds) {
2461 if (bound_read_framebuffer_) {
2462 bound_read_framebuffer_->UnbindRenderbuffer(
2463 GL_READ_FRAMEBUFFER, renderbuffer);
2464 }
2465 if (bound_draw_framebuffer_) {
2466 bound_draw_framebuffer_->UnbindRenderbuffer(
2467 GL_DRAW_FRAMEBUFFER, renderbuffer);
2468 }
2469 } else {
2470 if (bound_draw_framebuffer_) {
2471 bound_draw_framebuffer_->UnbindRenderbuffer(
2472 GL_FRAMEBUFFER, renderbuffer);
2473 }
2474 }
[email protected]297ca1c2011-06-20 23:08:462475 state_dirty_ = true;
[email protected]ae51d192010-04-27 00:48:032476 RemoveRenderbufferInfo(client_ids[ii]);
2477 }
[email protected]a25fa872010-03-25 02:57:582478 }
[email protected]07f54fcc2009-12-22 02:46:302479}
2480
[email protected]ae51d192010-04-27 00:48:032481void GLES2DecoderImpl::DeleteTexturesHelper(
2482 GLsizei n, const GLuint* client_ids) {
[email protected]a0b78dc2011-11-11 10:43:102483 bool supports_seperate_framebuffer_binds =
2484 feature_info_->feature_flags().chromium_framebuffer_multisample;
[email protected]a93bb842010-02-16 23:03:472485 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]a0b78dc2011-11-11 10:43:102486 TextureManager::TextureInfo* texture = GetTextureInfo(client_ids[ii]);
2487 if (texture && !texture->IsDeleted()) {
2488 if (texture->IsAttachedToFramebuffer()) {
[email protected]297ca1c2011-06-20 23:08:462489 state_dirty_ = true;
2490 }
[email protected]a0b78dc2011-11-11 10:43:102491 // Unbind texture from texture units.
2492 for (size_t jj = 0; jj < group_->max_texture_units(); ++jj) {
2493 texture_units_[ii].Unbind(texture);
2494 }
2495 // Unbind from current framebuffers.
2496 if (supports_seperate_framebuffer_binds) {
2497 if (bound_read_framebuffer_) {
2498 bound_read_framebuffer_->UnbindTexture(GL_READ_FRAMEBUFFER, texture);
2499 }
2500 if (bound_draw_framebuffer_) {
2501 bound_draw_framebuffer_->UnbindTexture(GL_DRAW_FRAMEBUFFER, texture);
2502 }
2503 } else {
2504 if (bound_draw_framebuffer_) {
2505 bound_draw_framebuffer_->UnbindTexture(GL_FRAMEBUFFER, texture);
2506 }
2507 }
2508 GLuint service_id = texture->service_id();
2509 if (texture->IsStreamTexture() && stream_texture_manager_) {
[email protected]b0af4f52011-09-28 22:04:422510 stream_texture_manager_->DestroyStreamTexture(service_id);
2511 }
[email protected]e51bdf32011-11-23 22:21:462512#if defined(OS_MACOSX)
2513 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2514 ReleaseIOSurfaceForTexture(service_id);
2515 }
2516#endif
[email protected]ae51d192010-04-27 00:48:032517 RemoveTextureInfo(client_ids[ii]);
2518 }
[email protected]a93bb842010-02-16 23:03:472519 }
[email protected]07f54fcc2009-12-22 02:46:302520}
2521
[email protected]43f28f832010-02-03 02:28:482522// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322523
[email protected]eb54a562010-01-20 21:55:182524bool GLES2DecoderImpl::MakeCurrent() {
[email protected]63c9b052012-05-17 18:27:382525 if (!context_.get() || !context_->MakeCurrent(surface_.get()))
2526 return false;
2527
2528 if (WasContextLost()) {
[email protected]38d139d2011-07-14 00:38:432529 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
[email protected]63c9b052012-05-17 18:27:382530 return false;
[email protected]38d139d2011-07-14 00:38:432531 }
2532
[email protected]63c9b052012-05-17 18:27:382533 return true;
[email protected]eb54a562010-01-20 21:55:182534}
2535
[email protected]a96a6022011-11-04 00:58:122536void GLES2DecoderImpl::ReleaseCurrent() {
2537 if (context_.get())
2538 context_->ReleaseCurrent(surface_.get());
2539}
2540
[email protected]8e3e0662010-08-23 18:46:302541void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
[email protected]0d6bfdc2011-11-02 01:32:202542 RenderbufferManager::RenderbufferInfo* renderbuffer =
2543 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
[email protected]8e3e0662010-08-23 18:46:302544 glBindRenderbufferEXT(
[email protected]0d6bfdc2011-11-02 01:32:202545 GL_RENDERBUFFER, renderbuffer ? renderbuffer->service_id() : 0);
[email protected]8e3e0662010-08-23 18:46:302546}
2547
2548static void RebindCurrentFramebuffer(
2549 GLenum target,
2550 FramebufferManager::FramebufferInfo* info,
[email protected]a3783712012-01-20 22:18:242551 GLuint back_buffer_service_id) {
[email protected]8e3e0662010-08-23 18:46:302552 GLuint framebuffer_id = info ? info->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462553
[email protected]a3783712012-01-20 22:18:242554 if (framebuffer_id == 0) {
2555 framebuffer_id = back_buffer_service_id;
[email protected]8e3e0662010-08-23 18:46:302556 }
[email protected]297ca1c2011-06-20 23:08:462557
[email protected]8e3e0662010-08-23 18:46:302558 glBindFramebufferEXT(target, framebuffer_id);
2559}
2560
2561void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]297ca1c2011-06-20 23:08:462562 state_dirty_ = true;
2563
[email protected]a3ded6d2010-10-19 06:44:392564 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302565 RebindCurrentFramebuffer(
2566 GL_FRAMEBUFFER,
2567 bound_draw_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242568 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302569 } else {
2570 RebindCurrentFramebuffer(
2571 GL_READ_FRAMEBUFFER_EXT,
2572 bound_read_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242573 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302574 RebindCurrentFramebuffer(
2575 GL_DRAW_FRAMEBUFFER_EXT,
2576 bound_draw_framebuffer_.get(),
[email protected]a3783712012-01-20 22:18:242577 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302578 }
2579}
2580
2581void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2582 GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
2583 GLuint last_id;
2584 if (info.bound_texture_2d) {
2585 last_id = info.bound_texture_2d->service_id();
2586 } else {
2587 last_id = 0;
2588 }
2589
2590 glBindTexture(GL_TEXTURE_2D, last_id);
2591 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
2592}
2593
[email protected]0d6bfdc2011-11-02 01:32:202594bool GLES2DecoderImpl::CheckFramebufferValid(
2595 FramebufferManager::FramebufferInfo* framebuffer,
2596 GLenum target, const char* func_name) {
[email protected]a0b78dc2011-11-11 10:43:102597 if (!framebuffer) {
[email protected]0d6bfdc2011-11-02 01:32:202598 return true;
2599 }
2600
[email protected]968351b2011-12-20 08:26:512601 if (framebuffer_manager()->IsComplete(framebuffer)) {
2602 return true;
2603 }
2604
[email protected]0d6bfdc2011-11-02 01:32:202605 GLenum completeness = framebuffer->IsPossiblyComplete();
2606 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
2607 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:432608 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
[email protected]3a03a8f2011-03-19 00:51:272609 return false;
2610 }
[email protected]0d6bfdc2011-11-02 01:32:202611
2612 // Are all the attachments cleared?
2613 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2614 texture_manager()->HaveUnclearedMips()) {
2615 if (!framebuffer->IsCleared()) {
2616 // Can we clear them?
2617 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2618 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:432619 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2620 "framebuffer incomplete (clear)");
[email protected]0d6bfdc2011-11-02 01:32:202621 return false;
2622 }
2623 ClearUnclearedAttachments(target, framebuffer);
2624 }
2625 }
2626
[email protected]968351b2011-12-20 08:26:512627 if (!framebuffer_manager()->IsComplete(framebuffer)) {
2628 if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
2629 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:432630 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2631 "framebuffer incomplete (check)");
[email protected]968351b2011-12-20 08:26:512632 return false;
2633 }
2634 framebuffer_manager()->MarkAsComplete(framebuffer);
2635 }
2636
[email protected]0d6bfdc2011-11-02 01:32:202637 // NOTE: At this point we don't know if the framebuffer is complete but
2638 // we DO know that everything that needs to be cleared has been cleared.
[email protected]3a03a8f2011-03-19 00:51:272639 return true;
2640}
2641
[email protected]0d6bfdc2011-11-02 01:32:202642bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
2643 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
2644 return CheckFramebufferValid(
2645 bound_draw_framebuffer_, GL_FRAMEBUFFER_EXT, func_name);
2646 }
2647 return CheckFramebufferValid(
2648 bound_draw_framebuffer_, GL_DRAW_FRAMEBUFFER_EXT, func_name) &&
2649 CheckFramebufferValid(
2650 bound_read_framebuffer_, GL_READ_FRAMEBUFFER_EXT, func_name);
2651}
2652
[email protected]8e3e0662010-08-23 18:46:302653gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
[email protected]0d6bfdc2011-11-02 01:32:202654 FramebufferManager::FramebufferInfo* framebuffer =
2655 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2656 if (framebuffer != NULL) {
[email protected]9edc6b22010-12-23 02:00:262657 const FramebufferManager::FramebufferInfo::Attachment* attachment =
[email protected]0d6bfdc2011-11-02 01:32:202658 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
[email protected]9edc6b22010-12-23 02:00:262659 if (attachment) {
2660 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502661 }
[email protected]9edc6b22010-12-23 02:00:262662 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022663 } else if (offscreen_target_frame_buffer_.get()) {
2664 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352665 } else {
[email protected]f62a5ab2011-05-23 20:34:152666 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022667 }
[email protected]246a70452010-03-05 21:53:502668}
2669
[email protected]9edc6b22010-12-23 02:00:262670GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202671 FramebufferManager::FramebufferInfo* framebuffer =
2672 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
2673 if (framebuffer != NULL) {
2674 return framebuffer->GetColorAttachmentFormat();
[email protected]297ca1c2011-06-20 23:08:462675 } else if (offscreen_target_frame_buffer_.get()) {
2676 return offscreen_target_color_format_;
2677 } else {
2678 return back_buffer_color_format_;
2679 }
2680}
2681
2682GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
[email protected]0d6bfdc2011-11-02 01:32:202683 FramebufferManager::FramebufferInfo* framebuffer =
2684 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
2685 if (framebuffer != NULL) {
2686 return framebuffer->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262687 } else if (offscreen_target_frame_buffer_.get()) {
2688 return offscreen_target_color_format_;
2689 } else {
[email protected]32fe9aa2011-01-21 23:47:132690 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262691 }
2692}
2693
[email protected]9a5afa432011-07-22 18:16:392694void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]34ff8b0c2010-10-01 20:06:022695 if (parent_) {
[email protected]2f2d7042010-04-14 21:45:582696 // Update the info about the offscreen saved color texture in the parent.
2697 // The reference to the parent is a weak pointer and will become null if the
2698 // parent is later destroyed.
[email protected]262d7aa2010-12-03 22:07:292699 TextureManager* parent_texture_manager = parent_->texture_manager();
[email protected]262d7aa2010-12-03 22:07:292700 parent_texture_manager->SetLevelInfo(
[email protected]8a61d872012-01-20 12:43:562701 offscreen_saved_color_texture_info_,
[email protected]ef526492010-06-02 23:12:252702 GL_TEXTURE_2D,
2703 0, // level
2704 GL_RGBA,
[email protected]799b4b22011-08-22 17:09:592705 offscreen_size_.width(),
2706 offscreen_size_.height(),
[email protected]ef526492010-06-02 23:12:252707 1, // depth
2708 0, // border
2709 GL_RGBA,
[email protected]0d6bfdc2011-11-02 01:32:202710 GL_UNSIGNED_BYTE,
2711 true);
[email protected]262d7aa2010-12-03 22:07:292712 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562713 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042714 GL_TEXTURE_MAG_FILTER,
2715 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292716 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562717 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042718 GL_TEXTURE_MIN_FILTER,
2719 GL_NEAREST);
[email protected]262d7aa2010-12-03 22:07:292720 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562721 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042722 GL_TEXTURE_WRAP_S,
2723 GL_CLAMP_TO_EDGE);
[email protected]262d7aa2010-12-03 22:07:292724 parent_texture_manager->SetParameter(
[email protected]8a61d872012-01-20 12:43:562725 offscreen_saved_color_texture_info_,
[email protected]8c515f82010-11-09 03:40:042726 GL_TEXTURE_WRAP_T,
2727 GL_CLAMP_TO_EDGE);
[email protected]8a61d872012-01-20 12:43:562728 } else {
2729 offscreen_saved_color_texture_info_ = NULL;
[email protected]0c8c9d22010-06-25 17:36:392730 }
[email protected]6217d392010-03-25 22:08:352731}
2732
[email protected]799b4b22011-08-22 17:09:592733void GLES2DecoderImpl::SetResizeCallback(
[email protected]9d37f062011-11-22 01:24:522734 const base::Callback<void(gfx::Size)>& callback) {
2735 resize_callback_ = callback;
[email protected]7ff86b92010-11-25 17:50:002736}
2737
[email protected]6b6e7ee2011-12-13 08:04:522738void GLES2DecoderImpl::SetMsgCallback(const MsgCallback& callback) {
2739 msg_callback_ = callback;
2740}
2741
[email protected]b0af4f52011-09-28 22:04:422742void GLES2DecoderImpl::SetStreamTextureManager(StreamTextureManager* manager) {
2743 stream_texture_manager_ = manager;
2744}
2745
[email protected]1318e922010-09-17 22:03:162746bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
2747 uint32* service_texture_id) {
2748 TextureManager::TextureInfo* texture =
2749 texture_manager()->GetTextureInfo(client_texture_id);
2750 if (texture) {
2751 *service_texture_id = texture->service_id();
2752 return true;
2753 }
2754 return false;
2755}
2756
[email protected]63c9b052012-05-17 18:27:382757void GLES2DecoderImpl::Destroy(bool have_context) {
2758 DCHECK(!have_context || context_->IsCurrent(NULL));
[email protected]97872062010-11-03 19:07:052759
[email protected]c826d732012-02-09 04:40:262760 ChildList children = children_;
2761 for (ChildList::iterator it = children.begin(); it != children.end(); ++it)
2762 (*it)->SetParent(NULL, 0);
2763 DCHECK(children_.empty());
[email protected]3c644d82011-06-20 19:58:242764 SetParent(NULL, 0);
2765
[email protected]80eb6b52012-01-19 00:14:412766 // Unbind everything.
[email protected]3757a372012-01-19 05:20:442767 vertex_attrib_manager_.reset();
[email protected]80eb6b52012-01-19 00:14:412768 texture_units_.reset();
2769 bound_array_buffer_ = NULL;
2770 bound_element_array_buffer_ = NULL;
[email protected]882ba1e22012-03-08 19:02:532771 current_query_ = NULL;
[email protected]80eb6b52012-01-19 00:14:412772 current_program_ = NULL;
2773 bound_read_framebuffer_ = NULL;
2774 bound_draw_framebuffer_ = NULL;
2775 bound_renderbuffer_ = NULL;
2776
[email protected]eadc96792010-10-27 19:39:392777 if (have_context) {
[email protected]c322e882012-05-23 18:06:182778 if (copy_texture_CHROMIUM_.get()) {
2779 copy_texture_CHROMIUM_->Destroy();
2780 copy_texture_CHROMIUM_.reset();
2781 }
[email protected]43410e92012-04-20 17:06:282782
[email protected]ca488e12010-12-13 20:06:142783 if (current_program_) {
2784 program_manager()->UnuseProgram(shader_manager(), current_program_);
2785 current_program_ = NULL;
2786 }
2787
[email protected]b1122982010-05-17 23:04:242788 if (attrib_0_buffer_id_) {
2789 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
2790 }
[email protected]8fbedc02010-11-18 18:43:402791 if (fixed_attrib_buffer_id_) {
2792 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
2793 }
[email protected]b1122982010-05-17 23:04:242794
[email protected]97872062010-11-03 19:07:052795 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:542796 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052797 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542798 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052799 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022800 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052801 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152802 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052803 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:152804 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052805 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:022806 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:052807 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:542808 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:272809 if (offscreen_resolved_frame_buffer_.get())
2810 offscreen_resolved_frame_buffer_->Destroy();
2811 if (offscreen_resolved_color_texture_.get())
2812 offscreen_resolved_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:052813 } else {
2814 if (offscreen_target_frame_buffer_.get())
2815 offscreen_target_frame_buffer_->Invalidate();
2816 if (offscreen_target_color_texture_.get())
2817 offscreen_target_color_texture_->Invalidate();
2818 if (offscreen_target_color_render_buffer_.get())
2819 offscreen_target_color_render_buffer_->Invalidate();
2820 if (offscreen_target_depth_render_buffer_.get())
2821 offscreen_target_depth_render_buffer_->Invalidate();
2822 if (offscreen_target_stencil_render_buffer_.get())
2823 offscreen_target_stencil_render_buffer_->Invalidate();
2824 if (offscreen_saved_frame_buffer_.get())
2825 offscreen_saved_frame_buffer_->Invalidate();
2826 if (offscreen_saved_color_texture_.get())
2827 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:272828 if (offscreen_resolved_frame_buffer_.get())
2829 offscreen_resolved_frame_buffer_->Invalidate();
2830 if (offscreen_resolved_color_texture_.get())
2831 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:022832 }
[email protected]43410e92012-04-20 17:06:282833 copy_texture_CHROMIUM_.reset();
[email protected]97872062010-11-03 19:07:052834
[email protected]882ba1e22012-03-08 19:02:532835 if (query_manager_.get()) {
2836 query_manager_->Destroy(have_context);
2837 query_manager_.reset();
2838 }
2839
[email protected]1871a092011-10-10 21:46:422840 if (group_) {
2841 group_->Destroy(have_context);
2842 group_ = NULL;
2843 }
[email protected]3ae019382011-10-05 19:42:412844
[email protected]fe871662011-06-16 20:43:052845 if (context_.get()) {
2846 context_->ReleaseCurrent(NULL);
[email protected]79311e82011-09-20 00:40:502847 context_ = NULL;
[email protected]fe871662011-06-16 20:43:052848 }
[email protected]0fc35742011-04-13 17:57:542849
[email protected]97872062010-11-03 19:07:052850 offscreen_target_frame_buffer_.reset();
2851 offscreen_target_color_texture_.reset();
2852 offscreen_target_color_render_buffer_.reset();
2853 offscreen_target_depth_render_buffer_.reset();
2854 offscreen_target_stencil_render_buffer_.reset();
2855 offscreen_saved_frame_buffer_.reset();
2856 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:272857 offscreen_resolved_frame_buffer_.reset();
2858 offscreen_resolved_color_texture_.reset();
[email protected]e51bdf32011-11-23 22:21:462859
2860#if defined(OS_MACOSX)
2861 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
2862 it != texture_to_io_surface_map_.end(); ++it) {
2863 CFRelease(it->second);
2864 }
2865 texture_to_io_surface_map_.clear();
2866#endif
[email protected]96449d2c2009-11-25 00:01:322867}
2868
[email protected]63c9b052012-05-17 18:27:382869void GLES2DecoderImpl::SetSurface(
2870 const scoped_refptr<gfx::GLSurface>& surface) {
2871 DCHECK(context_->IsCurrent(NULL));
2872 DCHECK(surface_.get());
2873 surface_ = surface;
2874 RestoreCurrentFramebufferBindings();
2875}
2876
[email protected]3c644d82011-06-20 19:58:242877bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent,
2878 uint32 new_parent_texture_id) {
[email protected]9a5afa432011-07-22 18:16:392879 if (!offscreen_saved_color_texture_.get())
2880 return false;
2881
[email protected]3c644d82011-06-20 19:58:242882 // Remove the saved frame buffer mapping from the parent decoder. The
2883 // parent pointer is a weak pointer so it will be null if the parent has
2884 // already been destroyed.
2885 if (parent_) {
[email protected]c826d732012-02-09 04:40:262886 ChildList::iterator it = std::find(
2887 parent_->children_.begin(),
2888 parent_->children_.end(),
2889 this);
2890 DCHECK(it != parent_->children_.end());
2891 parent_->children_.erase(it);
[email protected]3c644d82011-06-20 19:58:242892 // First check the texture has been mapped into the parent. This might not
2893 // be the case if initialization failed midway through.
2894 GLuint service_id = offscreen_saved_color_texture_->id();
2895 GLuint client_id = 0;
2896 if (parent_->texture_manager()->GetClientId(service_id, &client_id)) {
[email protected]80eb6b52012-01-19 00:14:412897 parent_->texture_manager()->RemoveTextureInfo(client_id);
[email protected]3c644d82011-06-20 19:58:242898 }
2899 }
2900
2901 GLES2DecoderImpl* new_parent_impl = static_cast<GLES2DecoderImpl*>(
2902 new_parent);
2903 if (new_parent_impl) {
[email protected]c826d732012-02-09 04:40:262904#ifndef NDEBUG
2905 ChildList::iterator it = std::find(
2906 new_parent_impl->children_.begin(),
2907 new_parent_impl->children_.end(),
2908 this);
2909 DCHECK(it == new_parent_impl->children_.end());
2910#endif
2911 new_parent_impl->children_.push_back(this);
[email protected]3c644d82011-06-20 19:58:242912 // Map the ID of the saved offscreen texture into the parent so that
2913 // it can reference it.
2914 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]98687862011-07-11 23:31:302915
2916 // Replace texture info when ID is already in use by parent.
2917 if (new_parent_impl->texture_manager()->GetTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412918 new_parent_texture_id))
[email protected]98687862011-07-11 23:31:302919 new_parent_impl->texture_manager()->RemoveTextureInfo(
[email protected]80eb6b52012-01-19 00:14:412920 new_parent_texture_id);
[email protected]98687862011-07-11 23:31:302921
[email protected]8a61d872012-01-20 12:43:562922 offscreen_saved_color_texture_info_ =
[email protected]5f4f2a732011-07-30 00:47:552923 new_parent_impl->CreateTextureInfo(new_parent_texture_id, service_id);
[email protected]8a61d872012-01-20 12:43:562924 offscreen_saved_color_texture_info_->SetNotOwned();
2925 new_parent_impl->texture_manager()->
2926 SetInfoTarget(offscreen_saved_color_texture_info_, GL_TEXTURE_2D);
[email protected]3c644d82011-06-20 19:58:242927
2928 parent_ = new_parent_impl->AsWeakPtr();
[email protected]9a5afa432011-07-22 18:16:392929
2930 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:242931 } else {
2932 parent_.reset();
[email protected]8a61d872012-01-20 12:43:562933 offscreen_saved_color_texture_info_ = NULL;
[email protected]3c644d82011-06-20 19:58:242934 }
2935
2936 return true;
2937}
2938
[email protected]1078f912011-12-23 13:12:142939void GLES2DecoderImpl::UpdateBackbufferMemoryAccounting() {
2940 size_t total = 0;
2941 if (offscreen_target_frame_buffer_.get()) {
2942 if (offscreen_target_color_texture_.get()) {
2943 total += offscreen_target_color_texture_->estimated_size();
2944 }
2945 if (offscreen_target_color_render_buffer_.get()) {
2946 total += offscreen_target_color_render_buffer_->estimated_size();
2947 }
2948 if (offscreen_target_depth_render_buffer_.get()) {
2949 total += offscreen_target_depth_render_buffer_->estimated_size();
2950 }
2951 if (offscreen_target_stencil_render_buffer_.get()) {
2952 total += offscreen_target_stencil_render_buffer_->estimated_size();
2953 }
2954 if (offscreen_saved_color_texture_.get()) {
2955 total += offscreen_saved_color_texture_->estimated_size();
2956 }
2957 if (offscreen_resolved_color_texture_.get()) {
2958 total += offscreen_resolved_color_texture_->estimated_size();
2959 }
2960 } else {
2961 gfx::Size size = surface_->GetSize();
2962 total += size.width() * size.height() *
2963 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_);
2964 }
2965 TRACE_COUNTER_ID1(
2966 "GLES2DecoderImpl", "BackbufferMemory", this, total);
2967}
2968
[email protected]799b4b22011-08-22 17:09:592969bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
2970 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
2971 if (!is_offscreen) {
2972 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
2973 << " with an onscreen framebuffer.";
2974 return false;
2975 }
2976
2977 if (offscreen_size_ == size)
2978 return true;
2979
2980 offscreen_size_ = size;
2981 int w = offscreen_size_.width();
2982 int h = offscreen_size_.height();
2983 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
2984 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2985 << "to allocate storage due to excessive dimensions.";
2986 return false;
2987 }
2988
2989 // Reallocate the offscreen target buffers.
2990 DCHECK(offscreen_target_color_format_);
2991 if (IsOffscreenBufferMultisampled()) {
2992 if (!offscreen_target_color_render_buffer_->AllocateStorage(
2993 offscreen_size_, offscreen_target_color_format_,
2994 offscreen_target_samples_)) {
2995 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
2996 << "to allocate storage for offscreen target color buffer.";
2997 return false;
2998 }
2999 } else {
3000 if (!offscreen_target_color_texture_->AllocateStorage(
3001 offscreen_size_, offscreen_target_color_format_)) {
3002 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3003 << "to allocate storage for offscreen target color texture.";
3004 return false;
3005 }
3006 }
3007 if (offscreen_target_depth_format_ &&
3008 !offscreen_target_depth_render_buffer_->AllocateStorage(
3009 offscreen_size_, offscreen_target_depth_format_,
3010 offscreen_target_samples_)) {
3011 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3012 << "to allocate storage for offscreen target depth buffer.";
3013 return false;
3014 }
3015 if (offscreen_target_stencil_format_ &&
3016 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3017 offscreen_size_, offscreen_target_stencil_format_,
3018 offscreen_target_samples_)) {
3019 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3020 << "to allocate storage for offscreen target stencil buffer.";
3021 return false;
3022 }
[email protected]1078f912011-12-23 13:12:143023 UpdateBackbufferMemoryAccounting();
[email protected]799b4b22011-08-22 17:09:593024
3025 // Attach the offscreen target buffers to the target frame buffer.
3026 if (IsOffscreenBufferMultisampled()) {
3027 offscreen_target_frame_buffer_->AttachRenderBuffer(
3028 GL_COLOR_ATTACHMENT0,
3029 offscreen_target_color_render_buffer_.get());
3030 } else {
3031 offscreen_target_frame_buffer_->AttachRenderTexture(
3032 offscreen_target_color_texture_.get());
3033 }
3034 if (offscreen_target_depth_format_) {
3035 offscreen_target_frame_buffer_->AttachRenderBuffer(
3036 GL_DEPTH_ATTACHMENT,
3037 offscreen_target_depth_render_buffer_.get());
3038 }
3039 const bool packed_depth_stencil =
3040 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3041 if (packed_depth_stencil) {
3042 offscreen_target_frame_buffer_->AttachRenderBuffer(
3043 GL_STENCIL_ATTACHMENT,
3044 offscreen_target_depth_render_buffer_.get());
3045 } else if (offscreen_target_stencil_format_) {
3046 offscreen_target_frame_buffer_->AttachRenderBuffer(
3047 GL_STENCIL_ATTACHMENT,
3048 offscreen_target_stencil_render_buffer_.get());
3049 }
3050
3051 if (offscreen_target_frame_buffer_->CheckStatus() !=
3052 GL_FRAMEBUFFER_COMPLETE) {
3053 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3054 << "because offscreen FBO was incomplete.";
3055 return false;
3056 }
3057
3058 // Clear the target frame buffer.
3059 {
3060 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3061 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3062 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3063 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3064 glClearStencil(0);
3065 glStencilMaskSeparate(GL_FRONT, -1);
3066 glStencilMaskSeparate(GL_BACK, -1);
3067 glClearDepth(0);
3068 glDepthMask(GL_TRUE);
3069 glDisable(GL_SCISSOR_TEST);
3070 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3071 RestoreClearState();
3072 }
[email protected]d85ef76d2011-09-08 22:21:433073
3074 // Destroy the offscreen resolved framebuffers.
3075 if (offscreen_resolved_frame_buffer_.get())
3076 offscreen_resolved_frame_buffer_->Destroy();
3077 if (offscreen_resolved_color_texture_.get())
3078 offscreen_resolved_color_texture_->Destroy();
3079 offscreen_resolved_color_texture_.reset();
3080 offscreen_resolved_frame_buffer_.reset();
3081
[email protected]799b4b22011-08-22 17:09:593082 return true;
[email protected]6217d392010-03-25 22:08:353083}
3084
[email protected]799b4b22011-08-22 17:09:593085error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
3086 uint32 immediate_data_size, const gles2::ResizeCHROMIUM& c) {
3087 GLuint width = static_cast<GLuint>(c.width);
3088 GLuint height = static_cast<GLuint>(c.height);
3089 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
[email protected]a0d989162011-11-22 13:15:073090#if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3091 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
[email protected]7ff86b92010-11-25 17:50:003092 // Make sure that we are done drawing to the back buffer before resizing.
3093 glFinish();
3094#endif
[email protected]799b4b22011-08-22 17:09:593095 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3096 if (is_offscreen) {
[email protected]7794d512012-04-17 20:36:493097 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3098 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3099 << "ResizeOffscreenFrameBuffer failed.";
[email protected]799b4b22011-08-22 17:09:593100 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:493101 }
[email protected]7ff86b92010-11-25 17:50:003102 }
[email protected]799b4b22011-08-22 17:09:593103
[email protected]9d37f062011-11-22 01:24:523104 if (!resize_callback_.is_null()) {
3105 resize_callback_.Run(gfx::Size(width, height));
[email protected]c777de52011-09-09 23:08:563106 DCHECK(context_->IsCurrent(surface_.get()));
[email protected]7794d512012-04-17 20:36:493107 if (!context_->IsCurrent(surface_.get())) {
3108 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3109 << "current after resize callback.";
[email protected]658f7562011-09-09 05:24:053110 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:493111 }
[email protected]658f7562011-09-09 05:24:053112 }
[email protected]799b4b22011-08-22 17:09:593113
[email protected]1078f912011-12-23 13:12:143114 UpdateBackbufferMemoryAccounting();
3115
[email protected]799b4b22011-08-22 17:09:593116 return error::kNoError;
[email protected]43ecf372010-11-16 19:19:393117}
3118
[email protected]96449d2c2009-11-25 00:01:323119const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3120 if (command_id > kStartPoint && command_id < kNumCommands) {
3121 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3122 }
3123 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3124}
3125
3126// Decode command with its arguments, and call the corresponding GL function.
3127// Note: args is a pointer to the command buffer. As such, it could be changed
3128// by a (malicious) client at any time, so if validation has to happen, it
3129// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:143130error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:323131 unsigned int command,
3132 unsigned int arg_count,
3133 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:143134 error::Error result = error::kNoError;
[email protected]e844ae22012-01-14 03:36:263135 if (log_commands()) {
[email protected]39ba4f02012-03-26 01:16:003136 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3137 // LOG(INFO), tried VLOG(1), no luck.
3138 LOG(ERROR) << "[" << this << "]" << "cmd: " << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193139 }
[email protected]96449d2c2009-11-25 00:01:323140 unsigned int command_index = command - kStartPoint - 1;
3141 if (command_index < arraysize(g_command_info)) {
3142 const CommandInfo& info = g_command_info[command_index];
3143 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3144 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3145 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:193146 uint32 immediate_data_size =
3147 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:323148 switch (command) {
3149 #define GLES2_CMD_OP(name) \
3150 case name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:193151 result = Handle ## name( \
3152 immediate_data_size, \
[email protected]96449d2c2009-11-25 00:01:323153 *static_cast<const name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:193154 break; \
[email protected]96449d2c2009-11-25 00:01:323155
3156 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:323157 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:383158 }
3159 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:303160 GLenum error;
3161 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]39ba4f02012-03-26 01:16:003162 LOG(ERROR) << "[" << this << "] "
3163 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3164 << GetCommandName(command);
[email protected]ad84a3a2012-06-08 21:42:433165 SetGLError(error, "DoCommand", "GL error from driver");
[email protected]b9849abf2009-11-25 19:13:193166 }
[email protected]96449d2c2009-11-25 00:01:323167 }
3168 } else {
[email protected]f7a64ee2010-02-01 22:24:143169 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:323170 }
[email protected]b9849abf2009-11-25 19:13:193171 } else {
3172 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:323173 }
[email protected]a3a93e7b2010-08-28 00:48:563174 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3175 result = current_decoder_error_;
3176 current_decoder_error_ = error::kNoError;
3177 }
[email protected]b9849abf2009-11-25 19:13:193178 return result;
[email protected]96449d2c2009-11-25 00:01:323179}
3180
[email protected]ae51d192010-04-27 00:48:033181void GLES2DecoderImpl::RemoveBufferInfo(GLuint client_id) {
3182 buffer_manager()->RemoveBufferInfo(client_id);
[email protected]3916c97e2010-02-25 03:20:503183}
3184
[email protected]ae51d192010-04-27 00:48:033185bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
3186 if (GetProgramInfo(client_id)) {
3187 return false;
3188 }
[email protected]96449d2c2009-11-25 00:01:323189 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:033190 if (service_id != 0) {
3191 CreateProgramInfo(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:323192 }
[email protected]ae51d192010-04-27 00:48:033193 return true;
[email protected]96449d2c2009-11-25 00:01:323194}
3195
[email protected]ae51d192010-04-27 00:48:033196bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
3197 if (GetShaderInfo(client_id)) {
3198 return false;
[email protected]96449d2c2009-11-25 00:01:323199 }
[email protected]ae51d192010-04-27 00:48:033200 GLuint service_id = glCreateShader(type);
3201 if (service_id != 0) {
[email protected]7cea56d92010-04-28 17:21:383202 CreateShaderInfo(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:033203 }
3204 return true;
[email protected]96449d2c2009-11-25 00:01:323205}
3206
[email protected]882ba1e22012-03-08 19:02:533207void GLES2DecoderImpl::DoFinish() {
3208 glFinish();
[email protected]22e3f552012-03-13 01:54:193209 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533210}
3211
3212void GLES2DecoderImpl::DoFlush() {
3213 glFlush();
[email protected]22e3f552012-03-13 01:54:193214 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533215}
3216
[email protected]3916c97e2010-02-25 03:20:503217void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:453218 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]660858b2011-07-13 23:16:143219 if (texture_index >= group_->max_texture_units()) {
[email protected]ad84a3a2012-06-08 21:42:433220 SetGLError(
3221 GL_INVALID_ENUM, "glActiveTexture", "texture_unit out of range.");
[email protected]3916c97e2010-02-25 03:20:503222 return;
3223 }
[email protected]36cef8ce2010-03-16 07:34:453224 active_texture_unit_ = texture_index;
3225 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:503226}
3227
[email protected]051b1372010-04-12 02:42:083228void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]3916c97e2010-02-25 03:20:503229 BufferManager::BufferInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083230 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033231 if (client_id != 0) {
3232 info = GetBufferInfo(client_id);
3233 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353234 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153235 LOG(ERROR) << "glBindBuffer: id not generated by glGenBuffers";
3236 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353237 return;
3238 }
3239
[email protected]ae51d192010-04-27 00:48:033240 // It's a new id so make a buffer info for it.
3241 glGenBuffersARB(1, &service_id);
3242 CreateBufferInfo(client_id, service_id);
3243 info = GetBufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573244 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103245 group_->GetIdAllocator(id_namespaces::kBuffers);
3246 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033247 }
[email protected]051b1372010-04-12 02:42:083248 }
[email protected]ae51d192010-04-27 00:48:033249 if (info) {
[email protected]4e8a5b122010-05-08 22:00:103250 if (!buffer_manager()->SetTarget(info, target)) {
[email protected]8eee29c2010-04-29 03:38:293251 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:433252 "glBindBuffer", "buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:473253 return;
3254 }
[email protected]ae51d192010-04-27 00:48:033255 service_id = info->service_id();
[email protected]a93bb842010-02-16 23:03:473256 }
[email protected]96449d2c2009-11-25 00:01:323257 switch (target) {
3258 case GL_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503259 bound_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323260 break;
3261 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]3916c97e2010-02-25 03:20:503262 bound_element_array_buffer_ = info;
[email protected]96449d2c2009-11-25 00:01:323263 break;
3264 default:
[email protected]a93bb842010-02-16 23:03:473265 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:323266 break;
3267 }
[email protected]051b1372010-04-12 02:42:083268 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:323269}
3270
[email protected]297ca1c2011-06-20 23:08:463271bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
3272 return (GLES2Util::GetChannelsForFormat(
3273 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3274}
3275
3276bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203277 FramebufferManager::FramebufferInfo* framebuffer =
3278 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3279 if (framebuffer) {
3280 return framebuffer->HasDepthAttachment();
[email protected]297ca1c2011-06-20 23:08:463281 }
3282 if (offscreen_target_frame_buffer_.get()) {
3283 return offscreen_target_depth_format_ != 0;
3284 }
3285 return back_buffer_has_depth_;
3286}
3287
3288bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
[email protected]0d6bfdc2011-11-02 01:32:203289 FramebufferManager::FramebufferInfo* framebuffer =
3290 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3291 if (framebuffer) {
3292 return framebuffer->HasStencilAttachment();
[email protected]297ca1c2011-06-20 23:08:463293 }
3294 if (offscreen_target_frame_buffer_.get()) {
3295 return offscreen_target_stencil_format_ != 0 ||
3296 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3297 }
3298 return back_buffer_has_stencil_;
3299}
3300
3301void GLES2DecoderImpl::ApplyDirtyState() {
3302 if (state_dirty_) {
3303 glColorMask(
3304 mask_red_, mask_green_, mask_blue_,
3305 mask_alpha_ && BoundFramebufferHasColorAttachmentWithAlpha());
3306 bool have_depth = BoundFramebufferHasDepthAttachment();
3307 glDepthMask(mask_depth_ && have_depth);
3308 EnableDisable(GL_DEPTH_TEST, enable_depth_test_ && have_depth);
3309 bool have_stencil = BoundFramebufferHasStencilAttachment();
3310 glStencilMaskSeparate(GL_FRONT, have_stencil ? mask_stencil_front_ : 0);
3311 glStencilMaskSeparate(GL_BACK, have_stencil ? mask_stencil_back_ : 0);
3312 EnableDisable(GL_STENCIL_TEST, enable_stencil_test_ && have_stencil);
[email protected]43410e92012-04-20 17:06:283313 EnableDisable(GL_CULL_FACE, enable_cull_face_);
3314 EnableDisable(GL_SCISSOR_TEST, enable_scissor_test_);
[email protected]0a1e9ad2012-05-04 21:13:033315 EnableDisable(GL_BLEND, enable_blend_);
[email protected]297ca1c2011-06-20 23:08:463316 state_dirty_ = false;
3317 }
3318}
3319
[email protected]78b514b2012-05-01 21:50:593320void GLES2DecoderImpl::BindAndApplyTextureParameters(
3321 TextureManager::TextureInfo* info) {
3322 glBindTexture(info->target(), info->service_id());
3323 glTexParameteri(info->target(), GL_TEXTURE_MIN_FILTER, info->min_filter());
3324 glTexParameteri(info->target(), GL_TEXTURE_MAG_FILTER, info->mag_filter());
3325 glTexParameteri(info->target(), GL_TEXTURE_WRAP_S, info->wrap_s());
3326 glTexParameteri(info->target(), GL_TEXTURE_WRAP_T, info->wrap_t());
3327}
3328
[email protected]b177ae22011-11-01 03:29:113329GLuint GLES2DecoderImpl::GetBackbufferServiceId() {
3330 return (offscreen_target_frame_buffer_.get()) ?
3331 offscreen_target_frame_buffer_->id() :
3332 surface_->GetBackingFrameBufferObject();
3333}
3334
[email protected]051b1372010-04-12 02:42:083335void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
3336 FramebufferManager::FramebufferInfo* info = NULL;
3337 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033338 if (client_id != 0) {
3339 info = GetFramebufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083340 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353341 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153342 LOG(ERROR)
3343 << "glBindFramebuffer: id not generated by glGenFramebuffers";
3344 current_decoder_error_ = error::kGenericError;
3345 return;
[email protected]bf5a8d132011-08-16 08:39:353346 }
3347
[email protected]ae51d192010-04-27 00:48:033348 // It's a new id so make a framebuffer info for it.
3349 glGenFramebuffersEXT(1, &service_id);
3350 CreateFramebufferInfo(client_id, service_id);
3351 info = GetFramebufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573352 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103353 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3354 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033355 } else {
3356 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083357 }
[email protected]06c8b082011-01-05 18:00:363358 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083359 }
[email protected]8e3e0662010-08-23 18:46:303360
3361 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
3362 bound_draw_framebuffer_ = info;
3363 }
3364 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
3365 bound_read_framebuffer_ = info;
3366 }
[email protected]6217d392010-03-25 22:08:353367
[email protected]297ca1c2011-06-20 23:08:463368 state_dirty_ = true;
3369
[email protected]b177ae22011-11-01 03:29:113370 // If we are rendering to the backbuffer get the FBO id for any simulated
3371 // backbuffer.
3372 if (info == NULL) {
3373 service_id = GetBackbufferServiceId();
[email protected]297ca1c2011-06-20 23:08:463374 }
[email protected]6217d392010-03-25 22:08:353375
[email protected]051b1372010-04-12 02:42:083376 glBindFramebufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563377}
3378
[email protected]051b1372010-04-12 02:42:083379void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
3380 RenderbufferManager::RenderbufferInfo* info = NULL;
3381 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033382 if (client_id != 0) {
3383 info = GetRenderbufferInfo(client_id);
[email protected]051b1372010-04-12 02:42:083384 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353385 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153386 LOG(ERROR)
3387 << "glBindRenderbuffer: id not generated by glGenRenderbuffers";
3388 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353389 return;
3390 }
3391
[email protected]ae51d192010-04-27 00:48:033392 // It's a new id so make a renderbuffer info for it.
3393 glGenRenderbuffersEXT(1, &service_id);
3394 CreateRenderbufferInfo(client_id, service_id);
[email protected]066849e32010-05-03 19:14:103395 info = GetRenderbufferInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573396 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103397 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3398 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033399 } else {
3400 service_id = info->service_id();
[email protected]051b1372010-04-12 02:42:083401 }
[email protected]06c8b082011-01-05 18:00:363402 info->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083403 }
3404 bound_renderbuffer_ = info;
3405 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563406}
3407
[email protected]051b1372010-04-12 02:42:083408void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]ae51d192010-04-27 00:48:033409 TextureManager::TextureInfo* info = NULL;
[email protected]051b1372010-04-12 02:42:083410 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033411 if (client_id != 0) {
3412 info = GetTextureInfo(client_id);
3413 if (!info) {
[email protected]bf5a8d132011-08-16 08:39:353414 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153415 LOG(ERROR) << "glBindTexture: id not generated by glGenTextures";
3416 current_decoder_error_ = error::kGenericError;
3417 return;
[email protected]bf5a8d132011-08-16 08:39:353418 }
3419
[email protected]ae51d192010-04-27 00:48:033420 // It's a new id so make a texture info for it.
3421 glGenTextures(1, &service_id);
[email protected]80eb6b52012-01-19 00:14:413422 DCHECK_NE(0u, service_id);
[email protected]ae51d192010-04-27 00:48:033423 CreateTextureInfo(client_id, service_id);
3424 info = GetTextureInfo(client_id);
[email protected]3b1ecc262011-08-03 22:49:573425 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103426 group_->GetIdAllocator(id_namespaces::kTextures);
3427 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033428 }
3429 } else {
3430 info = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:083431 }
[email protected]ae51d192010-04-27 00:48:033432
[email protected]1958e0e2010-04-22 05:17:153433 // Check the texture exists
3434 // Check that we are not trying to bind it to a different target.
[email protected]ae51d192010-04-27 00:48:033435 if (info->target() != 0 && info->target() != target) {
[email protected]8eee29c2010-04-29 03:38:293436 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:433437 "glBindTexture", "texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:153438 return;
3439 }
[email protected]b0af4f52011-09-28 22:04:423440 if (info->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
3441 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:433442 "glBindTexture", "illegal target for stream texture.");
[email protected]b0af4f52011-09-28 22:04:423443 return;
3444 }
[email protected]1958e0e2010-04-22 05:17:153445 if (info->target() == 0) {
[email protected]80eb6b52012-01-19 00:14:413446 texture_manager()->SetInfoTarget(info, target);
[email protected]a93bb842010-02-16 23:03:473447 }
[email protected]ae51d192010-04-27 00:48:033448 glBindTexture(target, info->service_id());
[email protected]3916c97e2010-02-25 03:20:503449 TextureUnit& unit = texture_units_[active_texture_unit_];
3450 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:473451 switch (target) {
3452 case GL_TEXTURE_2D:
[email protected]3916c97e2010-02-25 03:20:503453 unit.bound_texture_2d = info;
[email protected]a93bb842010-02-16 23:03:473454 break;
3455 case GL_TEXTURE_CUBE_MAP:
[email protected]3916c97e2010-02-25 03:20:503456 unit.bound_texture_cube_map = info;
[email protected]a93bb842010-02-16 23:03:473457 break;
[email protected]61eeb33f2011-07-26 15:30:313458 case GL_TEXTURE_EXTERNAL_OES:
3459 unit.bound_texture_external_oes = info;
[email protected]b0af4f52011-09-28 22:04:423460 if (info->IsStreamTexture()) {
3461 DCHECK(stream_texture_manager_);
3462 StreamTexture* stream_tex =
3463 stream_texture_manager_->LookupStreamTexture(info->service_id());
3464 if (stream_tex)
3465 stream_tex->Update();
3466 }
[email protected]61eeb33f2011-07-26 15:30:313467 break;
[email protected]e51bdf32011-11-23 22:21:463468 case GL_TEXTURE_RECTANGLE_ARB:
3469 unit.bound_texture_rectangle_arb = info;
3470 break;
[email protected]a93bb842010-02-16 23:03:473471 default:
3472 NOTREACHED(); // Validation should prevent us getting here.
3473 break;
3474 }
3475}
3476
[email protected]07f54fcc2009-12-22 02:46:303477void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443478 if (vertex_attrib_manager_->Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:123479 if (index != 0 ||
3480 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:243481 glDisableVertexAttribArray(index);
3482 }
[email protected]07f54fcc2009-12-22 02:46:303483 } else {
[email protected]8eee29c2010-04-29 03:38:293484 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:433485 "glDisableVertexAttribArray", "index out of range");
[email protected]07f54fcc2009-12-22 02:46:303486 }
3487}
3488
3489void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]3757a372012-01-19 05:20:443490 if (vertex_attrib_manager_->Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:303491 glEnableVertexAttribArray(index);
3492 } else {
[email protected]8eee29c2010-04-29 03:38:293493 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:433494 "glEnableVertexAttribArray", "index out of range");
[email protected]07f54fcc2009-12-22 02:46:303495 }
3496}
3497
[email protected]a93bb842010-02-16 23:03:473498void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]3916c97e2010-02-25 03:20:503499 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]97dc7cbe2011-12-06 17:26:173500 if (!info ||
[email protected]38c0a972012-05-12 00:48:023501 !texture_manager()->CanGenerateMipmaps(info)) {
[email protected]8eee29c2010-04-29 03:38:293502 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:433503 "glGenerateMipmaps", "Can not generate mips");
[email protected]a93bb842010-02-16 23:03:473504 return;
3505 }
[email protected]38c0a972012-05-12 00:48:023506
[email protected]7687479c2012-05-14 23:54:043507 if (!texture_manager()->ClearTextureLevel(this, info, target, 0)) {
[email protected]ad84a3a2012-06-08 21:42:433508 SetGLError(GL_OUT_OF_MEMORY, "glGenerateMipmaps", "dimensions too big");
[email protected]7687479c2012-05-14 23:54:043509 return;
3510 }
3511
[email protected]38c0a972012-05-12 00:48:023512 CopyRealGLErrorsToWrapper();
[email protected]59f3ca02011-03-26 22:24:193513 // Workaround for Mac driver bug. In the large scheme of things setting
3514 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
[email protected]a8bad262011-10-21 18:28:563515 // hit so there's probably no need to make this conditional. The bug appears
3516 // to be that if the filtering mode is set to something that doesn't require
3517 // mipmaps for rendering, or is never set to something other than the default,
3518 // then glGenerateMipmap misbehaves.
[email protected]c892a4e12012-05-08 18:20:193519 if (!disable_workarounds_) {
3520 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3521 }
[email protected]a93bb842010-02-16 23:03:473522 glGenerateMipmapEXT(target);
[email protected]c892a4e12012-05-08 18:20:193523 if (!disable_workarounds_) {
3524 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, info->min_filter());
3525 }
[email protected]38c0a972012-05-12 00:48:023526 GLenum error = PeekGLError();
3527 if (error == GL_NO_ERROR) {
3528 texture_manager()->MarkMipmapsGenerated(info);
3529 }
[email protected]a93bb842010-02-16 23:03:473530}
3531
[email protected]b273e432010-04-12 17:23:583532bool GLES2DecoderImpl::GetHelper(
3533 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:583534 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:153535 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
3536 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:433537 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
3538 *num_written = 1;
3539 if (params) {
3540 *params = GL_RGBA; // We don't support other formats.
3541 }
3542 return true;
3543 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3544 *num_written = 1;
3545 if (params) {
3546 *params = GL_UNSIGNED_BYTE; // We don't support other types.
3547 }
3548 return true;
3549 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
3550 *num_written = 1;
3551 if (params) {
3552 *params = group_->max_fragment_uniform_vectors();
3553 }
3554 return true;
3555 case GL_MAX_VARYING_VECTORS:
3556 *num_written = 1;
3557 if (params) {
3558 *params = group_->max_varying_vectors();
3559 }
3560 return true;
3561 case GL_MAX_VERTEX_UNIFORM_VECTORS:
3562 *num_written = 1;
3563 if (params) {
3564 *params = group_->max_vertex_uniform_vectors();
3565 }
3566 return true;
[email protected]4e8a5b122010-05-08 22:00:103567 }
[email protected]5cb735d2011-10-13 01:37:233568 }
3569 switch (pname) {
[email protected]5094b0f2010-11-09 19:45:243570 case GL_MAX_VIEWPORT_DIMS:
3571 if (offscreen_target_frame_buffer_.get()) {
3572 *num_written = 2;
3573 if (params) {
3574 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3575 params[1] = renderbuffer_manager()->max_renderbuffer_size();
3576 }
3577 return true;
3578 }
[email protected]5cb735d2011-10-13 01:37:233579 return false;
[email protected]84afefa2011-10-19 21:45:533580 case GL_MAX_SAMPLES:
3581 *num_written = 1;
3582 if (params) {
3583 params[0] = renderbuffer_manager()->max_samples();
3584 }
3585 return true;
3586 case GL_MAX_RENDERBUFFER_SIZE:
3587 *num_written = 1;
3588 if (params) {
3589 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3590 }
3591 return true;
[email protected]5cb735d2011-10-13 01:37:233592 case GL_MAX_TEXTURE_SIZE:
3593 *num_written = 1;
3594 if (params) {
3595 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
3596 }
3597 return true;
3598 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
3599 *num_written = 1;
3600 if (params) {
3601 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
3602 }
3603 return true;
[email protected]297ca1c2011-06-20 23:08:463604 case GL_COLOR_WRITEMASK:
3605 *num_written = 4;
3606 if (params) {
3607 params[0] = mask_red_;
3608 params[1] = mask_green_;
3609 params[2] = mask_blue_;
3610 params[3] = mask_alpha_;
3611 }
3612 return true;
3613 case GL_DEPTH_WRITEMASK:
3614 *num_written = 1;
3615 if (params) {
3616 params[0] = mask_depth_;
3617 }
3618 return true;
3619 case GL_STENCIL_BACK_WRITEMASK:
3620 *num_written = 1;
3621 if (params) {
3622 params[0] = mask_stencil_back_;
3623 }
3624 return true;
3625 case GL_STENCIL_WRITEMASK:
3626 *num_written = 1;
3627 if (params) {
3628 params[0] = mask_stencil_front_;
3629 }
3630 return true;
3631 case GL_DEPTH_TEST:
3632 *num_written = 1;
3633 if (params) {
3634 params[0] = enable_depth_test_;
3635 }
3636 return true;
3637 case GL_STENCIL_TEST:
3638 *num_written = 1;
3639 if (params) {
3640 params[0] = enable_stencil_test_;
3641 }
3642 return true;
3643 case GL_ALPHA_BITS:
3644 *num_written = 1;
3645 if (params) {
3646 GLint v = 0;
3647 glGetIntegerv(GL_ALPHA_BITS, &v);
3648 params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0;
3649 }
3650 return true;
3651 case GL_DEPTH_BITS:
3652 *num_written = 1;
3653 if (params) {
3654 GLint v = 0;
3655 glGetIntegerv(GL_DEPTH_BITS, &v);
3656 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
3657 }
3658 return true;
3659 case GL_STENCIL_BITS:
3660 *num_written = 1;
3661 if (params) {
3662 GLint v = 0;
3663 glGetIntegerv(GL_STENCIL_BITS, &v);
3664 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
3665 }
3666 return true;
[email protected]656dcaad2010-05-07 17:18:373667 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113668 *num_written = validators_->compressed_texture_format.GetValues().size();
3669 if (params) {
3670 for (GLint ii = 0; ii < *num_written; ++ii) {
3671 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
3672 }
3673 }
[email protected]656dcaad2010-05-07 17:18:373674 return true;
[email protected]b273e432010-04-12 17:23:583675 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
3676 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103677 if (params) {
[email protected]302ce6d2011-07-07 23:28:113678 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103679 }
[email protected]b273e432010-04-12 17:23:583680 return true;
3681 case GL_NUM_SHADER_BINARY_FORMATS:
3682 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103683 if (params) {
[email protected]302ce6d2011-07-07 23:28:113684 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:103685 }
[email protected]b273e432010-04-12 17:23:583686 return true;
3687 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:113688 *num_written = validators_->shader_binary_format.GetValues().size();
3689 if (params) {
3690 for (GLint ii = 0; ii < *num_written; ++ii) {
3691 params[ii] = validators_->shader_binary_format.GetValues()[ii];
3692 }
3693 }
3694 return true;
[email protected]b273e432010-04-12 17:23:583695 case GL_SHADER_COMPILER:
3696 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103697 if (params) {
3698 *params = GL_TRUE;
3699 }
[email protected]b273e432010-04-12 17:23:583700 return true;
[email protected]6b8cf1a2010-05-06 16:13:583701 case GL_ARRAY_BUFFER_BINDING:
3702 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103703 if (params) {
3704 if (bound_array_buffer_) {
3705 GLuint client_id = 0;
3706 buffer_manager()->GetClientId(bound_array_buffer_->service_id(),
3707 &client_id);
3708 *params = client_id;
3709 } else {
3710 *params = 0;
3711 }
[email protected]6b8cf1a2010-05-06 16:13:583712 }
3713 return true;
3714 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
3715 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103716 if (params) {
3717 if (bound_element_array_buffer_) {
3718 GLuint client_id = 0;
3719 buffer_manager()->GetClientId(
3720 bound_element_array_buffer_->service_id(),
3721 &client_id);
3722 *params = client_id;
3723 } else {
3724 *params = 0;
3725 }
[email protected]6b8cf1a2010-05-06 16:13:583726 }
3727 return true;
3728 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:303729 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:583730 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103731 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203732 FramebufferManager::FramebufferInfo* framebuffer =
3733 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
3734 if (framebuffer) {
[email protected]4e8a5b122010-05-08 22:00:103735 GLuint client_id = 0;
3736 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203737 framebuffer->service_id(), &client_id);
[email protected]8e3e0662010-08-23 18:46:303738 *params = client_id;
3739 } else {
3740 *params = 0;
3741 }
3742 }
3743 return true;
3744 case GL_READ_FRAMEBUFFER_BINDING:
3745 *num_written = 1;
3746 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203747 FramebufferManager::FramebufferInfo* framebuffer =
3748 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
3749 if (framebuffer) {
[email protected]8e3e0662010-08-23 18:46:303750 GLuint client_id = 0;
3751 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203752 framebuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103753 *params = client_id;
3754 } else {
3755 *params = 0;
3756 }
[email protected]6b8cf1a2010-05-06 16:13:583757 }
3758 return true;
3759 case GL_RENDERBUFFER_BINDING:
3760 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103761 if (params) {
[email protected]0d6bfdc2011-11-02 01:32:203762 RenderbufferManager::RenderbufferInfo* renderbuffer =
3763 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
3764 if (renderbuffer) {
[email protected]4e8a5b122010-05-08 22:00:103765 GLuint client_id = 0;
3766 renderbuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:203767 renderbuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:103768 *params = client_id;
3769 } else {
3770 *params = 0;
3771 }
[email protected]6b8cf1a2010-05-06 16:13:583772 }
3773 return true;
3774 case GL_CURRENT_PROGRAM:
3775 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:103776 if (params) {
3777 if (current_program_) {
3778 GLuint client_id = 0;
3779 program_manager()->GetClientId(
3780 current_program_->service_id(), &client_id);
3781 *params = client_id;
3782 } else {
3783 *params = 0;
3784 }
[email protected]6b8cf1a2010-05-06 16:13:583785 }
3786 return true;
[email protected]4e8a5b122010-05-08 22:00:103787 case GL_TEXTURE_BINDING_2D:
3788 *num_written = 1;
3789 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583790 TextureUnit& unit = texture_units_[active_texture_unit_];
3791 if (unit.bound_texture_2d) {
3792 GLuint client_id = 0;
3793 texture_manager()->GetClientId(
3794 unit.bound_texture_2d->service_id(), &client_id);
3795 *params = client_id;
3796 } else {
3797 *params = 0;
3798 }
[email protected]6b8cf1a2010-05-06 16:13:583799 }
[email protected]4e8a5b122010-05-08 22:00:103800 return true;
3801 case GL_TEXTURE_BINDING_CUBE_MAP:
3802 *num_written = 1;
3803 if (params) {
[email protected]6b8cf1a2010-05-06 16:13:583804 TextureUnit& unit = texture_units_[active_texture_unit_];
3805 if (unit.bound_texture_cube_map) {
3806 GLuint client_id = 0;
3807 texture_manager()->GetClientId(
3808 unit.bound_texture_cube_map->service_id(), &client_id);
3809 *params = client_id;
3810 } else {
3811 *params = 0;
3812 }
[email protected]6b8cf1a2010-05-06 16:13:583813 }
[email protected]4e8a5b122010-05-08 22:00:103814 return true;
[email protected]61eeb33f2011-07-26 15:30:313815 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3816 *num_written = 1;
3817 if (params) {
3818 TextureUnit& unit = texture_units_[active_texture_unit_];
3819 if (unit.bound_texture_external_oes) {
3820 GLuint client_id = 0;
3821 texture_manager()->GetClientId(
3822 unit.bound_texture_external_oes->service_id(), &client_id);
3823 *params = client_id;
3824 } else {
3825 *params = 0;
3826 }
3827 }
3828 return true;
[email protected]e51bdf32011-11-23 22:21:463829 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
3830 *num_written = 1;
3831 if (params) {
3832 TextureUnit& unit = texture_units_[active_texture_unit_];
3833 if (unit.bound_texture_rectangle_arb) {
3834 GLuint client_id = 0;
3835 texture_manager()->GetClientId(
3836 unit.bound_texture_rectangle_arb->service_id(), &client_id);
3837 *params = client_id;
3838 } else {
3839 *params = 0;
3840 }
3841 }
3842 return true;
[email protected]6c75c712012-06-19 15:43:173843 case GL_UNPACK_FLIP_Y_CHROMIUM:
3844 *num_written = 1;
3845 if (params) {
3846 params[0] = unpack_flip_y_;
3847 }
3848 return true;
3849 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
3850 *num_written = 1;
3851 if (params) {
3852 params[0] = unpack_premultiply_alpha_;
3853 }
3854 return true;
3855 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
3856 *num_written = 1;
3857 if (params) {
3858 params[0] = unpack_unpremultiply_alpha_;
3859 }
3860 return true;
[email protected]b273e432010-04-12 17:23:583861 default:
[email protected]4e8a5b122010-05-08 22:00:103862 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:533863 return false;
[email protected]b273e432010-04-12 17:23:583864 }
3865}
3866
[email protected]4e8a5b122010-05-08 22:00:103867bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
3868 GLenum pname, GLsizei* num_values) {
3869 return GetHelper(pname, NULL, num_values);
3870}
3871
[email protected]b273e432010-04-12 17:23:583872void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
3873 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103874 GLsizei num_written = 0;
3875 if (GetHelper(pname, NULL, &num_written)) {
3876 scoped_array<GLint> values(new GLint[num_written]);
3877 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583878 for (GLsizei ii = 0; ii < num_written; ++ii) {
3879 params[ii] = static_cast<GLboolean>(values[ii]);
3880 }
3881 } else {
3882 glGetBooleanv(pname, params);
3883 }
3884}
3885
3886void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
3887 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:103888 GLsizei num_written = 0;
3889 if (GetHelper(pname, NULL, &num_written)) {
3890 scoped_array<GLint> values(new GLint[num_written]);
3891 GetHelper(pname, values.get(), &num_written);
[email protected]b273e432010-04-12 17:23:583892 for (GLsizei ii = 0; ii < num_written; ++ii) {
3893 params[ii] = static_cast<GLfloat>(values[ii]);
3894 }
3895 } else {
3896 glGetFloatv(pname, params);
3897 }
3898}
3899
3900void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
3901 DCHECK(params);
3902 GLsizei num_written;
3903 if (!GetHelper(pname, params, &num_written)) {
3904 glGetIntegerv(pname, params);
3905 }
3906}
3907
[email protected]a0c3e972010-04-21 00:49:133908void GLES2DecoderImpl::DoGetProgramiv(
3909 GLuint program_id, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:583910 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3911 program_id, "glGetProgramiv");
[email protected]a0c3e972010-04-21 00:49:133912 if (!info) {
[email protected]a0c3e972010-04-21 00:49:133913 return;
3914 }
3915 info->GetProgramiv(pname, params);
3916}
3917
[email protected]258a3313f2011-10-18 20:13:573918void GLES2DecoderImpl::DoBindAttribLocation(
3919 GLuint program, GLuint index, const char* name) {
3920 if (!StringIsValidForGLES(name)) {
[email protected]ad84a3a2012-06-08 21:42:433921 SetGLError(GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:573922 return;
3923 }
[email protected]68dcb1f2012-04-07 00:14:563924 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
[email protected]ad84a3a2012-06-08 21:42:433925 SetGLError(GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
[email protected]68dcb1f2012-04-07 00:14:563926 return;
3927 }
3928 if (index >= group_->max_vertex_attribs()) {
[email protected]ad84a3a2012-06-08 21:42:433929 SetGLError(GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
[email protected]68dcb1f2012-04-07 00:14:563930 return;
3931 }
[email protected]6b8cf1a2010-05-06 16:13:583932 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
3933 program, "glBindAttribLocation");
[email protected]ae51d192010-04-27 00:48:033934 if (!info) {
[email protected]258a3313f2011-10-18 20:13:573935 return;
[email protected]558847a2010-03-24 07:02:543936 }
[email protected]c3e4c4e2012-03-02 19:23:243937 info->SetAttribLocationBinding(name, static_cast<GLint>(index));
[email protected]258a3313f2011-10-18 20:13:573938 glBindAttribLocation(info->service_id(), index, name);
3939}
3940
3941error::Error GLES2DecoderImpl::HandleBindAttribLocation(
3942 uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
3943 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543944 GLuint index = static_cast<GLuint>(c.index);
3945 uint32 name_size = c.data_size;
3946 const char* name = GetSharedMemoryAs<const char*>(
3947 c.name_shm_id, c.name_shm_offset, name_size);
3948 if (name == NULL) {
3949 return error::kOutOfBounds;
3950 }
3951 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573952 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543953 return error::kNoError;
3954}
3955
3956error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
3957 uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:583958 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543959 GLuint index = static_cast<GLuint>(c.index);
3960 uint32 name_size = c.data_size;
3961 const char* name = GetImmediateDataAs<const char*>(
3962 c, name_size, immediate_data_size);
3963 if (name == NULL) {
3964 return error::kOutOfBounds;
3965 }
3966 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:573967 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543968 return error::kNoError;
3969}
3970
3971error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
3972 uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:583973 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:543974 GLuint index = static_cast<GLuint>(c.index);
3975 Bucket* bucket = GetBucket(c.name_bucket_id);
3976 if (!bucket || bucket->size() == 0) {
3977 return error::kInvalidArguments;
3978 }
3979 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:183980 if (!bucket->GetAsString(&name_str)) {
3981 return error::kInvalidArguments;
3982 }
[email protected]258a3313f2011-10-18 20:13:573983 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:543984 return error::kNoError;
3985}
3986
[email protected]f7a64ee2010-02-01 22:24:143987error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ba3176a2009-12-16 18:19:463988 uint32 immediate_data_size, const gles2::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:033989 GLuint client_id = c.shader;
3990 if (client_id) {
3991 ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
3992 if (info) {
[email protected]ca488e12010-12-13 20:06:143993 if (!info->IsDeleted()) {
3994 glDeleteShader(info->service_id());
3995 shader_manager()->MarkAsDeleted(info);
3996 }
[email protected]ae51d192010-04-27 00:48:033997 } else {
[email protected]ad84a3a2012-06-08 21:42:433998 SetGLError(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
[email protected]ae51d192010-04-27 00:48:033999 }
[email protected]96449d2c2009-11-25 00:01:324000 }
[email protected]f7a64ee2010-02-01 22:24:144001 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324002}
4003
[email protected]f7a64ee2010-02-01 22:24:144004error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ba3176a2009-12-16 18:19:464005 uint32 immediate_data_size, const gles2::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:034006 GLuint client_id = c.program;
4007 if (client_id) {
4008 ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
4009 if (info) {
[email protected]ca488e12010-12-13 20:06:144010 if (!info->IsDeleted()) {
[email protected]ca488e12010-12-13 20:06:144011 program_manager()->MarkAsDeleted(shader_manager(), info);
4012 }
[email protected]ae51d192010-04-27 00:48:034013 } else {
[email protected]ad84a3a2012-06-08 21:42:434014 SetGLError(GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
[email protected]ae51d192010-04-27 00:48:034015 }
[email protected]96449d2c2009-11-25 00:01:324016 }
[email protected]f7a64ee2010-02-01 22:24:144017 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324018}
4019
[email protected]269200b12010-11-18 22:53:064020void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104021 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574022 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104023 for (GLsizei ii = 0; ii < n; ++ii) {
4024 id_allocator->FreeID(ids[ii]);
4025 }
4026}
4027
[email protected]269200b12010-11-18 22:53:064028error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
4029 uint32 immediate_data_size, const gles2::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104030 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4031 GLsizei n = static_cast<GLsizei>(c.n);
4032 uint32 data_size;
4033 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4034 return error::kOutOfBounds;
4035 }
4036 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4037 c.ids_shm_id, c.ids_shm_offset, data_size);
4038 if (n < 0) {
[email protected]ad84a3a2012-06-08 21:42:434039 SetGLError(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104040 return error::kNoError;
4041 }
4042 if (ids == NULL) {
4043 return error::kOutOfBounds;
4044 }
[email protected]269200b12010-11-18 22:53:064045 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:104046 return error::kNoError;
4047}
4048
[email protected]269200b12010-11-18 22:53:064049void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104050 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574051 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104052 if (id_offset == 0) {
4053 for (GLsizei ii = 0; ii < n; ++ii) {
4054 ids[ii] = id_allocator->AllocateID();
4055 }
4056 } else {
4057 for (GLsizei ii = 0; ii < n; ++ii) {
4058 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4059 id_offset = ids[ii] + 1;
4060 }
4061 }
4062}
4063
[email protected]269200b12010-11-18 22:53:064064error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
4065 uint32 immediate_data_size, const gles2::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104066 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4067 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4068 GLsizei n = static_cast<GLsizei>(c.n);
4069 uint32 data_size;
4070 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4071 return error::kOutOfBounds;
4072 }
4073 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4074 c.ids_shm_id, c.ids_shm_offset, data_size);
4075 if (n < 0) {
[email protected]ad84a3a2012-06-08 21:42:434076 SetGLError(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104077 return error::kNoError;
4078 }
4079 if (ids == NULL) {
4080 return error::kOutOfBounds;
4081 }
[email protected]269200b12010-11-18 22:53:064082 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:104083 return error::kNoError;
4084}
4085
[email protected]269200b12010-11-18 22:53:064086void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104087 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574088 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104089 for (GLsizei ii = 0; ii < n; ++ii) {
4090 if (!id_allocator->MarkAsUsed(ids[ii])) {
4091 for (GLsizei jj = 0; jj < ii; ++jj) {
4092 id_allocator->FreeID(ids[jj]);
4093 }
4094 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:434095 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4096 "attempt to register id that already exists");
[email protected]066849e32010-05-03 19:14:104097 return;
4098 }
4099 }
4100}
4101
[email protected]269200b12010-11-18 22:53:064102error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
4103 uint32 immediate_data_size, const gles2::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104104 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4105 GLsizei n = static_cast<GLsizei>(c.n);
4106 uint32 data_size;
4107 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4108 return error::kOutOfBounds;
4109 }
4110 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4111 c.ids_shm_id, c.ids_shm_offset, data_size);
4112 if (n < 0) {
[email protected]ad84a3a2012-06-08 21:42:434113 SetGLError(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104114 return error::kNoError;
4115 }
4116 if (ids == NULL) {
4117 return error::kOutOfBounds;
4118 }
[email protected]269200b12010-11-18 22:53:064119 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:104120 return error::kNoError;
4121}
4122
[email protected]3a03a8f2011-03-19 00:51:274123void GLES2DecoderImpl::DoClear(GLbitfield mask) {
[email protected]0d6bfdc2011-11-02 01:32:204124 if (CheckBoundFramebuffersValid("glClear")) {
[email protected]529c6672012-01-04 02:18:264125 UNSHIPPED_TRACE_EVENT_INSTANT2("test_gpu", "DoClear", "red", clear_red_,
4126 "green", clear_green_);
[email protected]297ca1c2011-06-20 23:08:464127 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:274128 glClear(mask);
4129 }
4130}
4131
[email protected]36cef8ce2010-03-16 07:34:454132void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4133 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:034134 GLuint client_renderbuffer_id) {
[email protected]8e3e0662010-08-23 18:46:304135 FramebufferManager::FramebufferInfo* framebuffer_info =
4136 GetFramebufferInfoForTarget(target);
4137 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294138 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434139 "glFramebufferRenderbuffer", "no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454140 return;
4141 }
[email protected]ae51d192010-04-27 00:48:034142 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:284143 RenderbufferManager::RenderbufferInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:034144 if (client_renderbuffer_id) {
[email protected]3a2e7c7b2010-08-06 01:12:284145 info = GetRenderbufferInfo(client_renderbuffer_id);
[email protected]ae51d192010-04-27 00:48:034146 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294147 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434148 "glFramebufferRenderbuffer", "unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:034149 return;
4150 }
4151 service_id = info->service_id();
4152 }
[email protected]9edc6b22010-12-23 02:00:264153 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034154 glFramebufferRenderbufferEXT(
4155 target, attachment, renderbuffertarget, service_id);
[email protected]1002c2d2011-06-28 22:39:044156 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264157 if (error == GL_NO_ERROR) {
[email protected]8e3e0662010-08-23 18:46:304158 framebuffer_info->AttachRenderbuffer(attachment, info);
[email protected]3a2e7c7b2010-08-06 01:12:284159 }
[email protected]297ca1c2011-06-20 23:08:464160 if (framebuffer_info == bound_draw_framebuffer_) {
4161 state_dirty_ = true;
4162 }
[email protected]3a2e7c7b2010-08-06 01:12:284163}
4164
[email protected]297ca1c2011-06-20 23:08:464165bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
[email protected]3a2e7c7b2010-08-06 01:12:284166 switch (cap) {
[email protected]0a1e9ad2012-05-04 21:13:034167 case GL_BLEND:
4168 enable_blend_ = enabled;
4169 return true;
[email protected]43410e92012-04-20 17:06:284170 case GL_CULL_FACE:
4171 enable_cull_face_ = enabled;
4172 return true;
[email protected]3a2e7c7b2010-08-06 01:12:284173 case GL_SCISSOR_TEST:
4174 enable_scissor_test_ = enabled;
[email protected]297ca1c2011-06-20 23:08:464175 return true;
4176 case GL_DEPTH_TEST: {
4177 if (enable_depth_test_ != enabled) {
4178 enable_depth_test_ = enabled;
4179 state_dirty_ = true;
4180 }
4181 return false;
4182 }
4183 case GL_STENCIL_TEST:
4184 if (enable_stencil_test_ != enabled) {
4185 enable_stencil_test_ = enabled;
4186 state_dirty_ = true;
4187 }
4188 return false;
[email protected]3a2e7c7b2010-08-06 01:12:284189 default:
[email protected]297ca1c2011-06-20 23:08:464190 return true;
[email protected]3a2e7c7b2010-08-06 01:12:284191 }
4192}
4193
4194void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464195 if (SetCapabilityState(cap, false)) {
4196 glDisable(cap);
4197 }
[email protected]3a2e7c7b2010-08-06 01:12:284198}
4199
4200void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464201 if (SetCapabilityState(cap, true)) {
4202 glEnable(cap);
4203 }
[email protected]3a2e7c7b2010-08-06 01:12:284204}
4205
[email protected]3dc69c42012-05-12 02:29:244206bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
4207 switch (cap) {
4208 case GL_BLEND:
4209 return enable_blend_;
4210 case GL_CULL_FACE:
4211 return enable_cull_face_;
4212 case GL_SCISSOR_TEST:
4213 return enable_scissor_test_;
4214 case GL_DEPTH_TEST:
4215 return enable_depth_test_;
4216 case GL_STENCIL_TEST:
4217 return enable_stencil_test_;
4218 default:
4219 return glIsEnabled(cap) != 0;
4220 }
4221}
4222
[email protected]3a2e7c7b2010-08-06 01:12:284223void GLES2DecoderImpl::DoClearColor(
4224 GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
4225 clear_red_ = red;
4226 clear_green_ = green;
4227 clear_blue_ = blue;
4228 clear_alpha_ = alpha;
4229 glClearColor(red, green, blue, alpha);
4230}
4231
4232void GLES2DecoderImpl::DoClearDepthf(GLclampf depth) {
4233 clear_depth_ = depth;
4234 glClearDepth(depth);
4235}
4236
4237void GLES2DecoderImpl::DoClearStencil(GLint s) {
4238 clear_stencil_ = s;
4239 glClearStencil(s);
4240}
4241
4242void GLES2DecoderImpl::DoColorMask(
4243 GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
4244 mask_red_ = red;
4245 mask_green_ = green;
4246 mask_blue_ = blue;
4247 mask_alpha_ = alpha;
[email protected]297ca1c2011-06-20 23:08:464248 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284249}
4250
4251void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
4252 mask_depth_ = depth;
[email protected]297ca1c2011-06-20 23:08:464253 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284254}
4255
4256void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
4257 mask_stencil_front_ = mask;
4258 mask_stencil_back_ = mask;
[email protected]297ca1c2011-06-20 23:08:464259 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284260}
4261
4262void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
[email protected]297ca1c2011-06-20 23:08:464263 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284264 mask_stencil_front_ = mask;
[email protected]297ca1c2011-06-20 23:08:464265 }
4266 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
[email protected]3a2e7c7b2010-08-06 01:12:284267 mask_stencil_back_ = mask;
4268 }
[email protected]297ca1c2011-06-20 23:08:464269 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284270}
4271
[email protected]0d6bfdc2011-11-02 01:32:204272// Assumes framebuffer is complete.
4273void GLES2DecoderImpl::ClearUnclearedAttachments(
[email protected]8e3e0662010-08-23 18:46:304274 GLenum target, FramebufferManager::FramebufferInfo* info) {
4275 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204276 // bind this to the DRAW point, clear then bind back to READ
4277 // TODO(gman): I don't think there is any guarantee that an FBO that
4278 // is complete on the READ attachment will be complete as a DRAW
4279 // attachment.
4280 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
4281 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, info->service_id());
[email protected]8e3e0662010-08-23 18:46:304282 }
[email protected]3a2e7c7b2010-08-06 01:12:284283 GLbitfield clear_bits = 0;
4284 if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:464285 glClearColor(
[email protected]0d6bfdc2011-11-02 01:32:204286 0.0f, 0.0f, 0.0f,
[email protected]297ca1c2011-06-20 23:08:464287 (GLES2Util::GetChannelsForFormat(
[email protected]0d6bfdc2011-11-02 01:32:204288 info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f : 1.0f);
[email protected]3a2e7c7b2010-08-06 01:12:284289 glColorMask(true, true, true, true);
4290 clear_bits |= GL_COLOR_BUFFER_BIT;
4291 }
4292
4293 if (info->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4294 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4295 glClearStencil(0);
4296 glStencilMask(-1);
4297 clear_bits |= GL_STENCIL_BUFFER_BIT;
4298 }
4299
4300 if (info->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4301 info->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
4302 glClearDepth(1.0f);
4303 glDepthMask(true);
4304 clear_bits |= GL_DEPTH_BUFFER_BIT;
4305 }
4306
4307 glDisable(GL_SCISSOR_TEST);
4308 glClear(clear_bits);
4309
[email protected]968351b2011-12-20 08:26:514310 framebuffer_manager()->MarkAttachmentsAsCleared(
4311 info, renderbuffer_manager(), texture_manager());
[email protected]3a2e7c7b2010-08-06 01:12:284312
[email protected]c007aa02010-09-02 22:22:404313 RestoreClearState();
4314
4315 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204316 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, info->service_id());
[email protected]87d1a3fe2011-12-01 04:25:484317 FramebufferManager::FramebufferInfo* framebuffer =
4318 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4319 GLuint service_id =
4320 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
4321 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
[email protected]c007aa02010-09-02 22:22:404322 }
4323}
4324
4325void GLES2DecoderImpl::RestoreClearState() {
[email protected]297ca1c2011-06-20 23:08:464326 state_dirty_ = true;
[email protected]3a2e7c7b2010-08-06 01:12:284327 glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
[email protected]3a2e7c7b2010-08-06 01:12:284328 glClearStencil(clear_stencil_);
[email protected]3a2e7c7b2010-08-06 01:12:284329 glClearDepth(clear_depth_);
[email protected]3a2e7c7b2010-08-06 01:12:284330 if (enable_scissor_test_) {
4331 glEnable(GL_SCISSOR_TEST);
4332 }
[email protected]36cef8ce2010-03-16 07:34:454333}
4334
4335GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]0d6bfdc2011-11-02 01:32:204336 FramebufferManager::FramebufferInfo* framebuffer =
[email protected]8e3e0662010-08-23 18:46:304337 GetFramebufferInfoForTarget(target);
[email protected]0d6bfdc2011-11-02 01:32:204338 if (!framebuffer) {
[email protected]36cef8ce2010-03-16 07:34:454339 return GL_FRAMEBUFFER_COMPLETE;
4340 }
[email protected]0d6bfdc2011-11-02 01:32:204341 GLenum completeness = framebuffer->IsPossiblyComplete();
4342 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4343 return completeness;
4344 }
[email protected]36cef8ce2010-03-16 07:34:454345 return glCheckFramebufferStatusEXT(target);
4346}
4347
4348void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:034349 GLenum target, GLenum attachment, GLenum textarget,
4350 GLuint client_texture_id, GLint level) {
[email protected]8e3e0662010-08-23 18:46:304351 FramebufferManager::FramebufferInfo* framebuffer_info =
4352 GetFramebufferInfoForTarget(target);
4353 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294354 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434355 "glFramebufferTexture2D", "no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:454356 return;
4357 }
[email protected]ae51d192010-04-27 00:48:034358 GLuint service_id = 0;
[email protected]3a2e7c7b2010-08-06 01:12:284359 TextureManager::TextureInfo* info = NULL;
[email protected]ae51d192010-04-27 00:48:034360 if (client_texture_id) {
[email protected]3a2e7c7b2010-08-06 01:12:284361 info = GetTextureInfo(client_texture_id);
[email protected]ae51d192010-04-27 00:48:034362 if (!info) {
[email protected]8eee29c2010-04-29 03:38:294363 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434364 "glFramebufferTexture2D", "unknown texture");
[email protected]ae51d192010-04-27 00:48:034365 return;
4366 }
4367 service_id = info->service_id();
4368 }
[email protected]0d6bfdc2011-11-02 01:32:204369
[email protected]80eb6b52012-01-19 00:14:414370 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
[email protected]0d6bfdc2011-11-02 01:32:204371 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:434372 "glFramebufferTexture2D", "level out of range");
[email protected]0d6bfdc2011-11-02 01:32:204373 return;
4374 }
4375
[email protected]9edc6b22010-12-23 02:00:264376 CopyRealGLErrorsToWrapper();
[email protected]ae51d192010-04-27 00:48:034377 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
[email protected]1002c2d2011-06-28 22:39:044378 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264379 if (error == GL_NO_ERROR) {
4380 framebuffer_info->AttachTexture(attachment, info, textarget, level);
[email protected]3a2e7c7b2010-08-06 01:12:284381 }
[email protected]297ca1c2011-06-20 23:08:464382 if (framebuffer_info == bound_draw_framebuffer_) {
4383 state_dirty_ = true;
4384 }
[email protected]36cef8ce2010-03-16 07:34:454385}
4386
4387void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4388 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]8e3e0662010-08-23 18:46:304389 FramebufferManager::FramebufferInfo* framebuffer_info =
4390 GetFramebufferInfoForTarget(target);
4391 if (!framebuffer_info) {
[email protected]8eee29c2010-04-29 03:38:294392 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434393 "glFramebufferAttachmentParameteriv", "no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454394 return;
4395 }
4396 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:574397 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4398 GLint type = 0;
4399 GLuint client_id = 0;
4400 glGetFramebufferAttachmentParameterivEXT(
4401 target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
4402 switch (type) {
4403 case GL_RENDERBUFFER: {
4404 renderbuffer_manager()->GetClientId(*params, &client_id);
4405 break;
4406 }
4407 case GL_TEXTURE: {
4408 texture_manager()->GetClientId(*params, &client_id);
4409 break;
4410 }
4411 default:
4412 break;
4413 }
4414 *params = client_id;
4415 }
[email protected]36cef8ce2010-03-16 07:34:454416}
4417
4418void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4419 GLenum target, GLenum pname, GLint* params) {
[email protected]0d6bfdc2011-11-02 01:32:204420 RenderbufferManager::RenderbufferInfo* renderbuffer =
4421 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4422 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294423 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434424 "glGetRenderbufferParameteriv", "no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454425 return;
4426 }
[email protected]3a03a8f2011-03-19 00:51:274427 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:434428 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4429 *params = renderbuffer->internal_format();
4430 break;
4431 case GL_RENDERBUFFER_WIDTH:
4432 *params = renderbuffer->width();
4433 break;
4434 case GL_RENDERBUFFER_HEIGHT:
4435 *params = renderbuffer->height();
4436 break;
4437 default:
4438 glGetRenderbufferParameterivEXT(target, pname, params);
4439 break;
[email protected]b71f52c2010-06-18 22:20:204440 }
[email protected]36cef8ce2010-03-16 07:34:454441}
4442
[email protected]8e3e0662010-08-23 18:46:304443void GLES2DecoderImpl::DoBlitFramebufferEXT(
4444 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
4445 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
4446 GLbitfield mask, GLenum filter) {
[email protected]a3ded6d2010-10-19 06:44:394447 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304448 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434449 "glBlitFramebufferEXT", "function not available");
[email protected]8e3e0662010-08-23 18:46:304450 }
[email protected]5094b0f2010-11-09 19:45:244451 if (IsAngle()) {
4452 glBlitFramebufferANGLE(
4453 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4454 } else {
4455 glBlitFramebufferEXT(
4456 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4457 }
[email protected]529c6672012-01-04 02:18:264458 UNSHIPPED_TRACE_EVENT_INSTANT1("test_gpu", "DoBlit", "width", srcX1 - srcX0);
[email protected]8e3e0662010-08-23 18:46:304459}
4460
4461void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
4462 GLenum target, GLsizei samples, GLenum internalformat,
4463 GLsizei width, GLsizei height) {
[email protected]a3ded6d2010-10-19 06:44:394464 if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:304465 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434466 "glRenderbufferStorageMultisampleEXT", "function not available");
[email protected]8e3e0662010-08-23 18:46:304467 return;
4468 }
[email protected]8e3e0662010-08-23 18:46:304469
[email protected]0d6bfdc2011-11-02 01:32:204470 RenderbufferManager::RenderbufferInfo* renderbuffer =
4471 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4472 if (!renderbuffer) {
4473 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434474 "glGetRenderbufferStorageMultisample", "no renderbuffer bound");
[email protected]0d6bfdc2011-11-02 01:32:204475 return;
4476 }
4477
[email protected]84afefa2011-10-19 21:45:534478 if (samples > renderbuffer_manager()->max_samples()) {
4479 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:434480 "glGetRenderbufferStorageMultisample", "samples too large");
[email protected]84afefa2011-10-19 21:45:534481 return;
4482 }
4483
4484 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4485 height > renderbuffer_manager()->max_renderbuffer_size()) {
4486 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:434487 "glGetRenderbufferStorageMultisample", "size too large");
[email protected]84afefa2011-10-19 21:45:534488 return;
4489 }
4490
[email protected]9edc6b22010-12-23 02:00:264491 GLenum impl_format = internalformat;
[email protected]8e3e0662010-08-23 18:46:304492 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264493 switch (impl_format) {
[email protected]8e3e0662010-08-23 18:46:304494 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264495 impl_format = GL_DEPTH_COMPONENT;
[email protected]8e3e0662010-08-23 18:46:304496 break;
4497 case GL_RGBA4:
4498 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264499 impl_format = GL_RGBA;
[email protected]8e3e0662010-08-23 18:46:304500 break;
4501 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264502 impl_format = GL_RGB;
[email protected]8e3e0662010-08-23 18:46:304503 break;
4504 }
4505 }
4506
[email protected]9edc6b22010-12-23 02:00:264507 CopyRealGLErrorsToWrapper();
[email protected]866b91c52011-03-23 14:38:084508 if (IsAngle()) {
4509 glRenderbufferStorageMultisampleANGLE(
4510 target, samples, impl_format, width, height);
4511 } else {
4512 glRenderbufferStorageMultisampleEXT(
4513 target, samples, impl_format, width, height);
4514 }
[email protected]1002c2d2011-06-28 22:39:044515 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264516 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514517 // TODO(gman): If renderbuffers tracked which framebuffers they were
4518 // attached to we could just mark those framebuffers as not complete.
4519 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204520 renderbuffer_manager()->SetInfo(
4521 renderbuffer, samples, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264522 }
[email protected]8e3e0662010-08-23 18:46:304523}
4524
[email protected]36cef8ce2010-03-16 07:34:454525void GLES2DecoderImpl::DoRenderbufferStorage(
4526 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]0d6bfdc2011-11-02 01:32:204527 RenderbufferManager::RenderbufferInfo* renderbuffer =
4528 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4529 if (!renderbuffer) {
[email protected]8eee29c2010-04-29 03:38:294530 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:434531 "glGetRenderbufferStorage", "no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454532 return;
4533 }
[email protected]876f6fee2010-08-02 23:10:324534
[email protected]84afefa2011-10-19 21:45:534535 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4536 height > renderbuffer_manager()->max_renderbuffer_size()) {
4537 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:434538 "glGetRenderbufferStorage", "size too large");
[email protected]84afefa2011-10-19 21:45:534539 return;
4540 }
4541
[email protected]9edc6b22010-12-23 02:00:264542 GLenum impl_format = internalformat;
[email protected]876f6fee2010-08-02 23:10:324543 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
[email protected]9edc6b22010-12-23 02:00:264544 switch (impl_format) {
[email protected]876f6fee2010-08-02 23:10:324545 case GL_DEPTH_COMPONENT16:
[email protected]9edc6b22010-12-23 02:00:264546 impl_format = GL_DEPTH_COMPONENT;
[email protected]876f6fee2010-08-02 23:10:324547 break;
4548 case GL_RGBA4:
4549 case GL_RGB5_A1:
[email protected]9edc6b22010-12-23 02:00:264550 impl_format = GL_RGBA;
[email protected]876f6fee2010-08-02 23:10:324551 break;
4552 case GL_RGB565:
[email protected]9edc6b22010-12-23 02:00:264553 impl_format = GL_RGB;
[email protected]876f6fee2010-08-02 23:10:324554 break;
4555 }
[email protected]b71f52c2010-06-18 22:20:204556 }
[email protected]876f6fee2010-08-02 23:10:324557
[email protected]9edc6b22010-12-23 02:00:264558 CopyRealGLErrorsToWrapper();
4559 glRenderbufferStorageEXT(target, impl_format, width, height);
[email protected]1002c2d2011-06-28 22:39:044560 GLenum error = PeekGLError();
[email protected]9edc6b22010-12-23 02:00:264561 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:514562 // TODO(gman): If tetxures tracked which framebuffers they were attached to
4563 // we could just mark those framebuffers as not complete.
4564 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:204565 renderbuffer_manager()->SetInfo(
4566 renderbuffer, 0, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:264567 }
[email protected]36cef8ce2010-03-16 07:34:454568}
4569
[email protected]07f54fcc2009-12-22 02:46:304570void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
[email protected]43ed3a72012-05-30 22:55:384571 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]6b8cf1a2010-05-06 16:13:584572 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
4573 program, "glLinkProgram");
[email protected]a93bb842010-02-16 23:03:474574 if (!info) {
[email protected]a93bb842010-02-16 23:03:474575 return;
4576 }
[email protected]05afda12011-01-20 00:17:344577
[email protected]2df73892012-04-28 01:09:544578 if (info->Link()) {
4579 if (info == current_program_.get()) {
4580 program_manager()->ClearUniforms(info);
4581 }
4582 }
[email protected]07f54fcc2009-12-22 02:46:304583};
4584
[email protected]3916c97e2010-02-25 03:20:504585void GLES2DecoderImpl::DoTexParameterf(
4586 GLenum target, GLenum pname, GLfloat param) {
4587 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]07f54fcc2009-12-22 02:46:304588 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:434589 SetGLError(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:244590 return;
[email protected]07f54fcc2009-12-22 02:46:304591 }
[email protected]cbb22e42011-05-12 23:36:244592
4593 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414594 info, pname, static_cast<GLint>(param))) {
[email protected]ad84a3a2012-06-08 21:42:434595 SetGLError(GL_INVALID_ENUM, "glTexParameterf", "param GL_INVALID_ENUM");
[email protected]cbb22e42011-05-12 23:36:244596 return;
4597 }
4598 glTexParameterf(target, pname, param);
[email protected]07f54fcc2009-12-22 02:46:304599}
4600
[email protected]3916c97e2010-02-25 03:20:504601void GLES2DecoderImpl::DoTexParameteri(
4602 GLenum target, GLenum pname, GLint param) {
4603 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4604 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:434605 SetGLError(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:244606 return;
[email protected]3916c97e2010-02-25 03:20:504607 }
[email protected]cbb22e42011-05-12 23:36:244608
[email protected]80eb6b52012-01-19 00:14:414609 if (!texture_manager()->SetParameter(info, pname, param)) {
[email protected]ad84a3a2012-06-08 21:42:434610 SetGLError(GL_INVALID_ENUM, "glTexParameteri", "param GL_INVALID_ENUM");
[email protected]cbb22e42011-05-12 23:36:244611 return;
4612 }
4613 glTexParameteri(target, pname, param);
[email protected]3916c97e2010-02-25 03:20:504614}
4615
4616void GLES2DecoderImpl::DoTexParameterfv(
4617 GLenum target, GLenum pname, const GLfloat* params) {
4618 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4619 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:434620 SetGLError(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:244621 return;
[email protected]3916c97e2010-02-25 03:20:504622 }
[email protected]cbb22e42011-05-12 23:36:244623
4624 if (!texture_manager()->SetParameter(
[email protected]80eb6b52012-01-19 00:14:414625 info, pname, static_cast<GLint>(params[0]))) {
[email protected]ad84a3a2012-06-08 21:42:434626 SetGLError(GL_INVALID_ENUM, "glTexParameterfv", "param GL_INVALID_ENUM");
[email protected]cbb22e42011-05-12 23:36:244627 return;
4628 }
4629 glTexParameterfv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504630}
4631
4632void GLES2DecoderImpl::DoTexParameteriv(
4633 GLenum target, GLenum pname, const GLint* params) {
4634 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
4635 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:434636 SetGLError(GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:244637 return;
[email protected]3916c97e2010-02-25 03:20:504638 }
[email protected]cbb22e42011-05-12 23:36:244639
[email protected]80eb6b52012-01-19 00:14:414640 if (!texture_manager()->SetParameter(info, pname, *params)) {
[email protected]ad84a3a2012-06-08 21:42:434641 SetGLError(GL_INVALID_ENUM, "glTexParameteriv", "param GL_INVALID_ENUM");
[email protected]cbb22e42011-05-12 23:36:244642 return;
4643 }
4644 glTexParameteriv(target, pname, params);
[email protected]3916c97e2010-02-25 03:20:504645}
4646
[email protected]939e7362010-05-13 20:49:104647bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]ca488e12010-12-13 20:06:144648 if (!current_program_) {
[email protected]ad84a3a2012-06-08 21:42:434649 // The program does not exist.
4650 SetGLError(GL_INVALID_OPERATION, function_name, "no program in use");
4651 return false;
[email protected]939e7362010-05-13 20:49:104652 }
[email protected]ca488e12010-12-13 20:06:144653 if (!current_program_->InUse()) {
[email protected]ad84a3a2012-06-08 21:42:434654 SetGLError(GL_INVALID_OPERATION, function_name, "program not linked");
[email protected]939e7362010-05-13 20:49:104655 return false;
4656 }
4657 return true;
4658}
4659
4660bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
4661 GLint location, const char* function_name) {
4662 if (!CheckCurrentProgram(function_name)) {
4663 return false;
4664 }
4665 return location != -1;
4666}
4667
[email protected]43c2f1f2011-03-25 18:35:364668bool GLES2DecoderImpl::PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124669 GLint fake_location, const char* function_name,
4670 GLint* real_location, GLenum* type, GLsizei* count) {
[email protected]43c2f1f2011-03-25 18:35:364671 DCHECK(type);
4672 DCHECK(count);
[email protected]1b0a6752012-02-22 03:44:124673 DCHECK(real_location);
4674 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
[email protected]939e7362010-05-13 20:49:104675 return false;
4676 }
[email protected]43c2f1f2011-03-25 18:35:364677 GLint array_index = -1;
4678 const ProgramManager::ProgramInfo::UniformInfo* info =
[email protected]1b0a6752012-02-22 03:44:124679 current_program_->GetUniformInfoByFakeLocation(
4680 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:364681 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:434682 SetGLError(GL_INVALID_OPERATION, function_name, "unknown location");
[email protected]939e7362010-05-13 20:49:104683 return false;
4684 }
[email protected]43c2f1f2011-03-25 18:35:364685 if (*count > 1 && !info->is_array) {
4686 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:434687 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
[email protected]43c2f1f2011-03-25 18:35:364688 return false;
4689 }
4690 *count = std::min(info->size - array_index, *count);
4691 if (*count <= 0) {
4692 return false;
4693 }
4694 *type = info->type;
[email protected]939e7362010-05-13 20:49:104695 return true;
4696}
4697
[email protected]1b0a6752012-02-22 03:44:124698void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
4699 GLenum type = 0;
4700 GLsizei count = 1;
4701 GLint real_location = -1;
4702 if (!PrepForSetUniformByLocation(
4703 fake_location, "glUniform1iv", &real_location, &type, &count)) {
[email protected]3916c97e2010-02-25 03:20:504704 return;
4705 }
[email protected]d20a6512012-05-02 20:17:464706 if (!current_program_->SetSamplers(
4707 group_->max_texture_units(), fake_location, 1, &v0)) {
[email protected]ad84a3a2012-06-08 21:42:434708 SetGLError(GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
[email protected]d20a6512012-05-02 20:17:464709 return;
4710 }
[email protected]1b0a6752012-02-22 03:44:124711 glUniform1i(real_location, v0);
[email protected]3916c97e2010-02-25 03:20:504712}
4713
4714void GLES2DecoderImpl::DoUniform1iv(
[email protected]1b0a6752012-02-22 03:44:124715 GLint fake_location, GLsizei count, const GLint *value) {
[email protected]43c2f1f2011-03-25 18:35:364716 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124717 GLint real_location = -1;
4718 if (!PrepForSetUniformByLocation(
4719 fake_location, "glUniform1iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364720 return;
4721 }
[email protected]74727112012-06-13 21:18:084722 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
4723 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]d20a6512012-05-02 20:17:464724 if (!current_program_->SetSamplers(
4725 group_->max_texture_units(), fake_location, count, value)) {
[email protected]ad84a3a2012-06-08 21:42:434726 SetGLError(GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
[email protected]d20a6512012-05-02 20:17:464727 return;
4728 }
[email protected]43c2f1f2011-03-25 18:35:364729 }
[email protected]1b0a6752012-02-22 03:44:124730 glUniform1iv(real_location, count, value);
[email protected]3916c97e2010-02-25 03:20:504731}
4732
[email protected]939e7362010-05-13 20:49:104733void GLES2DecoderImpl::DoUniform1fv(
[email protected]1b0a6752012-02-22 03:44:124734 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364735 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124736 GLint real_location = -1;
4737 if (!PrepForSetUniformByLocation(
4738 fake_location, "glUniform1fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104739 return;
4740 }
4741 if (type == GL_BOOL) {
4742 scoped_array<GLint> temp(new GLint[count]);
4743 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:534744 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104745 }
[email protected]1b0a6752012-02-22 03:44:124746 DoUniform1iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104747 } else {
[email protected]1b0a6752012-02-22 03:44:124748 glUniform1fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104749 }
4750}
4751
4752void GLES2DecoderImpl::DoUniform2fv(
[email protected]1b0a6752012-02-22 03:44:124753 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364754 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124755 GLint real_location = -1;
4756 if (!PrepForSetUniformByLocation(
4757 fake_location, "glUniform2fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104758 return;
4759 }
4760 if (type == GL_BOOL_VEC2) {
4761 GLsizei num_values = count * 2;
4762 scoped_array<GLint> temp(new GLint[num_values]);
4763 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534764 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104765 }
[email protected]1b0a6752012-02-22 03:44:124766 glUniform2iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104767 } else {
[email protected]1b0a6752012-02-22 03:44:124768 glUniform2fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104769 }
4770}
4771
4772void GLES2DecoderImpl::DoUniform3fv(
[email protected]1b0a6752012-02-22 03:44:124773 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364774 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124775 GLint real_location = -1;
4776 if (!PrepForSetUniformByLocation(
4777 fake_location, "glUniform3fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104778 return;
4779 }
4780 if (type == GL_BOOL_VEC3) {
4781 GLsizei num_values = count * 3;
4782 scoped_array<GLint> temp(new GLint[num_values]);
4783 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534784 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104785 }
[email protected]1b0a6752012-02-22 03:44:124786 glUniform3iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104787 } else {
[email protected]1b0a6752012-02-22 03:44:124788 glUniform3fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104789 }
4790}
4791
4792void GLES2DecoderImpl::DoUniform4fv(
[email protected]1b0a6752012-02-22 03:44:124793 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364794 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124795 GLint real_location = -1;
4796 if (!PrepForSetUniformByLocation(
4797 fake_location, "glUniform4fv", &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:104798 return;
4799 }
4800 if (type == GL_BOOL_VEC4) {
4801 GLsizei num_values = count * 4;
4802 scoped_array<GLint> temp(new GLint[num_values]);
4803 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:534804 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:104805 }
[email protected]1b0a6752012-02-22 03:44:124806 glUniform4iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:104807 } else {
[email protected]1b0a6752012-02-22 03:44:124808 glUniform4fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:104809 }
4810}
4811
[email protected]43c2f1f2011-03-25 18:35:364812void GLES2DecoderImpl::DoUniform2iv(
[email protected]1b0a6752012-02-22 03:44:124813 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364814 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124815 GLint real_location = -1;
4816 if (!PrepForSetUniformByLocation(
4817 fake_location, "glUniform2iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364818 return;
4819 }
[email protected]1b0a6752012-02-22 03:44:124820 glUniform2iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364821}
4822
4823void GLES2DecoderImpl::DoUniform3iv(
[email protected]1b0a6752012-02-22 03:44:124824 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364825 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124826 GLint real_location = -1;
4827 if (!PrepForSetUniformByLocation(
4828 fake_location, "glUniform3iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364829 return;
4830 }
[email protected]1b0a6752012-02-22 03:44:124831 glUniform3iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364832}
4833
4834void GLES2DecoderImpl::DoUniform4iv(
[email protected]1b0a6752012-02-22 03:44:124835 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:364836 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124837 GLint real_location = -1;
4838 if (!PrepForSetUniformByLocation(
4839 fake_location, "glUniform4iv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364840 return;
4841 }
[email protected]1b0a6752012-02-22 03:44:124842 glUniform4iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:364843}
4844
4845void GLES2DecoderImpl::DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:124846 GLint fake_location, GLsizei count, GLboolean transpose,
4847 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364848 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124849 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364850 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124851 fake_location, "glUniformMatrix2fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364852 return;
4853 }
[email protected]1b0a6752012-02-22 03:44:124854 glUniformMatrix2fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364855}
4856
4857void GLES2DecoderImpl::DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:124858 GLint fake_location, GLsizei count, GLboolean transpose,
4859 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364860 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124861 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364862 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124863 fake_location, "glUniformMatrix3fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364864 return;
4865 }
[email protected]1b0a6752012-02-22 03:44:124866 glUniformMatrix3fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364867}
4868
4869void GLES2DecoderImpl::DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:124870 GLint fake_location, GLsizei count, GLboolean transpose,
4871 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:364872 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:124873 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:364874 if (!PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:124875 fake_location, "glUniformMatrix4fv", &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:364876 return;
4877 }
[email protected]1b0a6752012-02-22 03:44:124878 glUniformMatrix4fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:364879}
4880
[email protected]3916c97e2010-02-25 03:20:504881void GLES2DecoderImpl::DoUseProgram(GLuint program) {
[email protected]ae51d192010-04-27 00:48:034882 GLuint service_id = 0;
[email protected]3916c97e2010-02-25 03:20:504883 ProgramManager::ProgramInfo* info = NULL;
4884 if (program) {
[email protected]6b8cf1a2010-05-06 16:13:584885 info = GetProgramInfoNotShader(program, "glUseProgram");
[email protected]3916c97e2010-02-25 03:20:504886 if (!info) {
[email protected]ae51d192010-04-27 00:48:034887 return;
4888 }
4889 if (!info->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:504890 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]ad84a3a2012-06-08 21:42:434891 SetGLError(GL_INVALID_OPERATION, "glUseProgram", "program not linked");
[email protected]3916c97e2010-02-25 03:20:504892 return;
4893 }
[email protected]ae51d192010-04-27 00:48:034894 service_id = info->service_id();
[email protected]3916c97e2010-02-25 03:20:504895 }
[email protected]ca488e12010-12-13 20:06:144896 if (current_program_) {
4897 program_manager()->UnuseProgram(shader_manager(), current_program_);
4898 }
[email protected]3916c97e2010-02-25 03:20:504899 current_program_ = info;
[email protected]2df73892012-04-28 01:09:544900 glUseProgram(service_id);
[email protected]ca488e12010-12-13 20:06:144901 if (current_program_) {
4902 program_manager()->UseProgram(current_program_);
4903 }
[email protected]3916c97e2010-02-25 03:20:504904}
4905
[email protected]96449d2c2009-11-25 00:01:324906GLenum GLES2DecoderImpl::GetGLError() {
4907 // Check the GL error first, then our wrapped error.
4908 GLenum error = glGetError();
4909 if (error == GL_NO_ERROR && error_bits_ != 0) {
[email protected]03f882a2010-01-08 20:46:374910 for (uint32 mask = 1; mask != 0; mask = mask << 1) {
[email protected]96449d2c2009-11-25 00:01:324911 if ((error_bits_ & mask) != 0) {
[email protected]ddd968b82010-03-02 00:44:294912 error = GLES2Util::GLErrorBitToGLError(mask);
[email protected]96449d2c2009-11-25 00:01:324913 break;
4914 }
4915 }
4916 }
4917
4918 if (error != GL_NO_ERROR) {
4919 // There was an error, clear the corresponding wrapped error.
[email protected]ddd968b82010-03-02 00:44:294920 error_bits_ &= ~GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324921 }
4922 return error;
4923}
4924
[email protected]1002c2d2011-06-28 22:39:044925GLenum GLES2DecoderImpl::PeekGLError() {
4926 GLenum error = glGetError();
4927 if (error != GL_NO_ERROR) {
[email protected]ad84a3a2012-06-08 21:42:434928 SetGLError(error, "", "");
[email protected]1002c2d2011-06-28 22:39:044929 }
4930 return error;
4931}
4932
[email protected]ad84a3a2012-06-08 21:42:434933void GLES2DecoderImpl::SetGLError(
4934 GLenum error, const char* function_name, const char* msg) {
[email protected]8eee29c2010-04-29 03:38:294935 if (msg) {
4936 last_error_ = msg;
[email protected]0f8afe82012-05-14 23:43:014937 LogMessage(std::string("GL ERROR :") +
[email protected]ad84a3a2012-06-08 21:42:434938 GLES2Util::GetStringEnum(error) + " : " +
4939 function_name + ": " + msg);
[email protected]8eee29c2010-04-29 03:38:294940 }
[email protected]ddd968b82010-03-02 00:44:294941 error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
[email protected]96449d2c2009-11-25 00:01:324942}
4943
[email protected]0f8afe82012-05-14 23:43:014944void GLES2DecoderImpl::LogMessage(const std::string& msg) {
4945 if (log_message_count_ < kMaxLogMessages ||
4946 CommandLine::ForCurrentProcess()->HasSwitch(
4947 switches::kDisableGLErrorLimit)) {
4948 ++log_message_count_;
4949 // LOG this unless logging is turned off as any chromium code that
4950 // generates these errors probably has a bug.
4951 if (log_synthesized_gl_errors()) {
[email protected]3f00df92012-06-19 00:44:584952 LOG(ERROR) << msg;
[email protected]0f8afe82012-05-14 23:43:014953 }
4954 if (!msg_callback_.is_null()) {
4955 msg_callback_.Run(0, msg);
4956 }
4957 } else {
4958 if (log_message_count_ == kMaxLogMessages) {
4959 ++log_message_count_;
4960 LOG(ERROR)
4961 << "Too many GL errors, not reporting any more for this context."
4962 << " use --disable-gl-error-limit to see all errors.";
4963 }
4964 }
4965}
4966
4967void GLES2DecoderImpl::RenderWarning(const std::string& msg) {
4968 LogMessage(std::string("RENDER WARNING: ") + msg);
4969}
4970
4971void GLES2DecoderImpl::PerformanceWarning(const std::string& msg) {
4972 LogMessage(std::string("PERFORMANCE WARNING: ") + msg);
4973}
4974
[email protected]07f54fcc2009-12-22 02:46:304975void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
4976 GLenum error;
4977 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]ad84a3a2012-06-08 21:42:434978 SetGLError(error, "", NULL);
[email protected]07f54fcc2009-12-22 02:46:304979 }
4980}
4981
[email protected]6217d392010-03-25 22:08:354982void GLES2DecoderImpl::ClearRealGLErrors() {
4983 GLenum error;
4984 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]3ed14d112011-12-13 22:05:514985 if (error != GL_OUT_OF_MEMORY) {
4986 // GL_OUT_OF_MEMORY can legally happen on lost device.
4987 NOTREACHED() << "GL error " << error << " was unhandled.";
4988 }
[email protected]6217d392010-03-25 22:08:354989 }
4990}
4991
[email protected]ef526492010-06-02 23:12:254992bool GLES2DecoderImpl::SetBlackTextureForNonRenderableTextures() {
[email protected]3916c97e2010-02-25 03:20:504993 DCHECK(current_program_);
[email protected]ef526492010-06-02 23:12:254994 // Only check if there are some unrenderable textures.
4995 if (!texture_manager()->HaveUnrenderableTextures()) {
4996 return false;
4997 }
4998 bool textures_set = false;
[email protected]3916c97e2010-02-25 03:20:504999 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
5000 current_program_->sampler_indices();
5001 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5002 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
5003 current_program_->GetUniformInfo(sampler_indices[ii]);
5004 DCHECK(uniform_info);
5005 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5006 GLuint texture_unit_index = uniform_info->texture_units[jj];
5007 if (texture_unit_index < group_->max_texture_units()) {
5008 TextureUnit& texture_unit = texture_units_[texture_unit_index];
5009 TextureManager::TextureInfo* texture_info =
[email protected]61eeb33f2011-07-26 15:30:315010 texture_unit.GetInfoForSamplerType(uniform_info->type);
[email protected]80eb6b52012-01-19 00:14:415011 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]ef526492010-06-02 23:12:255012 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:505013 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5014 glBindTexture(
[email protected]61eeb33f2011-07-26 15:30:315015 GetBindTargetForSamplerType(uniform_info->type),
[email protected]00f893d2010-08-24 18:55:495016 texture_manager()->black_texture_id(uniform_info->type));
[email protected]0f8afe82012-05-14 23:43:015017 RenderWarning(
5018 std::string("texture bound to texture unit ") +
5019 base::IntToString(texture_unit_index) +
5020 " is not renderable. It maybe non-power-of-2 and have "
5021 " incompatible texture filtering or is not "
5022 "'texture complete'");
[email protected]3916c97e2010-02-25 03:20:505023 }
5024 }
5025 // else: should this be an error?
5026 }
5027 }
[email protected]ef526492010-06-02 23:12:255028 return textures_set;
[email protected]3916c97e2010-02-25 03:20:505029}
5030
5031void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
5032 DCHECK(current_program_);
[email protected]3916c97e2010-02-25 03:20:505033 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
5034 current_program_->sampler_indices();
5035 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5036 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
5037 current_program_->GetUniformInfo(sampler_indices[ii]);
5038 DCHECK(uniform_info);
5039 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5040 GLuint texture_unit_index = uniform_info->texture_units[jj];
5041 if (texture_unit_index < group_->max_texture_units()) {
5042 TextureUnit& texture_unit = texture_units_[texture_unit_index];
5043 TextureManager::TextureInfo* texture_info =
5044 uniform_info->type == GL_SAMPLER_2D ?
5045 texture_unit.bound_texture_2d :
5046 texture_unit.bound_texture_cube_map;
[email protected]80eb6b52012-01-19 00:14:415047 if (!texture_info || !texture_manager()->CanRender(texture_info)) {
[email protected]3916c97e2010-02-25 03:20:505048 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5049 // Get the texture info that was previously bound here.
5050 texture_info = texture_unit.bind_target == GL_TEXTURE_2D ?
5051 texture_unit.bound_texture_2d :
5052 texture_unit.bound_texture_cube_map;
5053 glBindTexture(texture_unit.bind_target,
[email protected]ae51d192010-04-27 00:48:035054 texture_info ? texture_info->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:505055 }
5056 }
5057 }
5058 }
5059 // Set the active texture back to whatever the user had it as.
5060 glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
[email protected]07f54fcc2009-12-22 02:46:305061}
5062
[email protected]0d6bfdc2011-11-02 01:32:205063bool GLES2DecoderImpl::ClearUnclearedTextures() {
5064 // Only check if there are some uncleared textures.
5065 if (!texture_manager()->HaveUnsafeTextures()) {
5066 return true;
5067 }
5068
5069 // 1: Check all textures we are about to render with.
5070 if (current_program_) {
5071 const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
5072 current_program_->sampler_indices();
5073 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
5074 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
5075 current_program_->GetUniformInfo(sampler_indices[ii]);
5076 DCHECK(uniform_info);
5077 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5078 GLuint texture_unit_index = uniform_info->texture_units[jj];
5079 if (texture_unit_index < group_->max_texture_units()) {
5080 TextureUnit& texture_unit = texture_units_[texture_unit_index];
5081 TextureManager::TextureInfo* texture_info =
5082 texture_unit.GetInfoForSamplerType(uniform_info->type);
5083 if (texture_info && !texture_info->SafeToRenderFrom()) {
5084 if (!texture_manager()->ClearRenderableLevels(this, texture_info)) {
5085 return false;
5086 }
5087 }
5088 }
5089 }
5090 }
5091 }
5092 return true;
5093}
5094
[email protected]c6aef902012-02-14 03:31:425095bool GLES2DecoderImpl::IsDrawValid(
[email protected]ad84a3a2012-06-08 21:42:435096 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount) {
[email protected]689fa1c52010-06-09 18:35:035097 // NOTE: We specifically do not check current_program->IsValid() because
5098 // it could never be invalid since glUseProgram would have failed. While
5099 // glLinkProgram could later mark the program as invalid the previous
5100 // valid program will still function if it is still the current program.
[email protected]ca488e12010-12-13 20:06:145101 if (!current_program_) {
[email protected]3916c97e2010-02-25 03:20:505102 // The program does not exist.
5103 // But GL says no ERROR.
[email protected]0f8afe82012-05-14 23:43:015104 RenderWarning("Drawing with no current shader program.");
[email protected]3916c97e2010-02-25 03:20:505105 return false;
5106 }
[email protected]c6aef902012-02-14 03:31:425107
5108 // true if any enabled, used divisor is zero
5109 bool divisor0 = false;
[email protected]f39f4b3f2010-05-12 17:04:085110 // Validate all attribs currently enabled. If they are used by the current
5111 // program then check that they have enough elements to handle the draw call.
5112 // If they are not used by the current program check that they have a buffer
5113 // assigned.
5114 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:445115 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]f39f4b3f2010-05-12 17:04:085116 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
[email protected]8fbedc02010-11-18 18:43:405117 infos.begin(); it != infos.end(); ++it) {
[email protected]f39f4b3f2010-05-12 17:04:085118 const VertexAttribManager::VertexAttribInfo* info = *it;
5119 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5120 current_program_->GetAttribInfoByLocation(info->index());
5121 if (attrib_info) {
[email protected]c6aef902012-02-14 03:31:425122 divisor0 |= (info->divisor() == 0);
5123 GLuint count = info->MaxVertexAccessed(primcount, max_vertex_accessed);
[email protected]f39f4b3f2010-05-12 17:04:085124 // This attrib is used in the current program.
[email protected]c6aef902012-02-14 03:31:425125 if (!info->CanAccess(count)) {
[email protected]0f8afe82012-05-14 23:43:015126 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:435127 GL_INVALID_OPERATION, function_name,
[email protected]0f8afe82012-05-14 23:43:015128 (std::string(
[email protected]ad84a3a2012-06-08 21:42:435129 "attempt to access out of range vertices in attribute ") +
5130 base::IntToString(info->index())).c_str());
[email protected]f39f4b3f2010-05-12 17:04:085131 return false;
5132 }
5133 } else {
5134 // This attrib is not used in the current program.
[email protected]a0b78dc2011-11-11 10:43:105135 if (!info->buffer()) {
[email protected]f39f4b3f2010-05-12 17:04:085136 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:435137 GL_INVALID_OPERATION, function_name,
[email protected]0f8afe82012-05-14 23:43:015138 (std::string(
[email protected]ad84a3a2012-06-08 21:42:435139 "attempt to render with no buffer attached to "
[email protected]0f8afe82012-05-14 23:43:015140 "enabled attribute ") +
5141 base::IntToString(info->index())).c_str());
[email protected]f39f4b3f2010-05-12 17:04:085142 return false;
5143 }
[email protected]1d32bc82010-01-13 22:06:465144 }
[email protected]07f54fcc2009-12-22 02:46:305145 }
[email protected]c6aef902012-02-14 03:31:425146
5147 if (primcount && !divisor0) {
5148 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:435149 GL_INVALID_OPERATION, function_name,
5150 "attempt instanced render with all attributes having "
[email protected]c6aef902012-02-14 03:31:425151 "non-zero divisors");
5152 return false;
5153 }
5154
[email protected]3916c97e2010-02-25 03:20:505155 return true;
[email protected]b1122982010-05-17 23:04:245156}
5157
[email protected]c13e1da62011-09-09 21:48:305158bool GLES2DecoderImpl::SimulateAttrib0(
[email protected]ad84a3a2012-06-08 21:42:435159 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
[email protected]c13e1da62011-09-09 21:48:305160 DCHECK(simulated);
5161 *simulated = false;
5162
[email protected]876f6fee2010-08-02 23:10:325163 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
[email protected]c13e1da62011-09-09 21:48:305164 return true;
[email protected]876f6fee2010-08-02 23:10:325165
[email protected]b1122982010-05-17 23:04:245166 const VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445167 vertex_attrib_manager_->GetVertexAttribInfo(0);
[email protected]b1122982010-05-17 23:04:245168 // If it's enabled or it's not used then we don't need to do anything.
[email protected]fc753442011-02-04 19:49:495169 bool attrib_0_used = current_program_->GetAttribInfoByLocation(0) != NULL;
5170 if (info->enabled() && attrib_0_used) {
[email protected]c13e1da62011-09-09 21:48:305171 return true;
[email protected]b1122982010-05-17 23:04:245172 }
5173
[email protected]b1122982010-05-17 23:04:245174 // Make a buffer with a single repeated vec4 value enough to
5175 // simulate the constant value that is supposed to be here.
5176 // This is required to emulate GLES2 on GL.
[email protected]c13e1da62011-09-09 21:48:305177 typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
5178
5179 GLuint num_vertices = max_vertex_accessed + 1;
5180 GLuint size_needed = 0;
5181
5182 if (num_vertices == 0 ||
5183 !SafeMultiply(num_vertices, static_cast<GLuint>(sizeof(Vec4)),
5184 &size_needed) ||
5185 size_needed > 0x7FFFFFFFU) {
[email protected]ad84a3a2012-06-08 21:42:435186 SetGLError(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c13e1da62011-09-09 21:48:305187 return false;
5188 }
5189
[email protected]0f8afe82012-05-14 23:43:015190 PerformanceWarning(
5191 "Attribute 0 is disabled. This has signficant performance penalty");
5192
[email protected]c13e1da62011-09-09 21:48:305193 CopyRealGLErrorsToWrapper();
5194 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
5195
[email protected]8f0b86c2f2012-04-10 05:48:285196 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
5197 if (new_buffer) {
[email protected]fc753442011-02-04 19:49:495198 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305199 GLenum error = glGetError();
5200 if (error != GL_NO_ERROR) {
[email protected]ad84a3a2012-06-08 21:42:435201 SetGLError(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c13e1da62011-09-09 21:48:305202 return false;
5203 }
[email protected]fc753442011-02-04 19:49:495204 }
[email protected]8f0b86c2f2012-04-10 05:48:285205 if (new_buffer ||
5206 (attrib_0_used &&
5207 (!attrib_0_buffer_matches_value_ ||
5208 (info->value().v[0] != attrib_0_value_.v[0] ||
5209 info->value().v[1] != attrib_0_value_.v[1] ||
5210 info->value().v[2] != attrib_0_value_.v[2] ||
5211 info->value().v[3] != attrib_0_value_.v[3])))) {
[email protected]fc753442011-02-04 19:49:495212 std::vector<Vec4> temp(num_vertices, info->value());
5213 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
5214 attrib_0_buffer_matches_value_ = true;
[email protected]b1122982010-05-17 23:04:245215 attrib_0_value_ = info->value();
5216 attrib_0_size_ = size_needed;
5217 }
5218
5219 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5220
[email protected]c6aef902012-02-14 03:31:425221 if (info->divisor())
5222 glVertexAttribDivisorANGLE(0, 0);
5223
[email protected]c13e1da62011-09-09 21:48:305224 *simulated = true;
[email protected]b1122982010-05-17 23:04:245225 return true;
[email protected]b1122982010-05-17 23:04:245226}
5227
[email protected]43410e92012-04-20 17:06:285228void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib) {
[email protected]b1122982010-05-17 23:04:245229 const VertexAttribManager::VertexAttribInfo* info =
[email protected]43410e92012-04-20 17:06:285230 vertex_attrib_manager_->GetVertexAttribInfo(attrib);
[email protected]b1122982010-05-17 23:04:245231 const void* ptr = reinterpret_cast<const void*>(info->offset());
5232 BufferManager::BufferInfo* buffer_info = info->buffer();
5233 glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0);
5234 glVertexAttribPointer(
[email protected]43410e92012-04-20 17:06:285235 attrib, info->size(), info->type(), info->normalized(), info->gl_stride(),
[email protected]b1122982010-05-17 23:04:245236 ptr);
[email protected]c6aef902012-02-14 03:31:425237 if (info->divisor())
[email protected]43410e92012-04-20 17:06:285238 glVertexAttribDivisorANGLE(attrib, info->divisor());
[email protected]b1122982010-05-17 23:04:245239 glBindBuffer(GL_ARRAY_BUFFER,
5240 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
[email protected]43410e92012-04-20 17:06:285241
5242 if (info->enabled()) {
5243 glEnableVertexAttribArray(attrib);
5244 } else {
5245 glDisableVertexAttribArray(attrib);
5246 }
[email protected]b1122982010-05-17 23:04:245247}
[email protected]07f54fcc2009-12-22 02:46:305248
[email protected]8fbedc02010-11-18 18:43:405249bool GLES2DecoderImpl::SimulateFixedAttribs(
[email protected]ad84a3a2012-06-08 21:42:435250 const char* function_name,
[email protected]c6aef902012-02-14 03:31:425251 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
[email protected]8fbedc02010-11-18 18:43:405252 DCHECK(simulated);
5253 *simulated = false;
5254 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
5255 return true;
5256
[email protected]3757a372012-01-19 05:20:445257 if (!vertex_attrib_manager_->HaveFixedAttribs()) {
[email protected]8fbedc02010-11-18 18:43:405258 return true;
5259 }
5260
[email protected]0f8afe82012-05-14 23:43:015261 PerformanceWarning(
5262 "GL_FIXED attributes have a signficant performance penalty");
5263
[email protected]8fbedc02010-11-18 18:43:405264 // NOTE: we could be smart and try to check if a buffer is used
5265 // twice in 2 different attribs, find the overlapping parts and therefore
5266 // duplicate the minimum amount of data but this whole code path is not meant
5267 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
5268 // tests so we just add to the buffer attrib used.
5269
[email protected]c13e1da62011-09-09 21:48:305270 GLuint elements_needed = 0;
[email protected]8fbedc02010-11-18 18:43:405271 const VertexAttribManager::VertexAttribInfoList& infos =
[email protected]3757a372012-01-19 05:20:445272 vertex_attrib_manager_->GetEnabledVertexAttribInfos();
[email protected]8fbedc02010-11-18 18:43:405273 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5274 infos.begin(); it != infos.end(); ++it) {
5275 const VertexAttribManager::VertexAttribInfo* info = *it;
5276 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5277 current_program_->GetAttribInfoByLocation(info->index());
[email protected]c6aef902012-02-14 03:31:425278 GLuint max_accessed = info->MaxVertexAccessed(primcount,
5279 max_vertex_accessed);
5280 GLuint num_vertices = max_accessed + 1;
5281 if (num_vertices == 0) {
[email protected]ad84a3a2012-06-08 21:42:435282 SetGLError(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c6aef902012-02-14 03:31:425283 return false;
5284 }
[email protected]8fbedc02010-11-18 18:43:405285 if (attrib_info &&
[email protected]c6aef902012-02-14 03:31:425286 info->CanAccess(max_accessed) &&
[email protected]8fbedc02010-11-18 18:43:405287 info->type() == GL_FIXED) {
[email protected]c13e1da62011-09-09 21:48:305288 GLuint elements_used = 0;
5289 if (!SafeMultiply(num_vertices,
5290 static_cast<GLuint>(info->size()), &elements_used) ||
[email protected]8fbedc02010-11-18 18:43:405291 !SafeAdd(elements_needed, elements_used, &elements_needed)) {
[email protected]ad84a3a2012-06-08 21:42:435292 SetGLError(
5293 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]8fbedc02010-11-18 18:43:405294 return false;
5295 }
5296 }
5297 }
5298
[email protected]c13e1da62011-09-09 21:48:305299 const GLuint kSizeOfFloat = sizeof(float); // NOLINT
5300 GLuint size_needed = 0;
5301 if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed) ||
5302 size_needed > 0x7FFFFFFFU) {
[email protected]ad84a3a2012-06-08 21:42:435303 SetGLError(GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]8fbedc02010-11-18 18:43:405304 return false;
5305 }
5306
[email protected]c13e1da62011-09-09 21:48:305307 CopyRealGLErrorsToWrapper();
[email protected]8fbedc02010-11-18 18:43:405308
5309 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
[email protected]c13e1da62011-09-09 21:48:305310 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
[email protected]8fbedc02010-11-18 18:43:405311 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305312 GLenum error = glGetError();
5313 if (error != GL_NO_ERROR) {
[email protected]ad84a3a2012-06-08 21:42:435314 SetGLError(
5315 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]c13e1da62011-09-09 21:48:305316 return false;
5317 }
[email protected]8fbedc02010-11-18 18:43:405318 }
5319
5320 // Copy the elements and convert to float
5321 GLintptr offset = 0;
5322 for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
5323 infos.begin(); it != infos.end(); ++it) {
5324 const VertexAttribManager::VertexAttribInfo* info = *it;
5325 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
5326 current_program_->GetAttribInfoByLocation(info->index());
[email protected]c6aef902012-02-14 03:31:425327 GLuint max_accessed = info->MaxVertexAccessed(primcount,
5328 max_vertex_accessed);
5329 GLuint num_vertices = max_accessed + 1;
5330 if (num_vertices == 0) {
[email protected]ad84a3a2012-06-08 21:42:435331 SetGLError(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c6aef902012-02-14 03:31:425332 return false;
5333 }
[email protected]8fbedc02010-11-18 18:43:405334 if (attrib_info &&
[email protected]c6aef902012-02-14 03:31:425335 info->CanAccess(max_accessed) &&
[email protected]8fbedc02010-11-18 18:43:405336 info->type() == GL_FIXED) {
5337 int num_elements = info->size() * kSizeOfFloat;
5338 int size = num_elements * num_vertices;
5339 scoped_array<float> data(new float[size]);
5340 const int32* src = reinterpret_cast<const int32 *>(
5341 info->buffer()->GetRange(info->offset(), size));
5342 const int32* end = src + num_elements;
5343 float* dst = data.get();
5344 while (src != end) {
5345 *dst++ = static_cast<float>(*src++) / 65536.0f;
5346 }
5347 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
5348 glVertexAttribPointer(
5349 info->index(), info->size(), GL_FLOAT, false, 0,
5350 reinterpret_cast<GLvoid*>(offset));
5351 offset += size;
5352 }
5353 }
5354 *simulated = true;
5355 return true;
5356}
5357
5358void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
5359 // There's no need to call glVertexAttribPointer because we shadow all the
5360 // settings and passing GL_FIXED to it will not work.
5361 glBindBuffer(GL_ARRAY_BUFFER,
5362 bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
5363}
5364
[email protected]ad84a3a2012-06-08 21:42:435365error::Error GLES2DecoderImpl::DoDrawArrays(
5366 const char* function_name,
5367 bool instanced,
5368 GLenum mode,
5369 GLint first,
5370 GLsizei count,
5371 GLsizei primcount) {
[email protected]38d139d2011-07-14 00:38:435372 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]ad84a3a2012-06-08 21:42:435373 SetGLError(GL_INVALID_ENUM, function_name, "mode GL_INVALID_ENUM");
[email protected]38d139d2011-07-14 00:38:435374 return error::kNoError;
5375 }
5376 if (count < 0) {
[email protected]ad84a3a2012-06-08 21:42:435377 SetGLError(GL_INVALID_VALUE, function_name, "count < 0");
[email protected]38d139d2011-07-14 00:38:435378 return error::kNoError;
5379 }
[email protected]c6aef902012-02-14 03:31:425380 if (primcount < 0) {
[email protected]ad84a3a2012-06-08 21:42:435381 SetGLError(GL_INVALID_VALUE, function_name, "primcount < 0");
[email protected]c6aef902012-02-14 03:31:425382 return error::kNoError;
5383 }
[email protected]ad84a3a2012-06-08 21:42:435384 if (!CheckBoundFramebuffersValid(function_name)) {
[email protected]38d139d2011-07-14 00:38:435385 return error::kNoError;
5386 }
5387 // We have to check this here because the prototype for glDrawArrays
5388 // is GLint not GLsizei.
5389 if (first < 0) {
[email protected]ad84a3a2012-06-08 21:42:435390 SetGLError(GL_INVALID_VALUE, function_name, "first < 0");
[email protected]38d139d2011-07-14 00:38:435391 return error::kNoError;
5392 }
5393
[email protected]c6aef902012-02-14 03:31:425394 if (count == 0 || (instanced && primcount == 0)) {
[email protected]0f8afe82012-05-14 23:43:015395 RenderWarning("Render count or primcount is 0.");
[email protected]38d139d2011-07-14 00:38:435396 return error::kNoError;
5397 }
5398
5399 GLuint max_vertex_accessed = first + count - 1;
[email protected]ad84a3a2012-06-08 21:42:435400 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:205401 if (!ClearUnclearedTextures()) {
[email protected]ad84a3a2012-06-08 21:42:435402 SetGLError(GL_INVALID_VALUE, function_name, "out of memory");
[email protected]0d6bfdc2011-11-02 01:32:205403 return error::kNoError;
5404 }
[email protected]c13e1da62011-09-09 21:48:305405 bool simulated_attrib_0 = false;
[email protected]ad84a3a2012-06-08 21:42:435406 if (!SimulateAttrib0(
5407 function_name, max_vertex_accessed, &simulated_attrib_0)) {
[email protected]c13e1da62011-09-09 21:48:305408 return error::kNoError;
5409 }
[email protected]38d139d2011-07-14 00:38:435410 bool simulated_fixed_attribs = false;
[email protected]ad84a3a2012-06-08 21:42:435411 if (SimulateFixedAttribs(
5412 function_name, max_vertex_accessed, &simulated_fixed_attribs,
5413 primcount)) {
[email protected]38d139d2011-07-14 00:38:435414 bool textures_set = SetBlackTextureForNonRenderableTextures();
5415 ApplyDirtyState();
[email protected]c6aef902012-02-14 03:31:425416 if (!instanced) {
5417 glDrawArrays(mode, first, count);
5418 } else {
5419 glDrawArraysInstancedANGLE(mode, first, count, primcount);
5420 }
[email protected]22e3f552012-03-13 01:54:195421 ProcessPendingQueries();
[email protected]38d139d2011-07-14 00:38:435422 if (textures_set) {
5423 RestoreStateForNonRenderableTextures();
5424 }
5425 if (simulated_fixed_attribs) {
5426 RestoreStateForSimulatedFixedAttribs();
5427 }
5428 }
5429 if (simulated_attrib_0) {
[email protected]43410e92012-04-20 17:06:285430 RestoreStateForAttrib(0);
[email protected]38d139d2011-07-14 00:38:435431 }
5432 if (WasContextLost()) {
5433 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawArrays.";
5434 return error::kLostContext;
5435 }
5436 }
5437 return error::kNoError;
5438}
5439
[email protected]c6aef902012-02-14 03:31:425440error::Error GLES2DecoderImpl::HandleDrawArrays(
5441 uint32 immediate_data_size, const gles2::DrawArrays& c) {
[email protected]ad84a3a2012-06-08 21:42:435442 return DoDrawArrays("glDrawArrays",
5443 false,
[email protected]c6aef902012-02-14 03:31:425444 static_cast<GLenum>(c.mode),
5445 static_cast<GLint>(c.first),
5446 static_cast<GLsizei>(c.count),
5447 0);
5448}
5449
5450error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
5451 uint32 immediate_data_size, const gles2::DrawArraysInstancedANGLE& c) {
5452 if (!feature_info_->feature_flags().angle_instanced_arrays) {
5453 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435454 "glDrawArraysInstancedANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:425455 return error::kNoError;
5456 }
[email protected]ad84a3a2012-06-08 21:42:435457 return DoDrawArrays("glDrawArraysIntancedANGLE",
5458 true,
[email protected]c6aef902012-02-14 03:31:425459 static_cast<GLenum>(c.mode),
5460 static_cast<GLint>(c.first),
5461 static_cast<GLsizei>(c.count),
5462 static_cast<GLsizei>(c.primcount));
5463}
5464
[email protected]ad84a3a2012-06-08 21:42:435465error::Error GLES2DecoderImpl::DoDrawElements(
5466 const char* function_name,
5467 bool instanced,
5468 GLenum mode,
5469 GLsizei count,
5470 GLenum type,
5471 int32 offset,
5472 GLsizei primcount) {
[email protected]a0b78dc2011-11-11 10:43:105473 if (!bound_element_array_buffer_) {
[email protected]8eee29c2010-04-29 03:38:295474 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435475 function_name, "No element array buffer bound");
[email protected]8eee29c2010-04-29 03:38:295476 return error::kNoError;
5477 }
5478
[email protected]8eee29c2010-04-29 03:38:295479 if (count < 0) {
[email protected]ad84a3a2012-06-08 21:42:435480 SetGLError(GL_INVALID_VALUE, function_name, "count < 0");
[email protected]8eee29c2010-04-29 03:38:295481 return error::kNoError;
5482 }
5483 if (offset < 0) {
[email protected]ad84a3a2012-06-08 21:42:435484 SetGLError(GL_INVALID_VALUE, function_name, "offset < 0");
[email protected]8eee29c2010-04-29 03:38:295485 return error::kNoError;
5486 }
[email protected]9438b012010-06-15 22:55:055487 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]ad84a3a2012-06-08 21:42:435488 SetGLError(GL_INVALID_ENUM, function_name, "mode GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:295489 return error::kNoError;
5490 }
[email protected]9438b012010-06-15 22:55:055491 if (!validators_->index_type.IsValid(type)) {
[email protected]ad84a3a2012-06-08 21:42:435492 SetGLError(GL_INVALID_ENUM, function_name, "type GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:295493 return error::kNoError;
5494 }
[email protected]c6aef902012-02-14 03:31:425495 if (primcount < 0) {
[email protected]ad84a3a2012-06-08 21:42:435496 SetGLError(GL_INVALID_VALUE, function_name, "primcount < 0");
[email protected]c6aef902012-02-14 03:31:425497 return error::kNoError;
5498 }
[email protected]8eee29c2010-04-29 03:38:295499
[email protected]ad84a3a2012-06-08 21:42:435500 if (!CheckBoundFramebuffersValid(function_name)) {
[email protected]3a03a8f2011-03-19 00:51:275501 return error::kNoError;
5502 }
5503
[email protected]c6aef902012-02-14 03:31:425504 if (count == 0 || (instanced && primcount == 0)) {
[email protected]6c788fb72010-08-26 02:16:315505 return error::kNoError;
5506 }
5507
[email protected]8eee29c2010-04-29 03:38:295508 GLuint max_vertex_accessed;
5509 if (!bound_element_array_buffer_->GetMaxValueForRange(
5510 offset, count, type, &max_vertex_accessed)) {
5511 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435512 function_name, "range out of bounds for buffer");
[email protected]8eee29c2010-04-29 03:38:295513 return error::kNoError;
5514 }
5515
[email protected]ad84a3a2012-06-08 21:42:435516 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:205517 if (!ClearUnclearedTextures()) {
[email protected]ad84a3a2012-06-08 21:42:435518 SetGLError(GL_INVALID_VALUE, function_name, "out of memory");
[email protected]0d6bfdc2011-11-02 01:32:205519 return error::kNoError;
5520 }
[email protected]c13e1da62011-09-09 21:48:305521 bool simulated_attrib_0 = false;
[email protected]ad84a3a2012-06-08 21:42:435522 if (!SimulateAttrib0(
5523 function_name, max_vertex_accessed, &simulated_attrib_0)) {
[email protected]c13e1da62011-09-09 21:48:305524 return error::kNoError;
5525 }
[email protected]8fbedc02010-11-18 18:43:405526 bool simulated_fixed_attribs = false;
[email protected]ad84a3a2012-06-08 21:42:435527 if (SimulateFixedAttribs(
5528 function_name, max_vertex_accessed, &simulated_fixed_attribs,
5529 primcount)) {
[email protected]8fbedc02010-11-18 18:43:405530 bool textures_set = SetBlackTextureForNonRenderableTextures();
[email protected]297ca1c2011-06-20 23:08:465531 ApplyDirtyState();
[email protected]8fbedc02010-11-18 18:43:405532 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
[email protected]c6aef902012-02-14 03:31:425533 if (!instanced) {
5534 glDrawElements(mode, count, type, indices);
5535 } else {
5536 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
5537 }
[email protected]22e3f552012-03-13 01:54:195538 ProcessPendingQueries();
[email protected]8fbedc02010-11-18 18:43:405539 if (textures_set) {
5540 RestoreStateForNonRenderableTextures();
5541 }
5542 if (simulated_fixed_attribs) {
5543 RestoreStateForSimulatedFixedAttribs();
5544 }
[email protected]ba3176a2009-12-16 18:19:465545 }
[email protected]b1122982010-05-17 23:04:245546 if (simulated_attrib_0) {
[email protected]43410e92012-04-20 17:06:285547 RestoreStateForAttrib(0);
[email protected]b1122982010-05-17 23:04:245548 }
[email protected]38d139d2011-07-14 00:38:435549 if (WasContextLost()) {
5550 LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawElements.";
5551 return error::kLostContext;
5552 }
[email protected]96449d2c2009-11-25 00:01:325553 }
[email protected]f7a64ee2010-02-01 22:24:145554 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325555}
5556
[email protected]c6aef902012-02-14 03:31:425557error::Error GLES2DecoderImpl::HandleDrawElements(
5558 uint32 immediate_data_size, const gles2::DrawElements& c) {
[email protected]ad84a3a2012-06-08 21:42:435559 return DoDrawElements("glDrawElements",
5560 false,
[email protected]c6aef902012-02-14 03:31:425561 static_cast<GLenum>(c.mode),
5562 static_cast<GLsizei>(c.count),
5563 static_cast<GLenum>(c.type),
5564 static_cast<int32>(c.index_offset),
5565 0);
5566}
5567
5568error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
5569 uint32 immediate_data_size, const gles2::DrawElementsInstancedANGLE& c) {
5570 if (!feature_info_->feature_flags().angle_instanced_arrays) {
5571 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435572 "glDrawElementsInstancedANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:425573 return error::kNoError;
5574 }
[email protected]ad84a3a2012-06-08 21:42:435575 return DoDrawElements("glDrawElementsInstancedANGLE",
5576 true,
[email protected]c6aef902012-02-14 03:31:425577 static_cast<GLenum>(c.mode),
5578 static_cast<GLsizei>(c.count),
5579 static_cast<GLenum>(c.type),
5580 static_cast<int32>(c.index_offset),
5581 static_cast<GLsizei>(c.primcount));
5582}
5583
[email protected]269200b12010-11-18 22:53:065584GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:235585 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
5586 GLuint max_vertex_accessed = 0;
5587 BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
[email protected]8eee29c2010-04-29 03:38:295588 if (!info) {
[email protected]ae51d192010-04-27 00:48:035589 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]8eee29c2010-04-29 03:38:295590 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:435591 "GetMaxValueInBufferCHROMIUM", "unknown buffer");
[email protected]29a9eb52010-04-13 09:04:235592 } else {
5593 if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:035594 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]269200b12010-11-18 22:53:065595 SetGLError(
5596 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435597 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:235598 }
5599 }
5600 return max_vertex_accessed;
5601}
5602
[email protected]96449d2c2009-11-25 00:01:325603// Calls glShaderSource for the various versions of the ShaderSource command.
5604// Assumes that data / data_size points to a piece of memory that is in range
5605// of whatever context it came from (shared memory, immediate memory, bucket
5606// memory.)
[email protected]45bf5152010-02-12 00:11:315607error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035608 GLuint client_id, const char* data, uint32 data_size) {
[email protected]258a3313f2011-10-18 20:13:575609 std::string str(data, data + data_size);
[email protected]6b8cf1a2010-05-06 16:13:585610 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5611 client_id, "glShaderSource");
[email protected]45bf5152010-02-12 00:11:315612 if (!info) {
[email protected]45bf5152010-02-12 00:11:315613 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325614 }
[email protected]45bf5152010-02-12 00:11:315615 // Note: We don't actually call glShaderSource here. We wait until
5616 // the call to glCompileShader.
[email protected]258a3313f2011-10-18 20:13:575617 info->UpdateSource(str.c_str());
[email protected]f7a64ee2010-02-01 22:24:145618 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325619}
5620
[email protected]f7a64ee2010-02-01 22:24:145621error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]b9849abf2009-11-25 19:13:195622 uint32 immediate_data_size, const gles2::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:325623 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315624 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:325625 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:465626 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145627 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325628 }
[email protected]ae51d192010-04-27 00:48:035629 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:325630}
5631
[email protected]f7a64ee2010-02-01 22:24:145632error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]b9849abf2009-11-25 19:13:195633 uint32 immediate_data_size, const gles2::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:325634 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:315635 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:305636 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:465637 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:145638 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:325639 }
[email protected]ae51d192010-04-27 00:48:035640 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:315641}
5642
[email protected]558847a2010-03-24 07:02:545643error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
5644 uint32 immediate_data_size, const gles2::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:545645 Bucket* bucket = GetBucket(c.data_bucket_id);
5646 if (!bucket || bucket->size() == 0) {
5647 return error::kInvalidArguments;
5648 }
5649 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:035650 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:545651 bucket->size() - 1);
5652}
5653
[email protected]ae51d192010-04-27 00:48:035654void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]43ed3a72012-05-30 22:55:385655 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]6b8cf1a2010-05-06 16:13:585656 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5657 client_id, "glCompileShader");
[email protected]45bf5152010-02-12 00:11:315658 if (!info) {
[email protected]45bf5152010-02-12 00:11:315659 return;
5660 }
[email protected]de17df392010-04-23 21:09:415661 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
5662 // glShaderSource and then glCompileShader.
[email protected]df6cf1ad2011-01-29 01:20:525663 const char* shader_src = info->source() ? info->source()->c_str() : "";
[email protected]f57bb282010-11-12 00:51:345664 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:185665 if (use_shader_translator_) {
[email protected]f57bb282010-11-12 00:51:345666 translator = info->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:455667 vertex_translator_.get() : fragment_translator_.get();
[email protected]5236b752010-07-27 18:02:235668
[email protected]a550584e2010-09-17 18:01:455669 if (!translator->Translate(shader_src)) {
[email protected]f57bb282010-11-12 00:51:345670 info->SetStatus(false, translator->info_log(), NULL);
[email protected]b1d2dcb2010-05-17 19:24:185671 return;
5672 }
[email protected]a550584e2010-09-17 18:01:455673 shader_src = translator->translated_shader();
[email protected]93297702011-11-05 05:09:465674 if (!feature_info_->feature_flags().angle_translated_shader_source)
[email protected]d6a53e42011-10-05 00:09:365675 info->UpdateTranslatedSource(shader_src);
[email protected]de17df392010-04-23 21:09:415676 }
[email protected]de17df392010-04-23 21:09:415677
[email protected]ae51d192010-04-27 00:48:035678 glShaderSource(info->service_id(), 1, &shader_src, NULL);
5679 glCompileShader(info->service_id());
[email protected]93297702011-11-05 05:09:465680 if (feature_info_->feature_flags().angle_translated_shader_source) {
[email protected]d6a53e42011-10-05 00:09:365681 GLint max_len = 0;
5682 glGetShaderiv(info->service_id(),
5683 GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
5684 &max_len);
5685 scoped_array<char> temp(new char[max_len]);
5686 GLint len = 0;
5687 glGetTranslatedShaderSourceANGLE(
5688 info->service_id(), max_len, &len, temp.get());
5689 DCHECK(max_len == 0 || len < max_len);
5690 DCHECK(len == 0 || temp[len] == '\0');
5691 info->UpdateTranslatedSource(temp.get());
5692 }
5693
[email protected]e5186162010-06-14 18:54:415694 GLint status = GL_FALSE;
5695 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
5696 if (status) {
[email protected]f57bb282010-11-12 00:51:345697 info->SetStatus(true, "", translator);
[email protected]e5186162010-06-14 18:54:415698 } else {
[email protected]d9977d42010-09-01 20:27:025699 // We cannot reach here if we are using the shader translator.
5700 // All invalid shaders must be rejected by the translator.
5701 // All translated shaders must compile.
5702 LOG_IF(ERROR, use_shader_translator_)
5703 << "Shader translator allowed/produced an invalid shader.";
[email protected]1fd26d82010-11-04 16:06:335704 GLint max_len = 0;
5705 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
5706 scoped_array<char> temp(new char[max_len]);
[email protected]e5186162010-06-14 18:54:415707 GLint len = 0;
[email protected]1fd26d82010-11-04 16:06:335708 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
5709 DCHECK(max_len == 0 || len < max_len);
[email protected]d6a53e42011-10-05 00:09:365710 DCHECK(len == 0 || temp[len] == '\0');
[email protected]df6cf1ad2011-01-29 01:20:525711 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
[email protected]e5186162010-06-14 18:54:415712 }
[email protected]45bf5152010-02-12 00:11:315713};
5714
[email protected]ddd968b82010-03-02 00:44:295715void GLES2DecoderImpl::DoGetShaderiv(
5716 GLuint shader, GLenum pname, GLint* params) {
[email protected]6b8cf1a2010-05-06 16:13:585717 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5718 shader, "glGetShaderiv");
[email protected]ddd968b82010-03-02 00:44:295719 if (!info) {
[email protected]ddd968b82010-03-02 00:44:295720 return;
5721 }
[email protected]8f1ccdac2010-05-19 21:01:485722 switch (pname) {
5723 case GL_SHADER_SOURCE_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525724 *params = info->source() ? info->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:485725 return;
5726 case GL_COMPILE_STATUS:
[email protected]062c38b2012-01-18 03:25:105727 *params = compile_shader_always_succeeds_ ? true : info->IsValid();
[email protected]e5186162010-06-14 18:54:415728 return;
[email protected]8f1ccdac2010-05-19 21:01:485729 case GL_INFO_LOG_LENGTH:
[email protected]df6cf1ad2011-01-29 01:20:525730 *params = info->log_info() ? info->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:415731 return;
[email protected]d6a53e42011-10-05 00:09:365732 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5733 *params = info->translated_source() ?
5734 info->translated_source()->size() + 1 : 0;
5735 return;
[email protected]8f1ccdac2010-05-19 21:01:485736 default:
5737 break;
[email protected]ddd968b82010-03-02 00:44:295738 }
[email protected]8f1ccdac2010-05-19 21:01:485739 glGetShaderiv(info->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:295740}
5741
[email protected]ae51d192010-04-27 00:48:035742error::Error GLES2DecoderImpl::HandleGetShaderSource(
5743 uint32 immediate_data_size, const gles2::GetShaderSource& c) {
5744 GLuint shader = c.shader;
[email protected]ae51d192010-04-27 00:48:035745 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5746 Bucket* bucket = CreateBucket(bucket_id);
[email protected]6b8cf1a2010-05-06 16:13:585747 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5748 shader, "glGetShaderSource");
[email protected]df6cf1ad2011-01-29 01:20:525749 if (!info || !info->source()) {
[email protected]8eee29c2010-04-29 03:38:295750 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:295751 return error::kNoError;
5752 }
[email protected]df6cf1ad2011-01-29 01:20:525753 bucket->SetFromString(info->source()->c_str());
[email protected]ae51d192010-04-27 00:48:035754 return error::kNoError;
5755}
5756
[email protected]d6a53e42011-10-05 00:09:365757error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
5758 uint32 immediate_data_size,
5759 const gles2::GetTranslatedShaderSourceANGLE& c) {
5760 GLuint shader = c.shader;
5761
5762 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5763 Bucket* bucket = CreateBucket(bucket_id);
5764 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5765 shader, "glTranslatedGetShaderSourceANGLE");
5766 if (!info) {
5767 bucket->SetSize(0);
5768 return error::kNoError;
5769 }
5770
5771 bucket->SetFromString(info->translated_source() ?
5772 info->translated_source()->c_str() : NULL);
5773 return error::kNoError;
5774}
5775
[email protected]ae51d192010-04-27 00:48:035776error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
5777 uint32 immediate_data_size, const gles2::GetProgramInfoLog& c) {
5778 GLuint program = c.program;
[email protected]6b8cf1a2010-05-06 16:13:585779 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5780 Bucket* bucket = CreateBucket(bucket_id);
5781 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5782 program, "glGetProgramInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525783 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465784 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035785 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:315786 }
[email protected]df6cf1ad2011-01-29 01:20:525787 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035788 return error::kNoError;
5789}
5790
5791error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
5792 uint32 immediate_data_size, const gles2::GetShaderInfoLog& c) {
5793 GLuint shader = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:585794 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
5795 Bucket* bucket = CreateBucket(bucket_id);
5796 ShaderManager::ShaderInfo* info = GetShaderInfoNotProgram(
5797 shader, "glGetShaderInfoLog");
[email protected]df6cf1ad2011-01-29 01:20:525798 if (!info || !info->log_info()) {
[email protected]9a14ae612011-08-08 17:51:465799 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:035800 return error::kNoError;
5801 }
[email protected]df6cf1ad2011-01-29 01:20:525802 bucket->SetFromString(info->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:035803 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:325804}
5805
[email protected]1958e0e2010-04-22 05:17:155806bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105807 const BufferManager::BufferInfo* buffer = GetBufferInfo(client_id);
5808 return buffer && buffer->IsValid() && !buffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155809}
5810
5811bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105812 const FramebufferManager::FramebufferInfo* framebuffer =
[email protected]06c8b082011-01-05 18:00:365813 GetFramebufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105814 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155815}
5816
5817bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365818 // IsProgram is true for programs as soon as they are created, until they are
5819 // deleted and no longer in use.
[email protected]a0b78dc2011-11-11 10:43:105820 const ProgramManager::ProgramInfo* program = GetProgramInfo(client_id);
5821 return program != NULL && !program->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155822}
5823
5824bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105825 const RenderbufferManager::RenderbufferInfo* renderbuffer =
[email protected]06c8b082011-01-05 18:00:365826 GetRenderbufferInfo(client_id);
[email protected]a0b78dc2011-11-11 10:43:105827 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155828}
5829
5830bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:365831 // IsShader is true for shaders as soon as they are created, until they
5832 // are deleted and not attached to any programs.
[email protected]a0b78dc2011-11-11 10:43:105833 const ShaderManager::ShaderInfo* shader = GetShaderInfo(client_id);
5834 return shader != NULL && !shader->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:155835}
5836
5837bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]a0b78dc2011-11-11 10:43:105838 const TextureManager::TextureInfo* texture = GetTextureInfo(client_id);
5839 return texture && texture->IsValid() && !texture->IsDeleted();
[email protected]ae51d192010-04-27 00:48:035840}
5841
5842void GLES2DecoderImpl::DoAttachShader(
5843 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585844 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5845 program_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035846 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035847 return;
[email protected]1958e0e2010-04-22 05:17:155848 }
[email protected]6b8cf1a2010-05-06 16:13:585849 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5850 shader_client_id, "glAttachShader");
[email protected]ae51d192010-04-27 00:48:035851 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035852 return;
5853 }
[email protected]ca488e12010-12-13 20:06:145854 if (!program_info->AttachShader(shader_manager(), shader_info)) {
[email protected]fb96c8e2010-08-12 04:10:315855 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435856 "glAttachShader", "can not attach more than"
[email protected]fb96c8e2010-08-12 04:10:315857 " one shader of the same type.");
5858 return;
5859 }
[email protected]ae51d192010-04-27 00:48:035860 glAttachShader(program_info->service_id(), shader_info->service_id());
5861}
5862
5863void GLES2DecoderImpl::DoDetachShader(
5864 GLuint program_client_id, GLint shader_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585865 ProgramManager::ProgramInfo* program_info = GetProgramInfoNotShader(
5866 program_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035867 if (!program_info) {
[email protected]ae51d192010-04-27 00:48:035868 return;
5869 }
[email protected]6b8cf1a2010-05-06 16:13:585870 ShaderManager::ShaderInfo* shader_info = GetShaderInfoNotProgram(
5871 shader_client_id, "glDetachShader");
[email protected]ae51d192010-04-27 00:48:035872 if (!shader_info) {
[email protected]ae51d192010-04-27 00:48:035873 return;
5874 }
[email protected]9a0ccd42011-03-16 23:58:225875 if (!program_info->DetachShader(shader_manager(), shader_info)) {
5876 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:435877 "glDetachShader", "shader not attached to program");
[email protected]9a0ccd42011-03-16 23:58:225878 return;
5879 }
[email protected]ae51d192010-04-27 00:48:035880 glDetachShader(program_info->service_id(), shader_info->service_id());
5881}
5882
5883void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]6b8cf1a2010-05-06 16:13:585884 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
5885 program_client_id, "glValidateProgram");
[email protected]ae51d192010-04-27 00:48:035886 if (!info) {
[email protected]ae51d192010-04-27 00:48:035887 return;
5888 }
[email protected]d685a682011-04-29 16:19:575889 info->Validate();
[email protected]1958e0e2010-04-22 05:17:155890}
5891
[email protected]b1122982010-05-17 23:04:245892void GLES2DecoderImpl::DoGetVertexAttribfv(
5893 GLuint index, GLenum pname, GLfloat* params) {
5894 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445895 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245896 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:435897 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
[email protected]b1122982010-05-17 23:04:245898 return;
5899 }
5900 switch (pname) {
5901 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5902 BufferManager::BufferInfo* buffer = info->buffer();
5903 if (buffer && !buffer->IsDeleted()) {
5904 GLuint client_id;
5905 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5906 *params = static_cast<GLfloat>(client_id);
5907 }
5908 break;
5909 }
5910 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5911 *params = static_cast<GLfloat>(info->enabled());
5912 break;
5913 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5914 *params = static_cast<GLfloat>(info->size());
5915 break;
5916 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5917 *params = static_cast<GLfloat>(info->gl_stride());
5918 break;
5919 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5920 *params = static_cast<GLfloat>(info->type());
5921 break;
5922 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5923 *params = static_cast<GLfloat>(info->normalized());
5924 break;
5925 case GL_CURRENT_VERTEX_ATTRIB:
5926 params[0] = info->value().v[0];
5927 params[1] = info->value().v[1];
5928 params[2] = info->value().v[2];
5929 params[3] = info->value().v[3];
5930 break;
[email protected]c6aef902012-02-14 03:31:425931 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
5932 *params = static_cast<GLfloat>(info->divisor());
5933 break;
[email protected]b1122982010-05-17 23:04:245934 default:
5935 NOTREACHED();
5936 break;
5937 }
5938}
5939
5940void GLES2DecoderImpl::DoGetVertexAttribiv(
5941 GLuint index, GLenum pname, GLint* params) {
5942 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445943 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245944 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:435945 SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
[email protected]b1122982010-05-17 23:04:245946 return;
5947 }
5948 switch (pname) {
5949 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
5950 BufferManager::BufferInfo* buffer = info->buffer();
5951 if (buffer && !buffer->IsDeleted()) {
5952 GLuint client_id;
5953 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
5954 *params = client_id;
5955 }
5956 break;
5957 }
5958 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5959 *params = info->enabled();
5960 break;
5961 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5962 *params = info->size();
5963 break;
5964 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5965 *params = info->gl_stride();
5966 break;
5967 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5968 *params = info->type();
5969 break;
5970 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5971 *params = static_cast<GLint>(info->normalized());
5972 break;
[email protected]c6aef902012-02-14 03:31:425973 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
5974 *params = info->divisor();
5975 break;
[email protected]b1122982010-05-17 23:04:245976 case GL_CURRENT_VERTEX_ATTRIB:
5977 params[0] = static_cast<GLint>(info->value().v[0]);
5978 params[1] = static_cast<GLint>(info->value().v[1]);
5979 params[2] = static_cast<GLint>(info->value().v[2]);
5980 params[3] = static_cast<GLint>(info->value().v[3]);
5981 break;
5982 default:
5983 NOTREACHED();
5984 break;
5985 }
5986}
5987
5988void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
5989 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:445990 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:245991 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:435992 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f", "index out of range");
[email protected]b1122982010-05-17 23:04:245993 return;
5994 }
5995 VertexAttribManager::VertexAttribInfo::Vec4 value;
5996 value.v[0] = v0;
5997 value.v[1] = 0.0f;
5998 value.v[2] = 0.0f;
5999 value.v[3] = 1.0f;
6000 info->set_value(value);
6001 glVertexAttrib1f(index, v0);
6002}
6003
6004void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
6005 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:446006 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246007 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436008 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f", "index out of range");
[email protected]b1122982010-05-17 23:04:246009 return;
6010 }
6011 VertexAttribManager::VertexAttribInfo::Vec4 value;
6012 value.v[0] = v0;
6013 value.v[1] = v1;
6014 value.v[2] = 0.0f;
6015 value.v[3] = 1.0f;
6016 info->set_value(value);
6017 glVertexAttrib2f(index, v0, v1);
6018}
6019
6020void GLES2DecoderImpl::DoVertexAttrib3f(
6021 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
6022 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:446023 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246024 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436025 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f", "index out of range");
[email protected]b1122982010-05-17 23:04:246026 return;
6027 }
6028 VertexAttribManager::VertexAttribInfo::Vec4 value;
6029 value.v[0] = v0;
6030 value.v[1] = v1;
6031 value.v[2] = v2;
6032 value.v[3] = 1.0f;
6033 info->set_value(value);
6034 glVertexAttrib3f(index, v0, v1, v2);
6035}
6036
6037void GLES2DecoderImpl::DoVertexAttrib4f(
6038 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
6039 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:446040 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246041 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436042 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f", "index out of range");
[email protected]b1122982010-05-17 23:04:246043 return;
6044 }
6045 VertexAttribManager::VertexAttribInfo::Vec4 value;
6046 value.v[0] = v0;
6047 value.v[1] = v1;
6048 value.v[2] = v2;
6049 value.v[3] = v3;
6050 info->set_value(value);
6051 glVertexAttrib4f(index, v0, v1, v2, v3);
6052}
6053
6054void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
6055 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:446056 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246057 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436058 SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv", "index out of range");
[email protected]b1122982010-05-17 23:04:246059 return;
6060 }
6061 VertexAttribManager::VertexAttribInfo::Vec4 value;
6062 value.v[0] = v[0];
6063 value.v[1] = 0.0f;
6064 value.v[2] = 0.0f;
6065 value.v[3] = 1.0f;
6066 info->set_value(value);
6067 glVertexAttrib1fv(index, v);
6068}
6069
6070void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
6071 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:446072 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246073 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436074 SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv", "index out of range");
[email protected]b1122982010-05-17 23:04:246075 return;
6076 }
6077 VertexAttribManager::VertexAttribInfo::Vec4 value;
6078 value.v[0] = v[0];
6079 value.v[1] = v[1];
6080 value.v[2] = 0.0f;
6081 value.v[3] = 1.0f;
6082 info->set_value(value);
6083 glVertexAttrib2fv(index, v);
6084}
6085
6086void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
6087 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:446088 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246089 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436090 SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv", "index out of range");
[email protected]b1122982010-05-17 23:04:246091 return;
6092 }
6093 VertexAttribManager::VertexAttribInfo::Vec4 value;
6094 value.v[0] = v[0];
6095 value.v[1] = v[1];
6096 value.v[2] = v[2];
6097 value.v[3] = 1.0f;
6098 info->set_value(value);
6099 glVertexAttrib3fv(index, v);
6100}
6101
6102void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
6103 VertexAttribManager::VertexAttribInfo* info =
[email protected]3757a372012-01-19 05:20:446104 vertex_attrib_manager_->GetVertexAttribInfo(index);
[email protected]b1122982010-05-17 23:04:246105 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436106 SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv", "index out of range");
[email protected]b1122982010-05-17 23:04:246107 return;
6108 }
6109 VertexAttribManager::VertexAttribInfo::Vec4 value;
6110 value.v[0] = v[0];
6111 value.v[1] = v[1];
6112 value.v[2] = v[2];
6113 value.v[3] = v[3];
6114 info->set_value(value);
6115 glVertexAttrib4fv(index, v);
6116}
6117
[email protected]f7a64ee2010-02-01 22:24:146118error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]b9849abf2009-11-25 19:13:196119 uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
[email protected]8eee29c2010-04-29 03:38:296120 if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
6121 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436122 "glVertexAttribPointer", "no array buffer bound");
[email protected]8eee29c2010-04-29 03:38:296123 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326124 }
[email protected]8eee29c2010-04-29 03:38:296125
6126 GLuint indx = c.indx;
6127 GLint size = c.size;
6128 GLenum type = c.type;
6129 GLboolean normalized = c.normalized;
6130 GLsizei stride = c.stride;
6131 GLsizei offset = c.offset;
6132 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:056133 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]8eee29c2010-04-29 03:38:296134 SetGLError(GL_INVALID_ENUM,
[email protected]ad84a3a2012-06-08 21:42:436135 "glVertexAttribPointer", "type GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:296136 return error::kNoError;
6137 }
[email protected]9438b012010-06-15 22:55:056138 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ff81c192011-01-07 23:04:316139 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436140 "glVertexAttribPointer", "size GL_INVALID_VALUE");
[email protected]8eee29c2010-04-29 03:38:296141 return error::kNoError;
6142 }
6143 if (indx >= group_->max_vertex_attribs()) {
[email protected]ad84a3a2012-06-08 21:42:436144 SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
[email protected]8eee29c2010-04-29 03:38:296145 return error::kNoError;
6146 }
6147 if (stride < 0) {
6148 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436149 "glVertexAttribPointer", "stride < 0");
[email protected]8eee29c2010-04-29 03:38:296150 return error::kNoError;
6151 }
6152 if (stride > 255) {
6153 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436154 "glVertexAttribPointer", "stride > 255");
[email protected]8eee29c2010-04-29 03:38:296155 return error::kNoError;
6156 }
6157 if (offset < 0) {
6158 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436159 "glVertexAttribPointer", "offset < 0");
[email protected]8eee29c2010-04-29 03:38:296160 return error::kNoError;
6161 }
6162 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:316163 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:296164 if (offset % component_size > 0) {
[email protected]ff81c192011-01-07 23:04:316165 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436166 "glVertexAttribPointer", "offset not valid for type");
[email protected]ff81c192011-01-07 23:04:316167 return error::kNoError;
6168 }
6169 if (stride % component_size > 0) {
6170 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436171 "glVertexAttribPointer", "stride not valid for type");
[email protected]8eee29c2010-04-29 03:38:296172 return error::kNoError;
6173 }
[email protected]3757a372012-01-19 05:20:446174 vertex_attrib_manager_->SetAttribInfo(
[email protected]8fbedc02010-11-18 18:43:406175 indx,
[email protected]8eee29c2010-04-29 03:38:296176 bound_array_buffer_,
6177 size,
6178 type,
[email protected]b1122982010-05-17 23:04:246179 normalized,
6180 stride,
6181 stride != 0 ? stride : component_size * size,
[email protected]8eee29c2010-04-29 03:38:296182 offset);
[email protected]8fbedc02010-11-18 18:43:406183 if (type != GL_FIXED) {
6184 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
6185 }
[email protected]f7a64ee2010-02-01 22:24:146186 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326187}
6188
[email protected]43410e92012-04-20 17:06:286189void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
6190 GLsizei height) {
6191 viewport_x_ = x;
6192 viewport_y_ = y;
6193 viewport_width_ = std::min(width, viewport_max_width_);
6194 viewport_height_ = std::min(height, viewport_max_height_);
6195 glViewport(x, y, width, height);
6196}
6197
[email protected]c6aef902012-02-14 03:31:426198error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
6199 uint32 immediate_data_size, const gles2::VertexAttribDivisorANGLE& c) {
6200 if (!feature_info_->feature_flags().angle_instanced_arrays) {
6201 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436202 "glVertexAttribDivisorANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:426203 }
6204 GLuint index = c.index;
6205 GLuint divisor = c.divisor;
6206 if (index >= group_->max_vertex_attribs()) {
6207 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436208 "glVertexAttribDivisorANGLE", "index out of range");
[email protected]c6aef902012-02-14 03:31:426209 return error::kNoError;
6210 }
6211
6212 vertex_attrib_manager_->SetDivisor(
6213 index,
6214 divisor);
6215 glVertexAttribDivisorANGLE(index, divisor);
6216 return error::kNoError;
6217}
6218
[email protected]f7a64ee2010-02-01 22:24:146219error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]b9849abf2009-11-25 19:13:196220 uint32 immediate_data_size, const gles2::ReadPixels& c) {
[email protected]612d2f82009-12-08 20:49:316221 GLint x = c.x;
6222 GLint y = c.y;
6223 GLsizei width = c.width;
6224 GLsizei height = c.height;
6225 GLenum format = c.format;
6226 GLenum type = c.type;
[email protected]57f223832010-03-19 01:57:566227 if (width < 0 || height < 0) {
[email protected]ad84a3a2012-06-08 21:42:436228 SetGLError(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
[email protected]57f223832010-03-19 01:57:566229 return error::kNoError;
6230 }
[email protected]a51788e2010-02-24 21:54:256231 typedef gles2::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:186232 uint32 pixels_size;
[email protected]3458a64a2012-04-10 17:39:346233 if (!GLES2Util::ComputeImageDataSizes(
6234 width, height, format, type, pack_alignment_, &pixels_size, NULL, NULL)) {
[email protected]a76b0052010-03-05 00:33:186235 return error::kOutOfBounds;
6236 }
[email protected]612d2f82009-12-08 20:49:316237 void* pixels = GetSharedMemoryAs<void*>(
6238 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]a51788e2010-02-24 21:54:256239 Result* result = GetSharedMemoryAs<Result*>(
6240 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6241 if (!pixels || !result) {
[email protected]f7a64ee2010-02-01 22:24:146242 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466243 }
[email protected]a51788e2010-02-24 21:54:256244
[email protected]9438b012010-06-15 22:55:056245 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]ad84a3a2012-06-08 21:42:436246 SetGLError(GL_INVALID_ENUM, "glReadPixels", "format GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:296247 return error::kNoError;
6248 }
[email protected]9438b012010-06-15 22:55:056249 if (!validators_->pixel_type.IsValid(type)) {
[email protected]ad84a3a2012-06-08 21:42:436250 SetGLError(GL_INVALID_ENUM, "glReadPixels", "type GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:126251 return error::kNoError;
6252 }
[email protected]57f223832010-03-19 01:57:566253 if (width == 0 || height == 0) {
6254 return error::kNoError;
6255 }
6256
[email protected]57f223832010-03-19 01:57:566257 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:306258 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:566259
6260 GLint max_x;
6261 GLint max_y;
6262 if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
[email protected]ad84a3a2012-06-08 21:42:436263 SetGLError(GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:146264 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:316265 }
[email protected]57f223832010-03-19 01:57:566266
[email protected]0d6bfdc2011-11-02 01:32:206267 if (!CheckBoundFramebuffersValid("glReadPixels")) {
6268 return error::kNoError;
6269 }
6270
[email protected]a0b78dc2011-11-11 10:43:106271 CopyRealGLErrorsToWrapper();
6272
6273 ScopedResolvedFrameBufferBinder binder(this, false, true);
6274
[email protected]d37231fa2010-04-09 21:16:026275 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:566276 // The user requested an out of range area. Get the results 1 line
6277 // at a time.
6278 uint32 temp_size;
[email protected]3458a64a2012-04-10 17:39:346279 uint32 unpadded_row_size;
6280 uint32 padded_row_size;
6281 if (!GLES2Util::ComputeImageDataSizes(
6282 width, 2, format, type, pack_alignment_, &temp_size,
6283 &unpadded_row_size, &padded_row_size)) {
[email protected]ad84a3a2012-06-08 21:42:436284 SetGLError(GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]57f223832010-03-19 01:57:566285 return error::kNoError;
6286 }
6287
6288 GLint dest_x_offset = std::max(-x, 0);
6289 uint32 dest_row_offset;
[email protected]3458a64a2012-04-10 17:39:346290 if (!GLES2Util::ComputeImageDataSizes(
6291 dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset, NULL,
6292 NULL)) {
[email protected]ad84a3a2012-06-08 21:42:436293 SetGLError(GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]57f223832010-03-19 01:57:566294 return error::kNoError;
6295 }
6296
6297 // Copy each row into the larger dest rect.
6298 int8* dst = static_cast<int8*>(pixels);
6299 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:026300 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:566301 GLint read_width = read_end_x - read_x;
6302 for (GLint yy = 0; yy < height; ++yy) {
6303 GLint ry = y + yy;
6304
6305 // Clear the row.
6306 memset(dst, 0, unpadded_row_size);
6307
6308 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:026309 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:566310 glReadPixels(
6311 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
6312 }
6313 dst += padded_row_size;
6314 }
6315 } else {
6316 glReadPixels(x, y, width, height, format, type, pixels);
6317 }
[email protected]1002c2d2011-06-28 22:39:046318 GLenum error = PeekGLError();
[email protected]a51788e2010-02-24 21:54:256319 if (error == GL_NO_ERROR) {
6320 *result = true;
[email protected]4848b9f82011-03-10 18:37:566321
6322 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6323 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
[email protected]c892a4e12012-05-08 18:20:196324 if ((channels_exist & 0x0008) == 0 && !disable_workarounds_) {
[email protected]4848b9f82011-03-10 18:37:566325 // Set the alpha to 255 because some drivers are buggy in this regard.
6326 uint32 temp_size;
[email protected]3458a64a2012-04-10 17:39:346327
6328 uint32 unpadded_row_size;
6329 uint32 padded_row_size;
6330 if (!GLES2Util::ComputeImageDataSizes(
6331 width, 2, format, type, pack_alignment_, &temp_size,
6332 &unpadded_row_size, &padded_row_size)) {
[email protected]ad84a3a2012-06-08 21:42:436333 SetGLError(GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]4848b9f82011-03-10 18:37:566334 return error::kNoError;
6335 }
6336 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
6337 // of this implementation.
6338 if (type != GL_UNSIGNED_BYTE) {
[email protected]ad84a3a2012-06-08 21:42:436339 SetGLError(
6340 GL_INVALID_OPERATION, "glReadPixels",
6341 "unsupported readPixel format");
[email protected]4848b9f82011-03-10 18:37:566342 return error::kNoError;
6343 }
6344 switch (format) {
6345 case GL_RGBA:
[email protected]297ca1c2011-06-20 23:08:466346 case GL_BGRA_EXT:
[email protected]4848b9f82011-03-10 18:37:566347 case GL_ALPHA: {
6348 int offset = (format == GL_ALPHA) ? 0 : 3;
6349 int step = (format == GL_ALPHA) ? 1 : 4;
6350 uint8* dst = static_cast<uint8*>(pixels) + offset;
6351 for (GLint yy = 0; yy < height; ++yy) {
6352 uint8* end = dst + unpadded_row_size;
6353 for (uint8* d = dst; d < end; d += step) {
6354 *d = 255;
6355 }
6356 dst += padded_row_size;
6357 }
6358 break;
6359 }
6360 default:
6361 break;
6362 }
6363 }
[email protected]a51788e2010-02-24 21:54:256364 }
[email protected]4848b9f82011-03-10 18:37:566365
[email protected]f7a64ee2010-02-01 22:24:146366 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326367}
6368
[email protected]f7a64ee2010-02-01 22:24:146369error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]b9849abf2009-11-25 19:13:196370 uint32 immediate_data_size, const gles2::PixelStorei& c) {
6371 GLenum pname = c.pname;
6372 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:056373 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]ad84a3a2012-06-08 21:42:436374 SetGLError(GL_INVALID_ENUM, "glPixelStorei", "pname GL_INVALID_ENUM");
[email protected]d2cf0a2d2010-02-25 21:36:126375 return error::kNoError;
6376 }
[email protected]222471d2011-11-30 18:06:396377 switch (pname) {
6378 case GL_PACK_ALIGNMENT:
6379 case GL_UNPACK_ALIGNMENT:
6380 if (!validators_->pixel_store_alignment.IsValid(param)) {
6381 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436382 "glPixelStore", "param GL_INVALID_VALUE");
[email protected]222471d2011-11-30 18:06:396383 return error::kNoError;
6384 }
[email protected]164d6d52012-05-05 00:55:036385 break;
[email protected]0a1e9ad2012-05-04 21:13:036386 case GL_UNPACK_FLIP_Y_CHROMIUM:
6387 unpack_flip_y_ = (param != 0);
6388 return error::kNoError;
6389 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
6390 unpack_premultiply_alpha_ = (param != 0);
6391 return error::kNoError;
[email protected]6c75c712012-06-19 15:43:176392 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
6393 unpack_unpremultiply_alpha_ = (param != 0);
6394 return error::kNoError;
[email protected]222471d2011-11-30 18:06:396395 default:
6396 break;
[email protected]b9849abf2009-11-25 19:13:196397 }
6398 glPixelStorei(pname, param);
6399 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:436400 case GL_PACK_ALIGNMENT:
6401 pack_alignment_ = param;
6402 break;
6403 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
6404 break;
6405 case GL_UNPACK_ALIGNMENT:
6406 unpack_alignment_ = param;
6407 break;
6408 default:
6409 // Validation should have prevented us from getting here.
6410 NOTREACHED();
6411 break;
[email protected]b9849abf2009-11-25 19:13:196412 }
[email protected]f7a64ee2010-02-01 22:24:146413 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196414}
6415
[email protected]1c75a3702011-11-11 14:15:286416error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
6417 uint32 immediate_data_size, const gles2::PostSubBufferCHROMIUM& c) {
[email protected]43ed3a72012-05-30 22:55:386418 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
[email protected]aa258822011-11-22 13:52:256419 if (!context_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
[email protected]1c75a3702011-11-11 14:15:286420 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436421 "glPostSubBufferCHROMIUM", "command not supported by surface");
[email protected]1c75a3702011-11-11 14:15:286422 return error::kNoError;
6423 }
[email protected]7794d512012-04-17 20:36:496424 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
[email protected]1c75a3702011-11-11 14:15:286425 return error::kNoError;
[email protected]7794d512012-04-17 20:36:496426 } else {
6427 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
[email protected]1c75a3702011-11-11 14:15:286428 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:496429 }
[email protected]1c75a3702011-11-11 14:15:286430}
6431
[email protected]558847a2010-03-24 07:02:546432error::Error GLES2DecoderImpl::GetAttribLocationHelper(
6433 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6434 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576435 if (!StringIsValidForGLES(name_str.c_str())) {
[email protected]ad84a3a2012-06-08 21:42:436436 SetGLError(GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:576437 return error::kNoError;
6438 }
[email protected]6b8cf1a2010-05-06 16:13:586439 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6440 client_id, "glGetAttribLocation");
[email protected]ae51d192010-04-27 00:48:036441 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146442 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196443 }
[email protected]ae51d192010-04-27 00:48:036444 if (!info->IsValid()) {
[email protected]ad84a3a2012-06-08 21:42:436445 SetGLError(
6446 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
[email protected]0bfd9882010-02-05 23:02:256447 return error::kNoError;
6448 }
[email protected]b9849abf2009-11-25 19:13:196449 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546450 location_shm_id, location_shm_offset, sizeof(GLint));
6451 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146452 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196453 }
[email protected]558847a2010-03-24 07:02:546454 // Require the client to init this incase the context is lost and we are no
6455 // longer executing commands.
6456 if (*location != -1) {
6457 return error::kGenericError;
6458 }
[email protected]0bfd9882010-02-05 23:02:256459 *location = info->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:146460 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196461}
6462
[email protected]558847a2010-03-24 07:02:546463error::Error GLES2DecoderImpl::HandleGetAttribLocation(
6464 uint32 immediate_data_size, const gles2::GetAttribLocation& c) {
6465 uint32 name_size = c.data_size;
6466 const char* name = GetSharedMemoryAs<const char*>(
6467 c.name_shm_id, c.name_shm_offset, name_size);
6468 if (!name) {
6469 return error::kOutOfBounds;
6470 }
6471 String name_str(name, name_size);
6472 return GetAttribLocationHelper(
6473 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6474}
6475
[email protected]f7a64ee2010-02-01 22:24:146476error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196477 uint32 immediate_data_size, const gles2::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:546478 uint32 name_size = c.data_size;
6479 const char* name = GetImmediateDataAs<const char*>(
6480 c, name_size, immediate_data_size);
6481 if (!name) {
6482 return error::kOutOfBounds;
6483 }
6484 String name_str(name, name_size);
6485 return GetAttribLocationHelper(
6486 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6487}
6488
6489error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
6490 uint32 immediate_data_size, const gles2::GetAttribLocationBucket& c) {
6491 Bucket* bucket = GetBucket(c.name_bucket_id);
6492 if (!bucket) {
6493 return error::kInvalidArguments;
6494 }
6495 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186496 if (!bucket->GetAsString(&name_str)) {
6497 return error::kInvalidArguments;
6498 }
[email protected]558847a2010-03-24 07:02:546499 return GetAttribLocationHelper(
6500 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6501}
6502
6503error::Error GLES2DecoderImpl::GetUniformLocationHelper(
6504 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6505 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576506 if (!StringIsValidForGLES(name_str.c_str())) {
[email protected]ad84a3a2012-06-08 21:42:436507 SetGLError(GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:576508 return error::kNoError;
6509 }
[email protected]6b8cf1a2010-05-06 16:13:586510 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
6511 client_id, "glUniformLocation");
[email protected]ae51d192010-04-27 00:48:036512 if (!info) {
[email protected]f7a64ee2010-02-01 22:24:146513 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196514 }
[email protected]ae51d192010-04-27 00:48:036515 if (!info->IsValid()) {
[email protected]ad84a3a2012-06-08 21:42:436516 SetGLError(
6517 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
[email protected]0bfd9882010-02-05 23:02:256518 return error::kNoError;
6519 }
[email protected]b9849abf2009-11-25 19:13:196520 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:546521 location_shm_id, location_shm_offset, sizeof(GLint));
6522 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:146523 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196524 }
[email protected]558847a2010-03-24 07:02:546525 // Require the client to init this incase the context is lost an we are no
6526 // longer executing commands.
6527 if (*location != -1) {
6528 return error::kGenericError;
6529 }
[email protected]3f00df92012-06-19 00:44:586530 *location = GLES2Util::SwizzleLocation(
[email protected]1b0a6752012-02-22 03:44:126531 info->GetUniformFakeLocation(name_str));
[email protected]f7a64ee2010-02-01 22:24:146532 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196533}
6534
[email protected]f7a64ee2010-02-01 22:24:146535error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]b9849abf2009-11-25 19:13:196536 uint32 immediate_data_size, const gles2::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:196537 uint32 name_size = c.data_size;
6538 const char* name = GetSharedMemoryAs<const char*>(
6539 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:546540 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146541 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196542 }
6543 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546544 return GetUniformLocationHelper(
6545 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196546}
6547
[email protected]f7a64ee2010-02-01 22:24:146548error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]b9849abf2009-11-25 19:13:196549 uint32 immediate_data_size, const gles2::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:196550 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:306551 const char* name = GetImmediateDataAs<const char*>(
6552 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:546553 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:146554 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:196555 }
6556 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:546557 return GetUniformLocationHelper(
6558 c.program, c.location_shm_id, c.location_shm_offset, name_str);
6559}
6560
6561error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
6562 uint32 immediate_data_size, const gles2::GetUniformLocationBucket& c) {
6563 Bucket* bucket = GetBucket(c.name_bucket_id);
6564 if (!bucket) {
6565 return error::kInvalidArguments;
6566 }
6567 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:186568 if (!bucket->GetAsString(&name_str)) {
6569 return error::kInvalidArguments;
6570 }
[email protected]558847a2010-03-24 07:02:546571 return GetUniformLocationHelper(
6572 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:196573}
6574
[email protected]ddd968b82010-03-02 00:44:296575error::Error GLES2DecoderImpl::HandleGetString(
6576 uint32 immediate_data_size, const gles2::GetString& c) {
6577 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:056578 if (!validators_->string_type.IsValid(name)) {
[email protected]ad84a3a2012-06-08 21:42:436579 SetGLError(GL_INVALID_ENUM, "glGetString", "name GL_INVALID_ENUM");
[email protected]ddd968b82010-03-02 00:44:296580 return error::kNoError;
6581 }
[email protected]1958e0e2010-04-22 05:17:156582 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
6583 const char* str = NULL;
[email protected]f0d74742011-10-03 16:31:046584 std::string extensions;
[email protected]1958e0e2010-04-22 05:17:156585 switch (name) {
6586 case GL_VERSION:
6587 str = "OpenGL ES 2.0 Chromium";
6588 break;
6589 case GL_SHADING_LANGUAGE_VERSION:
6590 str = "OpenGL ES GLSL ES 1.0 Chromium";
6591 break;
[email protected]32939602012-05-09 06:25:166592 case GL_RENDERER:
6593 str = "Chromium";
6594 break;
6595 case GL_VENDOR:
6596 str = "Chromium";
6597 break;
[email protected]1958e0e2010-04-22 05:17:156598 case GL_EXTENSIONS:
[email protected]f0d74742011-10-03 16:31:046599 {
6600 // For WebGL contexts, strip out the OES derivatives extension if it has
6601 // not been enabled.
6602 if (force_webgl_glsl_validation_ &&
6603 !derivatives_explicitly_enabled_) {
6604 extensions = feature_info_->extensions();
6605 size_t offset = extensions.find(kOESDerivativeExtension);
6606 if (std::string::npos != offset) {
6607 extensions.replace(offset,
6608 offset + arraysize(kOESDerivativeExtension),
6609 std::string());
6610 }
6611 str = extensions.c_str();
6612 } else {
6613 str = feature_info_->extensions().c_str();
6614 }
[email protected]f0d74742011-10-03 16:31:046615 }
[email protected]1958e0e2010-04-22 05:17:156616 break;
6617 default:
6618 str = gl_str;
6619 break;
6620 }
[email protected]ddd968b82010-03-02 00:44:296621 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:156622 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:296623 return error::kNoError;
6624}
6625
[email protected]0c86dbf2010-03-05 08:14:116626void GLES2DecoderImpl::DoBufferData(
[email protected]b9363b22010-06-09 22:06:156627 GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
[email protected]9438b012010-06-15 22:55:056628 if (!validators_->buffer_target.IsValid(target)) {
[email protected]ad84a3a2012-06-08 21:42:436629 SetGLError(GL_INVALID_ENUM, "glBufferData", "target GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:296630 return;
6631 }
[email protected]9438b012010-06-15 22:55:056632 if (!validators_->buffer_usage.IsValid(usage)) {
[email protected]ad84a3a2012-06-08 21:42:436633 SetGLError(GL_INVALID_ENUM, "glBufferData", "usage GL_INVALID_ENUM");
[email protected]0c86dbf2010-03-05 08:14:116634 return;
[email protected]3b6ec202010-03-05 05:16:236635 }
6636 if (size < 0) {
[email protected]ad84a3a2012-06-08 21:42:436637 SetGLError(GL_INVALID_VALUE, "glBufferData", "size < 0");
[email protected]037896bd2010-04-21 19:07:286638 return;
[email protected]3b6ec202010-03-05 05:16:236639 }
6640 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
6641 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436642 SetGLError(GL_INVALID_VALUE, "glBufferData", "unknown buffer");
[email protected]037896bd2010-04-21 19:07:286643 return;
[email protected]3b6ec202010-03-05 05:16:236644 }
6645 // Clear the buffer to 0 if no initial data was passed in.
6646 scoped_array<int8> zero;
6647 if (!data) {
6648 zero.reset(new int8[size]);
6649 memset(zero.get(), 0, size);
6650 data = zero.get();
6651 }
[email protected]473c01ccb2011-06-07 01:33:306652
6653 if (!bufferdata_faster_than_buffersubdata_ &&
6654 size == info->size() && usage == info->usage()) {
6655 glBufferSubData(target, 0, size, data);
6656 info->SetRange(0, size, data);
6657 return;
6658 }
6659
[email protected]3b6ec202010-03-05 05:16:236660 CopyRealGLErrorsToWrapper();
6661 glBufferData(target, size, data, usage);
[email protected]1002c2d2011-06-28 22:39:046662 GLenum error = PeekGLError();
6663 if (error == GL_NO_ERROR) {
[email protected]473c01ccb2011-06-07 01:33:306664 buffer_manager()->SetInfo(info, size, usage);
[email protected]0c86dbf2010-03-05 08:14:116665 info->SetRange(0, size, data);
[email protected]3b6ec202010-03-05 05:16:236666 }
[email protected]0c86dbf2010-03-05 08:14:116667}
6668
6669error::Error GLES2DecoderImpl::HandleBufferData(
6670 uint32 immediate_data_size, const gles2::BufferData& c) {
6671 GLenum target = static_cast<GLenum>(c.target);
6672 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
6673 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
6674 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
6675 GLenum usage = static_cast<GLenum>(c.usage);
6676 const void* data = NULL;
6677 if (data_shm_id != 0 || data_shm_offset != 0) {
6678 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
6679 if (!data) {
6680 return error::kOutOfBounds;
6681 }
6682 }
6683 DoBufferData(target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:146684 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196685}
6686
[email protected]f7a64ee2010-02-01 22:24:146687error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]b9849abf2009-11-25 19:13:196688 uint32 immediate_data_size, const gles2::BufferDataImmediate& c) {
6689 GLenum target = static_cast<GLenum>(c.target);
6690 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:306691 const void* data = GetImmediateDataAs<const void*>(
6692 c, size, immediate_data_size);
6693 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146694 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:306695 }
[email protected]b9849abf2009-11-25 19:13:196696 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0c86dbf2010-03-05 08:14:116697 DoBufferData(target, size, data, usage);
6698 return error::kNoError;
6699}
6700
6701void GLES2DecoderImpl::DoBufferSubData(
6702 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]3916c97e2010-02-25 03:20:506703 BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476704 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:436705 SetGLError(GL_INVALID_VALUE, "glBufferSubData", "unknown buffer");
[email protected]037896bd2010-04-21 19:07:286706 return;
[email protected]a93bb842010-02-16 23:03:476707 }
[email protected]0c86dbf2010-03-05 08:14:116708 if (!info->SetRange(offset, size, data)) {
[email protected]ad84a3a2012-06-08 21:42:436709 SetGLError(GL_INVALID_VALUE, "glBufferSubData", "out of range");
[email protected]473c01ccb2011-06-07 01:33:306710 return;
[email protected]07f54fcc2009-12-22 02:46:306711 }
[email protected]473c01ccb2011-06-07 01:33:306712 if (bufferdata_faster_than_buffersubdata_ &&
6713 offset == 0 && size == info->size()) {
6714 glBufferData(target, size, data, info->usage());
6715 return;
6716 }
6717 glBufferSubData(target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:196718}
6719
[email protected]0d6bfdc2011-11-02 01:32:206720bool GLES2DecoderImpl::ClearLevel(
6721 unsigned service_id,
6722 unsigned bind_target,
6723 unsigned target,
6724 int level,
6725 unsigned format,
6726 unsigned type,
6727 int width,
[email protected]4502e6492011-12-14 19:39:156728 int height,
6729 bool is_texture_immutable) {
[email protected]81375742012-06-08 00:04:006730 uint32 channels = GLES2Util::GetChannelsForFormat(format);
6731 if (IsAngle() && (channels & GLES2Util::kDepth) != 0) {
6732 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
6733 // on depth formats.
6734 GLuint fb = 0;
6735 glGenFramebuffersEXT(1, &fb);
6736 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
6737
6738 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
6739 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
6740 GL_DEPTH_ATTACHMENT;
6741
6742 glFramebufferTexture2DEXT(
6743 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
6744 // ANGLE promises a depth only attachment ok.
6745 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
6746 GL_FRAMEBUFFER_COMPLETE) {
6747 return false;
6748 }
6749 glClearStencil(0);
6750 glStencilMask(-1);
6751 glClearDepth(1.0f);
6752 glDepthMask(true);
6753 glDisable(GL_SCISSOR_TEST);
6754 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
6755
6756 RestoreClearState();
6757
6758 glDeleteFramebuffersEXT(1, &fb);
6759 FramebufferManager::FramebufferInfo* framebuffer =
6760 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
6761 GLuint fb_service_id =
6762 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
6763 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
6764 return true;
6765 }
6766
[email protected]45d15a62012-04-18 14:33:176767 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
6768
6769 uint32 size;
6770 uint32 padded_row_size;
[email protected]3458a64a2012-04-10 17:39:346771 if (!GLES2Util::ComputeImageDataSizes(
[email protected]45d15a62012-04-18 14:33:176772 width, height, format, type, unpack_alignment_, &size,
6773 NULL, &padded_row_size)) {
[email protected]0d6bfdc2011-11-02 01:32:206774 return false;
6775 }
[email protected]45d15a62012-04-18 14:33:176776
[email protected]a5d3dad2012-05-26 04:34:446777 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
6778
[email protected]45d15a62012-04-18 14:33:176779 int tile_height;
6780
6781 if (size > kMaxZeroSize) {
6782 if (kMaxZeroSize < padded_row_size) {
6783 // That'd be an awfully large texture.
6784 return false;
6785 }
6786 // We should never have a large total size with a zero row size.
6787 DCHECK_GT(padded_row_size, 0U);
6788 tile_height = kMaxZeroSize / padded_row_size;
6789 if (!GLES2Util::ComputeImageDataSizes(
6790 width, tile_height, format, type, unpack_alignment_, &size, NULL,
6791 NULL)) {
6792 return false;
6793 }
[email protected]4502e6492011-12-14 19:39:156794 } else {
[email protected]45d15a62012-04-18 14:33:176795 tile_height = height;
6796 }
6797
6798 // Assumes the size has already been checked.
6799 scoped_array<char> zero(new char[size]);
6800 memset(zero.get(), 0, size);
6801 glBindTexture(bind_target, service_id);
6802
6803 GLint y = 0;
6804 while (y < height) {
6805 GLint h = y + tile_height > height ? height - y : tile_height;
6806 if (is_texture_immutable || h != height) {
6807 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
6808 } else {
6809 WrappedTexImage2D(
6810 target, level, format, width, h, 0, format, type, zero.get());
6811 }
6812 y += tile_height;
[email protected]4502e6492011-12-14 19:39:156813 }
[email protected]0d6bfdc2011-11-02 01:32:206814 TextureManager::TextureInfo* info = GetTextureInfoForTarget(bind_target);
6815 glBindTexture(bind_target, info ? info->service_id() : 0);
6816 return true;
6817}
6818
[email protected]ad84a3a2012-06-08 21:42:436819namespace {
6820
6821const int kS3TCBlockWidth = 4;
6822const int kS3TCBlockHeight = 4;
6823const int kS3TCDXT1BlockSize = 8;
6824const int kS3TCDXT3AndDXT5BlockSize = 16;
6825
6826bool IsValidDXTSize(GLint level, GLsizei size) {
6827 return (level && size == 1) ||
6828 (level && size == 2) || !(size % kS3TCBlockWidth);
6829}
6830
6831} // anonymous namespace.
6832
6833bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
6834 const char* function_name,
6835 GLsizei width, GLsizei height, GLenum format, size_t size) {
6836 unsigned int bytes_required = 0;
6837
6838 switch (format) {
6839 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
6840 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: {
6841 int num_blocks_across =
6842 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
6843 int num_blocks_down =
6844 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
6845 int num_blocks = num_blocks_across * num_blocks_down;
6846 bytes_required = num_blocks * kS3TCDXT1BlockSize;
6847 break;
6848 }
6849 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
6850 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
6851 int num_blocks_across =
6852 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
6853 int num_blocks_down =
6854 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
6855 int num_blocks = num_blocks_across * num_blocks_down;
6856 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
6857 break;
6858 }
6859 default:
6860 SetGLError(GL_INVALID_ENUM, function_name, "invalid format");
6861 return false;
6862 }
6863
6864 if (size != bytes_required) {
6865 SetGLError(
6866 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
6867 return false;
6868 }
6869
6870 return true;
6871}
6872
6873bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
6874 const char* function_name,
6875 GLint level, GLsizei width, GLsizei height, GLenum format) {
6876 switch (format) {
6877 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
6878 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
6879 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
6880 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
6881 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
6882 SetGLError(
6883 GL_INVALID_OPERATION, function_name,
6884 "width or height invalid for level");
6885 return false;
6886 }
6887 return true;
6888 }
6889 default:
6890 return false;
6891 }
6892}
6893
6894bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
6895 const char* function_name,
6896 GLenum target, GLint level, GLint xoffset, GLint yoffset,
6897 GLsizei width, GLsizei height, GLenum format,
6898 TextureManager::TextureInfo* texture) {
6899 if (xoffset < 0 || yoffset < 0) {
6900 SetGLError(
6901 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
6902 return false;
6903 }
6904
6905 switch (format) {
6906 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
6907 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
6908 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
6909 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
6910 const int kBlockWidth = 4;
6911 const int kBlockHeight = 4;
6912 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
6913 SetGLError(
6914 GL_INVALID_OPERATION, function_name,
6915 "xoffset or yoffset not multiple of 4");
6916 return false;
6917 }
6918 GLsizei tex_width = 0;
6919 GLsizei tex_height = 0;
6920 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
6921 width - xoffset > tex_width ||
6922 height - yoffset > tex_height) {
6923 SetGLError(
6924 GL_INVALID_OPERATION, function_name, "dimensions out of range");
6925 return false;
6926 }
6927 return ValidateCompressedTexDimensions(
6928 function_name, level, width, height, format);
6929 }
6930 default:
6931 return false;
6932 }
6933}
6934
[email protected]a93bb842010-02-16 23:03:476935error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
6936 GLenum target,
6937 GLint level,
6938 GLenum internal_format,
6939 GLsizei width,
6940 GLsizei height,
6941 GLint border,
6942 GLsizei image_size,
6943 const void* data) {
[email protected]a93bb842010-02-16 23:03:476944 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:056945 if (!validators_->texture_target.IsValid(target)) {
[email protected]8eee29c2010-04-29 03:38:296946 SetGLError(GL_INVALID_ENUM,
[email protected]ad84a3a2012-06-08 21:42:436947 "glCompressedTexImage2D", "target GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:296948 return error::kNoError;
6949 }
[email protected]9438b012010-06-15 22:55:056950 if (!validators_->compressed_texture_format.IsValid(
6951 internal_format)) {
[email protected]8eee29c2010-04-29 03:38:296952 SetGLError(GL_INVALID_ENUM,
[email protected]ad84a3a2012-06-08 21:42:436953 "glCompressedTexImage2D", "internal_format GL_INVALID_ENUM");
[email protected]a93bb842010-02-16 23:03:476954 return error::kNoError;
6955 }
[email protected]80eb6b52012-01-19 00:14:416956 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:476957 border != 0) {
[email protected]8eee29c2010-04-29 03:38:296958 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436959 "glCompressedTexImage2D", "dimensions out of range");
[email protected]a93bb842010-02-16 23:03:476960 return error::kNoError;
6961 }
[email protected]3916c97e2010-02-25 03:20:506962 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:476963 if (!info) {
[email protected]8eee29c2010-04-29 03:38:296964 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:436965 "glCompressedTexImage2D", "unknown texture target");
[email protected]a93bb842010-02-16 23:03:476966 return error::kNoError;
6967 }
[email protected]97dc7cbe2011-12-06 17:26:176968 if (info->IsImmutable()) {
6969 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436970 "glCompressedTexImage2D", "texture is immutable");
6971 return error::kNoError;
6972 }
6973
6974 if (!ValidateCompressedTexDimensions(
6975 "glCompressedTexImage2D", level, width, height, internal_format) ||
6976 !ValidateCompressedTexFuncData(
6977 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
[email protected]97dc7cbe2011-12-06 17:26:176978 return error::kNoError;
6979 }
[email protected]968351b2011-12-20 08:26:516980
6981 if (info->IsAttachedToFramebuffer()) {
6982 state_dirty_ = true;
6983 // TODO(gman): If textures tracked which framebuffers they were attached to
6984 // we could just mark those framebuffers as not complete.
6985 framebuffer_manager()->IncFramebufferStateChangeCount();
6986 }
6987
[email protected]a93bb842010-02-16 23:03:476988 scoped_array<int8> zero;
6989 if (!data) {
6990 zero.reset(new int8[image_size]);
6991 memset(zero.get(), 0, image_size);
6992 data = zero.get();
6993 }
[email protected]cadde4a2010-07-31 17:10:436994 CopyRealGLErrorsToWrapper();
[email protected]a93bb842010-02-16 23:03:476995 glCompressedTexImage2D(
6996 target, level, internal_format, width, height, border, image_size, data);
[email protected]1002c2d2011-06-28 22:39:046997 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:436998 if (error == GL_NO_ERROR) {
6999 texture_manager()->SetLevelInfo(
[email protected]0d6bfdc2011-11-02 01:32:207000 info, target, level, internal_format, width, height, 1, border, 0, 0,
7001 true);
[email protected]cadde4a2010-07-31 17:10:437002 }
[email protected]a93bb842010-02-16 23:03:477003 return error::kNoError;
7004}
7005
[email protected]f7a64ee2010-02-01 22:24:147006error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:197007 uint32 immediate_data_size, const gles2::CompressedTexImage2D& c) {
7008 GLenum target = static_cast<GLenum>(c.target);
7009 GLint level = static_cast<GLint>(c.level);
7010 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7011 GLsizei width = static_cast<GLsizei>(c.width);
7012 GLsizei height = static_cast<GLsizei>(c.height);
7013 GLint border = static_cast<GLint>(c.border);
7014 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
7015 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7016 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7017 const void* data = NULL;
7018 if (data_shm_id != 0 || data_shm_offset != 0) {
7019 data = GetSharedMemoryAs<const void*>(
7020 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:467021 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:147022 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197023 }
7024 }
[email protected]a93bb842010-02-16 23:03:477025 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:197026 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:197027}
7028
[email protected]f7a64ee2010-02-01 22:24:147029error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:197030 uint32 immediate_data_size, const gles2::CompressedTexImage2DImmediate& c) {
7031 GLenum target = static_cast<GLenum>(c.target);
7032 GLint level = static_cast<GLint>(c.level);
7033 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7034 GLsizei width = static_cast<GLsizei>(c.width);
7035 GLsizei height = static_cast<GLsizei>(c.height);
7036 GLint border = static_cast<GLint>(c.border);
7037 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:307038 const void* data = GetImmediateDataAs<const void*>(
7039 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:467040 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:147041 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:467042 }
[email protected]a93bb842010-02-16 23:03:477043 return DoCompressedTexImage2D(
7044 target, level, internal_format, width, height, border, image_size, data);
7045}
7046
[email protected]b6140d02010-05-17 14:47:167047error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
7048 uint32 immediate_data_size, const gles2::CompressedTexImage2DBucket& c) {
7049 GLenum target = static_cast<GLenum>(c.target);
7050 GLint level = static_cast<GLint>(c.level);
7051 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7052 GLsizei width = static_cast<GLsizei>(c.width);
7053 GLsizei height = static_cast<GLsizei>(c.height);
7054 GLint border = static_cast<GLint>(c.border);
7055 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287056 if (!bucket) {
7057 return error::kInvalidArguments;
7058 }
7059 uint32 data_size = bucket->size();
7060 GLsizei imageSize = data_size;
7061 const void* data = bucket->GetData(0, data_size);
7062 if (!data) {
7063 return error::kInvalidArguments;
7064 }
[email protected]b6140d02010-05-17 14:47:167065 return DoCompressedTexImage2D(
7066 target, level, internal_format, width, height, border,
[email protected]12f93d82011-10-17 21:16:287067 imageSize, data);
[email protected]b6140d02010-05-17 14:47:167068}
7069
7070error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
7071 uint32 immediate_data_size,
7072 const gles2::CompressedTexSubImage2DBucket& c) {
7073 GLenum target = static_cast<GLenum>(c.target);
7074 GLint level = static_cast<GLint>(c.level);
7075 GLint xoffset = static_cast<GLint>(c.xoffset);
7076 GLint yoffset = static_cast<GLint>(c.yoffset);
7077 GLsizei width = static_cast<GLsizei>(c.width);
7078 GLsizei height = static_cast<GLsizei>(c.height);
7079 GLenum format = static_cast<GLenum>(c.format);
7080 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287081 if (!bucket) {
7082 return error::kInvalidArguments;
7083 }
[email protected]b6140d02010-05-17 14:47:167084 uint32 data_size = bucket->size();
7085 GLsizei imageSize = data_size;
7086 const void* data = bucket->GetData(0, data_size);
[email protected]12f93d82011-10-17 21:16:287087 if (!data) {
7088 return error::kInvalidArguments;
7089 }
[email protected]9438b012010-06-15 22:55:057090 if (!validators_->texture_target.IsValid(target)) {
[email protected]b6140d02010-05-17 14:47:167091 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:437092 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target GL_INVALID_ENUM");
[email protected]b6140d02010-05-17 14:47:167093 return error::kNoError;
7094 }
[email protected]9438b012010-06-15 22:55:057095 if (!validators_->compressed_texture_format.IsValid(format)) {
7096 SetGLError(GL_INVALID_ENUM,
[email protected]ad84a3a2012-06-08 21:42:437097 "glCompressedTexSubImage2D", "format GL_INVALID_ENUM");
[email protected]9438b012010-06-15 22:55:057098 return error::kNoError;
7099 }
[email protected]b6140d02010-05-17 14:47:167100 if (width < 0) {
[email protected]ad84a3a2012-06-08 21:42:437101 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
[email protected]b6140d02010-05-17 14:47:167102 return error::kNoError;
7103 }
7104 if (height < 0) {
[email protected]ad84a3a2012-06-08 21:42:437105 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
[email protected]b6140d02010-05-17 14:47:167106 return error::kNoError;
7107 }
7108 if (imageSize < 0) {
[email protected]ad84a3a2012-06-08 21:42:437109 SetGLError(GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
[email protected]b6140d02010-05-17 14:47:167110 return error::kNoError;
7111 }
[email protected]cadde4a2010-07-31 17:10:437112 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:167113 target, level, xoffset, yoffset, width, height, format, imageSize, data);
7114 return error::kNoError;
7115}
7116
[email protected]81375742012-06-08 00:04:007117bool GLES2DecoderImpl::ValidateTextureParameters(
7118 const char* function_name,
7119 GLenum target, GLenum format, GLenum type, GLint level) {
7120 if (!feature_info_->GetTextureFormatValidator(format).IsValid(type)) {
[email protected]ad84a3a2012-06-08 21:42:437121 SetGLError(GL_INVALID_OPERATION, function_name,
7122 (std::string("invalid type ") +
[email protected]81375742012-06-08 00:04:007123 GLES2Util::GetStringEnum(type) + " for format " +
7124 GLES2Util::GetStringEnum(format)).c_str());
7125 return false;
7126 }
7127
7128 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7129 if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) {
[email protected]ad84a3a2012-06-08 21:42:437130 SetGLError(GL_INVALID_OPERATION, function_name,
7131 (std::string("invalid type ") +
[email protected]81375742012-06-08 00:04:007132 GLES2Util::GetStringEnum(type) + " for format " +
7133 GLES2Util::GetStringEnum(format)).c_str());
7134 return false;
7135 }
7136 return true;
7137}
7138
[email protected]a93bb842010-02-16 23:03:477139error::Error GLES2DecoderImpl::DoTexImage2D(
7140 GLenum target,
7141 GLint level,
7142 GLenum internal_format,
7143 GLsizei width,
7144 GLsizei height,
7145 GLint border,
7146 GLenum format,
7147 GLenum type,
7148 const void* pixels,
7149 uint32 pixels_size) {
[email protected]9438b012010-06-15 22:55:057150 if (!validators_->texture_target.IsValid(target)) {
[email protected]ad84a3a2012-06-08 21:42:437151 SetGLError(GL_INVALID_ENUM, "glTexImage2D", "target GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:297152 return error::kNoError;
7153 }
[email protected]9438b012010-06-15 22:55:057154 if (!validators_->texture_format.IsValid(internal_format)) {
[email protected]8eee29c2010-04-29 03:38:297155 SetGLError(GL_INVALID_ENUM,
[email protected]ad84a3a2012-06-08 21:42:437156 "glTexImage2D", "internal_format GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:297157 return error::kNoError;
7158 }
[email protected]9438b012010-06-15 22:55:057159 if (!validators_->texture_format.IsValid(format)) {
[email protected]ad84a3a2012-06-08 21:42:437160 SetGLError(GL_INVALID_ENUM, "glTexImage2D", "format GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:297161 return error::kNoError;
7162 }
[email protected]9438b012010-06-15 22:55:057163 if (!validators_->pixel_type.IsValid(type)) {
[email protected]ad84a3a2012-06-08 21:42:437164 SetGLError(GL_INVALID_ENUM, "glTexImage2D", "type GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:147165 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197166 }
[email protected]7b92c412010-07-20 17:48:257167 if (format != internal_format) {
[email protected]ad84a3a2012-06-08 21:42:437168 SetGLError(GL_INVALID_OPERATION,
7169 "glTexImage2D", "format != internalFormat");
[email protected]7b92c412010-07-20 17:48:257170 return error::kNoError;
7171 }
[email protected]81375742012-06-08 00:04:007172 if (!ValidateTextureParameters("glTexImage2D", target, format, type, level)) {
7173 return error::kNoError;
7174 }
[email protected]80eb6b52012-01-19 00:14:417175 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:477176 border != 0) {
[email protected]ad84a3a2012-06-08 21:42:437177 SetGLError(GL_INVALID_VALUE, "glTexImage2D", "dimensions out of range");
[email protected]a93bb842010-02-16 23:03:477178 return error::kNoError;
7179 }
[email protected]81375742012-06-08 00:04:007180 if ((GLES2Util::GetChannelsForFormat(format) &
7181 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && pixels) {
7182 SetGLError(
7183 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437184 "glTexImage2D", "can not supply data for depth or stencil textures");
[email protected]81375742012-06-08 00:04:007185 return error::kNoError;
7186 }
[email protected]3916c97e2010-02-25 03:20:507187 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
[email protected]a93bb842010-02-16 23:03:477188 if (!info) {
[email protected]8eee29c2010-04-29 03:38:297189 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437190 "glTexImage2D", "unknown texture for target");
[email protected]a93bb842010-02-16 23:03:477191 return error::kNoError;
7192 }
[email protected]0226c112011-07-22 03:25:077193
[email protected]97dc7cbe2011-12-06 17:26:177194 if (info->IsImmutable()) {
7195 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437196 "glTexImage2D", "texture is immutable");
[email protected]97dc7cbe2011-12-06 17:26:177197 return error::kNoError;
7198 }
7199
[email protected]0226c112011-07-22 03:25:077200 GLsizei tex_width = 0;
7201 GLsizei tex_height = 0;
7202 GLenum tex_type = 0;
7203 GLenum tex_format = 0;
7204 bool level_is_same =
7205 info->GetLevelSize(target, level, &tex_width, &tex_height) &&
7206 info->GetLevelType(target, level, &tex_type, &tex_format) &&
7207 width == tex_width && height == tex_height &&
7208 type == tex_type && format == tex_format;
7209
7210 if (level_is_same && !pixels) {
[email protected]1bed6222011-12-21 11:21:397211 // Just set the level info but mark the texture as uncleared.
7212 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:417213 info,
[email protected]1bed6222011-12-21 11:21:397214 target, level, internal_format, width, height, 1, border, format, type,
7215 false);
[email protected]ea72ed222011-08-17 18:58:437216 tex_image_2d_failed_ = false;
[email protected]0226c112011-07-22 03:25:077217 return error::kNoError;
7218 }
7219
[email protected]297ca1c2011-06-20 23:08:467220 if (info->IsAttachedToFramebuffer()) {
7221 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:517222 // TODO(gman): If textures tracked which framebuffers they were attached to
7223 // we could just mark those framebuffers as not complete.
7224 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:467225 }
7226
[email protected]1bed6222011-12-21 11:21:397227 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same && pixels) {
[email protected]0226c112011-07-22 03:25:077228 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
[email protected]57edfdad2012-02-07 04:57:157229 texture_manager()->SetLevelCleared(info, target, level);
[email protected]0226c112011-07-22 03:25:077230 tex_image_2d_failed_ = false;
7231 return error::kNoError;
[email protected]7488d962010-07-16 02:41:587232 }
[email protected]876f6fee2010-08-02 23:10:327233
[email protected]cadde4a2010-07-31 17:10:437234 CopyRealGLErrorsToWrapper();
[email protected]473c01ccb2011-06-07 01:33:307235 WrappedTexImage2D(
7236 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:477237 pixels);
[email protected]1002c2d2011-06-28 22:39:047238 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:437239 if (error == GL_NO_ERROR) {
[email protected]0d6bfdc2011-11-02 01:32:207240 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:417241 info,
[email protected]0d6bfdc2011-11-02 01:32:207242 target, level, internal_format, width, height, 1, border, format, type,
7243 pixels != NULL);
[email protected]b493ee622011-04-13 23:52:007244 tex_image_2d_failed_ = false;
[email protected]cadde4a2010-07-31 17:10:437245 }
[email protected]f7a64ee2010-02-01 22:24:147246 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197247}
7248
[email protected]f7a64ee2010-02-01 22:24:147249error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]b9849abf2009-11-25 19:13:197250 uint32 immediate_data_size, const gles2::TexImage2D& c) {
[email protected]43ed3a72012-05-30 22:55:387251 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]b493ee622011-04-13 23:52:007252 tex_image_2d_failed_ = true;
[email protected]b9849abf2009-11-25 19:13:197253 GLenum target = static_cast<GLenum>(c.target);
7254 GLint level = static_cast<GLint>(c.level);
7255 GLint internal_format = static_cast<GLint>(c.internalformat);
7256 GLsizei width = static_cast<GLsizei>(c.width);
7257 GLsizei height = static_cast<GLsizei>(c.height);
7258 GLint border = static_cast<GLint>(c.border);
7259 GLenum format = static_cast<GLenum>(c.format);
7260 GLenum type = static_cast<GLenum>(c.type);
7261 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
7262 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:187263 uint32 pixels_size;
[email protected]3458a64a2012-04-10 17:39:347264 if (!GLES2Util::ComputeImageDataSizes(
7265 width, height, format, type, unpack_alignment_, &pixels_size, NULL,
7266 NULL)) {
[email protected]a76b0052010-03-05 00:33:187267 return error::kOutOfBounds;
7268 }
[email protected]b9849abf2009-11-25 19:13:197269 const void* pixels = NULL;
7270 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
7271 pixels = GetSharedMemoryAs<const void*>(
7272 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:467273 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:147274 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197275 }
7276 }
[email protected]a93bb842010-02-16 23:03:477277 return DoTexImage2D(
[email protected]b9849abf2009-11-25 19:13:197278 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:477279 pixels, pixels_size);
[email protected]b9849abf2009-11-25 19:13:197280}
7281
[email protected]f7a64ee2010-02-01 22:24:147282error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]b9849abf2009-11-25 19:13:197283 uint32 immediate_data_size, const gles2::TexImage2DImmediate& c) {
7284 GLenum target = static_cast<GLenum>(c.target);
7285 GLint level = static_cast<GLint>(c.level);
[email protected]ba3176a2009-12-16 18:19:467286 GLint internal_format = static_cast<GLint>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:197287 GLsizei width = static_cast<GLsizei>(c.width);
7288 GLsizei height = static_cast<GLsizei>(c.height);
7289 GLint border = static_cast<GLint>(c.border);
7290 GLenum format = static_cast<GLenum>(c.format);
7291 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:187292 uint32 size;
[email protected]3458a64a2012-04-10 17:39:347293 if (!GLES2Util::ComputeImageDataSizes(
7294 width, height, format, type, unpack_alignment_, &size, NULL, NULL)) {
[email protected]a76b0052010-03-05 00:33:187295 return error::kOutOfBounds;
7296 }
[email protected]07f54fcc2009-12-22 02:46:307297 const void* pixels = GetImmediateDataAs<const void*>(
7298 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:467299 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:147300 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:467301 }
[email protected]a93bb842010-02-16 23:03:477302 DoTexImage2D(
[email protected]ba3176a2009-12-16 18:19:467303 target, level, internal_format, width, height, border, format, type,
[email protected]a93bb842010-02-16 23:03:477304 pixels, size);
[email protected]f7a64ee2010-02-01 22:24:147305 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327306}
7307
[email protected]cadde4a2010-07-31 17:10:437308void GLES2DecoderImpl::DoCompressedTexSubImage2D(
7309 GLenum target,
7310 GLint level,
7311 GLint xoffset,
7312 GLint yoffset,
7313 GLsizei width,
7314 GLsizei height,
7315 GLenum format,
7316 GLsizei image_size,
7317 const void * data) {
7318 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7319 if (!info) {
7320 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437321 "glCompressedTexSubImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:437322 return;
7323 }
7324 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:527325 GLenum internal_format = 0;
7326 if (!info->GetLevelType(target, level, &type, &internal_format)) {
7327 SetGLError(
7328 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437329 "glCompressedTexSubImage2D", "level does not exist.");
[email protected]df6cf1ad2011-01-29 01:20:527330 return;
7331 }
7332 if (internal_format != format) {
7333 SetGLError(
7334 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437335 "glCompressedTexSubImage2D", "format does not match internal format.");
[email protected]df6cf1ad2011-01-29 01:20:527336 return;
7337 }
7338 if (!info->ValidForTexture(
7339 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]cadde4a2010-07-31 17:10:437340 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:437341 "glCompressedTexSubImage2D", "bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:437342 return;
7343 }
[email protected]ad84a3a2012-06-08 21:42:437344
7345 if (!ValidateCompressedTexFuncData(
7346 "glCompressedTexSubImage2D", width, height, format, image_size) ||
7347 !ValidateCompressedTexSubDimensions(
7348 "glCompressedTexSubImage2D",
7349 target, level, xoffset, yoffset, width, height, format, info)) {
7350 return;
7351 }
7352
7353
[email protected]0d6bfdc2011-11-02 01:32:207354 // Note: There is no need to deal with texture cleared tracking here
7355 // because the validation above means you can only get here if the level
7356 // is already a matching compressed format and in that case
7357 // CompressedTexImage2D already cleared the texture.
[email protected]cadde4a2010-07-31 17:10:437358 glCompressedTexSubImage2D(
7359 target, level, xoffset, yoffset, width, height, format, image_size, data);
7360}
7361
[email protected]6e288612010-12-21 20:45:037362static void Clip(
7363 GLint start, GLint range, GLint sourceRange,
7364 GLint* out_start, GLint* out_range) {
7365 DCHECK(out_start);
7366 DCHECK(out_range);
7367 if (start < 0) {
7368 range += start;
7369 start = 0;
7370 }
7371 GLint end = start + range;
7372 if (end > sourceRange) {
7373 range -= end - sourceRange;
7374 }
7375 *out_start = start;
7376 *out_range = range;
7377}
7378
[email protected]cadde4a2010-07-31 17:10:437379void GLES2DecoderImpl::DoCopyTexImage2D(
[email protected]a5d3dad2012-05-26 04:34:447380 GLenum target,
7381 GLint level,
7382 GLenum internal_format,
7383 GLint x,
7384 GLint y,
7385 GLsizei width,
7386 GLsizei height,
7387 GLint border) {
[email protected]cadde4a2010-07-31 17:10:437388 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7389 if (!info) {
7390 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437391 "glCopyTexImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:437392 return;
7393 }
[email protected]97dc7cbe2011-12-06 17:26:177394 if (info->IsImmutable()) {
7395 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437396 "glCopyTexImage2D", "texture is immutable");
[email protected]97dc7cbe2011-12-06 17:26:177397 }
[email protected]80eb6b52012-01-19 00:14:417398 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:187399 border != 0) {
[email protected]ad84a3a2012-06-08 21:42:437400 SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
[email protected]f5719fb2010-08-04 18:27:187401 return;
7402 }
[email protected]81375742012-06-08 00:04:007403 if (!ValidateTextureParameters(
7404 "glCopyTexImage2D", target, internal_format, GL_UNSIGNED_BYTE, level)) {
7405 return;
7406 }
[email protected]f5719fb2010-08-04 18:27:187407
[email protected]9edc6b22010-12-23 02:00:267408 // Check we have compatible formats.
7409 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7410 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7411 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
7412
7413 if ((channels_needed & channels_exist) != channels_needed) {
[email protected]ad84a3a2012-06-08 21:42:437414 SetGLError(GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
[email protected]9edc6b22010-12-23 02:00:267415 return;
7416 }
7417
[email protected]81375742012-06-08 00:04:007418 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
7419 SetGLError(
7420 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437421 "glCopyImage2D", "can not be used with depth or stencil textures");
[email protected]81375742012-06-08 00:04:007422 return;
7423 }
7424
[email protected]a0b78dc2011-11-11 10:43:107425 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
7426 return;
7427 }
7428
[email protected]cadde4a2010-07-31 17:10:437429 CopyRealGLErrorsToWrapper();
[email protected]de26b3c2011-08-03 21:54:277430 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:037431 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:267432
[email protected]297ca1c2011-06-20 23:08:467433 if (info->IsAttachedToFramebuffer()) {
7434 state_dirty_ = true;
[email protected]968351b2011-12-20 08:26:517435 // TODO(gman): If textures tracked which framebuffers they were attached to
7436 // we could just mark those framebuffers as not complete.
7437 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]297ca1c2011-06-20 23:08:467438 }
7439
[email protected]9edc6b22010-12-23 02:00:267440 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:037441 GLint copyX = 0;
7442 GLint copyY = 0;
7443 GLint copyWidth = 0;
7444 GLint copyHeight = 0;
7445 Clip(x, width, size.width(), &copyX, &copyWidth);
7446 Clip(y, height, size.height(), &copyY, &copyHeight);
7447
7448 if (copyX != x ||
7449 copyY != y ||
7450 copyWidth != width ||
7451 copyHeight != height) {
7452 // some part was clipped so clear the texture.
[email protected]0d6bfdc2011-11-02 01:32:207453 if (!ClearLevel(
7454 info->service_id(), info->target(),
[email protected]4502e6492011-12-14 19:39:157455 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
7456 info->IsImmutable())) {
[email protected]ad84a3a2012-06-08 21:42:437457 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
[email protected]6e288612010-12-21 20:45:037458 return;
7459 }
[email protected]6e288612010-12-21 20:45:037460 if (copyHeight > 0 && copyWidth > 0) {
7461 GLint dx = copyX - x;
7462 GLint dy = copyY - y;
7463 GLint destX = dx;
7464 GLint destY = dy;
7465 glCopyTexSubImage2D(target, level,
7466 destX, destY, copyX, copyY,
7467 copyWidth, copyHeight);
7468 }
7469 } else {
7470 glCopyTexImage2D(target, level, internal_format,
7471 copyX, copyY, copyWidth, copyHeight, border);
7472 }
[email protected]1002c2d2011-06-28 22:39:047473 GLenum error = PeekGLError();
[email protected]cadde4a2010-07-31 17:10:437474 if (error == GL_NO_ERROR) {
7475 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:417476 info, target, level, internal_format, width, height, 1,
[email protected]0d6bfdc2011-11-02 01:32:207477 border, internal_format, GL_UNSIGNED_BYTE, true);
[email protected]cadde4a2010-07-31 17:10:437478 }
7479}
7480
7481void GLES2DecoderImpl::DoCopyTexSubImage2D(
[email protected]a5d3dad2012-05-26 04:34:447482 GLenum target,
7483 GLint level,
7484 GLint xoffset,
7485 GLint yoffset,
7486 GLint x,
7487 GLint y,
7488 GLsizei width,
7489 GLsizei height) {
[email protected]cadde4a2010-07-31 17:10:437490 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7491 if (!info) {
7492 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437493 "glCopyTexSubImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:437494 return;
7495 }
7496 GLenum type = 0;
7497 GLenum format = 0;
7498 if (!info->GetLevelType(target, level, &type, &format) ||
7499 !info->ValidForTexture(
7500 target, level, xoffset, yoffset, width, height, format, type)) {
7501 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:437502 "glCopyTexSubImage2D", "bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:437503 return;
7504 }
[email protected]9edc6b22010-12-23 02:00:267505
7506 // Check we have compatible formats.
7507 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7508 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7509 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
7510
7511 if ((channels_needed & channels_exist) != channels_needed) {
7512 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:437513 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
[email protected]9edc6b22010-12-23 02:00:267514 return;
7515 }
7516
[email protected]81375742012-06-08 00:04:007517 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
7518 SetGLError(
7519 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437520 "glCopySubImage2D", "can not be used with depth or stencil textures");
[email protected]81375742012-06-08 00:04:007521 return;
7522 }
7523
[email protected]a0b78dc2011-11-11 10:43:107524 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
7525 return;
7526 }
7527
[email protected]de26b3c2011-08-03 21:54:277528 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:037529 gfx::Size size = GetBoundReadFrameBufferSize();
7530 GLint copyX = 0;
7531 GLint copyY = 0;
7532 GLint copyWidth = 0;
7533 GLint copyHeight = 0;
7534 Clip(x, width, size.width(), &copyX, &copyWidth);
7535 Clip(y, height, size.height(), &copyY, &copyHeight);
[email protected]0d6bfdc2011-11-02 01:32:207536
7537 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
[email protected]ad84a3a2012-06-08 21:42:437538 SetGLError(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
[email protected]0d6bfdc2011-11-02 01:32:207539 return;
7540 }
7541
[email protected]6e288612010-12-21 20:45:037542 if (copyX != x ||
7543 copyY != y ||
7544 copyWidth != width ||
7545 copyHeight != height) {
[email protected]0d6bfdc2011-11-02 01:32:207546 // some part was clipped so clear the sub rect.
[email protected]6e288612010-12-21 20:45:037547 uint32 pixels_size = 0;
[email protected]3458a64a2012-04-10 17:39:347548 if (!GLES2Util::ComputeImageDataSizes(
7549 width, height, format, type, unpack_alignment_, &pixels_size, NULL,
7550 NULL)) {
[email protected]ad84a3a2012-06-08 21:42:437551 SetGLError(
7552 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
[email protected]6e288612010-12-21 20:45:037553 return;
7554 }
7555 scoped_array<char> zero(new char[pixels_size]);
7556 memset(zero.get(), 0, pixels_size);
7557 glTexSubImage2D(
7558 target, level, xoffset, yoffset, width, height,
7559 format, type, zero.get());
7560 }
[email protected]0d6bfdc2011-11-02 01:32:207561
[email protected]6e288612010-12-21 20:45:037562 if (copyHeight > 0 && copyWidth > 0) {
7563 GLint dx = copyX - x;
7564 GLint dy = copyY - y;
7565 GLint destX = xoffset + dx;
7566 GLint destY = yoffset + dy;
7567 glCopyTexSubImage2D(target, level,
7568 destX, destY, copyX, copyY,
7569 copyWidth, copyHeight);
7570 }
[email protected]cadde4a2010-07-31 17:10:437571}
7572
7573void GLES2DecoderImpl::DoTexSubImage2D(
7574 GLenum target,
7575 GLint level,
7576 GLint xoffset,
7577 GLint yoffset,
7578 GLsizei width,
7579 GLsizei height,
7580 GLenum format,
7581 GLenum type,
7582 const void * data) {
7583 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
7584 if (!info) {
7585 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437586 "glTexSubImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:437587 return;
7588 }
[email protected]df6cf1ad2011-01-29 01:20:527589 GLenum current_type = 0;
7590 GLenum internal_format = 0;
7591 if (!info->GetLevelType(target, level, &current_type, &internal_format)) {
7592 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:437593 GL_INVALID_OPERATION, "glTexSubImage2D", "level does not exist.");
[email protected]df6cf1ad2011-01-29 01:20:527594 return;
7595 }
7596 if (format != internal_format) {
7597 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437598 "glTexSubImage2D", "format does not match internal format.");
[email protected]df6cf1ad2011-01-29 01:20:527599 return;
7600 }
7601 if (type != current_type) {
7602 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437603 "glTexSubImage2D", "type does not match type of texture.");
[email protected]df6cf1ad2011-01-29 01:20:527604 return;
7605 }
7606
[email protected]cadde4a2010-07-31 17:10:437607 if (!info->ValidForTexture(
7608 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]ad84a3a2012-06-08 21:42:437609 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:437610 return;
7611 }
[email protected]473c01ccb2011-06-07 01:33:307612
[email protected]81375742012-06-08 00:04:007613 if ((GLES2Util::GetChannelsForFormat(format) &
7614 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
7615 SetGLError(
7616 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437617 "glTexSubImage2D", "can not supply data for depth or stencil textures");
[email protected]81375742012-06-08 00:04:007618 return;
7619 }
7620
[email protected]4502e6492011-12-14 19:39:157621 GLsizei tex_width = 0;
7622 GLsizei tex_height = 0;
7623 bool ok = info->GetLevelSize(target, level, &tex_width, &tex_height);
7624 DCHECK(ok);
7625 if (xoffset != 0 || yoffset != 0 ||
7626 width != tex_width || height != tex_height) {
7627 if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
[email protected]ad84a3a2012-06-08 21:42:437628 SetGLError(GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
[email protected]473c01ccb2011-06-07 01:33:307629 return;
7630 }
[email protected]4502e6492011-12-14 19:39:157631 glTexSubImage2D(
7632 target, level, xoffset, yoffset, width, height, format, type, data);
[email protected]0d6bfdc2011-11-02 01:32:207633 return;
7634 }
[email protected]4502e6492011-12-14 19:39:157635
7636 if (teximage2d_faster_than_texsubimage2d_ && !info->IsImmutable()) {
7637 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
7638 // same as internal_foramt. If that changes we'll need to look them up.
7639 WrappedTexImage2D(
7640 target, level, format, width, height, 0, format, type, data);
7641 } else {
7642 glTexSubImage2D(
7643 target, level, xoffset, yoffset, width, height, format, type, data);
7644 }
7645 texture_manager()->SetLevelCleared(info, target, level);
[email protected]cadde4a2010-07-31 17:10:437646}
7647
[email protected]b493ee622011-04-13 23:52:007648error::Error GLES2DecoderImpl::HandleTexSubImage2D(
7649 uint32 immediate_data_size, const gles2::TexSubImage2D& c) {
[email protected]43ed3a72012-05-30 22:55:387650 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:007651 GLboolean internal = static_cast<GLboolean>(c.internal);
7652 if (internal == GL_TRUE && tex_image_2d_failed_)
7653 return error::kNoError;
7654
7655 GLenum target = static_cast<GLenum>(c.target);
7656 GLint level = static_cast<GLint>(c.level);
7657 GLint xoffset = static_cast<GLint>(c.xoffset);
7658 GLint yoffset = static_cast<GLint>(c.yoffset);
7659 GLsizei width = static_cast<GLsizei>(c.width);
7660 GLsizei height = static_cast<GLsizei>(c.height);
7661 GLenum format = static_cast<GLenum>(c.format);
7662 GLenum type = static_cast<GLenum>(c.type);
7663 uint32 data_size;
[email protected]3458a64a2012-04-10 17:39:347664 if (!GLES2Util::ComputeImageDataSizes(
7665 width, height, format, type, unpack_alignment_, &data_size, NULL, NULL)) {
[email protected]b493ee622011-04-13 23:52:007666 return error::kOutOfBounds;
7667 }
7668 const void* pixels = GetSharedMemoryAs<const void*>(
7669 c.pixels_shm_id, c.pixels_shm_offset, data_size);
7670 if (!validators_->texture_target.IsValid(target)) {
[email protected]ad84a3a2012-06-08 21:42:437671 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D", "target GL_INVALID_ENUM");
[email protected]b493ee622011-04-13 23:52:007672 return error::kNoError;
7673 }
7674 if (width < 0) {
[email protected]ad84a3a2012-06-08 21:42:437675 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "width < 0");
[email protected]b493ee622011-04-13 23:52:007676 return error::kNoError;
7677 }
7678 if (height < 0) {
[email protected]ad84a3a2012-06-08 21:42:437679 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "height < 0");
[email protected]b493ee622011-04-13 23:52:007680 return error::kNoError;
7681 }
7682 if (!validators_->texture_format.IsValid(format)) {
[email protected]ad84a3a2012-06-08 21:42:437683 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D", "format GL_INVALID_ENUM");
[email protected]b493ee622011-04-13 23:52:007684 return error::kNoError;
7685 }
7686 if (!validators_->pixel_type.IsValid(type)) {
[email protected]ad84a3a2012-06-08 21:42:437687 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D", "type GL_INVALID_ENUM");
[email protected]b493ee622011-04-13 23:52:007688 return error::kNoError;
7689 }
7690 if (pixels == NULL) {
7691 return error::kOutOfBounds;
7692 }
7693 DoTexSubImage2D(
7694 target, level, xoffset, yoffset, width, height, format, type, pixels);
7695 return error::kNoError;
7696}
7697
7698error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
7699 uint32 immediate_data_size, const gles2::TexSubImage2DImmediate& c) {
7700 GLboolean internal = static_cast<GLboolean>(c.internal);
7701 if (internal == GL_TRUE && tex_image_2d_failed_)
7702 return error::kNoError;
7703
7704 GLenum target = static_cast<GLenum>(c.target);
7705 GLint level = static_cast<GLint>(c.level);
7706 GLint xoffset = static_cast<GLint>(c.xoffset);
7707 GLint yoffset = static_cast<GLint>(c.yoffset);
7708 GLsizei width = static_cast<GLsizei>(c.width);
7709 GLsizei height = static_cast<GLsizei>(c.height);
7710 GLenum format = static_cast<GLenum>(c.format);
7711 GLenum type = static_cast<GLenum>(c.type);
7712 uint32 data_size;
[email protected]3458a64a2012-04-10 17:39:347713 if (!GLES2Util::ComputeImageDataSizes(
7714 width, height, format, type, unpack_alignment_, &data_size, NULL, NULL)) {
[email protected]b493ee622011-04-13 23:52:007715 return error::kOutOfBounds;
7716 }
7717 const void* pixels = GetImmediateDataAs<const void*>(
7718 c, data_size, immediate_data_size);
7719 if (!validators_->texture_target.IsValid(target)) {
[email protected]ad84a3a2012-06-08 21:42:437720 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D", "target GL_INVALID_ENUM");
[email protected]b493ee622011-04-13 23:52:007721 return error::kNoError;
7722 }
7723 if (width < 0) {
[email protected]ad84a3a2012-06-08 21:42:437724 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "width < 0");
[email protected]b493ee622011-04-13 23:52:007725 return error::kNoError;
7726 }
7727 if (height < 0) {
[email protected]ad84a3a2012-06-08 21:42:437728 SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "height < 0");
[email protected]b493ee622011-04-13 23:52:007729 return error::kNoError;
7730 }
7731 if (!validators_->texture_format.IsValid(format)) {
[email protected]ad84a3a2012-06-08 21:42:437732 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D", "format GL_INVALID_ENUM");
[email protected]b493ee622011-04-13 23:52:007733 return error::kNoError;
7734 }
7735 if (!validators_->pixel_type.IsValid(type)) {
[email protected]ad84a3a2012-06-08 21:42:437736 SetGLError(GL_INVALID_ENUM, "glTexSubImage2D", "type GL_INVALID_ENUM");
[email protected]b493ee622011-04-13 23:52:007737 return error::kNoError;
7738 }
7739 if (pixels == NULL) {
7740 return error::kOutOfBounds;
7741 }
7742 DoTexSubImage2D(
7743 target, level, xoffset, yoffset, width, height, format, type, pixels);
7744 return error::kNoError;
7745}
7746
[email protected]f7a64ee2010-02-01 22:24:147747error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]b9849abf2009-11-25 19:13:197748 uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:367749 GLuint index = static_cast<GLuint>(c.index);
7750 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]0bfd9882010-02-05 23:02:257751 typedef gles2::GetVertexAttribPointerv::Result Result;
7752 Result* result = GetSharedMemoryAs<Result*>(
7753 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:367754 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:147755 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:367756 }
[email protected]07d0cc82010-02-17 04:51:407757 // Check that the client initialized the result.
7758 if (result->size != 0) {
7759 return error::kInvalidArguments;
7760 }
[email protected]9438b012010-06-15 22:55:057761 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]8eee29c2010-04-29 03:38:297762 SetGLError(GL_INVALID_ENUM,
[email protected]ad84a3a2012-06-08 21:42:437763 "glGetVertexAttribPointerv", "pname GL_INVALID_ENUM");
[email protected]f7a64ee2010-02-01 22:24:147764 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367765 }
[email protected]3916c97e2010-02-25 03:20:507766 if (index >= group_->max_vertex_attribs()) {
[email protected]8eee29c2010-04-29 03:38:297767 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:437768 "glGetVertexAttribPointerv", "index out of range.");
[email protected]f7a64ee2010-02-01 22:24:147769 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:367770 }
[email protected]0bfd9882010-02-05 23:02:257771 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:087772 *result->GetData() =
[email protected]3757a372012-01-19 05:20:447773 vertex_attrib_manager_->GetVertexAttribInfo(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:147774 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327775}
7776
[email protected]f7b85372010-02-03 01:11:377777bool GLES2DecoderImpl::GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127778 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:377779 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:127780 error::Error* error, GLint* real_location,
7781 GLuint* service_id, void** result_pointer, GLenum* result_type) {
[email protected]939e7362010-05-13 20:49:107782 DCHECK(error);
7783 DCHECK(service_id);
7784 DCHECK(result_pointer);
7785 DCHECK(result_type);
[email protected]1b0a6752012-02-22 03:44:127786 DCHECK(real_location);
[email protected]f7b85372010-02-03 01:11:377787 *error = error::kNoError;
7788 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:257789 SizedResult<GLint>* result;
7790 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7791 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
7792 if (!result) {
[email protected]f7b85372010-02-03 01:11:377793 *error = error::kOutOfBounds;
7794 return false;
7795 }
[email protected]0bfd9882010-02-05 23:02:257796 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:377797 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:257798 result->SetNumResults(0);
[email protected]6b8cf1a2010-05-06 16:13:587799 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7800 program, "glGetUniform");
[email protected]f7b85372010-02-03 01:11:377801 if (!info) {
[email protected]ae51d192010-04-27 00:48:037802 return false;
7803 }
7804 if (!info->IsValid()) {
[email protected]f7b85372010-02-03 01:11:377805 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]ad84a3a2012-06-08 21:42:437806 SetGLError(GL_INVALID_OPERATION, "glGetUniform", "program not linked");
[email protected]f7b85372010-02-03 01:11:377807 return false;
7808 }
[email protected]ae51d192010-04-27 00:48:037809 *service_id = info->service_id();
[email protected]43c2f1f2011-03-25 18:35:367810 GLint array_index = -1;
7811 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
[email protected]1b0a6752012-02-22 03:44:127812 info->GetUniformInfoByFakeLocation(
7813 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:367814 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:377815 // No such location.
[email protected]ad84a3a2012-06-08 21:42:437816 SetGLError(GL_INVALID_OPERATION, "glGetUniform", "unknown location");
[email protected]f7b85372010-02-03 01:11:377817 return false;
7818 }
[email protected]43c2f1f2011-03-25 18:35:367819 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:507820 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:377821 if (size == 0) {
[email protected]ad84a3a2012-06-08 21:42:437822 SetGLError(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
[email protected]f7b85372010-02-03 01:11:377823 return false;
7824 }
[email protected]0bfd9882010-02-05 23:02:257825 result = GetSharedMemoryAs<SizedResult<GLint>*>(
7826 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
7827 if (!result) {
[email protected]f7b85372010-02-03 01:11:377828 *error = error::kOutOfBounds;
7829 return false;
7830 }
[email protected]0bfd9882010-02-05 23:02:257831 result->size = size;
[email protected]939e7362010-05-13 20:49:107832 *result_type = type;
[email protected]f7b85372010-02-03 01:11:377833 return true;
7834}
7835
[email protected]f7a64ee2010-02-01 22:24:147836error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]b9849abf2009-11-25 19:13:197837 uint32 immediate_data_size, const gles2::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:377838 GLuint program = c.program;
[email protected]3f00df92012-06-19 00:44:587839 GLint fake_location = GLES2Util::UnswizzleLocation(c.location);
[email protected]f7b85372010-02-03 01:11:377840 GLuint service_id;
[email protected]939e7362010-05-13 20:49:107841 GLenum result_type;
[email protected]1b0a6752012-02-22 03:44:127842 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:377843 Error error;
[email protected]0bfd9882010-02-05 23:02:257844 void* result;
[email protected]f7b85372010-02-03 01:11:377845 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127846 program, fake_location, c.params_shm_id, c.params_shm_offset,
7847 &error, &real_location, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:257848 glGetUniformiv(
[email protected]1b0a6752012-02-22 03:44:127849 service_id, real_location,
[email protected]0bfd9882010-02-05 23:02:257850 static_cast<gles2::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:377851 }
7852 return error;
[email protected]96449d2c2009-11-25 00:01:327853}
7854
[email protected]f7a64ee2010-02-01 22:24:147855error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]b9849abf2009-11-25 19:13:197856 uint32 immediate_data_size, const gles2::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:377857 GLuint program = c.program;
[email protected]3f00df92012-06-19 00:44:587858 GLint fake_location = GLES2Util::UnswizzleLocation(c.location);
[email protected]f7b85372010-02-03 01:11:377859 GLuint service_id;
[email protected]1b0a6752012-02-22 03:44:127860 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:377861 Error error;
[email protected]0bfd9882010-02-05 23:02:257862 typedef gles2::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:107863 Result* result;
7864 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:377865 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:127866 program, fake_location, c.params_shm_id, c.params_shm_offset,
7867 &error, &real_location, &service_id,
7868 reinterpret_cast<void**>(&result), &result_type)) {
[email protected]939e7362010-05-13 20:49:107869 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
7870 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
7871 GLsizei num_values = result->GetNumResults();
7872 scoped_array<GLint> temp(new GLint[num_values]);
[email protected]1b0a6752012-02-22 03:44:127873 glGetUniformiv(service_id, real_location, temp.get());
[email protected]939e7362010-05-13 20:49:107874 GLfloat* dst = result->GetData();
7875 for (GLsizei ii = 0; ii < num_values; ++ii) {
7876 dst[ii] = (temp[ii] != 0);
7877 }
7878 } else {
[email protected]1b0a6752012-02-22 03:44:127879 glGetUniformfv(service_id, real_location, result->GetData());
[email protected]939e7362010-05-13 20:49:107880 }
[email protected]f7b85372010-02-03 01:11:377881 }
7882 return error;
[email protected]96449d2c2009-11-25 00:01:327883}
7884
[email protected]f7a64ee2010-02-01 22:24:147885error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]b9849abf2009-11-25 19:13:197886 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:257887 GLenum shader_type = static_cast<GLenum>(c.shadertype);
7888 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
7889 typedef gles2::GetShaderPrecisionFormat::Result Result;
7890 Result* result = GetSharedMemoryAs<Result*>(
7891 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7892 if (!result) {
7893 return error::kOutOfBounds;
7894 }
[email protected]07d0cc82010-02-17 04:51:407895 // Check that the client initialized the result.
7896 if (result->success != 0) {
7897 return error::kInvalidArguments;
7898 }
[email protected]9438b012010-06-15 22:55:057899 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]8eee29c2010-04-29 03:38:297900 SetGLError(GL_INVALID_ENUM,
[email protected]ad84a3a2012-06-08 21:42:437901 "glGetShaderPrecisionFormat", "shader_type GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:297902 return error::kNoError;
7903 }
[email protected]9438b012010-06-15 22:55:057904 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]8eee29c2010-04-29 03:38:297905 SetGLError(GL_INVALID_ENUM,
[email protected]ad84a3a2012-06-08 21:42:437906 "glGetShaderPrecisionFormat", "precision_type GL_INVALID_ENUM");
[email protected]8eee29c2010-04-29 03:38:297907 return error::kNoError;
7908 }
7909
7910 result->success = 1; // true
7911 switch (precision_type) {
7912 case GL_LOW_INT:
7913 case GL_MEDIUM_INT:
7914 case GL_HIGH_INT:
[email protected]0a34b582012-04-09 22:42:567915 // These values are for a 32-bit twos-complement integer format.
7916 result->min_range = 31;
7917 result->max_range = 30;
[email protected]8eee29c2010-04-29 03:38:297918 result->precision = 0;
[email protected]4e8a5b122010-05-08 22:00:107919 break;
[email protected]8eee29c2010-04-29 03:38:297920 case GL_LOW_FLOAT:
7921 case GL_MEDIUM_FLOAT:
7922 case GL_HIGH_FLOAT:
[email protected]0a34b582012-04-09 22:42:567923 // These values are for an IEEE single-precision floating-point format.
7924 result->min_range = 127;
7925 result->max_range = 127;
7926 result->precision = 23;
[email protected]8eee29c2010-04-29 03:38:297927 break;
7928 default:
7929 NOTREACHED();
7930 break;
[email protected]0bfd9882010-02-05 23:02:257931 }
[email protected]f7a64ee2010-02-01 22:24:147932 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327933}
7934
[email protected]f7a64ee2010-02-01 22:24:147935error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]b9849abf2009-11-25 19:13:197936 uint32 immediate_data_size, const gles2::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:257937 uint32 result_size = c.result_size;
[email protected]6b8cf1a2010-05-06 16:13:587938 GLuint program = static_cast<GLuint>(c.program);
7939 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7940 program, "glGetAttachedShaders");
[email protected]ae51d192010-04-27 00:48:037941 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257942 return error::kNoError;
7943 }
7944 typedef gles2::GetAttachedShaders::Result Result;
7945 uint32 max_count = Result::ComputeMaxResults(result_size);
7946 Result* result = GetSharedMemoryAs<Result*>(
7947 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
7948 if (!result) {
7949 return error::kOutOfBounds;
7950 }
[email protected]07d0cc82010-02-17 04:51:407951 // Check that the client initialized the result.
7952 if (result->size != 0) {
7953 return error::kInvalidArguments;
7954 }
[email protected]0bfd9882010-02-05 23:02:257955 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:037956 glGetAttachedShaders(
7957 info->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:257958 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:037959 if (!shader_manager()->GetClientId(result->GetData()[ii],
7960 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:257961 NOTREACHED();
7962 return error::kGenericError;
7963 }
7964 }
7965 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:147966 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327967}
7968
[email protected]f7a64ee2010-02-01 22:24:147969error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]b9849abf2009-11-25 19:13:197970 uint32 immediate_data_size, const gles2::GetActiveUniform& c) {
[email protected]0bfd9882010-02-05 23:02:257971 GLuint program = c.program;
7972 GLuint index = c.index;
7973 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:257974 typedef gles2::GetActiveUniform::Result Result;
7975 Result* result = GetSharedMemoryAs<Result*>(
7976 c.result_shm_id, c.result_shm_offset, sizeof(*result));
7977 if (!result) {
7978 return error::kOutOfBounds;
7979 }
[email protected]07d0cc82010-02-17 04:51:407980 // Check that the client initialized the result.
7981 if (result->success != 0) {
7982 return error::kInvalidArguments;
7983 }
[email protected]6b8cf1a2010-05-06 16:13:587984 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
7985 program, "glGetActiveUniform");
[email protected]ae51d192010-04-27 00:48:037986 if (!info) {
[email protected]0bfd9882010-02-05 23:02:257987 return error::kNoError;
7988 }
7989 const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
7990 info->GetUniformInfo(index);
7991 if (!uniform_info) {
[email protected]ad84a3a2012-06-08 21:42:437992 SetGLError(GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
[email protected]0bfd9882010-02-05 23:02:257993 return error::kNoError;
7994 }
7995 result->success = 1; // true.
7996 result->size = uniform_info->size;
7997 result->type = uniform_info->type;
7998 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:297999 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:148000 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328001}
8002
[email protected]f7a64ee2010-02-01 22:24:148003error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]b9849abf2009-11-25 19:13:198004 uint32 immediate_data_size, const gles2::GetActiveAttrib& c) {
[email protected]0bfd9882010-02-05 23:02:258005 GLuint program = c.program;
8006 GLuint index = c.index;
8007 uint32 name_bucket_id = c.name_bucket_id;
[email protected]0bfd9882010-02-05 23:02:258008 typedef gles2::GetActiveAttrib::Result Result;
8009 Result* result = GetSharedMemoryAs<Result*>(
8010 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8011 if (!result) {
8012 return error::kOutOfBounds;
8013 }
[email protected]07d0cc82010-02-17 04:51:408014 // Check that the client initialized the result.
8015 if (result->success != 0) {
8016 return error::kInvalidArguments;
8017 }
[email protected]6b8cf1a2010-05-06 16:13:588018 ProgramManager::ProgramInfo* info = GetProgramInfoNotShader(
8019 program, "glGetActiveAttrib");
[email protected]ae51d192010-04-27 00:48:038020 if (!info) {
[email protected]0bfd9882010-02-05 23:02:258021 return error::kNoError;
8022 }
8023 const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
8024 info->GetAttribInfo(index);
8025 if (!attrib_info) {
[email protected]ad84a3a2012-06-08 21:42:438026 SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
[email protected]0bfd9882010-02-05 23:02:258027 return error::kNoError;
8028 }
8029 result->success = 1; // true.
8030 result->size = attrib_info->size;
8031 result->type = attrib_info->type;
8032 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:298033 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:148034 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328035}
8036
[email protected]b273e432010-04-12 17:23:588037error::Error GLES2DecoderImpl::HandleShaderBinary(
8038 uint32 immediate_data_size, const gles2::ShaderBinary& c) {
8039#if 1 // No binary shader support.
[email protected]ad84a3a2012-06-08 21:42:438040 SetGLError(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
[email protected]b273e432010-04-12 17:23:588041 return error::kNoError;
8042#else
8043 GLsizei n = static_cast<GLsizei>(c.n);
8044 if (n < 0) {
[email protected]ad84a3a2012-06-08 21:42:438045 SetGLError(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
[email protected]b273e432010-04-12 17:23:588046 return error::kNoError;
8047 }
8048 GLsizei length = static_cast<GLsizei>(c.length);
8049 if (length < 0) {
[email protected]ad84a3a2012-06-08 21:42:438050 SetGLError(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
[email protected]b273e432010-04-12 17:23:588051 return error::kNoError;
8052 }
8053 uint32 data_size;
8054 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
8055 return error::kOutOfBounds;
8056 }
8057 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
8058 c.shaders_shm_id, c.shaders_shm_offset, data_size);
8059 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
8060 const void* binary = GetSharedMemoryAs<const void*>(
8061 c.binary_shm_id, c.binary_shm_offset, length);
8062 if (shaders == NULL || binary == NULL) {
8063 return error::kOutOfBounds;
8064 }
8065 scoped_array<GLuint> service_ids(new GLuint[n]);
8066 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ae51d192010-04-27 00:48:038067 ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
8068 if (!info) {
[email protected]ad84a3a2012-06-08 21:42:438069 SetGLError(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
[email protected]b273e432010-04-12 17:23:588070 return error::kNoError;
8071 }
[email protected]ae51d192010-04-27 00:48:038072 service_ids[ii] = info->service_id();
[email protected]b273e432010-04-12 17:23:588073 }
8074 // TODO(gman): call glShaderBinary
8075 return error::kNoError;
8076#endif
8077}
8078
[email protected]6217d392010-03-25 22:08:358079error::Error GLES2DecoderImpl::HandleSwapBuffers(
8080 uint32 immediate_data_size, const gles2::SwapBuffers& c) {
[email protected]64ace852011-05-19 21:49:498081 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8082 int this_frame_number = frame_number_++;
[email protected]da151512011-11-11 23:27:388083 // TRACE_EVENT for gpu tests:
[email protected]529c6672012-01-04 02:18:268084 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers",
8085 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
8086 "width", (is_offscreen ? offscreen_size_.width() :
8087 surface_->GetSize().width()));
[email protected]64ace852011-05-19 21:49:498088 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleSwapBuffers",
8089 "offscreen", is_offscreen,
8090 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:358091 // If offscreen then don't actually SwapBuffers to the display. Just copy
8092 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:498093 if (is_offscreen) {
[email protected]1fb8c482011-08-31 01:01:538094 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
8095 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
8096 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
8097 // fix this.
8098 if (needs_mac_nvidia_driver_workaround_) {
8099 offscreen_saved_frame_buffer_->Create();
8100 glFinish();
8101 }
8102
8103 // Allocate the offscreen saved color texture.
8104 DCHECK(offscreen_saved_color_format_);
8105 offscreen_saved_color_texture_->AllocateStorage(
8106 offscreen_size_, offscreen_saved_color_format_);
[email protected]1078f912011-12-23 13:12:148107 UpdateBackbufferMemoryAccounting();
[email protected]1fb8c482011-08-31 01:01:538108
8109 offscreen_saved_frame_buffer_->AttachRenderTexture(
8110 offscreen_saved_color_texture_.get());
8111 if (offscreen_saved_frame_buffer_->CheckStatus() !=
8112 GL_FRAMEBUFFER_COMPLETE) {
8113 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
8114 << "because offscreen saved FBO was incomplete.";
8115 return error::kLostContext;
8116 }
8117
[email protected]1fb8c482011-08-31 01:01:538118 // Clear the offscreen color texture.
8119 // TODO(piman): Is this still necessary?
8120 {
8121 ScopedFrameBufferBinder binder(this,
8122 offscreen_saved_frame_buffer_->id());
8123 glClearColor(0, 0, 0, 0);
8124 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
8125 glDisable(GL_SCISSOR_TEST);
8126 glClear(GL_COLOR_BUFFER_BIT);
8127 RestoreClearState();
8128 }
8129
8130 UpdateParentTextureInfo();
8131 }
8132
[email protected]6217d392010-03-25 22:08:358133 ScopedGLErrorSuppressor suppressor(this);
8134
[email protected]34ff8b0c2010-10-01 20:06:028135 if (IsOffscreenBufferMultisampled()) {
[email protected]51411e32012-01-19 20:21:138136 // For multisampled buffers, resolve the frame buffer.
[email protected]de26b3c2011-08-03 21:54:278137 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]89d6ed02011-04-20 00:23:238138 return error::kNoError;
[email protected]b86b14982010-10-11 18:45:488139 } else {
[email protected]069944672012-04-25 20:52:238140 ScopedFrameBufferBinder binder(this,
8141 offscreen_target_frame_buffer_->id());
[email protected]51411e32012-01-19 20:21:138142
[email protected]069944672012-04-25 20:52:238143 if (offscreen_target_buffer_preserved_) {
8144 // Copy the target frame buffer to the saved offscreen texture.
8145 offscreen_saved_color_texture_->Copy(
8146 offscreen_saved_color_texture_->size(),
8147 offscreen_saved_color_format_);
8148 } else {
8149 // Flip the textures in the parent context via the texture manager.
8150 if (!!offscreen_saved_color_texture_info_.get())
8151 offscreen_saved_color_texture_info_->
8152 SetServiceId(offscreen_target_color_texture_->id());
[email protected]8a61d872012-01-20 12:43:568153
[email protected]069944672012-04-25 20:52:238154 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
8155 offscreen_target_frame_buffer_->AttachRenderTexture(
8156 offscreen_target_color_texture_.get());
[email protected]b86b14982010-10-11 18:45:488157 }
[email protected]069944672012-04-25 20:52:238158
8159 // Ensure the side effects of the copy are visible to the parent
8160 // context. There is no need to do this for ANGLE because it uses a
8161 // single D3D device for all contexts.
8162 if (!IsAngle())
8163 glFlush();
[email protected]89d6ed02011-04-20 00:23:238164 return error::kNoError;
[email protected]0c8c9d22010-06-25 17:36:398165 }
[email protected]6217d392010-03-25 22:08:358166 } else {
[email protected]64ace852011-05-19 21:49:498167 TRACE_EVENT1("gpu", "GLContext::SwapBuffers", "frame", this_frame_number);
[email protected]f62a5ab2011-05-23 20:34:158168 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:018169 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]5259ead82010-09-10 18:02:028170 return error::kLostContext;
[email protected]d0498742010-09-20 20:27:018171 }
[email protected]6217d392010-03-25 22:08:358172 }
8173
[email protected]89d6ed02011-04-20 00:23:238174 return error::kNoError;
[email protected]6217d392010-03-25 22:08:358175}
8176
[email protected]d4239852011-08-12 04:51:228177error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
8178 uint32 immediate_data_size, const gles2::EnableFeatureCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:188179 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:288180 if (!bucket || bucket->size() == 0) {
8181 return error::kInvalidArguments;
8182 }
[email protected]d4239852011-08-12 04:51:228183 typedef gles2::EnableFeatureCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:188184 Result* result = GetSharedMemoryAs<Result*>(
8185 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8186 if (!result) {
8187 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:108188 }
[email protected]b1d2dcb2010-05-17 19:24:188189 // Check that the client initialized the result.
8190 if (*result != 0) {
8191 return error::kInvalidArguments;
8192 }
8193 std::string feature_str;
8194 if (!bucket->GetAsString(&feature_str)) {
8195 return error::kInvalidArguments;
8196 }
8197
8198 // TODO(gman): make this some kind of table to function pointer thingy.
[email protected]d4239852011-08-12 04:51:228199 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
[email protected]b1d2dcb2010-05-17 19:24:188200 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]d4239852011-08-12 04:51:228201 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
[email protected]8fbedc02010-11-18 18:43:408202 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
8203 // TODO(gman): decide how to remove the need for this const_cast.
8204 // I could make validators_ non const but that seems bad as this is the only
8205 // place it is needed. I could make some special friend class of validators
8206 // just to allow this to set them. That seems silly. I could refactor this
8207 // code to use the extension mechanism or the initialization attributes to
8208 // turn this feature on. Given that the only real point of this is to make
8209 // the conformance tests pass and given that there is lots of real work that
8210 // needs to be done it seems like refactoring for one to one of those
8211 // methods is a very low priority.
8212 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]f0d74742011-10-03 16:31:048213 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
8214 force_webgl_glsl_validation_ = true;
8215 InitializeShaderTranslator();
[email protected]b1d2dcb2010-05-17 19:24:188216 } else {
8217 return error::kNoError;
8218 }
8219
8220 *result = 1; // true.
8221 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:108222}
8223
[email protected]c2f8c8402010-12-06 18:07:248224error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
8225 uint32 immediate_data_size,
8226 const gles2::GetRequestableExtensionsCHROMIUM& c) {
8227 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]80eb6b52012-01-19 00:14:418228 FeatureInfo::Ref info(new FeatureInfo());
[email protected]e82fb792011-09-22 00:33:298229 info->Initialize(disallowed_features_, NULL);
[email protected]c2f8c8402010-12-06 18:07:248230 bucket->SetFromString(info->extensions().c_str());
8231 return error::kNoError;
8232}
8233
8234error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
8235 uint32 immediate_data_size, const gles2::RequestExtensionCHROMIUM& c) {
8236 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:288237 if (!bucket || bucket->size() == 0) {
8238 return error::kInvalidArguments;
8239 }
[email protected]c2f8c8402010-12-06 18:07:248240 std::string feature_str;
8241 if (!bucket->GetAsString(&feature_str)) {
8242 return error::kInvalidArguments;
8243 }
8244
8245 bool std_derivatives_enabled =
8246 feature_info_->feature_flags().oes_standard_derivatives;
8247 bool webglsl_enabled =
8248 feature_info_->feature_flags().chromium_webglsl;
8249
8250 feature_info_->AddFeatures(feature_str.c_str());
8251
[email protected]f0d74742011-10-03 16:31:048252 bool initialization_required = false;
8253 if (force_webgl_glsl_validation_ && !derivatives_explicitly_enabled_) {
8254 size_t derivatives_offset = feature_str.find(kOESDerivativeExtension);
8255 if (std::string::npos != derivatives_offset) {
8256 derivatives_explicitly_enabled_ = true;
8257 initialization_required = true;
8258 }
8259 }
8260
[email protected]c2f8c8402010-12-06 18:07:248261 // If we just enabled a feature which affects the shader translator,
8262 // we may need to re-initialize it.
8263 if (std_derivatives_enabled !=
8264 feature_info_->feature_flags().oes_standard_derivatives ||
8265 webglsl_enabled !=
[email protected]f0d74742011-10-03 16:31:048266 feature_info_->feature_flags().chromium_webglsl ||
8267 initialization_required) {
[email protected]c2f8c8402010-12-06 18:07:248268 InitializeShaderTranslator();
8269 }
8270
[email protected]302ce6d2011-07-07 23:28:118271 UpdateCapabilities();
8272
[email protected]c2f8c8402010-12-06 18:07:248273 return error::kNoError;
8274}
8275
[email protected]372e0412011-06-28 16:08:568276error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
8277 uint32 immediate_data_size, const gles2::GetMultipleIntegervCHROMIUM& c) {
8278 GLuint count = c.count;
8279 uint32 pnames_size;
8280 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
8281 return error::kOutOfBounds;
8282 }
8283 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
8284 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
8285 if (pnames == NULL) {
8286 return error::kOutOfBounds;
8287 }
8288
8289 // We have to copy them since we use them twice so the client
8290 // can't change them between the time we validate them and the time we use
8291 // them.
8292 scoped_array<GLenum> enums(new GLenum[count]);
8293 memcpy(enums.get(), pnames, pnames_size);
8294
8295 // Count up the space needed for the result.
8296 uint32 num_results = 0;
8297 for (GLuint ii = 0; ii < count; ++ii) {
8298 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
8299 if (num == 0) {
8300 SetGLError(GL_INVALID_ENUM,
[email protected]ad84a3a2012-06-08 21:42:438301 "glGetMulitpleCHROMIUM", "pname GL_INVALID_ENUM");
[email protected]372e0412011-06-28 16:08:568302 return error::kNoError;
8303 }
8304 // Num will never be more than 4.
8305 DCHECK_LE(num, 4u);
8306 if (!SafeAdd(num_results, num, &num_results)) {
8307 return error::kOutOfBounds;
8308 }
8309 }
8310
8311 uint32 result_size = 0;
8312 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
8313 return error::kOutOfBounds;
8314 }
8315
8316 if (result_size != static_cast<uint32>(c.size)) {
8317 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438318 "glGetMulitpleCHROMIUM", "bad size GL_INVALID_VALUE");
[email protected]372e0412011-06-28 16:08:568319 return error::kNoError;
8320 }
8321
8322 GLint* results = GetSharedMemoryAs<GLint*>(
8323 c.results_shm_id, c.results_shm_offset, result_size);
8324 if (results == NULL) {
8325 return error::kOutOfBounds;
8326 }
8327
8328 // Check the results have been cleared in case the context was lost.
8329 for (uint32 ii = 0; ii < num_results; ++ii) {
8330 if (results[ii]) {
8331 return error::kInvalidArguments;
8332 }
8333 }
8334
8335 // Get each result.
8336 GLint* start = results;
8337 for (GLuint ii = 0; ii < count; ++ii) {
8338 GLsizei num_written = 0;
8339 if (!GetHelper(enums[ii], results, &num_written)) {
8340 glGetIntegerv(enums[ii], results);
8341 }
8342 results += num_written;
8343 }
8344
8345 // Just to verify. Should this be a DCHECK?
8346 if (static_cast<uint32>(results - start) != num_results) {
8347 return error::kOutOfBounds;
8348 }
8349
8350 return error::kNoError;
8351}
8352
[email protected]2318d342011-07-11 22:27:428353error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
8354 uint32 immediate_data_size, const gles2::GetProgramInfoCHROMIUM& c) {
8355 GLuint program = static_cast<GLuint>(c.program);
8356 uint32 bucket_id = c.bucket_id;
8357 Bucket* bucket = CreateBucket(bucket_id);
8358 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
8359 ProgramManager::ProgramInfo* info = NULL;
[email protected]9a14ae612011-08-08 17:51:468360 info = GetProgramInfo(program);
8361 if (!info || !info->IsValid()) {
8362 return error::kNoError;
[email protected]2318d342011-07-11 22:27:428363 }
[email protected]5d4c6b22012-02-07 08:22:288364 info->GetProgramInfo(program_manager(), bucket);
[email protected]2318d342011-07-11 22:27:428365 return error::kNoError;
8366}
8367
[email protected]38d139d2011-07-14 00:38:438368error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
8369 switch (reset_status_) {
[email protected]ad84a3a2012-06-08 21:42:438370 case GL_NO_ERROR:
8371 // TODO(kbr): improve the precision of the error code in this case.
8372 // Consider delegating to context for error code if MakeCurrent fails.
8373 return error::kUnknown;
8374 case GL_GUILTY_CONTEXT_RESET_ARB:
8375 return error::kGuilty;
8376 case GL_INNOCENT_CONTEXT_RESET_ARB:
8377 return error::kInnocent;
8378 case GL_UNKNOWN_CONTEXT_RESET_ARB:
8379 return error::kUnknown;
[email protected]38d139d2011-07-14 00:38:438380 }
8381
8382 NOTREACHED();
8383 return error::kUnknown;
8384}
8385
8386bool GLES2DecoderImpl::WasContextLost() {
8387 if (context_->WasAllocatedUsingARBRobustness() && has_arb_robustness_) {
8388 GLenum status = glGetGraphicsResetStatusARB();
8389 if (status != GL_NO_ERROR) {
8390 // The graphics card was reset. Signal a lost context to the application.
8391 reset_status_ = status;
8392 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
8393 << " context lost via ARB_robustness. Reset status = 0x"
8394 << std::hex << status << std::dec;
8395 return true;
8396 }
8397 }
8398 return false;
8399}
8400
[email protected]882ba1e22012-03-08 19:02:538401bool GLES2DecoderImpl::GenQueriesEXTHelper(
8402 GLsizei n, const GLuint* client_ids) {
8403 for (GLsizei ii = 0; ii < n; ++ii) {
8404 if (query_manager_->GetQuery(client_ids[ii])) {
8405 return false;
8406 }
8407 }
[email protected]c45f1972012-03-14 07:27:368408 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
[email protected]882ba1e22012-03-08 19:02:538409 return true;
8410}
8411
8412void GLES2DecoderImpl::DeleteQueriesEXTHelper(
8413 GLsizei n, const GLuint* client_ids) {
8414 for (GLsizei ii = 0; ii < n; ++ii) {
8415 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
8416 if (query && !query->IsDeleted()) {
8417 if (query == current_query_) {
8418 current_query_ = NULL;
8419 }
[email protected]c45f1972012-03-14 07:27:368420 query->Destroy(true);
[email protected]882ba1e22012-03-08 19:02:538421 query_manager_->RemoveQuery(client_ids[ii]);
8422 }
8423 }
8424}
8425
[email protected]22e3f552012-03-13 01:54:198426bool GLES2DecoderImpl::ProcessPendingQueries() {
8427 if (query_manager_.get() == NULL) {
8428 return false;
8429 }
[email protected]c45f1972012-03-14 07:27:368430 if (!query_manager_->ProcessPendingQueries()) {
[email protected]22e3f552012-03-13 01:54:198431 current_decoder_error_ = error::kOutOfBounds;
8432 }
8433 return query_manager_->HavePendingQueries();
8434}
8435
[email protected]882ba1e22012-03-08 19:02:538436error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
8437 uint32 immediate_data_size, const gles2::BeginQueryEXT& c) {
8438 GLenum target = static_cast<GLenum>(c.target);
8439 GLuint client_id = static_cast<GLuint>(c.id);
8440 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
8441 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
8442
[email protected]c45f1972012-03-14 07:27:368443 switch (target) {
8444 case GL_COMMANDS_ISSUED_CHROMIUM:
8445 break;
8446 default:
8447 if (!feature_info_->feature_flags().occlusion_query_boolean) {
[email protected]ad84a3a2012-06-08 21:42:438448 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT", "not enabled");
[email protected]c45f1972012-03-14 07:27:368449 return error::kNoError;
8450 }
8451 break;
[email protected]882ba1e22012-03-08 19:02:538452 }
8453
8454 if (current_query_) {
8455 SetGLError(
[email protected]ad84a3a2012-06-08 21:42:438456 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
[email protected]882ba1e22012-03-08 19:02:538457 return error::kNoError;
8458 }
8459
8460 if (client_id == 0) {
[email protected]ad84a3a2012-06-08 21:42:438461 SetGLError(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
[email protected]882ba1e22012-03-08 19:02:538462 return error::kNoError;
8463 }
8464
8465 QueryManager::Query* query = query_manager_->GetQuery(client_id);
8466 if (!query) {
[email protected]c45f1972012-03-14 07:27:368467 // TODO(gman): Decide if we need this check.
8468 //
[email protected]882ba1e22012-03-08 19:02:538469 // Checks id was made by glGenQueries
[email protected]c45f1972012-03-14 07:27:368470 //
8471 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
8472 // for all Query ids but from the POV of the command buffer service maybe
8473 // you don't.
8474 //
8475 // The client can enforce this. I don't think the service cares.
8476 //
8477 // IdAllocatorInterface* id_allocator =
8478 // group_->GetIdAllocator(id_namespaces::kQueries);
8479 // if (!id_allocator->InUse(client_id)) {
8480 // SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438481 // "glBeginQueryEXT", "id not made by glGenQueriesEXT");
[email protected]c45f1972012-03-14 07:27:368482 // return error::kNoError;
8483 // }
8484 query = query_manager_->CreateQuery(
8485 target, client_id, sync_shm_id, sync_shm_offset);
[email protected]882ba1e22012-03-08 19:02:538486 }
8487
[email protected]c45f1972012-03-14 07:27:368488 if (query->target() != target) {
[email protected]ad84a3a2012-06-08 21:42:438489 SetGLError(
8490 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
[email protected]882ba1e22012-03-08 19:02:538491 return error::kNoError;
8492 } else if (query->shm_id() != sync_shm_id ||
8493 query->shm_offset() != sync_shm_offset) {
8494 DLOG(ERROR) << "Shared memory used by query not the same as before";
8495 return error::kInvalidArguments;
8496 }
8497
[email protected]c45f1972012-03-14 07:27:368498 if (!query_manager_->BeginQuery(query)) {
8499 return error::kOutOfBounds;
8500 }
[email protected]882ba1e22012-03-08 19:02:538501
[email protected]882ba1e22012-03-08 19:02:538502 current_query_ = query;
[email protected]882ba1e22012-03-08 19:02:538503 return error::kNoError;
8504}
8505
8506error::Error GLES2DecoderImpl::HandleEndQueryEXT(
8507 uint32 immediate_data_size, const gles2::EndQueryEXT& c) {
8508 GLenum target = static_cast<GLenum>(c.target);
8509 uint32 submit_count = static_cast<GLuint>(c.submit_count);
8510
8511 if (!current_query_) {
[email protected]ad84a3a2012-06-08 21:42:438512 SetGLError(GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
[email protected]882ba1e22012-03-08 19:02:538513 return error::kNoError;
8514 }
8515 if (current_query_->target() != target) {
8516 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438517 "glEndQueryEXT", "target does not match active query");
[email protected]882ba1e22012-03-08 19:02:538518 return error::kNoError;
8519 }
[email protected]882ba1e22012-03-08 19:02:538520
[email protected]c45f1972012-03-14 07:27:368521 if (!query_manager_->EndQuery(current_query_, submit_count)) {
8522 return error::kOutOfBounds;
8523 }
8524
8525 current_query_ = NULL;
[email protected]882ba1e22012-03-08 19:02:538526 return error::kNoError;
8527}
8528
[email protected]b0af4f52011-09-28 22:04:428529error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
8530 uint32 immediate_data_size,
8531 const gles2::CreateStreamTextureCHROMIUM& c) {
8532 if (!feature_info_->feature_flags().chromium_stream_texture) {
8533 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438534 "glOpenStreamTextureCHROMIUM", ""
[email protected]b0af4f52011-09-28 22:04:428535 "not supported.");
8536 return error::kNoError;
8537 }
8538
8539 uint32 client_id = c.client_id;
8540 typedef gles2::CreateStreamTextureCHROMIUM::Result Result;
8541 Result* result = GetSharedMemoryAs<Result*>(
8542 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8543
[email protected]e5081262012-01-05 23:09:038544 if (!result)
8545 return error::kOutOfBounds;
[email protected]b0af4f52011-09-28 22:04:428546 *result = GL_ZERO;
8547 TextureManager::TextureInfo* info =
8548 texture_manager()->GetTextureInfo(client_id);
8549 if (!info) {
8550 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438551 "glCreateStreamTextureCHROMIUM", ""
[email protected]b0af4f52011-09-28 22:04:428552 "bad texture id.");
8553 return error::kNoError;
8554 }
8555
8556 if (info->IsStreamTexture()) {
8557 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438558 "glCreateStreamTextureCHROMIUM", ""
[email protected]b0af4f52011-09-28 22:04:428559 "is already a stream texture.");
8560 return error::kNoError;
8561 }
8562
8563 if (info->target() && info->target() != GL_TEXTURE_EXTERNAL_OES) {
8564 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438565 "glCreateStreamTextureCHROMIUM", ""
[email protected]b0af4f52011-09-28 22:04:428566 "is already bound to incompatible target.");
8567 return error::kNoError;
8568 }
8569
8570 if (!stream_texture_manager_)
8571 return error::kInvalidArguments;
8572
8573 GLuint object_id = stream_texture_manager_->CreateStreamTexture(
8574 info->service_id(), client_id);
8575
8576 if (object_id) {
8577 info->SetStreamTexture(true);
8578 } else {
8579 SetGLError(GL_OUT_OF_MEMORY,
[email protected]ad84a3a2012-06-08 21:42:438580 "glCreateStreamTextureCHROMIUM", ""
[email protected]b0af4f52011-09-28 22:04:428581 "failed to create platform texture.");
8582 }
8583
8584 *result = object_id;
8585 return error::kNoError;
8586}
8587
8588error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
8589 uint32 immediate_data_size,
8590 const gles2::DestroyStreamTextureCHROMIUM& c) {
8591 GLuint client_id = c.texture;
8592 TextureManager::TextureInfo* info =
8593 texture_manager()->GetTextureInfo(client_id);
8594 if (info && info->IsStreamTexture()) {
8595 if (!stream_texture_manager_)
8596 return error::kInvalidArguments;
8597
8598 stream_texture_manager_->DestroyStreamTexture(info->service_id());
8599 info->SetStreamTexture(false);
[email protected]80eb6b52012-01-19 00:14:418600 texture_manager()->SetInfoTarget(info, 0);
[email protected]b0af4f52011-09-28 22:04:428601 } else {
8602 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438603 "glDestroyStreamTextureCHROMIUM", "bad texture id.");
[email protected]b0af4f52011-09-28 22:04:428604 }
8605
8606 return error::kNoError;
8607}
8608
[email protected]e51bdf32011-11-23 22:21:468609#if defined(OS_MACOSX)
8610void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
8611 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
8612 texture_id);
8613 if (it != texture_to_io_surface_map_.end()) {
8614 // Found a previous IOSurface bound to this texture; release it.
8615 CFTypeRef surface = it->second;
8616 CFRelease(surface);
8617 texture_to_io_surface_map_.erase(it);
8618 }
8619}
8620#endif
8621
8622void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
8623 GLenum target, GLsizei width, GLsizei height,
8624 GLuint io_surface_id, GLuint plane) {
8625#if defined(OS_MACOSX)
8626 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
[email protected]ad84a3a2012-06-08 21:42:438627 SetGLError(
8628 GL_INVALID_OPERATION,
8629 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
[email protected]e51bdf32011-11-23 22:21:468630 return;
8631 }
8632
8633 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
8634 if (!surface_support) {
8635 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438636 "glTexImageIOSurface2DCHROMIUM", "only supported on 10.6.");
[email protected]e51bdf32011-11-23 22:21:468637 return;
8638 }
8639
8640 if (target != GL_TEXTURE_RECTANGLE_ARB) {
8641 // This might be supported in the future, and if we could require
8642 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
8643 // could delete a lot of code. For now, perform strict validation so we
8644 // know what's going on.
8645 SetGLError(
8646 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438647 "glTexImageIOSurface2DCHROMIUM",
8648 "requires TEXTURE_RECTANGLE_ARB target");
[email protected]e51bdf32011-11-23 22:21:468649 return;
8650 }
8651
8652 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8653 if (!info) {
8654 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438655 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
[email protected]e51bdf32011-11-23 22:21:468656 return;
8657 }
8658 if (info == texture_manager()->GetDefaultTextureInfo(target)) {
8659 // Maybe this is conceptually valid, but disallow it to avoid accidents.
8660 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438661 "glTexImageIOSurface2DCHROMIUM", "can't bind default texture");
[email protected]e51bdf32011-11-23 22:21:468662 return;
8663 }
8664
8665 // Look up the new IOSurface. Note that because of asynchrony
8666 // between processes this might fail; during live resizing the
8667 // plugin process might allocate and release an IOSurface before
8668 // this process gets a chance to look it up. Hold on to any old
8669 // IOSurface in this case.
8670 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
8671 if (!surface) {
[email protected]ad84a3a2012-06-08 21:42:438672 SetGLError(
8673 GL_INVALID_OPERATION,
8674 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
[email protected]e51bdf32011-11-23 22:21:468675 return;
8676 }
8677
8678 // Release any IOSurface previously bound to this texture.
8679 ReleaseIOSurfaceForTexture(info->service_id());
8680
8681 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
8682 texture_to_io_surface_map_.insert(
8683 std::make_pair(info->service_id(), surface));
8684
8685 CGLContextObj context =
8686 static_cast<CGLContextObj>(context_->GetHandle());
8687
8688 CGLError err = surface_support->CGLTexImageIOSurface2D(
8689 context,
8690 target,
8691 GL_RGBA,
8692 width,
8693 height,
8694 GL_BGRA,
8695 GL_UNSIGNED_INT_8_8_8_8_REV,
8696 surface,
8697 plane);
8698
8699 if (err != kCGLNoError) {
8700 SetGLError(
8701 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438702 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
[email protected]e51bdf32011-11-23 22:21:468703 return;
8704 }
8705
8706 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:418707 info, target, 0, GL_RGBA, width, height, 1, 0,
[email protected]e51bdf32011-11-23 22:21:468708 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
8709
8710#else
8711 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438712 "glTexImageIOSurface2DCHROMIUM", "not supported.");
[email protected]e51bdf32011-11-23 22:21:468713#endif
8714}
8715
[email protected]97dc7cbe2011-12-06 17:26:178716static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
8717 switch (internalformat) {
8718 case GL_RGB565:
8719 return GL_RGB;
8720 case GL_RGBA4:
8721 return GL_RGBA;
8722 case GL_RGB5_A1:
8723 return GL_RGBA;
8724 case GL_RGB8_OES:
8725 return GL_RGB;
8726 case GL_RGBA8_OES:
8727 return GL_RGBA;
8728 case GL_LUMINANCE8_ALPHA8_EXT:
8729 return GL_LUMINANCE_ALPHA;
8730 case GL_LUMINANCE8_EXT:
8731 return GL_LUMINANCE;
8732 case GL_ALPHA8_EXT:
8733 return GL_ALPHA;
8734 case GL_RGBA32F_EXT:
8735 return GL_RGBA;
8736 case GL_RGB32F_EXT:
8737 return GL_RGB;
8738 case GL_ALPHA32F_EXT:
8739 return GL_ALPHA;
8740 case GL_LUMINANCE32F_EXT:
8741 return GL_LUMINANCE;
8742 case GL_LUMINANCE_ALPHA32F_EXT:
8743 return GL_LUMINANCE_ALPHA;
8744 case GL_RGBA16F_EXT:
8745 return GL_RGBA;
8746 case GL_RGB16F_EXT:
8747 return GL_RGB;
8748 case GL_ALPHA16F_EXT:
8749 return GL_ALPHA;
8750 case GL_LUMINANCE16F_EXT:
8751 return GL_LUMINANCE;
8752 case GL_LUMINANCE_ALPHA16F_EXT:
8753 return GL_LUMINANCE_ALPHA;
8754 case GL_BGRA8_EXT:
8755 return GL_BGRA_EXT;
8756 default:
8757 return GL_NONE;
8758 }
8759}
8760
[email protected]43410e92012-04-20 17:06:288761void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
[email protected]0a1e9ad2012-05-04 21:13:038762 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
8763 GLenum internal_format) {
[email protected]43410e92012-04-20 17:06:288764 TextureManager::TextureInfo* dest_info = GetTextureInfo(dest_id);
8765 TextureManager::TextureInfo* source_info = GetTextureInfo(source_id);
8766
8767 if (!source_info || !dest_info) {
[email protected]ad84a3a2012-06-08 21:42:438768 SetGLError(GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
[email protected]43410e92012-04-20 17:06:288769 return;
8770 }
8771
8772 if (GL_TEXTURE_2D != target) {
8773 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438774 "glCopyTextureCHROMIUM", "invalid texture target");
[email protected]43410e92012-04-20 17:06:288775 return;
8776 }
8777
[email protected]0a1e9ad2012-05-04 21:13:038778 if (dest_info->target() != GL_TEXTURE_2D ||
8779 source_info->target() != GL_TEXTURE_2D) {
8780 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438781 "glCopyTextureCHROMIUM", "invalid texture target binding");
[email protected]0a1e9ad2012-05-04 21:13:038782 return;
8783 }
8784
[email protected]43410e92012-04-20 17:06:288785 int source_width, source_height, dest_width, dest_height;
8786 if (!source_info->GetLevelSize(GL_TEXTURE_2D, 0, &source_width,
8787 &source_height)) {
8788 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438789 "glCopyTextureChromium", "source texture has no level 0");
[email protected]43410e92012-04-20 17:06:288790 return;
8791 }
8792
[email protected]43410e92012-04-20 17:06:288793 // Check that this type of texture is allowed.
8794 if (!texture_manager()->ValidForTarget(GL_TEXTURE_2D, level, source_width,
8795 source_height, 1)) {
8796 SetGLError(GL_INVALID_VALUE,
[email protected]ad84a3a2012-06-08 21:42:438797 "glCopyTextureCHROMIUM", "Bad dimensions");
[email protected]43410e92012-04-20 17:06:288798 return;
8799 }
8800
[email protected]cf6b8f62012-05-25 21:43:378801 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
8802 // needed because it takes 10s of milliseconds to initialize.
8803 if (!copy_texture_CHROMIUM_.get()) {
8804 CopyRealGLErrorsToWrapper();
8805 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
8806 copy_texture_CHROMIUM_->Initialize();
8807 RestoreCurrentFramebufferBindings();
8808 if (PeekGLError() != GL_NO_ERROR)
8809 return;
8810 }
8811
[email protected]0a1e9ad2012-05-04 21:13:038812 GLenum dest_type;
8813 GLenum dest_internal_format;
8814 bool dest_level_defined = dest_info->GetLevelSize(GL_TEXTURE_2D, level,
8815 &dest_width,
8816 &dest_height);
[email protected]43410e92012-04-20 17:06:288817
[email protected]0a1e9ad2012-05-04 21:13:038818 if (dest_level_defined) {
8819 dest_info->GetLevelType(GL_TEXTURE_2D, level, &dest_type,
8820 &dest_internal_format);
8821 } else {
8822 GLenum source_internal_format;
8823 source_info->GetLevelType(GL_TEXTURE_2D, 0, &dest_type,
8824 &source_internal_format);
8825 }
8826
8827 // Resize the destination texture to the dimensions of the source texture.
8828 if (!dest_level_defined || dest_width != source_width ||
8829 dest_height != source_height ||
8830 dest_internal_format != internal_format) {
[email protected]43410e92012-04-20 17:06:288831 // Ensure that the glTexImage2D succeeds.
8832 CopyRealGLErrorsToWrapper();
[email protected]0a1e9ad2012-05-04 21:13:038833 glBindTexture(GL_TEXTURE_2D, dest_info->service_id());
[email protected]43410e92012-04-20 17:06:288834 WrappedTexImage2D(
8835 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
[email protected]0a1e9ad2012-05-04 21:13:038836 0, internal_format, dest_type, NULL);
[email protected]43410e92012-04-20 17:06:288837 GLenum error = PeekGLError();
[email protected]0a1e9ad2012-05-04 21:13:038838 if (error != GL_NO_ERROR) {
8839 RestoreCurrentTexture2DBindings();
[email protected]43410e92012-04-20 17:06:288840 return;
[email protected]0a1e9ad2012-05-04 21:13:038841 }
[email protected]43410e92012-04-20 17:06:288842
8843 texture_manager()->SetLevelInfo(
8844 dest_info, GL_TEXTURE_2D, level, internal_format, source_width,
[email protected]0a1e9ad2012-05-04 21:13:038845 source_height, 1, 0, internal_format, dest_type, true);
[email protected]f7024712012-05-15 21:30:258846 } else {
8847 texture_manager()->SetLevelCleared(dest_info, GL_TEXTURE_2D, level);
[email protected]43410e92012-04-20 17:06:288848 }
8849
8850 state_dirty_ = true;
[email protected]0a1e9ad2012-05-04 21:13:038851 glViewport(0, 0, source_width, source_height);
[email protected]43410e92012-04-20 17:06:288852 copy_texture_CHROMIUM_->DoCopyTexture(target, source_info->service_id(),
8853 dest_info->service_id(), level,
8854 unpack_flip_y_,
[email protected]6c75c712012-06-19 15:43:178855 unpack_premultiply_alpha_,
8856 unpack_unpremultiply_alpha_);
[email protected]43410e92012-04-20 17:06:288857 glViewport(viewport_x_, viewport_y_, viewport_width_, viewport_height_);
8858
8859 // Restore all of the state touched by the extension.
8860 if (current_program_)
8861 glUseProgram(current_program_->service_id());
8862 else
8863 glUseProgram(0);
8864
8865 RestoreCurrentFramebufferBindings();
8866 RestoreCurrentTexture2DBindings();
8867 RestoreStateForAttrib(
8868 CopyTextureCHROMIUMResourceManager::kVertexPositionAttrib);
8869 RestoreStateForAttrib(
8870 CopyTextureCHROMIUMResourceManager::kVertexTextureAttrib);
8871
8872 ApplyDirtyState();
8873}
8874
[email protected]97dc7cbe2011-12-06 17:26:178875static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
8876 switch (internalformat) {
8877 case GL_RGB565:
8878 return GL_UNSIGNED_SHORT_5_6_5;
8879 case GL_RGBA4:
8880 return GL_UNSIGNED_SHORT_4_4_4_4;
8881 case GL_RGB5_A1:
8882 return GL_UNSIGNED_SHORT_5_5_5_1;
8883 case GL_RGB8_OES:
8884 return GL_UNSIGNED_BYTE;
8885 case GL_RGBA8_OES:
8886 return GL_UNSIGNED_BYTE;
8887 case GL_LUMINANCE8_ALPHA8_EXT:
8888 return GL_UNSIGNED_BYTE;
8889 case GL_LUMINANCE8_EXT:
8890 return GL_UNSIGNED_BYTE;
8891 case GL_ALPHA8_EXT:
8892 return GL_UNSIGNED_BYTE;
8893 case GL_RGBA32F_EXT:
8894 return GL_FLOAT;
8895 case GL_RGB32F_EXT:
8896 return GL_FLOAT;
8897 case GL_ALPHA32F_EXT:
8898 return GL_FLOAT;
8899 case GL_LUMINANCE32F_EXT:
8900 return GL_FLOAT;
8901 case GL_LUMINANCE_ALPHA32F_EXT:
8902 return GL_FLOAT;
8903 case GL_RGBA16F_EXT:
8904 return GL_HALF_FLOAT_OES;
8905 case GL_RGB16F_EXT:
8906 return GL_HALF_FLOAT_OES;
8907 case GL_ALPHA16F_EXT:
8908 return GL_HALF_FLOAT_OES;
8909 case GL_LUMINANCE16F_EXT:
8910 return GL_HALF_FLOAT_OES;
8911 case GL_LUMINANCE_ALPHA16F_EXT:
8912 return GL_HALF_FLOAT_OES;
8913 case GL_BGRA8_EXT:
8914 return GL_UNSIGNED_BYTE;
8915 default:
8916 return GL_NONE;
8917 }
8918}
8919
8920void GLES2DecoderImpl::DoTexStorage2DEXT(
[email protected]a5d3dad2012-05-26 04:34:448921 GLenum target,
8922 GLint levels,
8923 GLenum internal_format,
8924 GLsizei width,
8925 GLsizei height) {
[email protected]43ed3a72012-05-30 22:55:388926 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
[email protected]80eb6b52012-01-19 00:14:418927 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
[email protected]97dc7cbe2011-12-06 17:26:178928 TextureManager::ComputeMipMapCount(width, height, 1) < levels) {
[email protected]ad84a3a2012-06-08 21:42:438929 SetGLError(
8930 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
[email protected]97dc7cbe2011-12-06 17:26:178931 return;
8932 }
8933 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8934 if (!info) {
8935 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438936 "glTexStorage2DEXT", "unknown texture for target");
[email protected]97dc7cbe2011-12-06 17:26:178937 return;
8938 }
8939 if (info->IsAttachedToFramebuffer()) {
8940 state_dirty_ = true;
8941 }
8942 if (info->IsImmutable()) {
8943 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438944 "glTexStorage2DEXT", "texture is immutable");
[email protected]97dc7cbe2011-12-06 17:26:178945 return;
8946 }
8947 CopyRealGLErrorsToWrapper();
[email protected]f0e6a34f2012-01-04 20:53:408948 glTexStorage2DEXT(target, levels, GetTexInternalFormat(internal_format),
8949 width, height);
[email protected]97dc7cbe2011-12-06 17:26:178950 GLenum error = PeekGLError();
8951 if (error == GL_NO_ERROR) {
8952 GLenum format = ExtractFormatFromStorageFormat(internal_format);
8953 GLenum type = ExtractTypeFromStorageFormat(internal_format);
[email protected]4502e6492011-12-14 19:39:158954 GLsizei level_width = width;
8955 GLsizei level_height = height;
8956 for (int ii = 0; ii < levels; ++ii) {
8957 texture_manager()->SetLevelInfo(
[email protected]80eb6b52012-01-19 00:14:418958 info, target, 0, format, level_width, level_height, 1, 0, format,
8959 type, false);
[email protected]4502e6492011-12-14 19:39:158960 level_width = std::max(1, level_width >> 1);
8961 level_height = std::max(1, level_height >> 1);
8962 }
[email protected]97dc7cbe2011-12-06 17:26:178963 info->SetImmutable(true);
8964 }
[email protected]97dc7cbe2011-12-06 17:26:178965}
[email protected]e51bdf32011-11-23 22:21:468966
[email protected]78b514b2012-05-01 21:50:598967error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
8968 uint32 immediate_data_size, const gles2::GenMailboxCHROMIUM& c) {
8969 MailboxName name;
8970 mailbox_manager()->GenerateMailboxName(&name);
8971 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
8972 Bucket* bucket = CreateBucket(bucket_id);
8973
8974 bucket->SetSize(GL_MAILBOX_SIZE_CHROMIUM);
8975 bucket->SetData(&name, 0, GL_MAILBOX_SIZE_CHROMIUM);
8976
8977 return error::kNoError;
8978}
8979
8980void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
8981 const GLbyte* mailbox) {
8982 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
8983 if (!info) {
8984 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438985 "glProduceTextureCHROMIUM", "unknown texture for target");
[email protected]78b514b2012-05-01 21:50:598986 return;
8987 }
8988
8989 TextureDefinition* definition = texture_manager()->Save(info);
8990 if (!definition) {
8991 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:438992 "glProduceTextureCHROMIUM", "invalid texture");
[email protected]78b514b2012-05-01 21:50:598993 return;
8994 }
8995
8996 if (!group_->mailbox_manager()->ProduceTexture(
8997 target,
8998 *reinterpret_cast<const MailboxName*>(mailbox),
8999 definition,
9000 texture_manager())) {
9001 bool success = texture_manager()->Restore(info, definition);
9002 DCHECK(success);
9003 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439004 "glProduceTextureCHROMIUM", "invalid mailbox name");
[email protected]78b514b2012-05-01 21:50:599005 return;
9006 }
9007
9008 BindAndApplyTextureParameters(info);
9009}
9010
9011void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
9012 const GLbyte* mailbox) {
9013 TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
9014 if (!info) {
9015 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439016 "glConsumeTextureCHROMIUM", "unknown texture for target");
[email protected]78b514b2012-05-01 21:50:599017 return;
9018 }
9019
9020 scoped_ptr<TextureDefinition> definition(
9021 group_->mailbox_manager()->ConsumeTexture(
9022 target,
9023 *reinterpret_cast<const MailboxName*>(mailbox)));
9024 if (!definition.get()) {
9025 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439026 "glConsumeTextureCHROMIUM", "invalid mailbox name");
[email protected]78b514b2012-05-01 21:50:599027 return;
9028 }
9029
9030 if (!texture_manager()->Restore(info, definition.release())) {
9031 SetGLError(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439032 "glConsumeTextureCHROMIUM", "invalid texture");
[email protected]78b514b2012-05-01 21:50:599033 return;
9034 }
9035
9036 BindAndApplyTextureParameters(info);
9037}
9038
[email protected]96449d2c2009-11-25 00:01:329039// Include the auto-generated part of this file. We split this because it means
9040// we can easily edit the non-auto generated parts right here in this file
9041// instead of having to edit some template or the code generator.
9042#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
9043
9044} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:259045} // namespace gpu