blob: a9b1f1e0ecae7c78ad1b0b3a524580bb7ad93570 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
6
7#include <stdio.h>
8
9#include <algorithm>
10#include <list>
11#include <map>
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000012#include <stack>
Torne (Richard Coles)58218062012-11-14 11:43:16 +000013#include <string>
14#include <vector>
15
16#include "base/at_exit.h"
17#include "base/atomicops.h"
18#include "base/bind.h"
19#include "base/command_line.h"
20#include "base/debug/trace_event.h"
21#if defined(OS_MACOSX)
22#include "base/mac/scoped_cftyperef.h"
23#endif
24#include "base/memory/scoped_ptr.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010025#include "base/strings/string_number_conversions.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000026#include "build/build_config.h"
27#define GLES2_GPU_SERVICE 1
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010028#include "gpu/command_buffer/common/debug_marker_manager.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000029#include "gpu/command_buffer/common/gles2_cmd_format.h"
30#include "gpu/command_buffer/common/gles2_cmd_utils.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000031#include "gpu/command_buffer/common/id_allocator.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010032#include "gpu/command_buffer/common/mailbox.h"
33#include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
34#include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000035#include "gpu/command_buffer/service/buffer_manager.h"
36#include "gpu/command_buffer/service/cmd_buffer_engine.h"
37#include "gpu/command_buffer/service/context_group.h"
38#include "gpu/command_buffer/service/context_state.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010039#include "gpu/command_buffer/service/error_state.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000040#include "gpu/command_buffer/service/feature_info.h"
41#include "gpu/command_buffer/service/framebuffer_manager.h"
42#include "gpu/command_buffer/service/gl_utils.h"
43#include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
44#include "gpu/command_buffer/service/gles2_cmd_validation.h"
45#include "gpu/command_buffer/service/gpu_switches.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000046#include "gpu/command_buffer/service/gpu_tracer.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000047#include "gpu/command_buffer/service/image_manager.h"
48#include "gpu/command_buffer/service/mailbox_manager.h"
49#include "gpu/command_buffer/service/memory_tracking.h"
50#include "gpu/command_buffer/service/program_manager.h"
51#include "gpu/command_buffer/service/query_manager.h"
52#include "gpu/command_buffer/service/renderbuffer_manager.h"
53#include "gpu/command_buffer/service/shader_manager.h"
54#include "gpu/command_buffer/service/shader_translator.h"
55#include "gpu/command_buffer/service/shader_translator_cache.h"
56#include "gpu/command_buffer/service/stream_texture.h"
57#include "gpu/command_buffer/service/stream_texture_manager.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000058#include "gpu/command_buffer/service/texture_manager.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000059#include "gpu/command_buffer/service/vertex_array_manager.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010060#include "gpu/command_buffer/service/vertex_attrib_manager.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000061#include "ui/gl/gl_bindings.h"
Ben Murdocha3f7b4e2013-07-24 10:36:34 +010062#include "ui/gl/gl_fence.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000063#include "ui/gl/gl_image.h"
64#include "ui/gl/gl_implementation.h"
65#include "ui/gl/gl_surface.h"
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010066
Torne (Richard Coles)58218062012-11-14 11:43:16 +000067#if defined(OS_MACOSX)
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010068#include "ui/gl/io_surface_support_mac.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000069#endif
70
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000071// TODO(zmo): we can't include "City.h" due to type def conflicts.
72extern uint64 CityHash64(const char*, size_t);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000073
74namespace gpu {
75namespace gles2 {
76
77namespace {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000078
Torne (Richard Coles)58218062012-11-14 11:43:16 +000079static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010080static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
81static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000082
83#if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
84khronos_uint64_t CityHashForAngle(const char* name, unsigned int len) {
85 return static_cast<khronos_uint64_t>(
86 CityHash64(name, static_cast<size_t>(len)));
87}
88#endif
89
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010090static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
91 GLint rangeMax,
92 GLint precision) {
93 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
94}
95
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000096static void GetShaderPrecisionFormatImpl(GLenum shader_type,
97 GLenum precision_type,
98 GLint *range, GLint *precision) {
99 switch (precision_type) {
100 case GL_LOW_INT:
101 case GL_MEDIUM_INT:
102 case GL_HIGH_INT:
103 // These values are for a 32-bit twos-complement integer format.
104 range[0] = 31;
105 range[1] = 30;
106 *precision = 0;
107 break;
108 case GL_LOW_FLOAT:
109 case GL_MEDIUM_FLOAT:
110 case GL_HIGH_FLOAT:
111 // These values are for an IEEE single-precision floating-point format.
112 range[0] = 127;
113 range[1] = 127;
114 *precision = 23;
115 break;
116 default:
117 NOTREACHED();
118 break;
119 }
120
121 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
122 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
123 // This function is sometimes defined even though it's really just
124 // a stub, so we need to set range and precision as if it weren't
125 // defined before calling it.
126 // On Mac OS with some GPUs, calling this generates a
127 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
128 // platforms.
129 glGetShaderPrecisionFormat(shader_type, precision_type,
130 range, precision);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100131
132 // TODO(brianderson): Make the following official workarounds.
133
134 // Some drivers have bugs where they report the ranges as a negative number.
135 // Taking the absolute value here shouldn't hurt because negative numbers
136 // aren't expected anyway.
137 range[0] = abs(range[0]);
138 range[1] = abs(range[1]);
139
140 // If the driver reports a precision for highp float that isn't actually
141 // highp, don't pretend like it's supported because shader compilation will
142 // fail anyway.
143 if (precision_type == GL_HIGH_FLOAT &&
144 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
145 range[0] = 0;
146 range[1] = 0;
147 *precision = 0;
148 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000149 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000150}
151
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000152} // namespace
153
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000154class GLES2DecoderImpl;
155
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000156// Local versions of the SET_GL_ERROR macros
157#define LOCAL_SET_GL_ERROR(error, function_name, msg) \
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100158 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000159#define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100160 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
161 function_name, value, label)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000162#define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100163 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
164 function_name, pname)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000165#define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100166 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
167 function_name)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000168#define LOCAL_PEEK_GL_ERROR(function_name) \
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100169 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000170#define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100171 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000172#define LOCAL_PERFORMANCE_WARNING(msg) \
173 PerformanceWarning(__FILE__, __LINE__, msg)
174#define LOCAL_RENDER_WARNING(msg) \
175 RenderWarning(__FILE__, __LINE__, msg)
176
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000177// Check that certain assumptions the code makes are true. There are places in
178// the code where shared memory is passed direclty to GL. Example, glUniformiv,
179// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
180// a few others) are 32bits. If they are not 32bits the code will have to change
181// to call those GL functions with service side memory and then copy the results
182// to shared memory, converting the sizes.
183COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
184 GLint_not_same_size_as_uint32);
185COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
186 GLint_not_same_size_as_uint32);
187COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
188 GLfloat_not_same_size_as_float);
189
190// TODO(kbr): the use of this anonymous namespace core dumps the
191// linker on Mac OS X 10.6 when the symbol ordering file is used
192// namespace {
193
194// Returns the address of the first byte after a struct.
195template <typename T>
196const void* AddressAfterStruct(const T& pod) {
197 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
198}
199
200// Returns the address of the frst byte after the struct or NULL if size >
201// immediate_data_size.
202template <typename RETURN_TYPE, typename COMMAND_TYPE>
203RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
204 uint32 size,
205 uint32 immediate_data_size) {
206 return (size <= immediate_data_size) ?
207 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
208 NULL;
209}
210
211// Computes the data size for certain gl commands like glUniform.
212bool ComputeDataSize(
213 GLuint count,
214 size_t size,
215 unsigned int elements_per_unit,
216 uint32* dst) {
217 uint32 value;
218 if (!SafeMultiplyUint32(count, size, &value)) {
219 return false;
220 }
221 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
222 return false;
223 }
224 *dst = value;
225 return true;
226}
227
228// A struct to hold info about each command.
229struct CommandInfo {
230 int arg_flags; // How to handle the arguments for this command
231 int arg_count; // How many arguments are expected for this command.
232};
233
234// A table of CommandInfo for all the commands.
235const CommandInfo g_command_info[] = {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000236 #define GLES2_CMD_OP(name) { \
237 cmds::name::kArgFlags, \
238 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000239
240 GLES2_COMMAND_LIST(GLES2_CMD_OP)
241
242 #undef GLES2_CMD_OP
243};
244
245// Return true if a character belongs to the ASCII subset as defined in
246// GLSL ES 1.0 spec section 3.1.
247static bool CharacterIsValidForGLES(unsigned char c) {
248 // Printing characters are valid except " $ ` @ \ ' DEL.
249 if (c >= 32 && c <= 126 &&
250 c != '"' &&
251 c != '$' &&
252 c != '`' &&
253 c != '@' &&
254 c != '\\' &&
255 c != '\'') {
256 return true;
257 }
258 // Horizontal tab, line feed, vertical tab, form feed, carriage return
259 // are also valid.
260 if (c >= 9 && c <= 13) {
261 return true;
262 }
263
264 return false;
265}
266
267static bool StringIsValidForGLES(const char* str) {
268 for (; *str; ++str) {
269 if (!CharacterIsValidForGLES(*str)) {
270 return false;
271 }
272 }
273 return true;
274}
275
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000276// Wrapper for glEnable/glDisable that doesn't suck.
277static void EnableDisable(GLenum pname, bool enable) {
278 if (enable) {
279 glEnable(pname);
280 } else {
281 glDisable(pname);
282 }
283}
284
285// This class prevents any GL errors that occur when it is in scope from
286// being reported to the client.
287class ScopedGLErrorSuppressor {
288 public:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000289 explicit ScopedGLErrorSuppressor(
290 const char* function_name, GLES2DecoderImpl* decoder);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000291 ~ScopedGLErrorSuppressor();
292 private:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000293 const char* function_name_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000294 GLES2DecoderImpl* decoder_;
295 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
296};
297
298// Temporarily changes a decoder's bound 2D texture and restore it when this
299// object goes out of scope. Also temporarily switches to using active texture
300// unit zero in case the client has changed that to something invalid.
301class ScopedTexture2DBinder {
302 public:
303 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
304 ~ScopedTexture2DBinder();
305
306 private:
307 GLES2DecoderImpl* decoder_;
308 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
309};
310
311// Temporarily changes a decoder's bound render buffer and restore it when this
312// object goes out of scope.
313class ScopedRenderBufferBinder {
314 public:
315 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
316 ~ScopedRenderBufferBinder();
317
318 private:
319 GLES2DecoderImpl* decoder_;
320 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
321};
322
323// Temporarily changes a decoder's bound frame buffer and restore it when this
324// object goes out of scope.
325class ScopedFrameBufferBinder {
326 public:
327 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
328 ~ScopedFrameBufferBinder();
329
330 private:
331 GLES2DecoderImpl* decoder_;
332 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
333};
334
335// Temporarily changes a decoder's bound frame buffer to a resolved version of
336// the multisampled offscreen render buffer if that buffer is multisampled, and,
337// if it is bound or enforce_internal_framebuffer is true. If internal is
338// true, the resolved framebuffer is not visible to the parent.
339class ScopedResolvedFrameBufferBinder {
340 public:
341 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
342 bool enforce_internal_framebuffer,
343 bool internal);
344 ~ScopedResolvedFrameBufferBinder();
345
346 private:
347 GLES2DecoderImpl* decoder_;
348 bool resolve_and_bind_;
349 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
350};
351
352// This class records texture upload time when in scope.
353class ScopedTextureUploadTimer {
354 public:
355 explicit ScopedTextureUploadTimer(GLES2DecoderImpl* decoder);
356 ~ScopedTextureUploadTimer();
357
358 private:
359 GLES2DecoderImpl* decoder_;
360 base::TimeTicks begin_time_;
361 DISALLOW_COPY_AND_ASSIGN(ScopedTextureUploadTimer);
362};
363
364// Encapsulates an OpenGL texture.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000365class BackTexture {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000366 public:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000367 explicit BackTexture(GLES2DecoderImpl* decoder);
368 ~BackTexture();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000369
370 // Create a new render texture.
371 void Create();
372
373 // Set the initial size and format of a render texture or resize it.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000374 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000375
376 // Copy the contents of the currently bound frame buffer.
377 void Copy(const gfx::Size& size, GLenum format);
378
379 // Destroy the render texture. This must be explicitly called before
380 // destroying this object.
381 void Destroy();
382
383 // Invalidate the texture. This can be used when a context is lost and it is
384 // not possible to make it current in order to free the resource.
385 void Invalidate();
386
387 GLuint id() const {
388 return id_;
389 }
390
391 gfx::Size size() const {
392 return size_;
393 }
394
395 size_t estimated_size() const {
396 return memory_tracker_.GetMemRepresented();
397 }
398
399 private:
400 GLES2DecoderImpl* decoder_;
401 MemoryTypeTracker memory_tracker_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000402 size_t bytes_allocated_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000403 GLuint id_;
404 gfx::Size size_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000405 DISALLOW_COPY_AND_ASSIGN(BackTexture);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000406};
407
408// Encapsulates an OpenGL render buffer of any format.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000409class BackRenderbuffer {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000410 public:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000411 explicit BackRenderbuffer(GLES2DecoderImpl* decoder);
412 ~BackRenderbuffer();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000413
414 // Create a new render buffer.
415 void Create();
416
417 // Set the initial size and format of a render buffer or resize it.
418 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
419
420 // Destroy the render buffer. This must be explicitly called before destroying
421 // this object.
422 void Destroy();
423
424 // Invalidate the render buffer. This can be used when a context is lost and
425 // it is not possible to make it current in order to free the resource.
426 void Invalidate();
427
428 GLuint id() const {
429 return id_;
430 }
431
432 size_t estimated_size() const {
433 return memory_tracker_.GetMemRepresented();
434 }
435
436 private:
437 GLES2DecoderImpl* decoder_;
438 MemoryTypeTracker memory_tracker_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000439 size_t bytes_allocated_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000440 GLuint id_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000441 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000442};
443
444// Encapsulates an OpenGL frame buffer.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000445class BackFramebuffer {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000446 public:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000447 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
448 ~BackFramebuffer();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000449
450 // Create a new frame buffer.
451 void Create();
452
453 // Attach a color render buffer to a frame buffer.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000454 void AttachRenderTexture(BackTexture* texture);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000455
456 // Attach a render buffer to a frame buffer. Note that this unbinds any
457 // currently bound frame buffer.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000458 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000459
460 // Destroy the frame buffer. This must be explicitly called before destroying
461 // this object.
462 void Destroy();
463
464 // Invalidate the frame buffer. This can be used when a context is lost and it
465 // is not possible to make it current in order to free the resource.
466 void Invalidate();
467
468 // See glCheckFramebufferStatusEXT.
469 GLenum CheckStatus();
470
471 GLuint id() const {
472 return id_;
473 }
474
475 private:
476 GLES2DecoderImpl* decoder_;
477 GLuint id_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000478 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000479};
480
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100481struct FenceCallback {
482 explicit FenceCallback()
483 : fence(gfx::GLFence::Create()) {
484 DCHECK(fence);
485 }
486 void AddCallback(base::Closure cb) {
487 callbacks.push_back(cb);
488 }
489 std::vector<base::Closure> callbacks;
490 scoped_ptr<gfx::GLFence> fence;
491};
492
493
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000494// } // anonymous namespace.
495
496bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
497 uint32* service_texture_id) {
498 return false;
499}
500
501GLES2Decoder::GLES2Decoder()
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100502 : initialized_(false),
503 debug_(false),
504 log_commands_(false) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000505}
506
507GLES2Decoder::~GLES2Decoder() {
508}
509
510bool GLES2Decoder::testing_force_is_angle_;
511
512void GLES2Decoder::set_testing_force_is_angle(bool force) {
513 testing_force_is_angle_ = force;
514}
515
516bool GLES2Decoder::IsAngle() {
517#if defined(OS_WIN)
518 return testing_force_is_angle_ ||
519 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
520#else
521 return testing_force_is_angle_;
522#endif
523}
524
525// This class implements GLES2Decoder so we don't have to expose all the GLES2
526// cmd stuff to outside this class.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000527class GLES2DecoderImpl : public GLES2Decoder {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000528 public:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000529 // Used by PrepForSetUniformByLocation to validate types.
530 struct BaseUniformInfo {
531 const GLenum* const valid_types;
532 size_t num_valid_types;
533 };
534
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000535 explicit GLES2DecoderImpl(ContextGroup* group);
536 virtual ~GLES2DecoderImpl();
537
538 // Overridden from AsyncAPIInterface.
539 virtual Error DoCommand(unsigned int command,
540 unsigned int arg_count,
541 const void* args) OVERRIDE;
542
543 // Overridden from AsyncAPIInterface.
544 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
545
546 // Overridden from GLES2Decoder.
547 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
548 const scoped_refptr<gfx::GLContext>& context,
549 bool offscreen,
550 const gfx::Size& size,
551 const DisallowedFeatures& disallowed_features,
552 const char* allowed_extensions,
553 const std::vector<int32>& attribs) OVERRIDE;
554 virtual void Destroy(bool have_context) OVERRIDE;
555 virtual void SetSurface(
556 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100557 virtual bool ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000558 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
559 void UpdateParentTextureInfo();
560 virtual bool MakeCurrent() OVERRIDE;
561 virtual void ReleaseCurrent() OVERRIDE;
562 virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
563 virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
564 virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
565 virtual void RestoreState() const OVERRIDE;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000566
567 virtual void RestoreActiveTexture() const OVERRIDE {
568 state_.RestoreActiveTexture();
569 }
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100570 virtual void RestoreAllTextureUnitBindings() const OVERRIDE {
571 state_.RestoreAllTextureUnitBindings();
572 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000573 virtual void RestoreAttribute(unsigned index) const OVERRIDE {
574 state_.RestoreAttribute(index);
575 }
576 virtual void RestoreBufferBindings() const OVERRIDE {
577 state_.RestoreBufferBindings();
578 }
579 virtual void RestoreGlobalState() const OVERRIDE {
580 state_.RestoreGlobalState();
581 }
582 virtual void RestoreProgramBindings() const OVERRIDE {
583 state_.RestoreProgramBindings();
584 }
585 virtual void RestoreRenderbufferBindings() const OVERRIDE {
586 state_.RestoreRenderbufferBindings();
587 }
588 virtual void RestoreTextureUnitBindings(unsigned unit) const OVERRIDE {
589 state_.RestoreTextureUnitBindings(unit);
590 }
591 virtual void RestoreFramebufferBindings() const OVERRIDE;
592 virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
593
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000594 virtual QueryManager* GetQueryManager() OVERRIDE {
595 return query_manager_.get();
596 }
597 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
598 return vertex_array_manager_.get();
599 }
600 virtual bool ProcessPendingQueries() OVERRIDE;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000601 virtual bool HasMoreIdleWork() OVERRIDE;
602 virtual void PerformIdleWork() OVERRIDE;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000603
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100604 virtual void WaitForReadPixels(base::Closure callback) OVERRIDE;
605
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000606 virtual void SetResizeCallback(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100607 const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000608
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100609 virtual Logger* GetLogger() OVERRIDE;
610 virtual ErrorState* GetErrorState() OVERRIDE;
611
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000612 virtual void SetShaderCacheCallback(
613 const ShaderCacheCallback& callback) OVERRIDE;
614 virtual void SetWaitSyncPointCallback(
615 const WaitSyncPointCallback& callback) OVERRIDE;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000616
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100617 virtual AsyncPixelTransferManager*
618 GetAsyncPixelTransferManager() OVERRIDE;
619 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
620 virtual void SetAsyncPixelTransferManagerForTest(
621 AsyncPixelTransferManager* manager) OVERRIDE;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000622 void ProcessFinishedAsyncTransfers();
623
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000624 virtual bool GetServiceTextureId(uint32 client_texture_id,
625 uint32* service_texture_id) OVERRIDE;
626
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000627 virtual uint32 GetTextureUploadCount() OVERRIDE;
628 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
629 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
630 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE;
631
632 // Restores the current state to the user's settings.
633 void RestoreCurrentFramebufferBindings();
634 void RestoreCurrentRenderbufferBindings();
635 void RestoreCurrentTexture2DBindings();
636
637 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
638 void ApplyDirtyState();
639
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000640 // These check the state of the currently bound framebuffer or the
641 // backbuffer if no framebuffer is bound.
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100642 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
643 // check with all attached and enabled color attachments.
644 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000645 bool BoundFramebufferHasDepthAttachment();
646 bool BoundFramebufferHasStencilAttachment();
647
648 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
649
650 private:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000651 friend class ScopedFrameBufferBinder;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000652 friend class ScopedGLErrorSuppressor;
653 friend class ScopedResolvedFrameBufferBinder;
654 friend class ScopedTextureUploadTimer;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000655 friend class BackTexture;
656 friend class BackRenderbuffer;
657 friend class BackFramebuffer;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000658
659 // Initialize or re-initialize the shader translator.
660 bool InitializeShaderTranslator();
661
662 void UpdateCapabilities();
663
664 // Helpers for the glGen and glDelete functions.
665 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
666 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
667 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
668 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
669 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
670 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
671 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
672 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
673 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
674 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
675 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
676 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
677
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000678 // Workarounds
679 void OnFboChanged() const;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100680 void OnUseFramebuffer() const;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000681
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000682 // TODO(gman): Cache these pointers?
683 BufferManager* buffer_manager() {
684 return group_->buffer_manager();
685 }
686
687 RenderbufferManager* renderbuffer_manager() {
688 return group_->renderbuffer_manager();
689 }
690
691 FramebufferManager* framebuffer_manager() {
692 return group_->framebuffer_manager();
693 }
694
695 ProgramManager* program_manager() {
696 return group_->program_manager();
697 }
698
699 ShaderManager* shader_manager() {
700 return group_->shader_manager();
701 }
702
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000703 const TextureManager* texture_manager() const {
704 return group_->texture_manager();
705 }
706
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000707 TextureManager* texture_manager() {
708 return group_->texture_manager();
709 }
710
711 MailboxManager* mailbox_manager() {
712 return group_->mailbox_manager();
713 }
714
715 ImageManager* image_manager() {
716 return group_->image_manager();
717 }
718
719 VertexArrayManager* vertex_array_manager() {
720 return vertex_array_manager_.get();
721 }
722
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000723 MemoryTracker* memory_tracker() {
724 return group_->memory_tracker();
725 }
726
Ben Murdocheb525c52013-07-10 11:40:50 +0100727 StreamTextureManager* stream_texture_manager() const {
728 return group_->stream_texture_manager();
729 }
730
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000731 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
732 MemoryTracker* tracker = memory_tracker();
733 if (tracker) {
734 return tracker->EnsureGPUMemoryAvailable(estimated_size);
735 }
736 return true;
737 }
738
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000739 bool IsOffscreenBufferMultisampled() const {
740 return offscreen_target_samples_ > 1;
741 }
742
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000743 // Creates a Texture for the given texture.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100744 TextureRef* CreateTexture(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000745 GLuint client_id, GLuint service_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000746 return texture_manager()->CreateTexture(client_id, service_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000747 }
748
749 // Gets the texture info for the given texture. Returns NULL if none exists.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100750 TextureRef* GetTexture(GLuint client_id) const {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000751 return texture_manager()->GetTexture(client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000752 }
753
754 // Deletes the texture info for the given texture.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000755 void RemoveTexture(GLuint client_id) {
756 texture_manager()->RemoveTexture(client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000757 }
758
759 // Get the size (in pixels) of the currently bound frame buffer (either FBO
760 // or regular back buffer).
761 gfx::Size GetBoundReadFrameBufferSize();
762
763 // Get the format of the currently bound frame buffer (either FBO or regular
764 // back buffer)
765 GLenum GetBoundReadFrameBufferInternalFormat();
766 GLenum GetBoundDrawFrameBufferInternalFormat();
767
768 // Wrapper for CompressedTexImage2D commands.
769 error::Error DoCompressedTexImage2D(
770 GLenum target,
771 GLint level,
772 GLenum internal_format,
773 GLsizei width,
774 GLsizei height,
775 GLint border,
776 GLsizei image_size,
777 const void* data);
778
779 // Wrapper for CompressedTexSubImage2D.
780 void DoCompressedTexSubImage2D(
781 GLenum target,
782 GLint level,
783 GLint xoffset,
784 GLint yoffset,
785 GLsizei width,
786 GLsizei height,
787 GLenum format,
788 GLsizei imageSize,
789 const void * data);
790
791 // Wrapper for CopyTexImage2D.
792 void DoCopyTexImage2D(
793 GLenum target,
794 GLint level,
795 GLenum internal_format,
796 GLint x,
797 GLint y,
798 GLsizei width,
799 GLsizei height,
800 GLint border);
801
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100802 // Wrapper for SwapBuffers.
803 void DoSwapBuffers();
804
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000805 // Wrapper for CopyTexSubImage2D.
806 void DoCopyTexSubImage2D(
807 GLenum target,
808 GLint level,
809 GLint xoffset,
810 GLint yoffset,
811 GLint x,
812 GLint y,
813 GLsizei width,
814 GLsizei height);
815
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000816 // Validation for TexImage2D commands.
817 bool ValidateTexImage2D(
818 const char* function_name,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000819 GLenum target,
820 GLint level,
821 GLenum internal_format,
822 GLsizei width,
823 GLsizei height,
824 GLint border,
825 GLenum format,
826 GLenum type,
827 const void* pixels,
828 uint32 pixels_size);
829
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000830 // Wrapper for TexImage2D commands.
831 void DoTexImage2D(
832 GLenum target,
833 GLint level,
834 GLenum internal_format,
835 GLsizei width,
836 GLsizei height,
837 GLint border,
838 GLenum format,
839 GLenum type,
840 const void* pixels,
841 uint32 pixels_size);
842
843 // Validation for TexSubImage2D.
844 bool ValidateTexSubImage2D(
845 error::Error* error,
846 const char* function_name,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000847 GLenum target,
848 GLint level,
849 GLint xoffset,
850 GLint yoffset,
851 GLsizei width,
852 GLsizei height,
853 GLenum format,
854 GLenum type,
855 const void * data);
856
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000857 // Wrapper for TexSubImage2D.
858 error::Error DoTexSubImage2D(
859 GLenum target,
860 GLint level,
861 GLint xoffset,
862 GLint yoffset,
863 GLsizei width,
864 GLsizei height,
865 GLenum format,
866 GLenum type,
867 const void * data);
868
869 // Extra validation for async tex(Sub)Image2D.
870 bool ValidateAsyncTransfer(
871 const char* function_name,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100872 TextureRef* texture_ref,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000873 GLenum target,
874 GLint level,
875 const void * data);
876
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000877 // Wrapper for TexImageIOSurface2DCHROMIUM.
878 void DoTexImageIOSurface2DCHROMIUM(
879 GLenum target,
880 GLsizei width,
881 GLsizei height,
882 GLuint io_surface_id,
883 GLuint plane);
884
885 void DoCopyTextureCHROMIUM(
886 GLenum target,
887 GLuint source_id,
888 GLuint target_id,
889 GLint level,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100890 GLenum internal_format,
891 GLenum dest_type);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000892
893 // Wrapper for TexStorage2DEXT.
894 void DoTexStorage2DEXT(
895 GLenum target,
896 GLint levels,
897 GLenum internal_format,
898 GLsizei width,
899 GLsizei height);
900
901 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
902 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
903
904 void DoBindTexImage2DCHROMIUM(
905 GLenum target,
906 GLint image_id);
907 void DoReleaseTexImage2DCHROMIUM(
908 GLenum target,
909 GLint image_id);
910
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000911 void DoTraceEndCHROMIUM(void);
912
913 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
914
915 // Creates a Program for the given program.
916 Program* CreateProgram(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000917 GLuint client_id, GLuint service_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000918 return program_manager()->CreateProgram(client_id, service_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000919 }
920
921 // Gets the program info for the given program. Returns NULL if none exists.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000922 Program* GetProgram(GLuint client_id) {
923 return program_manager()->GetProgram(client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000924 }
925
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000926#if defined(NDEBUG)
927 void LogClientServiceMapping(
928 const char* /* function_name */,
929 GLuint /* client_id */,
930 GLuint /* service_id */) {
931 }
932 template<typename T>
933 void LogClientServiceForInfo(
934 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
935 }
936#else
937 void LogClientServiceMapping(
938 const char* function_name, GLuint client_id, GLuint service_id) {
939 if (service_logging_) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100940 DLOG(INFO) << "[" << logger_.GetLogPrefix() << "] " << function_name
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000941 << ": client_id = " << client_id
942 << ", service_id = " << service_id;
943 }
944 }
945 template<typename T>
946 void LogClientServiceForInfo(
947 T* info, GLuint client_id, const char* function_name) {
948 if (info) {
949 LogClientServiceMapping(function_name, client_id, info->service_id());
950 }
951 }
952#endif
953
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000954 // Gets the program info for the given program. If it's not a program
955 // generates a GL error. Returns NULL if not program.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000956 Program* GetProgramInfoNotShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000957 GLuint client_id, const char* function_name) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000958 Program* program = GetProgram(client_id);
959 if (!program) {
960 if (GetShader(client_id)) {
961 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000962 GL_INVALID_OPERATION, function_name, "shader passed for program");
963 } else {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000964 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000965 }
966 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000967 LogClientServiceForInfo(program, client_id, function_name);
968 return program;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000969 }
970
971
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000972 // Creates a Shader for the given shader.
973 Shader* CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000974 GLuint client_id,
975 GLuint service_id,
976 GLenum shader_type) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000977 return shader_manager()->CreateShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000978 client_id, service_id, shader_type);
979 }
980
981 // Gets the shader info for the given shader. Returns NULL if none exists.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000982 Shader* GetShader(GLuint client_id) {
983 return shader_manager()->GetShader(client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000984 }
985
986 // Gets the shader info for the given shader. If it's not a shader generates a
987 // GL error. Returns NULL if not shader.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000988 Shader* GetShaderInfoNotProgram(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000989 GLuint client_id, const char* function_name) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000990 Shader* shader = GetShader(client_id);
991 if (!shader) {
992 if (GetProgram(client_id)) {
993 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000994 GL_INVALID_OPERATION, function_name, "program passed for shader");
995 } else {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000996 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000997 GL_INVALID_VALUE, function_name, "unknown shader");
998 }
999 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001000 LogClientServiceForInfo(shader, client_id, function_name);
1001 return shader;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001002 }
1003
1004 // Creates a buffer info for the given buffer.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001005 void CreateBuffer(GLuint client_id, GLuint service_id) {
1006 return buffer_manager()->CreateBuffer(client_id, service_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001007 }
1008
1009 // Gets the buffer info for the given buffer.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001010 Buffer* GetBuffer(GLuint client_id) {
1011 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1012 return buffer;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001013 }
1014
1015 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1016 // on glDeleteBuffers so we can make sure the user does not try to render
1017 // with deleted buffers.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001018 void RemoveBuffer(GLuint client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001019
1020 // Creates a framebuffer info for the given framebuffer.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001021 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1022 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001023 }
1024
1025 // Gets the framebuffer info for the given framebuffer.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001026 Framebuffer* GetFramebuffer(GLuint client_id) {
1027 return framebuffer_manager()->GetFramebuffer(client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001028 }
1029
1030 // Removes the framebuffer info for the given framebuffer.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001031 void RemoveFramebuffer(GLuint client_id) {
1032 framebuffer_manager()->RemoveFramebuffer(client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001033 }
1034
1035 // Creates a renderbuffer info for the given renderbuffer.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001036 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1037 return renderbuffer_manager()->CreateRenderbuffer(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001038 client_id, service_id);
1039 }
1040
1041 // Gets the renderbuffer info for the given renderbuffer.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001042 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1043 return renderbuffer_manager()->GetRenderbuffer(client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001044 }
1045
1046 // Removes the renderbuffer info for the given renderbuffer.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001047 void RemoveRenderbuffer(GLuint client_id) {
1048 renderbuffer_manager()->RemoveRenderbuffer(client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001049 }
1050
1051 // Gets the vertex attrib manager for the given vertex array.
1052 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1053 VertexAttribManager* info =
1054 vertex_array_manager()->GetVertexAttribManager(client_id);
1055 return info;
1056 }
1057
1058 // Removes the vertex attrib manager for the given vertex array.
1059 void RemoveVertexAttribManager(GLuint client_id) {
1060 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1061 }
1062
1063 // Creates a vertex attrib manager for the given vertex array.
1064 void CreateVertexAttribManager(GLuint client_id, GLuint service_id) {
1065 return vertex_array_manager()->CreateVertexAttribManager(
1066 client_id, service_id, group_->max_vertex_attribs());
1067 }
1068
1069 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1070 void DoBindUniformLocationCHROMIUM(
1071 GLuint client_id, GLint location, const char* name);
1072
1073 error::Error GetAttribLocationHelper(
1074 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1075 const std::string& name_str);
1076
1077 error::Error GetUniformLocationHelper(
1078 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1079 const std::string& name_str);
1080
1081 // Helper for glShaderSource.
1082 error::Error ShaderSourceHelper(
1083 GLuint client_id, const char* data, uint32 data_size);
1084
1085 // Clear any textures used by the current program.
1086 bool ClearUnclearedTextures();
1087
1088 // Clear any uncleared level in texture.
1089 // Returns false if there was a generated GL error.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001090 bool ClearTexture(Texture* texture);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001091
1092 // Clears any uncleared attachments attached to the given frame buffer.
1093 // Returns false if there was a generated GL error.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001094 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001095
1096 // overridden from GLES2Decoder
1097 virtual bool ClearLevel(unsigned service_id,
1098 unsigned bind_target,
1099 unsigned target,
1100 int level,
1101 unsigned format,
1102 unsigned type,
1103 int width,
1104 int height,
1105 bool is_texture_immutable) OVERRIDE;
1106
1107 // Restore all GL state that affects clearing.
1108 void RestoreClearState();
1109
1110 // Remembers the state of some capabilities.
1111 // Returns: true if glEnable/glDisable should actually be called.
1112 bool SetCapabilityState(GLenum cap, bool enabled);
1113
1114 // Check that the currently bound framebuffers are valid.
1115 // Generates GL error if not.
1116 bool CheckBoundFramebuffersValid(const char* func_name);
1117
1118 // Check if a framebuffer meets our requirements.
1119 bool CheckFramebufferValid(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001120 Framebuffer* framebuffer,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001121 GLenum target,
1122 const char* func_name);
1123
1124 // Checks if the current program exists and is valid. If not generates the
1125 // appropriate GL error. Returns true if the current program is in a usable
1126 // state.
1127 bool CheckCurrentProgram(const char* function_name);
1128
1129 // Checks if the current program exists and is valid and that location is not
1130 // -1. If the current program is not valid generates the appropriate GL
1131 // error. Returns true if the current program is in a usable state and
1132 // location is not -1.
1133 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1134
1135 // Gets the type of a uniform for a location in the current program. Sets GL
1136 // errors if the current program is not valid. Returns true if the current
1137 // program is valid and the location exists. Adjusts count so it
1138 // does not overflow the uniform.
1139 bool PrepForSetUniformByLocation(
1140 GLint fake_location, const char* function_name,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001141 const BaseUniformInfo& base_info,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001142 GLint* real_location, GLenum* type, GLsizei* count);
1143
1144 // Gets the service id for any simulated backbuffer fbo.
1145 GLuint GetBackbufferServiceId() const;
1146
1147 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1148 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001149
1150 // Helper for glGetVertexAttrib
1151 void GetVertexAttribHelper(
1152 const VertexAttrib* attrib, GLenum pname, GLint* param);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001153
1154 // Wrapper for glCreateProgram
1155 bool CreateProgramHelper(GLuint client_id);
1156
1157 // Wrapper for glCreateShader
1158 bool CreateShaderHelper(GLenum type, GLuint client_id);
1159
1160 // Wrapper for glActiveTexture
1161 void DoActiveTexture(GLenum texture_unit);
1162
1163 // Wrapper for glAttachShader
1164 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1165
1166 // Wrapper for glBindBuffer since we need to track the current targets.
1167 void DoBindBuffer(GLenum target, GLuint buffer);
1168
1169 // Wrapper for glBindFramebuffer since we need to track the current targets.
1170 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1171
1172 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1173 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1174
1175 // Wrapper for glBindTexture since we need to track the current targets.
1176 void DoBindTexture(GLenum target, GLuint texture);
1177
1178 // Wrapper for glBindVertexArrayOES
1179 void DoBindVertexArrayOES(GLuint array);
1180 void EmulateVertexArrayState();
1181
1182 // Wrapper for glBlitFramebufferEXT.
1183 void DoBlitFramebufferEXT(
1184 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1185 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1186 GLbitfield mask, GLenum filter);
1187
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001188 // Wrapper for glBufferSubData.
1189 void DoBufferSubData(
1190 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1191
1192 // Wrapper for glCheckFramebufferStatus
1193 GLenum DoCheckFramebufferStatus(GLenum target);
1194
1195 // Wrapper for glClear
1196 error::Error DoClear(GLbitfield mask);
1197
1198 // Wrappers for various state.
1199 void DoDepthRangef(GLclampf znear, GLclampf zfar);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001200 void DoSampleCoverage(GLclampf value, GLboolean invert);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001201
1202 // Wrapper for glCompileShader.
1203 void DoCompileShader(GLuint shader);
1204
1205 // Helper for DeleteSharedIdsCHROMIUM commands.
1206 void DoDeleteSharedIdsCHROMIUM(
1207 GLuint namespace_id, GLsizei n, const GLuint* ids);
1208
1209 // Wrapper for glDetachShader
1210 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1211
1212 // Wrapper for glDisable
1213 void DoDisable(GLenum cap);
1214
1215 // Wrapper for glDisableVertexAttribArray.
1216 void DoDisableVertexAttribArray(GLuint index);
1217
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001218 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1219 // attachments.
1220 void DoDiscardFramebufferEXT(GLenum target,
1221 GLsizei numAttachments,
1222 const GLenum* attachments);
1223
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001224 // Wrapper for glEnable
1225 void DoEnable(GLenum cap);
1226
1227 // Wrapper for glEnableVertexAttribArray.
1228 void DoEnableVertexAttribArray(GLuint index);
1229
1230 // Wrapper for glFinish.
1231 void DoFinish();
1232
1233 // Wrapper for glFlush.
1234 void DoFlush();
1235
1236 // Wrapper for glFramebufferRenderbufffer.
1237 void DoFramebufferRenderbuffer(
1238 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1239 GLuint renderbuffer);
1240
1241 // Wrapper for glFramebufferTexture2D.
1242 void DoFramebufferTexture2D(
1243 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1244 GLint level);
1245
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001246 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1247 void DoFramebufferTexture2DMultisample(
1248 GLenum target, GLenum attachment, GLenum textarget,
1249 GLuint texture, GLint level, GLsizei samples);
1250
1251 // Common implementation for both DoFramebufferTexture2D wrappers.
1252 void DoFramebufferTexture2DCommon(const char* name,
1253 GLenum target, GLenum attachment, GLenum textarget,
1254 GLuint texture, GLint level, GLsizei samples);
1255
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001256 // Wrapper for glGenerateMipmap
1257 void DoGenerateMipmap(GLenum target);
1258
1259 // Helper for GenSharedIdsCHROMIUM commands.
1260 void DoGenSharedIdsCHROMIUM(
1261 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1262
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001263 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1264 // to account for different pname values defined in different extension
1265 // variants.
1266 GLenum AdjustGetPname(GLenum pname);
1267
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001268 // Wrapper for DoGetBooleanv.
1269 void DoGetBooleanv(GLenum pname, GLboolean* params);
1270
1271 // Wrapper for DoGetFloatv.
1272 void DoGetFloatv(GLenum pname, GLfloat* params);
1273
1274 // Wrapper for glGetFramebufferAttachmentParameteriv.
1275 void DoGetFramebufferAttachmentParameteriv(
1276 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1277
1278 // Wrapper for glGetIntegerv.
1279 void DoGetIntegerv(GLenum pname, GLint* params);
1280
1281 // Gets the max value in a range in a buffer.
1282 GLuint DoGetMaxValueInBufferCHROMIUM(
1283 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1284
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001285 // Wrapper for glGetBufferParameteriv.
1286 void DoGetBufferParameteriv(
1287 GLenum target, GLenum pname, GLint* params);
1288
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001289 // Wrapper for glGetProgramiv.
1290 void DoGetProgramiv(
1291 GLuint program_id, GLenum pname, GLint* params);
1292
1293 // Wrapper for glRenderbufferParameteriv.
1294 void DoGetRenderbufferParameteriv(
1295 GLenum target, GLenum pname, GLint* params);
1296
1297 // Wrapper for glGetShaderiv
1298 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1299
1300 // Wrappers for glGetVertexAttrib.
1301 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1302 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1303
1304 // Wrappers for glIsXXX functions.
1305 bool DoIsEnabled(GLenum cap);
1306 bool DoIsBuffer(GLuint client_id);
1307 bool DoIsFramebuffer(GLuint client_id);
1308 bool DoIsProgram(GLuint client_id);
1309 bool DoIsRenderbuffer(GLuint client_id);
1310 bool DoIsShader(GLuint client_id);
1311 bool DoIsTexture(GLuint client_id);
1312 bool DoIsVertexArrayOES(GLuint client_id);
1313
1314 // Wrapper for glLinkProgram
1315 void DoLinkProgram(GLuint program);
1316
1317 // Helper for RegisterSharedIdsCHROMIUM.
1318 void DoRegisterSharedIdsCHROMIUM(
1319 GLuint namespace_id, GLsizei n, const GLuint* ids);
1320
1321 // Wrapper for glRenderbufferStorage.
1322 void DoRenderbufferStorage(
1323 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1324
1325 // Wrapper for glRenderbufferStorageMultisampleEXT.
1326 void DoRenderbufferStorageMultisample(
1327 GLenum target, GLsizei samples, GLenum internalformat,
1328 GLsizei width, GLsizei height);
1329
1330 // Wrapper for glReleaseShaderCompiler.
1331 void DoReleaseShaderCompiler() { }
1332
1333 // Wrappers for glTexParameter functions.
1334 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1335 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1336 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1337 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1338
1339 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1340 // spec only these 2 functions can be used to set sampler uniforms.
1341 void DoUniform1i(GLint fake_location, GLint v0);
1342 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1343 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1344 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1345 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1346
1347 // Wrappers for glUniformfv because some drivers don't correctly accept
1348 // bool uniforms.
1349 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1350 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1351 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1352 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1353
1354 void DoUniformMatrix2fv(
1355 GLint fake_location, GLsizei count, GLboolean transpose,
1356 const GLfloat* value);
1357 void DoUniformMatrix3fv(
1358 GLint fake_location, GLsizei count, GLboolean transpose,
1359 const GLfloat* value);
1360 void DoUniformMatrix4fv(
1361 GLint fake_location, GLsizei count, GLboolean transpose,
1362 const GLfloat* value);
1363
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001364 bool SetVertexAttribValue(
1365 const char* function_name, GLuint index, const GLfloat* value);
1366
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001367 // Wrappers for glVertexAttrib??
1368 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1369 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1370 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1371 void DoVertexAttrib4f(
1372 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1373 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1374 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1375 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1376 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1377
1378 // Wrapper for glViewport
1379 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1380
1381 // Wrapper for glUseProgram
1382 void DoUseProgram(GLuint program);
1383
1384 // Wrapper for glValidateProgram.
1385 void DoValidateProgram(GLuint program_client_id);
1386
1387 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1388 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1389 void DoPopGroupMarkerEXT(void);
1390
1391 // Gets the number of values that will be returned by glGetXXX. Returns
1392 // false if pname is unknown.
1393 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1394
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001395 // Checks if the current program and vertex attributes are valid for drawing.
1396 bool IsDrawValid(
1397 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount);
1398
1399 // Returns true if successful, simulated will be true if attrib0 was
1400 // simulated.
1401 bool SimulateAttrib0(
1402 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1403 void RestoreStateForAttrib(GLuint attrib);
1404
Ben Murdoch558790d2013-07-30 15:19:42 +01001405 // If texture is a stream texture, this will update the stream to the newest
1406 // buffer.
1407 void UpdateStreamTextureIfNeeded(Texture* texture);
1408
1409 // Returns false if unrenderable textures were replaced.
1410 bool PrepareTexturesForRender();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001411 void RestoreStateForNonRenderableTextures();
1412
1413 // Returns true if GL_FIXED attribs were simulated.
1414 bool SimulateFixedAttribs(
1415 const char* function_name,
1416 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1417 void RestoreStateForSimulatedFixedAttribs();
1418
1419 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1420 // cases (primcount is 0 for non-instanced).
1421 error::Error DoDrawArrays(
1422 const char* function_name,
1423 bool instanced, GLenum mode, GLint first, GLsizei count,
1424 GLsizei primcount);
1425 error::Error DoDrawElements(
1426 const char* function_name,
1427 bool instanced, GLenum mode, GLsizei count, GLenum type,
1428 int32 offset, GLsizei primcount);
1429
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001430 // Gets the texture id for a given target.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001431 TextureRef* GetTextureInfoForTarget(GLenum target) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001432 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001433 TextureRef* texture = NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001434 switch (target) {
1435 case GL_TEXTURE_2D:
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001436 texture = unit.bound_texture_2d.get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001437 break;
1438 case GL_TEXTURE_CUBE_MAP:
1439 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1440 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1441 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1442 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1443 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1444 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001445 texture = unit.bound_texture_cube_map.get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001446 break;
1447 case GL_TEXTURE_EXTERNAL_OES:
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001448 texture = unit.bound_texture_external_oes.get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001449 break;
1450 case GL_TEXTURE_RECTANGLE_ARB:
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001451 texture = unit.bound_texture_rectangle_arb.get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001452 break;
1453 default:
1454 NOTREACHED();
1455 return NULL;
1456 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001457 return texture;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001458 }
1459
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001460 TextureRef* GetTextureInfoForTargetUnlessDefault(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001461 GLenum target) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001462 TextureRef* texture = GetTextureInfoForTarget(target);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001463 if (!texture)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001464 return NULL;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001465 if (texture == texture_manager()->GetDefaultTextureInfo(target))
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001466 return NULL;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001467 return texture;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001468 }
1469
1470 GLenum GetBindTargetForSamplerType(GLenum type) {
1471 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1472 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1473 switch (type) {
1474 case GL_SAMPLER_2D:
1475 return GL_TEXTURE_2D;
1476 case GL_SAMPLER_CUBE:
1477 return GL_TEXTURE_CUBE_MAP;
1478 case GL_SAMPLER_EXTERNAL_OES:
1479 return GL_TEXTURE_EXTERNAL_OES;
1480 case GL_SAMPLER_2D_RECT_ARB:
1481 return GL_TEXTURE_RECTANGLE_ARB;
1482 }
1483
1484 NOTREACHED();
1485 return 0;
1486 }
1487
1488 // Gets the framebuffer info for a particular target.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001489 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1490 Framebuffer* framebuffer = NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001491 switch (target) {
1492 case GL_FRAMEBUFFER:
1493 case GL_DRAW_FRAMEBUFFER_EXT:
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001494 framebuffer = state_.bound_draw_framebuffer.get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001495 break;
1496 case GL_READ_FRAMEBUFFER_EXT:
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001497 framebuffer = state_.bound_read_framebuffer.get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001498 break;
1499 default:
1500 NOTREACHED();
1501 break;
1502 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001503 return framebuffer;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001504 }
1505
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001506 Renderbuffer* GetRenderbufferInfoForTarget(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001507 GLenum target) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001508 Renderbuffer* renderbuffer = NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001509 switch (target) {
1510 case GL_RENDERBUFFER:
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001511 renderbuffer = state_.bound_renderbuffer.get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001512 break;
1513 default:
1514 NOTREACHED();
1515 break;
1516 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001517 return renderbuffer;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001518 }
1519
1520 // Validates the program and location for a glGetUniform call and returns
1521 // a SizeResult setup to receive the result. Returns true if glGetUniform
1522 // should be called.
1523 bool GetUniformSetup(
1524 GLuint program, GLint fake_location,
1525 uint32 shm_id, uint32 shm_offset,
1526 error::Error* error, GLint* real_location, GLuint* service_id,
1527 void** result, GLenum* result_type);
1528
1529 // Computes the estimated memory used for the backbuffer and passes it to
1530 // the tracing system.
1531 size_t GetBackbufferMemoryTotal();
1532
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001533 virtual bool WasContextLost() OVERRIDE;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001534 virtual bool WasContextLostByRobustnessExtension() OVERRIDE;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001535 virtual void LoseContext(uint32 reset_status) OVERRIDE;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001536
1537#if defined(OS_MACOSX)
1538 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1539#endif
1540
1541 // Validates the combination of texture parameters. For example validates that
1542 // for a given format the specific type, level and targets are valid.
1543 // Synthesizes the correct GL error if invalid. Returns true if valid.
1544 bool ValidateTextureParameters(
1545 const char* function_name,
1546 GLenum target, GLenum format, GLenum type, GLint level);
1547
1548 bool ValidateCompressedTexDimensions(
1549 const char* function_name,
1550 GLint level, GLsizei width, GLsizei height, GLenum format);
1551 bool ValidateCompressedTexFuncData(
1552 const char* function_name,
1553 GLsizei width, GLsizei height, GLenum format, size_t size);
1554 bool ValidateCompressedTexSubDimensions(
1555 const char* function_name,
1556 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1557 GLsizei width, GLsizei height, GLenum format,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001558 Texture* texture);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001559
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001560 void RenderWarning(const char* filename, int line, const std::string& msg);
1561 void PerformanceWarning(
1562 const char* filename, int line, const std::string& msg);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001563
1564 const FeatureInfo::FeatureFlags& features() const {
1565 return feature_info_->feature_flags();
1566 }
1567
1568 const FeatureInfo::Workarounds& workarounds() const {
1569 return feature_info_->workarounds();
1570 }
1571
1572 bool ShouldDeferDraws() {
1573 return !offscreen_target_frame_buffer_.get() &&
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001574 state_.bound_draw_framebuffer.get() == NULL &&
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001575 surface_->DeferDraws();
1576 }
1577
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001578 bool ShouldDeferReads() {
1579 return !offscreen_target_frame_buffer_.get() &&
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001580 state_.bound_read_framebuffer.get() == NULL &&
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001581 surface_->DeferDraws();
1582 }
1583
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01001584 void ProcessPendingReadPixels();
1585 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1586
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001587 // Generate a member function prototype for each command in an automated and
1588 // typesafe way.
1589 #define GLES2_CMD_OP(name) \
1590 Error Handle ## name( \
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001591 uint32 immediate_data_size, \
1592 const cmds::name& args); \
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001593
1594 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1595
1596 #undef GLES2_CMD_OP
1597
1598 // The GL context this decoder renders to on behalf of the client.
1599 scoped_refptr<gfx::GLSurface> surface_;
1600 scoped_refptr<gfx::GLContext> context_;
1601
1602 // The ContextGroup for this decoder uses to track resources.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001603 scoped_refptr<ContextGroup> group_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001604
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001605 DebugMarkerManager debug_marker_manager_;
1606 Logger logger_;
1607
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001608 // All the state for this context.
1609 ContextState state_;
1610
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001611 // Current width and height of the offscreen frame buffer.
1612 gfx::Size offscreen_size_;
1613
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001614 // Util to help with GL.
1615 GLES2Util util_;
1616
1617 // unpack flip y as last set by glPixelStorei
1618 bool unpack_flip_y_;
1619
1620 // unpack (un)premultiply alpha as last set by glPixelStorei
1621 bool unpack_premultiply_alpha_;
1622 bool unpack_unpremultiply_alpha_;
1623
1624 // Default vertex attribs manager, used when no VAOs are bound.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001625 scoped_refptr<VertexAttribManager> default_vertex_attrib_manager_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001626
1627 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1628 GLuint attrib_0_buffer_id_;
1629
1630 // The value currently in attrib_0.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001631 Vec4 attrib_0_value_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001632
1633 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1634 bool attrib_0_buffer_matches_value_;
1635
1636 // The size of attrib 0.
1637 GLsizei attrib_0_size_;
1638
1639 // The buffer used to simulate GL_FIXED attribs.
1640 GLuint fixed_attrib_buffer_id_;
1641
1642 // The size of fiixed attrib buffer.
1643 GLsizei fixed_attrib_buffer_size_;
1644
1645 // state saved for clearing so we can clear render buffers and then
1646 // restore to these values.
1647 bool clear_state_dirty_;
1648
1649 // The offscreen frame buffer that the client renders to. With EGL, the
1650 // depth and stencil buffers are separate. With regular GL there is a single
1651 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1652 // offscreen_target_stencil_render_buffer_ is unused.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001653 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1654 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1655 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1656 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1657 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001658 GLenum offscreen_target_color_format_;
1659 GLenum offscreen_target_depth_format_;
1660 GLenum offscreen_target_stencil_format_;
1661 GLsizei offscreen_target_samples_;
1662 GLboolean offscreen_target_buffer_preserved_;
1663
1664 // The copy that is saved when SwapBuffers is called.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001665 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1666 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001667 scoped_refptr<TextureRef>
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001668 offscreen_saved_color_texture_info_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001669
1670 // The copy that is used as the destination for multi-sample resolves.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001671 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1672 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001673 GLenum offscreen_saved_color_format_;
1674
1675 scoped_ptr<QueryManager> query_manager_;
1676
1677 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1678
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001679 base::Callback<void(gfx::Size, float)> resize_callback_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001680
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001681 WaitSyncPointCallback wait_sync_point_callback_;
1682
1683 ShaderCacheCallback shader_cache_callback_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001684
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001685 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001686
1687 // The format of the back buffer_
1688 GLenum back_buffer_color_format_;
1689 bool back_buffer_has_depth_;
1690 bool back_buffer_has_stencil_;
1691
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001692 // Backbuffer attachments that are currently undefined.
1693 uint32 backbuffer_needs_clear_bits_;
1694
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001695 bool teximage2d_faster_than_texsubimage2d_;
1696
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001697 // The current decoder error.
1698 error::Error current_decoder_error_;
1699
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001700 bool use_shader_translator_;
1701 scoped_refptr<ShaderTranslator> vertex_translator_;
1702 scoped_refptr<ShaderTranslator> fragment_translator_;
1703
1704 DisallowedFeatures disallowed_features_;
1705
1706 // Cached from ContextGroup
1707 const Validators* validators_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001708 scoped_refptr<FeatureInfo> feature_info_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001709
1710 // This indicates all the following texSubImage2D calls that are part of the
1711 // failed texImage2D call should be ignored.
1712 bool tex_image_2d_failed_;
1713
1714 int frame_number_;
1715
1716 bool has_robustness_extension_;
1717 GLenum reset_status_;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001718 bool reset_by_robustness_extension_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001719
1720 // These flags are used to override the state of the shared feature_info_
1721 // member. Because the same FeatureInfo instance may be shared among many
1722 // contexts, the assumptions on the availablity of extensions in WebGL
1723 // contexts may be broken. These flags override the shared state to preserve
1724 // WebGL semantics.
1725 bool force_webgl_glsl_validation_;
1726 bool derivatives_explicitly_enabled_;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001727 bool frag_depth_explicitly_enabled_;
1728 bool draw_buffers_explicitly_enabled_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001729
1730 bool compile_shader_always_succeeds_;
1731
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001732 // Log extra info.
1733 bool service_logging_;
1734
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001735#if defined(OS_MACOSX)
1736 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1737 TextureToIOSurfaceMap texture_to_io_surface_map_;
1738#endif
1739
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001740 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1741
1742 // Cached values of the currently assigned viewport dimensions.
1743 GLsizei viewport_max_width_;
1744 GLsizei viewport_max_height_;
1745
1746 // Command buffer stats.
1747 int texture_upload_count_;
1748 base::TimeDelta total_texture_upload_time_;
1749 base::TimeDelta total_processing_commands_time_;
1750
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001751 scoped_ptr<GPUTracer> gpu_tracer_;
1752
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01001753 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1754
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001755 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1756};
1757
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001758ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1759 const char* function_name, GLES2DecoderImpl* decoder)
1760 : function_name_(function_name),
1761 decoder_(decoder) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001762 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(decoder_->GetErrorState(),
1763 function_name_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001764}
1765
1766ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001767 ERRORSTATE_CLEAR_REAL_GL_ERRORS(decoder_->GetErrorState(), function_name_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001768}
1769
1770ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1771 GLuint id)
1772 : decoder_(decoder) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001773 ScopedGLErrorSuppressor suppressor(
1774 "ScopedTexture2DBinder::ctor", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001775
1776 // TODO(apatrick): Check if there are any other states that need to be reset
1777 // before binding a new texture.
1778 glActiveTexture(GL_TEXTURE0);
1779 glBindTexture(GL_TEXTURE_2D, id);
1780}
1781
1782ScopedTexture2DBinder::~ScopedTexture2DBinder() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001783 ScopedGLErrorSuppressor suppressor(
1784 "ScopedTexture2DBinder::dtor", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001785 decoder_->RestoreCurrentTexture2DBindings();
1786}
1787
1788ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1789 GLuint id)
1790 : decoder_(decoder) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001791 ScopedGLErrorSuppressor suppressor(
1792 "ScopedRenderBufferBinder::ctor", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001793 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1794}
1795
1796ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001797 ScopedGLErrorSuppressor suppressor(
1798 "ScopedRenderBufferBinder::dtor", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001799 decoder_->RestoreCurrentRenderbufferBindings();
1800}
1801
1802ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1803 GLuint id)
1804 : decoder_(decoder) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001805 ScopedGLErrorSuppressor suppressor(
1806 "ScopedFrameBufferBinder::ctor", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001807 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001808 decoder->OnFboChanged();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001809}
1810
1811ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001812 ScopedGLErrorSuppressor suppressor(
1813 "ScopedFrameBufferBinder::dtor", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001814 decoder_->RestoreCurrentFramebufferBindings();
1815}
1816
1817ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
1818 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
1819 : decoder_(decoder) {
1820 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1821 decoder_->IsOffscreenBufferMultisampled() &&
1822 (!decoder_->state_.bound_read_framebuffer.get() ||
1823 enforce_internal_framebuffer));
1824 if (!resolve_and_bind_)
1825 return;
1826
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001827 ScopedGLErrorSuppressor suppressor(
1828 "ScopedResolvedFrameBufferBinder::ctor", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001829 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1830 decoder_->offscreen_target_frame_buffer_->id());
1831 GLuint targetid;
1832 if (internal) {
1833 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1834 decoder_->offscreen_resolved_frame_buffer_.reset(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001835 new BackFramebuffer(decoder_));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001836 decoder_->offscreen_resolved_frame_buffer_->Create();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001837 decoder_->offscreen_resolved_color_texture_.reset(
1838 new BackTexture(decoder_));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001839 decoder_->offscreen_resolved_color_texture_->Create();
1840
1841 DCHECK(decoder_->offscreen_saved_color_format_);
1842 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001843 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
1844 false);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001845 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1846 decoder_->offscreen_resolved_color_texture_.get());
1847 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1848 GL_FRAMEBUFFER_COMPLETE) {
1849 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1850 << "because offscreen resolved FBO was incomplete.";
1851 return;
1852 }
1853 }
1854 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1855 } else {
1856 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1857 }
1858 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
1859 const int width = decoder_->offscreen_size_.width();
1860 const int height = decoder_->offscreen_size_.height();
1861 glDisable(GL_SCISSOR_TEST);
1862 if (GLES2Decoder::IsAngle()) {
1863 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1864 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1865 } else {
1866 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1867 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1868 }
1869 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
1870}
1871
1872ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1873 if (!resolve_and_bind_)
1874 return;
1875
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001876 ScopedGLErrorSuppressor suppressor(
1877 "ScopedResolvedFrameBufferBinder::dtor", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001878 decoder_->RestoreCurrentFramebufferBindings();
1879 if (decoder_->state_.enable_flags.scissor_test) {
1880 glEnable(GL_SCISSOR_TEST);
1881 }
1882}
1883
1884ScopedTextureUploadTimer::ScopedTextureUploadTimer(GLES2DecoderImpl* decoder)
1885 : decoder_(decoder),
1886 begin_time_(base::TimeTicks::HighResNow()) {
1887}
1888
1889ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
1890 decoder_->texture_upload_count_++;
1891 decoder_->total_texture_upload_time_ +=
1892 base::TimeTicks::HighResNow() - begin_time_;
1893}
1894
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001895BackTexture::BackTexture(GLES2DecoderImpl* decoder)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001896 : decoder_(decoder),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001897 memory_tracker_(decoder->memory_tracker(), MemoryTracker::kUnmanaged),
1898 bytes_allocated_(0),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001899 id_(0) {
1900}
1901
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001902BackTexture::~BackTexture() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001903 // This does not destroy the render texture because that would require that
1904 // the associated GL context was current. Just check that it was explicitly
1905 // destroyed.
1906 DCHECK_EQ(id_, 0u);
1907}
1908
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001909void BackTexture::Create() {
1910 ScopedGLErrorSuppressor suppressor("BackTexture::Create", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001911 Destroy();
1912 glGenTextures(1, &id_);
1913 ScopedTexture2DBinder binder(decoder_, id_);
1914 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1915 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1916 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1917 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1918
1919 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1920 // never called on an offscreen context, no data will ever be uploaded to the
1921 // saved offscreen color texture (it is deferred until to when SwapBuffers
1922 // is called). My idea is that some nvidia drivers might have a bug where
1923 // deleting a texture that has never been populated might cause a
1924 // crash.
1925 glTexImage2D(
1926 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001927
1928 bytes_allocated_ = 16u * 16u * 4u;
1929 memory_tracker_.TrackMemAlloc(bytes_allocated_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001930}
1931
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001932bool BackTexture::AllocateStorage(
1933 const gfx::Size& size, GLenum format, bool zero) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001934 DCHECK_NE(id_, 0u);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001935 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001936 ScopedTexture2DBinder binder(decoder_, id_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001937 uint32 image_size = 0;
1938 GLES2Util::ComputeImageDataSizes(
1939 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
1940 NULL, NULL);
1941
1942 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
1943 return false;
1944 }
1945
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001946 scoped_ptr<char[]> zero_data;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001947 if (zero) {
1948 zero_data.reset(new char[image_size]);
1949 memset(zero_data.get(), 0, image_size);
1950 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001951
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001952 glTexImage2D(GL_TEXTURE_2D,
1953 0, // mip level
1954 format,
1955 size.width(),
1956 size.height(),
1957 0, // border
1958 format,
1959 GL_UNSIGNED_BYTE,
1960 zero_data.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001961
1962 size_ = size;
1963
1964 bool success = glGetError() == GL_NO_ERROR;
1965 if (success) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001966 memory_tracker_.TrackMemFree(bytes_allocated_);
1967 bytes_allocated_ = image_size;
1968 memory_tracker_.TrackMemAlloc(bytes_allocated_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001969 }
1970 return success;
1971}
1972
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001973void BackTexture::Copy(const gfx::Size& size, GLenum format) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001974 DCHECK_NE(id_, 0u);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001975 ScopedGLErrorSuppressor suppressor("BackTexture::Copy", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001976 ScopedTexture2DBinder binder(decoder_, id_);
1977 glCopyTexImage2D(GL_TEXTURE_2D,
1978 0, // level
1979 format,
1980 0, 0,
1981 size.width(),
1982 size.height(),
1983 0); // border
1984}
1985
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001986void BackTexture::Destroy() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001987 if (id_ != 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001988 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001989 glDeleteTextures(1, &id_);
1990 id_ = 0;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001991 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001992 memory_tracker_.TrackMemFree(bytes_allocated_);
1993 bytes_allocated_ = 0;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001994}
1995
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001996void BackTexture::Invalidate() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001997 id_ = 0;
1998}
1999
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002000BackRenderbuffer::BackRenderbuffer(GLES2DecoderImpl* decoder)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002001 : decoder_(decoder),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002002 memory_tracker_(decoder->memory_tracker(), MemoryTracker::kUnmanaged),
2003 bytes_allocated_(0),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002004 id_(0) {
2005}
2006
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002007BackRenderbuffer::~BackRenderbuffer() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002008 // This does not destroy the render buffer because that would require that
2009 // the associated GL context was current. Just check that it was explicitly
2010 // destroyed.
2011 DCHECK_EQ(id_, 0u);
2012}
2013
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002014void BackRenderbuffer::Create() {
2015 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002016 Destroy();
2017 glGenRenderbuffersEXT(1, &id_);
2018}
2019
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002020bool BackRenderbuffer::AllocateStorage(const gfx::Size& size, GLenum format,
2021 GLsizei samples) {
2022 ScopedGLErrorSuppressor suppressor(
2023 "BackRenderbuffer::AllocateStorage", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002024 ScopedRenderBufferBinder binder(decoder_, id_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002025
2026 uint32 estimated_size = 0;
2027 if (!RenderbufferManager::ComputeEstimatedRenderbufferSize(
2028 size.width(), size.height(), samples, format, &estimated_size)) {
2029 return false;
2030 }
2031
2032 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2033 return false;
2034 }
2035
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002036 if (samples <= 1) {
2037 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2038 format,
2039 size.width(),
2040 size.height());
2041 } else {
2042 if (GLES2Decoder::IsAngle()) {
2043 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
2044 samples,
2045 format,
2046 size.width(),
2047 size.height());
2048 } else {
2049 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
2050 samples,
2051 format,
2052 size.width(),
2053 size.height());
2054 }
2055 }
2056 bool success = glGetError() == GL_NO_ERROR;
2057 if (success) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002058 memory_tracker_.TrackMemFree(bytes_allocated_);
2059 bytes_allocated_ = estimated_size;
2060 memory_tracker_.TrackMemAlloc(bytes_allocated_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002061 }
2062 return success;
2063}
2064
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002065void BackRenderbuffer::Destroy() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002066 if (id_ != 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002067 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002068 glDeleteRenderbuffersEXT(1, &id_);
2069 id_ = 0;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002070 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002071 memory_tracker_.TrackMemFree(bytes_allocated_);
2072 bytes_allocated_ = 0;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002073}
2074
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002075void BackRenderbuffer::Invalidate() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002076 id_ = 0;
2077}
2078
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002079BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002080 : decoder_(decoder),
2081 id_(0) {
2082}
2083
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002084BackFramebuffer::~BackFramebuffer() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002085 // This does not destroy the frame buffer because that would require that
2086 // the associated GL context was current. Just check that it was explicitly
2087 // destroyed.
2088 DCHECK_EQ(id_, 0u);
2089}
2090
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002091void BackFramebuffer::Create() {
2092 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002093 Destroy();
2094 glGenFramebuffersEXT(1, &id_);
2095}
2096
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002097void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002098 DCHECK_NE(id_, 0u);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002099 ScopedGLErrorSuppressor suppressor(
2100 "BackFramebuffer::AttachRenderTexture", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002101 ScopedFrameBufferBinder binder(decoder_, id_);
2102 GLuint attach_id = texture ? texture->id() : 0;
2103 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2104 GL_COLOR_ATTACHMENT0,
2105 GL_TEXTURE_2D,
2106 attach_id,
2107 0);
2108}
2109
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002110void BackFramebuffer::AttachRenderBuffer(GLenum target,
2111 BackRenderbuffer* render_buffer) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002112 DCHECK_NE(id_, 0u);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002113 ScopedGLErrorSuppressor suppressor(
2114 "BackFramebuffer::AttachRenderBuffer", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002115 ScopedFrameBufferBinder binder(decoder_, id_);
2116 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2117 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2118 target,
2119 GL_RENDERBUFFER,
2120 attach_id);
2121}
2122
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002123void BackFramebuffer::Destroy() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002124 if (id_ != 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002125 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002126 glDeleteFramebuffersEXT(1, &id_);
2127 id_ = 0;
2128 }
2129}
2130
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002131void BackFramebuffer::Invalidate() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002132 id_ = 0;
2133}
2134
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002135GLenum BackFramebuffer::CheckStatus() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002136 DCHECK_NE(id_, 0u);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002137 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus", decoder_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002138 ScopedFrameBufferBinder binder(decoder_, id_);
2139 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2140}
2141
2142GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2143 return new GLES2DecoderImpl(group);
2144}
2145
2146GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2147 : GLES2Decoder(),
2148 group_(group),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002149 logger_(&debug_marker_manager_),
2150 state_(group_->feature_info(), &logger_),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002151 unpack_flip_y_(false),
2152 unpack_premultiply_alpha_(false),
2153 unpack_unpremultiply_alpha_(false),
2154 attrib_0_buffer_id_(0),
2155 attrib_0_buffer_matches_value_(true),
2156 attrib_0_size_(0),
2157 fixed_attrib_buffer_id_(0),
2158 fixed_attrib_buffer_size_(0),
2159 clear_state_dirty_(true),
2160 offscreen_target_color_format_(0),
2161 offscreen_target_depth_format_(0),
2162 offscreen_target_stencil_format_(0),
2163 offscreen_target_samples_(0),
2164 offscreen_target_buffer_preserved_(true),
2165 offscreen_saved_color_format_(0),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002166 back_buffer_color_format_(0),
2167 back_buffer_has_depth_(false),
2168 back_buffer_has_stencil_(false),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002169 backbuffer_needs_clear_bits_(0),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002170 teximage2d_faster_than_texsubimage2d_(true),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002171 current_decoder_error_(error::kNoError),
2172 use_shader_translator_(true),
2173 validators_(group_->feature_info()->validators()),
2174 feature_info_(group_->feature_info()),
2175 tex_image_2d_failed_(false),
2176 frame_number_(0),
2177 has_robustness_extension_(false),
2178 reset_status_(GL_NO_ERROR),
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002179 reset_by_robustness_extension_(false),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002180 force_webgl_glsl_validation_(false),
2181 derivatives_explicitly_enabled_(false),
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002182 frag_depth_explicitly_enabled_(false),
2183 draw_buffers_explicitly_enabled_(false),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002184 compile_shader_always_succeeds_(false),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002185 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2186 switches::kEnableGPUServiceLoggingGPU)),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002187 viewport_max_width_(0),
2188 viewport_max_height_(0),
2189 texture_upload_count_(0) {
2190 DCHECK(group);
2191
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002192 attrib_0_value_.v[0] = 0.0f;
2193 attrib_0_value_.v[1] = 0.0f;
2194 attrib_0_value_.v[2] = 0.0f;
2195 attrib_0_value_.v[3] = 1.0f;
2196
2197 // The shader translator is used for WebGL even when running on EGL
2198 // because additional restrictions are needed (like only enabling
2199 // GL_OES_standard_derivatives on demand). It is used for the unit
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002200 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2201 // the empty string to CompileShader and this is not a valid shader.
2202 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002203 CommandLine::ForCurrentProcess()->HasSwitch(
2204 switches::kDisableGLSLTranslator)) {
2205 use_shader_translator_ = false;
2206 }
2207
2208 // TODO(gman): Consider setting this based on GPU and/or driver.
2209 if (IsAngle()) {
2210 teximage2d_faster_than_texsubimage2d_ = false;
2211 }
2212}
2213
2214GLES2DecoderImpl::~GLES2DecoderImpl() {
2215}
2216
2217bool GLES2DecoderImpl::Initialize(
2218 const scoped_refptr<gfx::GLSurface>& surface,
2219 const scoped_refptr<gfx::GLContext>& context,
2220 bool offscreen,
2221 const gfx::Size& size,
2222 const DisallowedFeatures& disallowed_features,
2223 const char* allowed_extensions,
2224 const std::vector<int32>& attribs) {
2225 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2226 DCHECK(context->IsCurrent(surface.get()));
2227 DCHECK(!context_.get());
2228
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002229 set_initialized();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002230 gpu_tracer_ = GPUTracer::Create();
2231
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002232 if (CommandLine::ForCurrentProcess()->HasSwitch(
2233 switches::kEnableGPUDebugging)) {
2234 set_debug(true);
2235 }
2236
2237 if (CommandLine::ForCurrentProcess()->HasSwitch(
2238 switches::kEnableGPUCommandLogging)) {
2239 set_log_commands(true);
2240 }
2241
2242 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2243 switches::kCompileShaderAlwaysSucceeds);
2244
2245
2246 // Take ownership of the context and surface. The surface can be replaced with
2247 // SetSurface.
2248 context_ = context;
2249 surface_ = surface;
2250
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002251 if (!group_->Initialize(this, disallowed_features, allowed_extensions)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002252 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
2253 << "failed to initialize.";
2254 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2255 Destroy(true);
2256 return false;
2257 }
2258 CHECK_GL_ERROR();
2259
2260 disallowed_features_ = disallowed_features;
2261
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002262 state_.attrib_values.resize(group_->max_vertex_attribs());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002263 default_vertex_attrib_manager_ = new VertexAttribManager();
2264 default_vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
2265
2266 // vertex_attrib_manager is set to default_vertex_attrib_manager_ by this call
2267 DoBindVertexArrayOES(0);
2268
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002269 query_manager_.reset(new QueryManager(this, feature_info_.get()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002270 vertex_array_manager_.reset(new VertexArrayManager());
2271
2272 util_.set_num_compressed_texture_formats(
2273 validators_->compressed_texture_format.GetValues().size());
2274
2275 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2276 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2277 // OpenGL ES 2.0 does not have this issue.
2278 glEnableVertexAttribArray(0);
2279 }
2280 glGenBuffersARB(1, &attrib_0_buffer_id_);
2281 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2282 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2283 glBindBuffer(GL_ARRAY_BUFFER, 0);
2284 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2285
2286 state_.texture_units.resize(group_->max_texture_units());
2287 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2288 glActiveTexture(GL_TEXTURE0 + tt);
2289 // We want the last bind to be 2D.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002290 TextureRef* ref;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002291 if (features().oes_egl_image_external) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002292 ref = texture_manager()->GetDefaultTextureInfo(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002293 GL_TEXTURE_EXTERNAL_OES);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002294 state_.texture_units[tt].bound_texture_external_oes = ref;
2295 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref->service_id());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002296 }
2297 if (features().arb_texture_rectangle) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002298 ref = texture_manager()->GetDefaultTextureInfo(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002299 GL_TEXTURE_RECTANGLE_ARB);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002300 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2301 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref->service_id());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002302 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002303 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2304 state_.texture_units[tt].bound_texture_cube_map = ref;
2305 glBindTexture(GL_TEXTURE_CUBE_MAP, ref->service_id());
2306 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2307 state_.texture_units[tt].bound_texture_2d = ref;
2308 glBindTexture(GL_TEXTURE_2D, ref->service_id());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002309 }
2310 glActiveTexture(GL_TEXTURE0);
2311 CHECK_GL_ERROR();
2312
2313 ContextCreationAttribParser attrib_parser;
2314 if (!attrib_parser.Parse(attribs))
2315 return false;
2316
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002317 if (offscreen) {
2318 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002319 features().chromium_framebuffer_multisample) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002320 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2321 // max_sample_count must be initialized to a sane value. If
2322 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2323 GLint max_sample_count = 1;
2324 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2325 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2326 max_sample_count);
2327 } else {
2328 offscreen_target_samples_ = 1;
2329 }
2330 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
2331
2332 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2333 const bool rgb8_supported =
2334 context_->HasExtension("GL_OES_rgb8_rgba8");
2335 // The only available default render buffer formats in GLES2 have very
2336 // little precision. Don't enable multisampling unless 8-bit render
2337 // buffer formats are available--instead fall back to 8-bit textures.
2338 if (rgb8_supported && offscreen_target_samples_ > 1) {
2339 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2340 GL_RGBA8 : GL_RGB8;
2341 } else {
2342 offscreen_target_samples_ = 1;
2343 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2344 GL_RGBA : GL_RGB;
2345 }
2346
2347 // ANGLE only supports packed depth/stencil formats, so use it if it is
2348 // available.
2349 const bool depth24_stencil8_supported =
2350 context_->HasExtension("GL_OES_packed_depth_stencil");
2351 VLOG(1) << "GL_OES_packed_depth_stencil "
2352 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2353 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2354 depth24_stencil8_supported) {
2355 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2356 offscreen_target_stencil_format_ = 0;
2357 } else {
2358 // It may be the case that this depth/stencil combination is not
2359 // supported, but this will be checked later by CheckFramebufferStatus.
2360 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2361 GL_DEPTH_COMPONENT16 : 0;
2362 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2363 GL_STENCIL_INDEX8 : 0;
2364 }
2365 } else {
2366 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2367 GL_RGBA : GL_RGB;
2368
2369 // If depth is requested at all, use the packed depth stencil format if
2370 // it's available, as some desktop GL drivers don't support any non-packed
2371 // formats for depth attachments.
2372 const bool depth24_stencil8_supported =
2373 context_->HasExtension("GL_EXT_packed_depth_stencil");
2374 VLOG(1) << "GL_EXT_packed_depth_stencil "
2375 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2376
2377 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2378 depth24_stencil8_supported) {
2379 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2380 offscreen_target_stencil_format_ = 0;
2381 } else {
2382 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2383 GL_DEPTH_COMPONENT : 0;
2384 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2385 GL_STENCIL_INDEX : 0;
2386 }
2387 }
2388
2389 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2390 GL_RGBA : GL_RGB;
2391
2392 // Create the target frame buffer. This is the one that the client renders
2393 // directly to.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002394 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002395 offscreen_target_frame_buffer_->Create();
2396 // Due to GLES2 format limitations, either the color texture (for
2397 // non-multisampling) or the color render buffer (for multisampling) will be
2398 // attached to the offscreen frame buffer. The render buffer has more
2399 // limited formats available to it, but the texture can't do multisampling.
2400 if (IsOffscreenBufferMultisampled()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002401 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(this));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002402 offscreen_target_color_render_buffer_->Create();
2403 } else {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002404 offscreen_target_color_texture_.reset(new BackTexture(this));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002405 offscreen_target_color_texture_->Create();
2406 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002407 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(this));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002408 offscreen_target_depth_render_buffer_->Create();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002409 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(this));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002410 offscreen_target_stencil_render_buffer_->Create();
2411
2412 // Create the saved offscreen texture. The target frame buffer is copied
2413 // here when SwapBuffers is called.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002414 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002415 offscreen_saved_frame_buffer_->Create();
2416 //
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002417 offscreen_saved_color_texture_.reset(new BackTexture(this));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002418 offscreen_saved_color_texture_->Create();
2419
2420 // Allocate the render buffers at their initial size and check the status
2421 // of the frame buffers is okay.
2422 if (!ResizeOffscreenFrameBuffer(size)) {
2423 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2424 Destroy(true);
2425 return false;
2426 }
2427
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002428 // Allocate the offscreen saved color texture.
2429 DCHECK(offscreen_saved_color_format_);
2430 offscreen_saved_color_texture_->AllocateStorage(
2431 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2432
2433 offscreen_saved_frame_buffer_->AttachRenderTexture(
2434 offscreen_saved_color_texture_.get());
2435 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2436 GL_FRAMEBUFFER_COMPLETE) {
2437 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2438 Destroy(true);
2439 return false;
2440 }
2441
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002442 // Bind to the new default frame buffer (the offscreen target frame buffer).
2443 // This should now be associated with ID zero.
2444 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002445 } else {
2446 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2447 // These are NOT if the back buffer has these proprorties. They are
2448 // if we want the command buffer to enforce them regardless of what
2449 // the real backbuffer is assuming the real back buffer gives us more than
2450 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2451 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2452 // can't do anything about that.
2453
2454 GLint v = 0;
2455 glGetIntegerv(GL_ALPHA_BITS, &v);
2456 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2457 // user requested RGB then RGB. If the user did not specify a preference
2458 // than use whatever we were given. Same for DEPTH and STENCIL.
2459 back_buffer_color_format_ =
2460 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2461 glGetIntegerv(GL_DEPTH_BITS, &v);
2462 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2463 glGetIntegerv(GL_STENCIL_BITS, &v);
2464 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002465 }
2466
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002467 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2468 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2469 // isn't well documented; it was discovered in the Khronos OpenGL ES
2470 // mailing list archives. It also implicitly enables the desktop GL
2471 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2472 // variable in fragment shaders.
2473 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2474 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2475 glEnable(GL_POINT_SPRITE);
2476 }
2477
2478 has_robustness_extension_ =
2479 context->HasExtension("GL_ARB_robustness") ||
2480 context->HasExtension("GL_EXT_robustness");
2481
2482 if (!InitializeShaderTranslator()) {
2483 return false;
2484 }
2485
2486 state_.viewport_width = size.width();
2487 state_.viewport_height = size.height();
2488
2489 GLint viewport_params[4] = { 0 };
2490 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2491 viewport_max_width_ = viewport_params[0];
2492 viewport_max_height_ = viewport_params[1];
2493
2494 state_.scissor_width = state_.viewport_width;
2495 state_.scissor_height = state_.viewport_height;
2496
2497 // Set all the default state because some GL drivers get it wrong.
2498 state_.InitCapabilities();
2499 state_.InitState();
2500 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002501
2502 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2503 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2504 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2505 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2506
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002507 bool call_gl_clear = true;
2508#if defined(OS_ANDROID)
2509 // Temporary workaround for Android WebView because this clear ignores the
2510 // clip and corrupts that external UI of the App. Not calling glClear is ok
2511 // because the system already clears the buffer before each draw. Proper
2512 // fix might be setting the scissor clip properly before initialize. See
2513 // crbug.com/259023 for details.
2514 call_gl_clear = surface_->GetHandle();
2515#endif
2516 if (call_gl_clear) {
2517 // Clear the backbuffer.
2518 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2519 }
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01002520
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002521 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
2522 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2523 }
2524
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002525 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2526 context_->SetUnbindFboOnMakeCurrent();
2527 }
2528
2529 // Only compositor contexts are known to use only the subset of GL
2530 // that can be safely migrated between the iGPU and the dGPU. Mark
2531 // those contexts as safe to forcibly transition between the GPUs.
2532 // http://crbug.com/180876, http://crbug.com/227228
2533 if (!offscreen)
2534 context_->SetSafeToForceGpuSwitch();
2535
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002536 async_pixel_transfer_manager_.reset(
2537 AsyncPixelTransferManager::Create(context.get()));
2538 async_pixel_transfer_manager_->Initialize(texture_manager());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002539
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002540 return true;
2541}
2542
2543void GLES2DecoderImpl::UpdateCapabilities() {
2544 util_.set_num_compressed_texture_formats(
2545 validators_->compressed_texture_format.GetValues().size());
2546 util_.set_num_shader_binary_formats(
2547 validators_->shader_binary_format.GetValues().size());
2548}
2549
2550bool GLES2DecoderImpl::InitializeShaderTranslator() {
2551 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2552
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002553 if (!use_shader_translator_) {
2554 return true;
2555 }
2556 ShBuiltInResources resources;
2557 ShInitBuiltInResources(&resources);
2558 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2559 resources.MaxVertexUniformVectors =
2560 group_->max_vertex_uniform_vectors();
2561 resources.MaxVaryingVectors = group_->max_varying_vectors();
2562 resources.MaxVertexTextureImageUnits =
2563 group_->max_vertex_texture_image_units();
2564 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2565 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2566 resources.MaxFragmentUniformVectors =
2567 group_->max_fragment_uniform_vectors();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002568 resources.MaxDrawBuffers = group_->max_draw_buffers();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002569 resources.MaxExpressionComplexity = 256;
2570 resources.MaxCallStackDepth = 256;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002571
2572#if (ANGLE_SH_VERSION >= 110)
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002573 GLint range[2] = { 0, 0 };
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002574 GLint precision = 0;
2575 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2576 range, &precision);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01002577 resources.FragmentPrecisionHigh =
2578 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002579#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002580
2581 if (force_webgl_glsl_validation_) {
2582 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002583 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
2584 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002585 } else {
2586 resources.OES_standard_derivatives =
2587 features().oes_standard_derivatives ? 1 : 0;
2588 resources.ARB_texture_rectangle =
2589 features().arb_texture_rectangle ? 1 : 0;
2590 resources.OES_EGL_image_external =
2591 features().oes_egl_image_external ? 1 : 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002592 resources.EXT_draw_buffers =
2593 features().ext_draw_buffers ? 1 : 0;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002594 resources.EXT_frag_depth =
2595 features().ext_frag_depth ? 1 : 0;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002596 }
2597
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002598 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2599 : SH_GLES2_SPEC;
2600 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
2601#if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
2602 resources.HashFunction = &CityHashForAngle;
2603#else
2604 resources.HashFunction = &CityHash64;
2605#endif
2606 else
2607 resources.HashFunction = NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002608 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2609 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2610 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2611 ShaderTranslatorInterface::GlslBuiltInFunctionBehavior function_behavior =
2612 workarounds().needs_glsl_built_in_function_emulation ?
2613 ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated :
2614 ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal;
2615
2616 ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
2617 vertex_translator_ = cache->GetTranslator(
2618 SH_VERTEX_SHADER, shader_spec, &resources,
2619 implementation_type, function_behavior);
2620 if (!vertex_translator_.get()) {
2621 LOG(ERROR) << "Could not initialize vertex shader translator.";
2622 Destroy(true);
2623 return false;
2624 }
2625
2626 fragment_translator_ = cache->GetTranslator(
2627 SH_FRAGMENT_SHADER, shader_spec, &resources,
2628 implementation_type, function_behavior);
2629 if (!fragment_translator_.get()) {
2630 LOG(ERROR) << "Could not initialize fragment shader translator.";
2631 Destroy(true);
2632 return false;
2633 }
2634 return true;
2635}
2636
2637bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
2638 for (GLsizei ii = 0; ii < n; ++ii) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002639 if (GetBuffer(client_ids[ii])) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002640 return false;
2641 }
2642 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002643 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002644 glGenBuffersARB(n, service_ids.get());
2645 for (GLsizei ii = 0; ii < n; ++ii) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002646 CreateBuffer(client_ids[ii], service_ids[ii]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002647 }
2648 return true;
2649}
2650
2651bool GLES2DecoderImpl::GenFramebuffersHelper(
2652 GLsizei n, const GLuint* client_ids) {
2653 for (GLsizei ii = 0; ii < n; ++ii) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002654 if (GetFramebuffer(client_ids[ii])) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002655 return false;
2656 }
2657 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002658 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002659 glGenFramebuffersEXT(n, service_ids.get());
2660 for (GLsizei ii = 0; ii < n; ++ii) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002661 CreateFramebuffer(client_ids[ii], service_ids[ii]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002662 }
2663 return true;
2664}
2665
2666bool GLES2DecoderImpl::GenRenderbuffersHelper(
2667 GLsizei n, const GLuint* client_ids) {
2668 for (GLsizei ii = 0; ii < n; ++ii) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002669 if (GetRenderbuffer(client_ids[ii])) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002670 return false;
2671 }
2672 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002673 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002674 glGenRenderbuffersEXT(n, service_ids.get());
2675 for (GLsizei ii = 0; ii < n; ++ii) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002676 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002677 }
2678 return true;
2679}
2680
2681bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2682 for (GLsizei ii = 0; ii < n; ++ii) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002683 if (GetTexture(client_ids[ii])) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002684 return false;
2685 }
2686 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002687 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002688 glGenTextures(n, service_ids.get());
2689 for (GLsizei ii = 0; ii < n; ++ii) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002690 CreateTexture(client_ids[ii], service_ids[ii]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002691 }
2692 return true;
2693}
2694
2695void GLES2DecoderImpl::DeleteBuffersHelper(
2696 GLsizei n, const GLuint* client_ids) {
2697 for (GLsizei ii = 0; ii < n; ++ii) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002698 Buffer* buffer = GetBuffer(client_ids[ii]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002699 if (buffer && !buffer->IsDeleted()) {
2700 state_.vertex_attrib_manager->Unbind(buffer);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002701 if (state_.bound_array_buffer.get() == buffer) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002702 state_.bound_array_buffer = NULL;
2703 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002704 RemoveBuffer(client_ids[ii]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002705 }
2706 }
2707}
2708
2709void GLES2DecoderImpl::DeleteFramebuffersHelper(
2710 GLsizei n, const GLuint* client_ids) {
2711 bool supports_separate_framebuffer_binds =
2712 features().chromium_framebuffer_multisample;
2713
2714 for (GLsizei ii = 0; ii < n; ++ii) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002715 Framebuffer* framebuffer =
2716 GetFramebuffer(client_ids[ii]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002717 if (framebuffer && !framebuffer->IsDeleted()) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002718 if (framebuffer == state_.bound_draw_framebuffer.get()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002719 state_.bound_draw_framebuffer = NULL;
2720 clear_state_dirty_ = true;
2721 GLenum target = supports_separate_framebuffer_binds ?
2722 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2723 glBindFramebufferEXT(target, GetBackbufferServiceId());
2724 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002725 if (framebuffer == state_.bound_read_framebuffer.get()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002726 state_.bound_read_framebuffer = NULL;
2727 GLenum target = supports_separate_framebuffer_binds ?
2728 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
2729 glBindFramebufferEXT(target, GetBackbufferServiceId());
2730 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002731 OnFboChanged();
2732 RemoveFramebuffer(client_ids[ii]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002733 }
2734 }
2735}
2736
2737void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2738 GLsizei n, const GLuint* client_ids) {
2739 bool supports_separate_framebuffer_binds =
2740 features().chromium_framebuffer_multisample;
2741 for (GLsizei ii = 0; ii < n; ++ii) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002742 Renderbuffer* renderbuffer =
2743 GetRenderbuffer(client_ids[ii]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002744 if (renderbuffer && !renderbuffer->IsDeleted()) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002745 if (state_.bound_renderbuffer.get() == renderbuffer) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002746 state_.bound_renderbuffer = NULL;
2747 }
2748 // Unbind from current framebuffers.
2749 if (supports_separate_framebuffer_binds) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002750 if (state_.bound_read_framebuffer.get()) {
2751 state_.bound_read_framebuffer
2752 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002753 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002754 if (state_.bound_draw_framebuffer.get()) {
2755 state_.bound_draw_framebuffer
2756 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002757 }
2758 } else {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002759 if (state_.bound_draw_framebuffer.get()) {
2760 state_.bound_draw_framebuffer
2761 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002762 }
2763 }
2764 clear_state_dirty_ = true;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002765 RemoveRenderbuffer(client_ids[ii]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002766 }
2767 }
2768}
2769
2770void GLES2DecoderImpl::DeleteTexturesHelper(
2771 GLsizei n, const GLuint* client_ids) {
2772 bool supports_separate_framebuffer_binds =
2773 features().chromium_framebuffer_multisample;
2774 for (GLsizei ii = 0; ii < n; ++ii) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002775 TextureRef* texture_ref = GetTexture(client_ids[ii]);
2776 if (texture_ref) {
2777 Texture* texture = texture_ref->texture();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002778 if (texture->IsAttachedToFramebuffer()) {
2779 clear_state_dirty_ = true;
2780 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002781 // Unbind texture_ref from texture_ref units.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002782 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002783 state_.texture_units[jj].Unbind(texture_ref);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002784 }
2785 // Unbind from current framebuffers.
2786 if (supports_separate_framebuffer_binds) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002787 if (state_.bound_read_framebuffer.get()) {
2788 state_.bound_read_framebuffer
2789 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002790 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002791 if (state_.bound_draw_framebuffer.get()) {
2792 state_.bound_draw_framebuffer
2793 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002794 }
2795 } else {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002796 if (state_.bound_draw_framebuffer.get()) {
2797 state_.bound_draw_framebuffer
2798 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002799 }
2800 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002801#if defined(OS_MACOSX)
Ben Murdocheb525c52013-07-10 11:40:50 +01002802 GLuint service_id = texture->service_id();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002803 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2804 ReleaseIOSurfaceForTexture(service_id);
2805 }
2806#endif
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002807 RemoveTexture(client_ids[ii]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002808 }
2809 }
2810}
2811
2812// } // anonymous namespace
2813
2814bool GLES2DecoderImpl::MakeCurrent() {
2815 if (!context_.get() || !context_->MakeCurrent(surface_.get()))
2816 return false;
2817
2818 if (WasContextLost()) {
2819 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002820
2821 // Some D3D drivers cannot recover from device lost in the GPU process
2822 // sandbox. Allow a new GPU process to launch.
2823 if (workarounds().exit_on_context_lost) {
2824 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
2825 << " a D3D device in the Chrome GPU process sandbox.";
2826 exit(0);
2827 }
2828
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002829 return false;
2830 }
2831
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002832 ProcessFinishedAsyncTransfers();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002833
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002834 // Rebind the FBO if it was unbound by the context.
2835 if (workarounds().unbind_fbo_on_context_switch)
2836 RestoreFramebufferBindings();
2837
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002838 clear_state_dirty_ = true;
2839
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002840 return true;
2841}
2842
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002843void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01002844 ProcessPendingReadPixels();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002845 if (engine() && query_manager_.get())
2846 query_manager_->ProcessPendingTransferQueries();
2847
2848 // TODO(epenner): Is there a better place to do this?
2849 // This needs to occur before we execute any batch of commands
2850 // from the client, as the client may have recieved an async
2851 // completion while issuing those commands.
2852 // "DidFlushStart" would be ideal if we had such a callback.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002853 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002854}
2855
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002856void GLES2DecoderImpl::ReleaseCurrent() {
2857 if (context_.get())
2858 context_->ReleaseCurrent(surface_.get());
2859}
2860
2861void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002862 Renderbuffer* renderbuffer =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002863 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
2864 glBindRenderbufferEXT(
2865 GL_RENDERBUFFER, renderbuffer ? renderbuffer->service_id() : 0);
2866}
2867
2868static void RebindCurrentFramebuffer(
2869 GLenum target,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002870 Framebuffer* framebuffer,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002871 GLuint back_buffer_service_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002872 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002873
2874 if (framebuffer_id == 0) {
2875 framebuffer_id = back_buffer_service_id;
2876 }
2877
2878 glBindFramebufferEXT(target, framebuffer_id);
2879}
2880
2881void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
2882 clear_state_dirty_ = true;
2883
2884 if (!features().chromium_framebuffer_multisample) {
2885 RebindCurrentFramebuffer(
2886 GL_FRAMEBUFFER,
2887 state_.bound_draw_framebuffer.get(),
2888 GetBackbufferServiceId());
2889 } else {
2890 RebindCurrentFramebuffer(
2891 GL_READ_FRAMEBUFFER_EXT,
2892 state_.bound_read_framebuffer.get(),
2893 GetBackbufferServiceId());
2894 RebindCurrentFramebuffer(
2895 GL_DRAW_FRAMEBUFFER_EXT,
2896 state_.bound_draw_framebuffer.get(),
2897 GetBackbufferServiceId());
2898 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002899 OnFboChanged();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002900}
2901
2902void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
2903 TextureUnit& info = state_.texture_units[0];
2904 GLuint last_id;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002905 if (info.bound_texture_2d.get()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002906 last_id = info.bound_texture_2d->service_id();
2907 } else {
2908 last_id = 0;
2909 }
2910
2911 glBindTexture(GL_TEXTURE_2D, last_id);
2912 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
2913}
2914
2915bool GLES2DecoderImpl::CheckFramebufferValid(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002916 Framebuffer* framebuffer,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002917 GLenum target, const char* func_name) {
2918 if (!framebuffer) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002919 if (backbuffer_needs_clear_bits_) {
2920 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2921 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
2922 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2923 glClearStencil(0);
2924 glStencilMask(-1);
2925 glClearDepth(1.0f);
2926 glDepthMask(true);
2927 glDisable(GL_SCISSOR_TEST);
2928 glClear(backbuffer_needs_clear_bits_);
2929 backbuffer_needs_clear_bits_ = 0;
2930 RestoreClearState();
2931 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002932 return true;
2933 }
2934
2935 if (framebuffer_manager()->IsComplete(framebuffer)) {
2936 return true;
2937 }
2938
2939 GLenum completeness = framebuffer->IsPossiblyComplete();
2940 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002941 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002942 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
2943 return false;
2944 }
2945
2946 // Are all the attachments cleared?
2947 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2948 texture_manager()->HaveUnclearedMips()) {
2949 if (!framebuffer->IsCleared()) {
2950 // Can we clear them?
2951 if (framebuffer->GetStatus(texture_manager(), target) !=
2952 GL_FRAMEBUFFER_COMPLETE) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002953 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002954 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2955 "framebuffer incomplete (clear)");
2956 return false;
2957 }
2958 ClearUnclearedAttachments(target, framebuffer);
2959 }
2960 }
2961
2962 if (!framebuffer_manager()->IsComplete(framebuffer)) {
2963 if (framebuffer->GetStatus(texture_manager(), target) !=
2964 GL_FRAMEBUFFER_COMPLETE) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002965 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002966 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2967 "framebuffer incomplete (check)");
2968 return false;
2969 }
2970 framebuffer_manager()->MarkAsComplete(framebuffer);
2971 }
2972
2973 // NOTE: At this point we don't know if the framebuffer is complete but
2974 // we DO know that everything that needs to be cleared has been cleared.
2975 return true;
2976}
2977
2978bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
2979 if (!features().chromium_framebuffer_multisample) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002980 bool valid = CheckFramebufferValid(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002981 state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT, func_name);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002982
2983 if (valid)
2984 OnUseFramebuffer();
2985
2986 return valid;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002987 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002988 return CheckFramebufferValid(state_.bound_draw_framebuffer.get(),
2989 GL_DRAW_FRAMEBUFFER_EXT,
2990 func_name) &&
2991 CheckFramebufferValid(state_.bound_read_framebuffer.get(),
2992 GL_READ_FRAMEBUFFER_EXT,
2993 func_name);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002994}
2995
2996gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002997 Framebuffer* framebuffer =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002998 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
2999 if (framebuffer != NULL) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003000 const Framebuffer::Attachment* attachment =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003001 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3002 if (attachment) {
3003 return gfx::Size(attachment->width(), attachment->height());
3004 }
3005 return gfx::Size(0, 0);
3006 } else if (offscreen_target_frame_buffer_.get()) {
3007 return offscreen_size_;
3008 } else {
3009 return surface_->GetSize();
3010 }
3011}
3012
3013GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003014 Framebuffer* framebuffer =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003015 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3016 if (framebuffer != NULL) {
3017 return framebuffer->GetColorAttachmentFormat();
3018 } else if (offscreen_target_frame_buffer_.get()) {
3019 return offscreen_target_color_format_;
3020 } else {
3021 return back_buffer_color_format_;
3022 }
3023}
3024
3025GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003026 Framebuffer* framebuffer =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003027 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3028 if (framebuffer != NULL) {
3029 return framebuffer->GetColorAttachmentFormat();
3030 } else if (offscreen_target_frame_buffer_.get()) {
3031 return offscreen_target_color_format_;
3032 } else {
3033 return back_buffer_color_format_;
3034 }
3035}
3036
3037void GLES2DecoderImpl::UpdateParentTextureInfo() {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003038 if (!offscreen_saved_color_texture_info_.get())
3039 return;
3040 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3041 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3042 texture_manager()->SetLevelInfo(
3043 offscreen_saved_color_texture_info_.get(),
3044 GL_TEXTURE_2D,
3045 0, // level
3046 GL_RGBA,
3047 offscreen_size_.width(),
3048 offscreen_size_.height(),
3049 1, // depth
3050 0, // border
3051 GL_RGBA,
3052 GL_UNSIGNED_BYTE,
3053 true);
3054 texture_manager()->SetParameter(
3055 "UpdateParentTextureInfo",
3056 GetErrorState(),
3057 offscreen_saved_color_texture_info_.get(),
3058 GL_TEXTURE_MAG_FILTER,
3059 GL_NEAREST);
3060 texture_manager()->SetParameter(
3061 "UpdateParentTextureInfo",
3062 GetErrorState(),
3063 offscreen_saved_color_texture_info_.get(),
3064 GL_TEXTURE_MIN_FILTER,
3065 GL_NEAREST);
3066 texture_manager()->SetParameter(
3067 "UpdateParentTextureInfo",
3068 GetErrorState(),
3069 offscreen_saved_color_texture_info_.get(),
3070 GL_TEXTURE_WRAP_S,
3071 GL_CLAMP_TO_EDGE);
3072 texture_manager()->SetParameter(
3073 "UpdateParentTextureInfo",
3074 GetErrorState(),
3075 offscreen_saved_color_texture_info_.get(),
3076 GL_TEXTURE_WRAP_T,
3077 GL_CLAMP_TO_EDGE);
3078 TextureRef* texture_ref = GetTextureInfoForTarget(target);
3079 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003080}
3081
3082void GLES2DecoderImpl::SetResizeCallback(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003083 const base::Callback<void(gfx::Size, float)>& callback) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003084 resize_callback_ = callback;
3085}
3086
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003087Logger* GLES2DecoderImpl::GetLogger() {
3088 return &logger_;
3089}
3090
3091ErrorState* GLES2DecoderImpl::GetErrorState() {
3092 return state_.GetErrorState();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003093}
3094
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003095void GLES2DecoderImpl::SetShaderCacheCallback(
3096 const ShaderCacheCallback& callback) {
3097 shader_cache_callback_ = callback;
3098}
3099
3100void GLES2DecoderImpl::SetWaitSyncPointCallback(
3101 const WaitSyncPointCallback& callback) {
3102 wait_sync_point_callback_ = callback;
3103}
3104
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003105AsyncPixelTransferManager*
3106 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3107 return async_pixel_transfer_manager_.get();
3108}
3109
3110void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3111 async_pixel_transfer_manager_.reset();
3112}
3113
3114void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3115 AsyncPixelTransferManager* manager) {
3116 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003117}
3118
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003119bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3120 uint32* service_texture_id) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003121 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3122 if (texture_ref) {
3123 *service_texture_id = texture_ref->service_id();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003124 return true;
3125 }
3126 return false;
3127}
3128
3129uint32 GLES2DecoderImpl::GetTextureUploadCount() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003130 return texture_upload_count_ +
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003131 async_pixel_transfer_manager_->GetTextureUploadCount();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003132}
3133
3134base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003135 return total_texture_upload_time_ +
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003136 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003137}
3138
3139base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3140 return total_processing_commands_time_;
3141}
3142
3143void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3144 total_processing_commands_time_ += time;
3145}
3146
3147void GLES2DecoderImpl::Destroy(bool have_context) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003148 if (!initialized())
3149 return;
3150
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003151 DCHECK(!have_context || context_->IsCurrent(NULL));
3152
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003153 // Unbind everything.
3154 state_.vertex_attrib_manager = NULL;
3155 default_vertex_attrib_manager_ = NULL;
3156 state_.texture_units.clear();
3157 state_.bound_array_buffer = NULL;
3158 state_.current_query = NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003159 state_.bound_read_framebuffer = NULL;
3160 state_.bound_draw_framebuffer = NULL;
3161 state_.bound_renderbuffer = NULL;
3162
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01003163 if (offscreen_saved_color_texture_info_.get()) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003164 DCHECK(offscreen_target_color_texture_);
3165 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3166 offscreen_saved_color_texture_->id());
3167 offscreen_saved_color_texture_->Invalidate();
3168 offscreen_saved_color_texture_info_ = NULL;
3169 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003170 if (have_context) {
3171 if (copy_texture_CHROMIUM_.get()) {
3172 copy_texture_CHROMIUM_->Destroy();
3173 copy_texture_CHROMIUM_.reset();
3174 }
3175
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003176 if (state_.current_program.get()) {
3177 program_manager()->UnuseProgram(shader_manager(),
3178 state_.current_program.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003179 }
3180
3181 if (attrib_0_buffer_id_) {
3182 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3183 }
3184 if (fixed_attrib_buffer_id_) {
3185 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3186 }
3187
3188 if (offscreen_target_frame_buffer_.get())
3189 offscreen_target_frame_buffer_->Destroy();
3190 if (offscreen_target_color_texture_.get())
3191 offscreen_target_color_texture_->Destroy();
3192 if (offscreen_target_color_render_buffer_.get())
3193 offscreen_target_color_render_buffer_->Destroy();
3194 if (offscreen_target_depth_render_buffer_.get())
3195 offscreen_target_depth_render_buffer_->Destroy();
3196 if (offscreen_target_stencil_render_buffer_.get())
3197 offscreen_target_stencil_render_buffer_->Destroy();
3198 if (offscreen_saved_frame_buffer_.get())
3199 offscreen_saved_frame_buffer_->Destroy();
3200 if (offscreen_saved_color_texture_.get())
3201 offscreen_saved_color_texture_->Destroy();
3202 if (offscreen_resolved_frame_buffer_.get())
3203 offscreen_resolved_frame_buffer_->Destroy();
3204 if (offscreen_resolved_color_texture_.get())
3205 offscreen_resolved_color_texture_->Destroy();
3206 } else {
3207 if (offscreen_target_frame_buffer_.get())
3208 offscreen_target_frame_buffer_->Invalidate();
3209 if (offscreen_target_color_texture_.get())
3210 offscreen_target_color_texture_->Invalidate();
3211 if (offscreen_target_color_render_buffer_.get())
3212 offscreen_target_color_render_buffer_->Invalidate();
3213 if (offscreen_target_depth_render_buffer_.get())
3214 offscreen_target_depth_render_buffer_->Invalidate();
3215 if (offscreen_target_stencil_render_buffer_.get())
3216 offscreen_target_stencil_render_buffer_->Invalidate();
3217 if (offscreen_saved_frame_buffer_.get())
3218 offscreen_saved_frame_buffer_->Invalidate();
3219 if (offscreen_saved_color_texture_.get())
3220 offscreen_saved_color_texture_->Invalidate();
3221 if (offscreen_resolved_frame_buffer_.get())
3222 offscreen_resolved_frame_buffer_->Invalidate();
3223 if (offscreen_resolved_color_texture_.get())
3224 offscreen_resolved_color_texture_->Invalidate();
3225 }
Ben Murdochbbcdd452013-07-25 10:06:34 +01003226
3227 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3228 // Otherwise, we can leak objects. http://crbug.com/258772.
3229 // state_.current_program must be reset before group_ is reset because
3230 // the later deletes the ProgramManager object that referred by
3231 // state_.current_program object.
3232 state_.current_program = NULL;
3233
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003234 copy_texture_CHROMIUM_.reset();
3235
3236 if (query_manager_.get()) {
3237 query_manager_->Destroy(have_context);
3238 query_manager_.reset();
3239 }
3240
3241 if (vertex_array_manager_ .get()) {
3242 vertex_array_manager_->Destroy(have_context);
3243 vertex_array_manager_.reset();
3244 }
3245
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003246 offscreen_target_frame_buffer_.reset();
3247 offscreen_target_color_texture_.reset();
3248 offscreen_target_color_render_buffer_.reset();
3249 offscreen_target_depth_render_buffer_.reset();
3250 offscreen_target_stencil_render_buffer_.reset();
3251 offscreen_saved_frame_buffer_.reset();
3252 offscreen_saved_color_texture_.reset();
3253 offscreen_resolved_frame_buffer_.reset();
3254 offscreen_resolved_color_texture_.reset();
3255
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003256 // Should destroy the transfer manager before the texture manager held
3257 // by the context group.
3258 async_pixel_transfer_manager_.reset();
3259
3260 if (group_.get()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003261 group_->Destroy(this, have_context);
3262 group_ = NULL;
3263 }
3264
3265 if (context_.get()) {
3266 context_->ReleaseCurrent(NULL);
3267 context_ = NULL;
3268 }
3269
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003270#if defined(OS_MACOSX)
3271 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3272 it != texture_to_io_surface_map_.end(); ++it) {
3273 CFRelease(it->second);
3274 }
3275 texture_to_io_surface_map_.clear();
3276#endif
3277}
3278
3279void GLES2DecoderImpl::SetSurface(
3280 const scoped_refptr<gfx::GLSurface>& surface) {
3281 DCHECK(context_->IsCurrent(NULL));
3282 DCHECK(surface_.get());
3283 surface_ = surface;
3284 RestoreCurrentFramebufferBindings();
3285}
3286
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003287bool GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003288 if (!offscreen_saved_color_texture_.get())
3289 return false;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003290 if (!offscreen_saved_color_texture_info_.get()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003291 GLuint service_id = offscreen_saved_color_texture_->id();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003292 offscreen_saved_color_texture_info_ = TextureRef::Create(
3293 texture_manager(), 0, service_id);
3294 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3295 GL_TEXTURE_2D);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003296 UpdateParentTextureInfo();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003297 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003298 gpu::gles2::MailboxName name;
3299 memcpy(name.key, mailbox.name, sizeof(mailbox.name));
3300 return mailbox_manager()->ProduceTexture(
3301 GL_TEXTURE_2D, name, offscreen_saved_color_texture_info_->texture());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003302}
3303
3304size_t GLES2DecoderImpl::GetBackbufferMemoryTotal() {
3305 size_t total = 0;
3306 if (offscreen_target_frame_buffer_.get()) {
3307 if (offscreen_target_color_texture_.get()) {
3308 total += offscreen_target_color_texture_->estimated_size();
3309 }
3310 if (offscreen_target_color_render_buffer_.get()) {
3311 total += offscreen_target_color_render_buffer_->estimated_size();
3312 }
3313 if (offscreen_target_depth_render_buffer_.get()) {
3314 total += offscreen_target_depth_render_buffer_->estimated_size();
3315 }
3316 if (offscreen_target_stencil_render_buffer_.get()) {
3317 total += offscreen_target_stencil_render_buffer_->estimated_size();
3318 }
3319 if (offscreen_saved_color_texture_.get()) {
3320 total += offscreen_saved_color_texture_->estimated_size();
3321 }
3322 if (offscreen_resolved_color_texture_.get()) {
3323 total += offscreen_resolved_color_texture_->estimated_size();
3324 }
3325 } else {
3326 gfx::Size size = surface_->GetSize();
3327 total += size.width() * size.height() *
3328 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_);
3329 }
3330 return total;
3331}
3332
3333bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3334 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3335 if (!is_offscreen) {
3336 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3337 << " with an onscreen framebuffer.";
3338 return false;
3339 }
3340
3341 if (offscreen_size_ == size)
3342 return true;
3343
3344 offscreen_size_ = size;
3345 int w = offscreen_size_.width();
3346 int h = offscreen_size_.height();
3347 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3348 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3349 << "to allocate storage due to excessive dimensions.";
3350 return false;
3351 }
3352
3353 // Reallocate the offscreen target buffers.
3354 DCHECK(offscreen_target_color_format_);
3355 if (IsOffscreenBufferMultisampled()) {
3356 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3357 offscreen_size_, offscreen_target_color_format_,
3358 offscreen_target_samples_)) {
3359 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3360 << "to allocate storage for offscreen target color buffer.";
3361 return false;
3362 }
3363 } else {
3364 if (!offscreen_target_color_texture_->AllocateStorage(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003365 offscreen_size_, offscreen_target_color_format_, false)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003366 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3367 << "to allocate storage for offscreen target color texture.";
3368 return false;
3369 }
3370 }
3371 if (offscreen_target_depth_format_ &&
3372 !offscreen_target_depth_render_buffer_->AllocateStorage(
3373 offscreen_size_, offscreen_target_depth_format_,
3374 offscreen_target_samples_)) {
3375 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3376 << "to allocate storage for offscreen target depth buffer.";
3377 return false;
3378 }
3379 if (offscreen_target_stencil_format_ &&
3380 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3381 offscreen_size_, offscreen_target_stencil_format_,
3382 offscreen_target_samples_)) {
3383 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3384 << "to allocate storage for offscreen target stencil buffer.";
3385 return false;
3386 }
3387
3388 // Attach the offscreen target buffers to the target frame buffer.
3389 if (IsOffscreenBufferMultisampled()) {
3390 offscreen_target_frame_buffer_->AttachRenderBuffer(
3391 GL_COLOR_ATTACHMENT0,
3392 offscreen_target_color_render_buffer_.get());
3393 } else {
3394 offscreen_target_frame_buffer_->AttachRenderTexture(
3395 offscreen_target_color_texture_.get());
3396 }
3397 if (offscreen_target_depth_format_) {
3398 offscreen_target_frame_buffer_->AttachRenderBuffer(
3399 GL_DEPTH_ATTACHMENT,
3400 offscreen_target_depth_render_buffer_.get());
3401 }
3402 const bool packed_depth_stencil =
3403 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3404 if (packed_depth_stencil) {
3405 offscreen_target_frame_buffer_->AttachRenderBuffer(
3406 GL_STENCIL_ATTACHMENT,
3407 offscreen_target_depth_render_buffer_.get());
3408 } else if (offscreen_target_stencil_format_) {
3409 offscreen_target_frame_buffer_->AttachRenderBuffer(
3410 GL_STENCIL_ATTACHMENT,
3411 offscreen_target_stencil_render_buffer_.get());
3412 }
3413
3414 if (offscreen_target_frame_buffer_->CheckStatus() !=
3415 GL_FRAMEBUFFER_COMPLETE) {
3416 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3417 << "because offscreen FBO was incomplete.";
3418 return false;
3419 }
3420
3421 // Clear the target frame buffer.
3422 {
3423 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3424 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3425 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3426 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3427 glClearStencil(0);
3428 glStencilMaskSeparate(GL_FRONT, -1);
3429 glStencilMaskSeparate(GL_BACK, -1);
3430 glClearDepth(0);
3431 glDepthMask(GL_TRUE);
3432 glDisable(GL_SCISSOR_TEST);
3433 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3434 RestoreClearState();
3435 }
3436
3437 // Destroy the offscreen resolved framebuffers.
3438 if (offscreen_resolved_frame_buffer_.get())
3439 offscreen_resolved_frame_buffer_->Destroy();
3440 if (offscreen_resolved_color_texture_.get())
3441 offscreen_resolved_color_texture_->Destroy();
3442 offscreen_resolved_color_texture_.reset();
3443 offscreen_resolved_frame_buffer_.reset();
3444
3445 return true;
3446}
3447
3448error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003449 uint32 immediate_data_size, const cmds::ResizeCHROMIUM& c) {
3450 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003451 return error::kDeferCommandUntilLater;
3452
3453 GLuint width = static_cast<GLuint>(c.width);
3454 GLuint height = static_cast<GLuint>(c.height);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003455 GLfloat scale_factor = c.scale_factor;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003456 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003457
3458 width = std::max(1U, width);
3459 height = std::max(1U, height);
3460
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003461#if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3462 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
3463 // Make sure that we are done drawing to the back buffer before resizing.
3464 glFinish();
3465#endif
3466 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3467 if (is_offscreen) {
3468 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3469 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3470 << "ResizeOffscreenFrameBuffer failed.";
3471 return error::kLostContext;
3472 }
3473 }
3474
3475 if (!resize_callback_.is_null()) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003476 resize_callback_.Run(gfx::Size(width, height), scale_factor);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003477 DCHECK(context_->IsCurrent(surface_.get()));
3478 if (!context_->IsCurrent(surface_.get())) {
3479 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3480 << "current after resize callback.";
3481 return error::kLostContext;
3482 }
3483 }
3484
3485 return error::kNoError;
3486}
3487
3488const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3489 if (command_id > kStartPoint && command_id < kNumCommands) {
3490 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3491 }
3492 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3493}
3494
3495// Decode command with its arguments, and call the corresponding GL function.
3496// Note: args is a pointer to the command buffer. As such, it could be changed
3497// by a (malicious) client at any time, so if validation has to happen, it
3498// should operate on a copy of them.
3499error::Error GLES2DecoderImpl::DoCommand(
3500 unsigned int command,
3501 unsigned int arg_count,
3502 const void* cmd_data) {
3503 error::Error result = error::kNoError;
3504 if (log_commands()) {
3505 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3506 // LOG(INFO), tried VLOG(1), no luck.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003507 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" << "cmd: "
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003508 << GetCommandName(command);
3509 }
3510 unsigned int command_index = command - kStartPoint - 1;
3511 if (command_index < arraysize(g_command_info)) {
3512 const CommandInfo& info = g_command_info[command_index];
3513 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3514 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3515 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
3516 uint32 immediate_data_size =
3517 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
3518 switch (command) {
3519 #define GLES2_CMD_OP(name) \
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003520 case cmds::name::kCmdId: \
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003521 result = Handle ## name( \
3522 immediate_data_size, \
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003523 *static_cast<const gles2::cmds::name*>(cmd_data)); \
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003524 break; \
3525
3526 GLES2_COMMAND_LIST(GLES2_CMD_OP)
3527 #undef GLES2_CMD_OP
3528 }
3529 if (debug()) {
3530 GLenum error;
3531 while ((error = glGetError()) != GL_NO_ERROR) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003532 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003533 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3534 << GetCommandName(command);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003535 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003536 }
3537 }
3538 } else {
3539 result = error::kInvalidArguments;
3540 }
3541 } else {
3542 result = DoCommonCommand(command, arg_count, cmd_data);
3543 }
3544 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3545 result = current_decoder_error_;
3546 current_decoder_error_ = error::kNoError;
3547 }
3548 return result;
3549}
3550
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003551void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3552 buffer_manager()->RemoveBuffer(client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003553}
3554
3555bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003556 if (GetProgram(client_id)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003557 return false;
3558 }
3559 GLuint service_id = glCreateProgram();
3560 if (service_id != 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003561 CreateProgram(client_id, service_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003562 }
3563 return true;
3564}
3565
3566bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003567 if (GetShader(client_id)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003568 return false;
3569 }
3570 GLuint service_id = glCreateShader(type);
3571 if (service_id != 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003572 CreateShader(client_id, service_id, type);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003573 }
3574 return true;
3575}
3576
3577void GLES2DecoderImpl::DoFinish() {
3578 glFinish();
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01003579 ProcessPendingReadPixels();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003580 ProcessPendingQueries();
3581}
3582
3583void GLES2DecoderImpl::DoFlush() {
3584 glFlush();
3585 ProcessPendingQueries();
3586}
3587
3588void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
3589 GLuint texture_index = texture_unit - GL_TEXTURE0;
3590 if (texture_index >= state_.texture_units.size()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003591 LOCAL_SET_GL_ERROR_INVALID_ENUM(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003592 "glActiveTexture", texture_unit, "texture_unit");
3593 return;
3594 }
3595 state_.active_texture_unit = texture_index;
3596 glActiveTexture(texture_unit);
3597}
3598
3599void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003600 Buffer* buffer = NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003601 GLuint service_id = 0;
3602 if (client_id != 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003603 buffer = GetBuffer(client_id);
3604 if (!buffer) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003605 if (!group_->bind_generates_resource()) {
3606 LOG(ERROR) << "glBindBuffer: id not generated by glGenBuffers";
3607 current_decoder_error_ = error::kGenericError;
3608 return;
3609 }
3610
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003611 // It's a new id so make a buffer buffer for it.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003612 glGenBuffersARB(1, &service_id);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003613 CreateBuffer(client_id, service_id);
3614 buffer = GetBuffer(client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003615 IdAllocatorInterface* id_allocator =
3616 group_->GetIdAllocator(id_namespaces::kBuffers);
3617 id_allocator->MarkAsUsed(client_id);
3618 }
3619 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003620 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
3621 if (buffer) {
3622 if (!buffer_manager()->SetTarget(buffer, target)) {
3623 LOCAL_SET_GL_ERROR(
3624 GL_INVALID_OPERATION,
3625 "glBindBuffer", "buffer bound to more than 1 target");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003626 return;
3627 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003628 service_id = buffer->service_id();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003629 }
3630 switch (target) {
3631 case GL_ARRAY_BUFFER:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003632 state_.bound_array_buffer = buffer;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003633 break;
3634 case GL_ELEMENT_ARRAY_BUFFER:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003635 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003636 break;
3637 default:
3638 NOTREACHED(); // Validation should prevent us getting here.
3639 break;
3640 }
3641 glBindBuffer(target, service_id);
3642}
3643
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01003644bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3645 bool all_draw_buffers) {
3646 Framebuffer* framebuffer =
3647 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3648 if (!all_draw_buffers || !framebuffer) {
3649 return (GLES2Util::GetChannelsForFormat(
3650 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3651 }
3652 return framebuffer->HasAlphaMRT();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003653}
3654
3655bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003656 Framebuffer* framebuffer =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003657 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3658 if (framebuffer) {
3659 return framebuffer->HasDepthAttachment();
3660 }
3661 if (offscreen_target_frame_buffer_.get()) {
3662 return offscreen_target_depth_format_ != 0;
3663 }
3664 return back_buffer_has_depth_;
3665}
3666
3667bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003668 Framebuffer* framebuffer =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003669 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3670 if (framebuffer) {
3671 return framebuffer->HasStencilAttachment();
3672 }
3673 if (offscreen_target_frame_buffer_.get()) {
3674 return offscreen_target_stencil_format_ != 0 ||
3675 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3676 }
3677 return back_buffer_has_stencil_;
3678}
3679
3680void GLES2DecoderImpl::ApplyDirtyState() {
3681 if (clear_state_dirty_) {
3682 glColorMask(
3683 state_.color_mask_red, state_.color_mask_green, state_.color_mask_blue,
3684 state_.color_mask_alpha &&
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01003685 BoundFramebufferHasColorAttachmentWithAlpha(true));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003686 bool have_depth = BoundFramebufferHasDepthAttachment();
3687 glDepthMask(state_.depth_mask && have_depth);
3688 EnableDisable(GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
3689 bool have_stencil = BoundFramebufferHasStencilAttachment();
3690 glStencilMaskSeparate(
3691 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
3692 glStencilMaskSeparate(
3693 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
3694 EnableDisable(
3695 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
3696 EnableDisable(GL_CULL_FACE, state_.enable_flags.cull_face);
3697 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
3698 EnableDisable(GL_BLEND, state_.enable_flags.blend);
3699 clear_state_dirty_ = false;
3700 }
3701}
3702
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003703GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003704 return (offscreen_target_frame_buffer_.get())
3705 ? offscreen_target_frame_buffer_->id()
3706 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003707}
3708
3709void GLES2DecoderImpl::RestoreState() const {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003710 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3711 "context", logger_.GetLogPrefix());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003712 // Restore the Framebuffer first because of bugs in Intel drivers.
3713 // Intel drivers incorrectly clip the viewport settings to
3714 // the size of the current framebuffer object.
3715 RestoreFramebufferBindings();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003716 state_.RestoreState();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003717}
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003718
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003719void GLES2DecoderImpl::RestoreFramebufferBindings() const {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003720 GLuint service_id = state_.bound_draw_framebuffer.get()
3721 ? state_.bound_draw_framebuffer->service_id()
3722 : GetBackbufferServiceId();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003723 if (!features().chromium_framebuffer_multisample) {
3724 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
3725 } else {
3726 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003727 service_id = state_.bound_read_framebuffer.get()
3728 ? state_.bound_read_framebuffer->service_id()
3729 : GetBackbufferServiceId();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003730 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
3731 }
3732 OnFboChanged();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003733}
3734
3735void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003736 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
3737 if (texture) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003738 GLenum target = texture->target();
3739 glBindTexture(target, service_id);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003740 glTexParameteri(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003741 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003742 glTexParameteri(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003743 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003744 glTexParameteri(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003745 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003746 glTexParameteri(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003747 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003748 RestoreTextureUnitBindings(state_.active_texture_unit);
3749 }
3750}
3751
3752void GLES2DecoderImpl::OnFboChanged() const {
3753 if (workarounds().restore_scissor_on_fbo_change)
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003754 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
3755}
3756
3757// Called after the FBO is checked for completeness.
3758void GLES2DecoderImpl::OnUseFramebuffer() const {
3759 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
3760 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003761 // The driver forgets the correct scissor when modifying the FBO binding.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003762 glScissor(state_.scissor_x,
3763 state_.scissor_y,
3764 state_.scissor_width,
3765 state_.scissor_height);
3766
3767 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
3768 // it's unclear how this bug works.
3769 glFlush();
3770 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003771}
3772
3773void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003774 Framebuffer* framebuffer = NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003775 GLuint service_id = 0;
3776 if (client_id != 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003777 framebuffer = GetFramebuffer(client_id);
3778 if (!framebuffer) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003779 if (!group_->bind_generates_resource()) {
3780 LOG(ERROR)
3781 << "glBindFramebuffer: id not generated by glGenFramebuffers";
3782 current_decoder_error_ = error::kGenericError;
3783 return;
3784 }
3785
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003786 // It's a new id so make a framebuffer framebuffer for it.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003787 glGenFramebuffersEXT(1, &service_id);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003788 CreateFramebuffer(client_id, service_id);
3789 framebuffer = GetFramebuffer(client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003790 IdAllocatorInterface* id_allocator =
3791 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3792 id_allocator->MarkAsUsed(client_id);
3793 } else {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003794 service_id = framebuffer->service_id();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003795 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003796 framebuffer->MarkAsValid();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003797 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003798 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003799
3800 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003801 state_.bound_draw_framebuffer = framebuffer;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003802 }
3803 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003804 state_.bound_read_framebuffer = framebuffer;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003805 }
3806
3807 clear_state_dirty_ = true;
3808
3809 // If we are rendering to the backbuffer get the FBO id for any simulated
3810 // backbuffer.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003811 if (framebuffer == NULL) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003812 service_id = GetBackbufferServiceId();
3813 }
3814
3815 glBindFramebufferEXT(target, service_id);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003816 OnFboChanged();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003817}
3818
3819void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003820 Renderbuffer* renderbuffer = NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003821 GLuint service_id = 0;
3822 if (client_id != 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003823 renderbuffer = GetRenderbuffer(client_id);
3824 if (!renderbuffer) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003825 if (!group_->bind_generates_resource()) {
3826 LOG(ERROR)
3827 << "glBindRenderbuffer: id not generated by glGenRenderbuffers";
3828 current_decoder_error_ = error::kGenericError;
3829 return;
3830 }
3831
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003832 // It's a new id so make a renderbuffer renderbuffer for it.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003833 glGenRenderbuffersEXT(1, &service_id);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003834 CreateRenderbuffer(client_id, service_id);
3835 renderbuffer = GetRenderbuffer(client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003836 IdAllocatorInterface* id_allocator =
3837 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3838 id_allocator->MarkAsUsed(client_id);
3839 } else {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003840 service_id = renderbuffer->service_id();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003841 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003842 renderbuffer->MarkAsValid();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003843 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003844 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenerbuffer");
3845 state_.bound_renderbuffer = renderbuffer;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003846 glBindRenderbufferEXT(target, service_id);
3847}
3848
3849void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003850 TextureRef* texture_ref = NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003851 GLuint service_id = 0;
3852 if (client_id != 0) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003853 texture_ref = GetTexture(client_id);
3854 if (!texture_ref) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003855 if (!group_->bind_generates_resource()) {
3856 LOG(ERROR) << "glBindTexture: id not generated by glGenTextures";
3857 current_decoder_error_ = error::kGenericError;
3858 return;
3859 }
3860
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003861 // It's a new id so make a texture texture for it.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003862 glGenTextures(1, &service_id);
3863 DCHECK_NE(0u, service_id);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003864 CreateTexture(client_id, service_id);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003865 texture_ref = GetTexture(client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003866 IdAllocatorInterface* id_allocator =
3867 group_->GetIdAllocator(id_namespaces::kTextures);
3868 id_allocator->MarkAsUsed(client_id);
3869 }
3870 } else {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003871 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003872 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003873 Texture* texture = texture_ref->texture();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003874
3875 // Check the texture exists
3876 // Check that we are not trying to bind it to a different target.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003877 if (texture->target() != 0 && texture->target() != target) {
3878 LOCAL_SET_GL_ERROR(
3879 GL_INVALID_OPERATION,
3880 "glBindTexture", "texture bound to more than 1 target.");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003881 return;
3882 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003883 if (texture->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
3884 LOCAL_SET_GL_ERROR(
3885 GL_INVALID_OPERATION,
3886 "glBindTexture", "illegal target for stream texture.");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003887 return;
3888 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003889 LogClientServiceForInfo(texture, client_id, "glBindTexture");
3890 if (texture->target() == 0) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003891 texture_manager()->SetTarget(texture_ref, target);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003892 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003893 glBindTexture(target, texture->service_id());
3894
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003895 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
3896 unit.bind_target = target;
3897 switch (target) {
3898 case GL_TEXTURE_2D:
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003899 unit.bound_texture_2d = texture_ref;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003900 break;
3901 case GL_TEXTURE_CUBE_MAP:
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003902 unit.bound_texture_cube_map = texture_ref;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003903 break;
3904 case GL_TEXTURE_EXTERNAL_OES:
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003905 unit.bound_texture_external_oes = texture_ref;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003906 break;
3907 case GL_TEXTURE_RECTANGLE_ARB:
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003908 unit.bound_texture_rectangle_arb = texture_ref;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003909 break;
3910 default:
3911 NOTREACHED(); // Validation should prevent us getting here.
3912 break;
3913 }
3914}
3915
3916void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
3917 if (state_.vertex_attrib_manager->Enable(index, false)) {
3918 if (index != 0 ||
3919 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
3920 glDisableVertexAttribArray(index);
3921 }
3922 } else {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003923 LOCAL_SET_GL_ERROR(
3924 GL_INVALID_VALUE,
3925 "glDisableVertexAttribArray", "index out of range");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003926 }
3927}
3928
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003929void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
3930 GLsizei numAttachments,
3931 const GLenum* attachments) {
3932 Framebuffer* framebuffer =
3933 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
3934
3935 // Validates the attachments. If one of them fails
3936 // the whole command fails.
3937 for (GLsizei i = 0; i < numAttachments; ++i) {
3938 if ((framebuffer &&
3939 !validators_->attachment.IsValid(attachments[i])) ||
3940 (!framebuffer &&
3941 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
3942 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3943 "glDiscardFramebufferEXT", attachments[i], "attachments");
3944 return;
3945 }
3946 }
3947
3948 // Marks each one of them as not cleared
3949 for (GLsizei i = 0; i < numAttachments; ++i) {
3950 if (framebuffer) {
3951 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
3952 texture_manager(),
3953 attachments[i],
3954 false);
3955 } else {
3956 switch (attachments[i]) {
3957 case GL_COLOR_EXT:
3958 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
3959 break;
3960 case GL_DEPTH_EXT:
3961 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
3962 case GL_STENCIL_EXT:
3963 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
3964 break;
3965 default:
3966 NOTREACHED();
3967 break;
3968 }
3969 }
3970 }
3971
3972 glDiscardFramebufferEXT(target, numAttachments, attachments);
3973}
3974
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003975void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
3976 if (state_.vertex_attrib_manager->Enable(index, true)) {
3977 glEnableVertexAttribArray(index);
3978 } else {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003979 LOCAL_SET_GL_ERROR(
3980 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003981 }
3982}
3983
3984void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003985 TextureRef* texture_ref = GetTextureInfoForTarget(target);
3986 if (!texture_ref ||
3987 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003988 LOCAL_SET_GL_ERROR(
3989 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003990 return;
3991 }
3992
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003993 if (target == GL_TEXTURE_CUBE_MAP) {
3994 for (int i = 0; i < 6; ++i) {
3995 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003996 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003997 LOCAL_SET_GL_ERROR(
3998 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
3999 return;
4000 }
4001 }
4002 } else {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01004003 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004004 LOCAL_SET_GL_ERROR(
4005 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4006 return;
4007 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004008 }
4009
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004010 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004011 // Workaround for Mac driver bug. In the large scheme of things setting
4012 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4013 // hit so there's probably no need to make this conditional. The bug appears
4014 // to be that if the filtering mode is set to something that doesn't require
4015 // mipmaps for rendering, or is never set to something other than the default,
4016 // then glGenerateMipmap misbehaves.
4017 if (workarounds().set_texture_filter_before_generating_mipmap) {
4018 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4019 }
4020 glGenerateMipmapEXT(target);
4021 if (workarounds().set_texture_filter_before_generating_mipmap) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01004022 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4023 texture_ref->texture()->min_filter());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004024 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004025 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004026 if (error == GL_NO_ERROR) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01004027 texture_manager()->MarkMipmapsGenerated(texture_ref);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004028 }
4029}
4030
4031bool GLES2DecoderImpl::GetHelper(
4032 GLenum pname, GLint* params, GLsizei* num_written) {
4033 DCHECK(num_written);
4034 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4035 switch (pname) {
4036 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4037 *num_written = 1;
4038 if (params) {
4039 *params = GL_RGBA; // We don't support other formats.
4040 }
4041 return true;
4042 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4043 *num_written = 1;
4044 if (params) {
4045 *params = GL_UNSIGNED_BYTE; // We don't support other types.
4046 }
4047 return true;
4048 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
4049 *num_written = 1;
4050 if (params) {
4051 *params = group_->max_fragment_uniform_vectors();
4052 }
4053 return true;
4054 case GL_MAX_VARYING_VECTORS:
4055 *num_written = 1;
4056 if (params) {
4057 *params = group_->max_varying_vectors();
4058 }
4059 return true;
4060 case GL_MAX_VERTEX_UNIFORM_VECTORS:
4061 *num_written = 1;
4062 if (params) {
4063 *params = group_->max_vertex_uniform_vectors();
4064 }
4065 return true;
4066 }
4067 }
4068 switch (pname) {
4069 case GL_MAX_VIEWPORT_DIMS:
4070 if (offscreen_target_frame_buffer_.get()) {
4071 *num_written = 2;
4072 if (params) {
4073 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4074 params[1] = renderbuffer_manager()->max_renderbuffer_size();
4075 }
4076 return true;
4077 }
4078 return false;
4079 case GL_MAX_SAMPLES:
4080 *num_written = 1;
4081 if (params) {
4082 params[0] = renderbuffer_manager()->max_samples();
4083 }
4084 return true;
4085 case GL_MAX_RENDERBUFFER_SIZE:
4086 *num_written = 1;
4087 if (params) {
4088 params[0] = renderbuffer_manager()->max_renderbuffer_size();
4089 }
4090 return true;
4091 case GL_MAX_TEXTURE_SIZE:
4092 *num_written = 1;
4093 if (params) {
4094 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4095 }
4096 return true;
4097 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4098 *num_written = 1;
4099 if (params) {
4100 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4101 }
4102 return true;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004103 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4104 *num_written = 1;
4105 if (params) {
4106 params[0] = group_->max_color_attachments();
4107 }
4108 return true;
4109 case GL_MAX_DRAW_BUFFERS_ARB:
4110 *num_written = 1;
4111 if (params) {
4112 params[0] = group_->max_draw_buffers();
4113 }
4114 return true;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004115 case GL_ALPHA_BITS:
4116 *num_written = 1;
4117 if (params) {
4118 GLint v = 0;
4119 glGetIntegerv(GL_ALPHA_BITS, &v);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01004120 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004121 }
4122 return true;
4123 case GL_DEPTH_BITS:
4124 *num_written = 1;
4125 if (params) {
4126 GLint v = 0;
4127 glGetIntegerv(GL_DEPTH_BITS, &v);
4128 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4129 }
4130 return true;
4131 case GL_STENCIL_BITS:
4132 *num_written = 1;
4133 if (params) {
4134 GLint v = 0;
4135 glGetIntegerv(GL_STENCIL_BITS, &v);
4136 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4137 }
4138 return true;
4139 case GL_COMPRESSED_TEXTURE_FORMATS:
4140 *num_written = validators_->compressed_texture_format.GetValues().size();
4141 if (params) {
4142 for (GLint ii = 0; ii < *num_written; ++ii) {
4143 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4144 }
4145 }
4146 return true;
4147 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4148 *num_written = 1;
4149 if (params) {
4150 *params = validators_->compressed_texture_format.GetValues().size();
4151 }
4152 return true;
4153 case GL_NUM_SHADER_BINARY_FORMATS:
4154 *num_written = 1;
4155 if (params) {
4156 *params = validators_->shader_binary_format.GetValues().size();
4157 }
4158 return true;
4159 case GL_SHADER_BINARY_FORMATS:
4160 *num_written = validators_->shader_binary_format.GetValues().size();
4161 if (params) {
4162 for (GLint ii = 0; ii < *num_written; ++ii) {
4163 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4164 }
4165 }
4166 return true;
4167 case GL_SHADER_COMPILER:
4168 *num_written = 1;
4169 if (params) {
4170 *params = GL_TRUE;
4171 }
4172 return true;
4173 case GL_ARRAY_BUFFER_BINDING:
4174 *num_written = 1;
4175 if (params) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004176 if (state_.bound_array_buffer.get()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004177 GLuint client_id = 0;
4178 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
4179 &client_id);
4180 *params = client_id;
4181 } else {
4182 *params = 0;
4183 }
4184 }
4185 return true;
4186 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4187 *num_written = 1;
4188 if (params) {
4189 if (state_.vertex_attrib_manager->element_array_buffer()) {
4190 GLuint client_id = 0;
4191 buffer_manager()->GetClientId(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004192 state_.vertex_attrib_manager->element_array_buffer()->
4193 service_id(), &client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004194 *params = client_id;
4195 } else {
4196 *params = 0;
4197 }
4198 }
4199 return true;
4200 case GL_FRAMEBUFFER_BINDING:
4201 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
4202 *num_written = 1;
4203 if (params) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004204 Framebuffer* framebuffer =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004205 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4206 if (framebuffer) {
4207 GLuint client_id = 0;
4208 framebuffer_manager()->GetClientId(
4209 framebuffer->service_id(), &client_id);
4210 *params = client_id;
4211 } else {
4212 *params = 0;
4213 }
4214 }
4215 return true;
4216 case GL_READ_FRAMEBUFFER_BINDING_EXT:
4217 *num_written = 1;
4218 if (params) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004219 Framebuffer* framebuffer =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004220 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
4221 if (framebuffer) {
4222 GLuint client_id = 0;
4223 framebuffer_manager()->GetClientId(
4224 framebuffer->service_id(), &client_id);
4225 *params = client_id;
4226 } else {
4227 *params = 0;
4228 }
4229 }
4230 return true;
4231 case GL_RENDERBUFFER_BINDING:
4232 *num_written = 1;
4233 if (params) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004234 Renderbuffer* renderbuffer =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004235 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4236 if (renderbuffer) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004237 *params = renderbuffer->client_id();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004238 } else {
4239 *params = 0;
4240 }
4241 }
4242 return true;
4243 case GL_CURRENT_PROGRAM:
4244 *num_written = 1;
4245 if (params) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004246 if (state_.current_program.get()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004247 GLuint client_id = 0;
4248 program_manager()->GetClientId(
4249 state_.current_program->service_id(), &client_id);
4250 *params = client_id;
4251 } else {
4252 *params = 0;
4253 }
4254 }
4255 return true;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004256 case GL_VERTEX_ARRAY_BINDING_OES:
4257 *num_written = 1;
4258 if (params) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004259 if (state_.vertex_attrib_manager.get() !=
4260 default_vertex_attrib_manager_.get()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004261 GLuint client_id = 0;
4262 vertex_array_manager_->GetClientId(
4263 state_.vertex_attrib_manager->service_id(), &client_id);
4264 *params = client_id;
4265 } else {
4266 *params = 0;
4267 }
4268 }
4269 return true;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004270 case GL_TEXTURE_BINDING_2D:
4271 *num_written = 1;
4272 if (params) {
4273 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004274 if (unit.bound_texture_2d.get()) {
4275 *params = unit.bound_texture_2d->client_id();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004276 } else {
4277 *params = 0;
4278 }
4279 }
4280 return true;
4281 case GL_TEXTURE_BINDING_CUBE_MAP:
4282 *num_written = 1;
4283 if (params) {
4284 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004285 if (unit.bound_texture_cube_map.get()) {
4286 *params = unit.bound_texture_cube_map->client_id();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004287 } else {
4288 *params = 0;
4289 }
4290 }
4291 return true;
4292 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4293 *num_written = 1;
4294 if (params) {
4295 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004296 if (unit.bound_texture_external_oes.get()) {
4297 *params = unit.bound_texture_external_oes->client_id();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004298 } else {
4299 *params = 0;
4300 }
4301 }
4302 return true;
4303 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4304 *num_written = 1;
4305 if (params) {
4306 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004307 if (unit.bound_texture_rectangle_arb.get()) {
4308 *params = unit.bound_texture_rectangle_arb->client_id();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004309 } else {
4310 *params = 0;
4311 }
4312 }
4313 return true;
4314 case GL_UNPACK_FLIP_Y_CHROMIUM:
4315 *num_written = 1;
4316 if (params) {
4317 params[0] = unpack_flip_y_;
4318 }
4319 return true;
4320 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4321 *num_written = 1;
4322 if (params) {
4323 params[0] = unpack_premultiply_alpha_;
4324 }
4325 return true;
4326 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4327 *num_written = 1;
4328 if (params) {
4329 params[0] = unpack_unpremultiply_alpha_;
4330 }
4331 return true;
4332 default:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004333 if (pname >= GL_DRAW_BUFFER0_ARB &&
4334 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4335 *num_written = 1;
4336 if (params) {
4337 Framebuffer* framebuffer =
4338 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4339 if (framebuffer) {
4340 params[0] = framebuffer->GetDrawBuffer(pname);
4341 } else { // backbuffer
4342 if (pname == GL_DRAW_BUFFER0_ARB)
4343 params[0] = group_->draw_buffer();
4344 else
4345 params[0] = GL_NONE;
4346 }
4347 }
4348 return true;
4349 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004350 *num_written = util_.GLGetNumValuesReturned(pname);
4351 return false;
4352 }
4353}
4354
4355bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4356 GLenum pname, GLsizei* num_values) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004357 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004358 return true;
4359 }
4360 return GetHelper(pname, NULL, num_values);
4361}
4362
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004363GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4364 if (GL_MAX_SAMPLES == pname &&
4365 features().use_img_for_multisampled_render_to_texture) {
4366 return GL_MAX_SAMPLES_IMG;
4367 }
4368 return pname;
4369}
4370
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004371void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4372 DCHECK(params);
4373 GLsizei num_written = 0;
4374 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01004375 scoped_ptr<GLint[]> values(new GLint[num_written]);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004376 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004377 GetHelper(pname, values.get(), &num_written);
4378 }
4379 for (GLsizei ii = 0; ii < num_written; ++ii) {
4380 params[ii] = static_cast<GLboolean>(values[ii]);
4381 }
4382 } else {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004383 pname = AdjustGetPname(pname);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004384 glGetBooleanv(pname, params);
4385 }
4386}
4387
4388void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4389 DCHECK(params);
4390 GLsizei num_written = 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004391 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004392 if (GetHelper(pname, NULL, &num_written)) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01004393 scoped_ptr<GLint[]> values(new GLint[num_written]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004394 GetHelper(pname, values.get(), &num_written);
4395 for (GLsizei ii = 0; ii < num_written; ++ii) {
4396 params[ii] = static_cast<GLfloat>(values[ii]);
4397 }
4398 } else {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004399 pname = AdjustGetPname(pname);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004400 glGetFloatv(pname, params);
4401 }
4402 }
4403}
4404
4405void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4406 DCHECK(params);
4407 GLsizei num_written;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004408 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004409 !GetHelper(pname, params, &num_written)) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004410 pname = AdjustGetPname(pname);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004411 glGetIntegerv(pname, params);
4412 }
4413}
4414
4415void GLES2DecoderImpl::DoGetProgramiv(
4416 GLuint program_id, GLenum pname, GLint* params) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004417 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4418 if (!program) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004419 return;
4420 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004421 program->GetProgramiv(pname, params);
4422}
4423
4424void GLES2DecoderImpl::DoGetBufferParameteriv(
4425 GLenum target, GLenum pname, GLint* params) {
Ben Murdoch9ab55632013-07-18 11:57:30 +01004426 // Just delegate it. Some validation is actually done before this.
4427 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4428 &state_, target, pname, params);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004429}
4430
4431void GLES2DecoderImpl::DoBindAttribLocation(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004432 GLuint program_id, GLuint index, const char* name) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004433 if (!StringIsValidForGLES(name)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004434 LOCAL_SET_GL_ERROR(
4435 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004436 return;
4437 }
4438 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004439 LOCAL_SET_GL_ERROR(
4440 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004441 return;
4442 }
4443 if (index >= group_->max_vertex_attribs()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004444 LOCAL_SET_GL_ERROR(
4445 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004446 return;
4447 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004448 Program* program = GetProgramInfoNotShader(
4449 program_id, "glBindAttribLocation");
4450 if (!program) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004451 return;
4452 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004453 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4454 glBindAttribLocation(program->service_id(), index, name);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004455}
4456
4457error::Error GLES2DecoderImpl::HandleBindAttribLocation(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004458 uint32 immediate_data_size, const cmds::BindAttribLocation& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004459 GLuint program = static_cast<GLuint>(c.program);
4460 GLuint index = static_cast<GLuint>(c.index);
4461 uint32 name_size = c.data_size;
4462 const char* name = GetSharedMemoryAs<const char*>(
4463 c.name_shm_id, c.name_shm_offset, name_size);
4464 if (name == NULL) {
4465 return error::kOutOfBounds;
4466 }
4467 String name_str(name, name_size);
4468 DoBindAttribLocation(program, index, name_str.c_str());
4469 return error::kNoError;
4470}
4471
4472error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004473 uint32 immediate_data_size, const cmds::BindAttribLocationImmediate& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004474 GLuint program = static_cast<GLuint>(c.program);
4475 GLuint index = static_cast<GLuint>(c.index);
4476 uint32 name_size = c.data_size;
4477 const char* name = GetImmediateDataAs<const char*>(
4478 c, name_size, immediate_data_size);
4479 if (name == NULL) {
4480 return error::kOutOfBounds;
4481 }
4482 String name_str(name, name_size);
4483 DoBindAttribLocation(program, index, name_str.c_str());
4484 return error::kNoError;
4485}
4486
4487error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004488 uint32 immediate_data_size, const cmds::BindAttribLocationBucket& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004489 GLuint program = static_cast<GLuint>(c.program);
4490 GLuint index = static_cast<GLuint>(c.index);
4491 Bucket* bucket = GetBucket(c.name_bucket_id);
4492 if (!bucket || bucket->size() == 0) {
4493 return error::kInvalidArguments;
4494 }
4495 std::string name_str;
4496 if (!bucket->GetAsString(&name_str)) {
4497 return error::kInvalidArguments;
4498 }
4499 DoBindAttribLocation(program, index, name_str.c_str());
4500 return error::kNoError;
4501}
4502
4503void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004504 GLuint program_id, GLint location, const char* name) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004505 if (!StringIsValidForGLES(name)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004506 LOCAL_SET_GL_ERROR(
4507 GL_INVALID_VALUE,
4508 "glBindUniformLocationCHROMIUM", "Invalid character");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004509 return;
4510 }
4511 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004512 LOCAL_SET_GL_ERROR(
4513 GL_INVALID_OPERATION,
4514 "glBindUniformLocationCHROMIUM", "reserved prefix");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004515 return;
4516 }
4517 if (location < 0 || static_cast<uint32>(location) >=
4518 (group_->max_fragment_uniform_vectors() +
4519 group_->max_vertex_uniform_vectors()) * 4) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004520 LOCAL_SET_GL_ERROR(
4521 GL_INVALID_VALUE,
4522 "glBindUniformLocationCHROMIUM", "location out of range");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004523 return;
4524 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004525 Program* program = GetProgramInfoNotShader(
4526 program_id, "glBindUniformLocationCHROMIUM");
4527 if (!program) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004528 return;
4529 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004530 if (!program->SetUniformLocationBinding(name, location)) {
4531 LOCAL_SET_GL_ERROR(
4532 GL_INVALID_VALUE,
4533 "glBindUniformLocationCHROMIUM", "location out of range");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004534 }
4535}
4536
4537error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUM(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004538 uint32 immediate_data_size, const cmds::BindUniformLocationCHROMIUM& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004539 GLuint program = static_cast<GLuint>(c.program);
4540 GLint location = static_cast<GLint>(c.location);
4541 uint32 name_size = c.data_size;
4542 const char* name = GetSharedMemoryAs<const char*>(
4543 c.name_shm_id, c.name_shm_offset, name_size);
4544 if (name == NULL) {
4545 return error::kOutOfBounds;
4546 }
4547 String name_str(name, name_size);
4548 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4549 return error::kNoError;
4550}
4551
4552error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMImmediate(
4553 uint32 immediate_data_size,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004554 const cmds::BindUniformLocationCHROMIUMImmediate& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004555 GLuint program = static_cast<GLuint>(c.program);
4556 GLint location = static_cast<GLint>(c.location);
4557 uint32 name_size = c.data_size;
4558 const char* name = GetImmediateDataAs<const char*>(
4559 c, name_size, immediate_data_size);
4560 if (name == NULL) {
4561 return error::kOutOfBounds;
4562 }
4563 String name_str(name, name_size);
4564 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4565 return error::kNoError;
4566}
4567
4568error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4569 uint32 immediate_data_size,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004570 const cmds::BindUniformLocationCHROMIUMBucket& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004571 GLuint program = static_cast<GLuint>(c.program);
4572 GLint location = static_cast<GLint>(c.location);
4573 Bucket* bucket = GetBucket(c.name_bucket_id);
4574 if (!bucket || bucket->size() == 0) {
4575 return error::kInvalidArguments;
4576 }
4577 std::string name_str;
4578 if (!bucket->GetAsString(&name_str)) {
4579 return error::kInvalidArguments;
4580 }
4581 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4582 return error::kNoError;
4583}
4584
4585error::Error GLES2DecoderImpl::HandleDeleteShader(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004586 uint32 immediate_data_size, const cmds::DeleteShader& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004587 GLuint client_id = c.shader;
4588 if (client_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004589 Shader* shader = GetShader(client_id);
4590 if (shader) {
4591 if (!shader->IsDeleted()) {
4592 glDeleteShader(shader->service_id());
4593 shader_manager()->MarkAsDeleted(shader);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004594 }
4595 } else {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004596 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004597 }
4598 }
4599 return error::kNoError;
4600}
4601
4602error::Error GLES2DecoderImpl::HandleDeleteProgram(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004603 uint32 immediate_data_size, const cmds::DeleteProgram& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004604 GLuint client_id = c.program;
4605 if (client_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004606 Program* program = GetProgram(client_id);
4607 if (program) {
4608 if (!program->IsDeleted()) {
4609 program_manager()->MarkAsDeleted(shader_manager(), program);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004610 }
4611 } else {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004612 LOCAL_SET_GL_ERROR(
4613 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004614 }
4615 }
4616 return error::kNoError;
4617}
4618
4619void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
4620 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4621 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4622 for (GLsizei ii = 0; ii < n; ++ii) {
4623 id_allocator->FreeID(ids[ii]);
4624 }
4625}
4626
4627error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004628 uint32 immediate_data_size, const cmds::DeleteSharedIdsCHROMIUM& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004629 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4630 GLsizei n = static_cast<GLsizei>(c.n);
4631 uint32 data_size;
4632 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4633 return error::kOutOfBounds;
4634 }
4635 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4636 c.ids_shm_id, c.ids_shm_offset, data_size);
4637 if (n < 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004638 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004639 return error::kNoError;
4640 }
4641 if (ids == NULL) {
4642 return error::kOutOfBounds;
4643 }
4644 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
4645 return error::kNoError;
4646}
4647
4648void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
4649 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
4650 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4651 if (id_offset == 0) {
4652 for (GLsizei ii = 0; ii < n; ++ii) {
4653 ids[ii] = id_allocator->AllocateID();
4654 }
4655 } else {
4656 for (GLsizei ii = 0; ii < n; ++ii) {
4657 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4658 id_offset = ids[ii] + 1;
4659 }
4660 }
4661}
4662
4663error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004664 uint32 immediate_data_size, const cmds::GenSharedIdsCHROMIUM& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004665 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4666 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4667 GLsizei n = static_cast<GLsizei>(c.n);
4668 uint32 data_size;
4669 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4670 return error::kOutOfBounds;
4671 }
4672 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4673 c.ids_shm_id, c.ids_shm_offset, data_size);
4674 if (n < 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004675 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004676 return error::kNoError;
4677 }
4678 if (ids == NULL) {
4679 return error::kOutOfBounds;
4680 }
4681 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
4682 return error::kNoError;
4683}
4684
4685void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
4686 GLuint namespace_id, GLsizei n, const GLuint* ids) {
4687 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
4688 for (GLsizei ii = 0; ii < n; ++ii) {
4689 if (!id_allocator->MarkAsUsed(ids[ii])) {
4690 for (GLsizei jj = 0; jj < ii; ++jj) {
4691 id_allocator->FreeID(ids[jj]);
4692 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004693 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004694 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4695 "attempt to register id that already exists");
4696 return;
4697 }
4698 }
4699}
4700
4701error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004702 uint32 immediate_data_size, const cmds::RegisterSharedIdsCHROMIUM& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004703 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4704 GLsizei n = static_cast<GLsizei>(c.n);
4705 uint32 data_size;
4706 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4707 return error::kOutOfBounds;
4708 }
4709 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4710 c.ids_shm_id, c.ids_shm_offset, data_size);
4711 if (n < 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004712 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004713 return error::kNoError;
4714 }
4715 if (ids == NULL) {
4716 return error::kOutOfBounds;
4717 }
4718 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
4719 return error::kNoError;
4720}
4721
4722error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004723 DCHECK(!ShouldDeferDraws());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004724 if (CheckBoundFramebuffersValid("glClear")) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004725 ApplyDirtyState();
4726 glClear(mask);
4727 }
4728 return error::kNoError;
4729}
4730
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004731void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4732 GLenum target, GLenum attachment, GLenum renderbuffertarget,
4733 GLuint client_renderbuffer_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004734 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4735 if (!framebuffer) {
4736 LOCAL_SET_GL_ERROR(
4737 GL_INVALID_OPERATION,
4738 "glFramebufferRenderbuffer", "no framebuffer bound");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004739 return;
4740 }
4741 GLuint service_id = 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004742 Renderbuffer* renderbuffer = NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004743 if (client_renderbuffer_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004744 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
4745 if (!renderbuffer) {
4746 LOCAL_SET_GL_ERROR(
4747 GL_INVALID_OPERATION,
4748 "glFramebufferRenderbuffer", "unknown renderbuffer");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004749 return;
4750 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004751 service_id = renderbuffer->service_id();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004752 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004753 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004754 glFramebufferRenderbufferEXT(
4755 target, attachment, renderbuffertarget, service_id);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004756 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004757 if (error == GL_NO_ERROR) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004758 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004759 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004760 if (framebuffer == state_.bound_draw_framebuffer.get()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004761 clear_state_dirty_ = true;
4762 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004763 OnFboChanged();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004764}
4765
4766void GLES2DecoderImpl::DoDisable(GLenum cap) {
4767 if (SetCapabilityState(cap, false)) {
4768 glDisable(cap);
4769 }
4770}
4771
4772void GLES2DecoderImpl::DoEnable(GLenum cap) {
4773 if (SetCapabilityState(cap, true)) {
4774 glEnable(cap);
4775 }
4776}
4777
4778void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
4779 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
4780 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
4781 glDepthRange(znear, zfar);
4782}
4783
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004784void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004785 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
4786 state_.sample_coverage_invert = (invert != 0);
4787 glSampleCoverage(state_.sample_coverage_value, invert);
4788}
4789
4790// Assumes framebuffer is complete.
4791void GLES2DecoderImpl::ClearUnclearedAttachments(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004792 GLenum target, Framebuffer* framebuffer) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004793 if (target == GL_READ_FRAMEBUFFER_EXT) {
4794 // bind this to the DRAW point, clear then bind back to READ
4795 // TODO(gman): I don't think there is any guarantee that an FBO that
4796 // is complete on the READ attachment will be complete as a DRAW
4797 // attachment.
4798 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004799 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004800 }
4801 GLbitfield clear_bits = 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004802 if (framebuffer->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004803 glClearColor(
4804 0.0f, 0.0f, 0.0f,
4805 (GLES2Util::GetChannelsForFormat(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004806 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
4807 1.0f);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004808 glColorMask(true, true, true, true);
4809 clear_bits |= GL_COLOR_BUFFER_BIT;
4810 }
4811
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004812 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4813 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004814 glClearStencil(0);
4815 glStencilMask(-1);
4816 clear_bits |= GL_STENCIL_BUFFER_BIT;
4817 }
4818
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004819 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4820 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004821 glClearDepth(1.0f);
4822 glDepthMask(true);
4823 clear_bits |= GL_DEPTH_BUFFER_BIT;
4824 }
4825
4826 glDisable(GL_SCISSOR_TEST);
4827 glClear(clear_bits);
4828
4829 framebuffer_manager()->MarkAttachmentsAsCleared(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004830 framebuffer, renderbuffer_manager(), texture_manager());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004831
4832 RestoreClearState();
4833
4834 if (target == GL_READ_FRAMEBUFFER_EXT) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004835 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
4836 Framebuffer* draw_framebuffer =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004837 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004838 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
4839 GetBackbufferServiceId();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004840 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
4841 }
4842}
4843
4844void GLES2DecoderImpl::RestoreClearState() {
4845 clear_state_dirty_ = true;
4846 glClearColor(
4847 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
4848 state_.color_clear_alpha);
4849 glClearStencil(state_.stencil_clear);
4850 glClearDepth(state_.depth_clear);
4851 if (state_.enable_flags.scissor_test) {
4852 glEnable(GL_SCISSOR_TEST);
4853 }
4854}
4855
4856GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004857 Framebuffer* framebuffer =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004858 GetFramebufferInfoForTarget(target);
4859 if (!framebuffer) {
4860 return GL_FRAMEBUFFER_COMPLETE;
4861 }
4862 GLenum completeness = framebuffer->IsPossiblyComplete();
4863 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4864 return completeness;
4865 }
4866 return framebuffer->GetStatus(texture_manager(), target);
4867}
4868
4869void GLES2DecoderImpl::DoFramebufferTexture2D(
4870 GLenum target, GLenum attachment, GLenum textarget,
4871 GLuint client_texture_id, GLint level) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004872 DoFramebufferTexture2DCommon(
4873 "glFramebufferTexture2D", target, attachment,
4874 textarget, client_texture_id, level, 0);
4875}
4876
4877void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
4878 GLenum target, GLenum attachment, GLenum textarget,
4879 GLuint client_texture_id, GLint level, GLsizei samples) {
4880 if (!features().multisampled_render_to_texture) {
4881 LOCAL_SET_GL_ERROR(
4882 GL_INVALID_OPERATION,
4883 "glFramebufferTexture2DMultisample", "function not available");
4884 return;
4885 }
4886 DoFramebufferTexture2DCommon(
4887 "glFramebufferTexture2DMultisample", target, attachment,
4888 textarget, client_texture_id, level, samples);
4889}
4890
4891void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
4892 const char* name, GLenum target, GLenum attachment, GLenum textarget,
4893 GLuint client_texture_id, GLint level, GLsizei samples) {
4894 if (samples > renderbuffer_manager()->max_samples()) {
4895 LOCAL_SET_GL_ERROR(
4896 GL_INVALID_VALUE,
4897 "glFramebufferTexture2DMultisample", "samples too large");
4898 return;
4899 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004900 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4901 if (!framebuffer) {
4902 LOCAL_SET_GL_ERROR(
4903 GL_INVALID_OPERATION,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004904 name, "no framebuffer bound.");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004905 return;
4906 }
4907 GLuint service_id = 0;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01004908 TextureRef* texture_ref = NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004909 if (client_texture_id) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01004910 texture_ref = GetTexture(client_texture_id);
4911 if (!texture_ref) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004912 LOCAL_SET_GL_ERROR(
4913 GL_INVALID_OPERATION,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004914 name, "unknown texture_ref");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004915 return;
4916 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01004917 service_id = texture_ref->service_id();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004918 }
4919
4920 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004921 LOCAL_SET_GL_ERROR(
4922 GL_INVALID_VALUE,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004923 name, "level out of range");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004924 return;
4925 }
4926
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004927 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
4928 if (0 == samples) {
4929 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
4930 } else {
4931 if (features().use_img_for_multisampled_render_to_texture) {
4932 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
4933 service_id, level, samples);
4934 } else {
4935 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
4936 service_id, level, samples);
4937 }
4938 }
4939 GLenum error = LOCAL_PEEK_GL_ERROR(name);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004940 if (error == GL_NO_ERROR) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004941 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
4942 samples);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004943 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004944 if (framebuffer == state_.bound_draw_framebuffer.get()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004945 clear_state_dirty_ = true;
4946 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004947 OnFboChanged();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004948}
4949
4950void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4951 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004952 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4953 if (!framebuffer) {
4954 LOCAL_SET_GL_ERROR(
4955 GL_INVALID_OPERATION,
4956 "glFramebufferAttachmentParameteriv", "no framebuffer bound");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004957 return;
4958 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004959 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004960 const Framebuffer::Attachment* attachment_object =
4961 framebuffer->GetAttachment(attachment);
4962 *params = attachment_object ? attachment_object->object_name() : 0;
4963 } else {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004964 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
4965 features().use_img_for_multisampled_render_to_texture) {
4966 pname = GL_TEXTURE_SAMPLES_IMG;
4967 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004968 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004969 }
4970}
4971
4972void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4973 GLenum target, GLenum pname, GLint* params) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004974 Renderbuffer* renderbuffer =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004975 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4976 if (!renderbuffer) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004977 LOCAL_SET_GL_ERROR(
4978 GL_INVALID_OPERATION,
4979 "glGetRenderbufferParameteriv", "no renderbuffer bound");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004980 return;
4981 }
4982 switch (pname) {
4983 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4984 *params = renderbuffer->internal_format();
4985 break;
4986 case GL_RENDERBUFFER_WIDTH:
4987 *params = renderbuffer->width();
4988 break;
4989 case GL_RENDERBUFFER_HEIGHT:
4990 *params = renderbuffer->height();
4991 break;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004992 case GL_RENDERBUFFER_SAMPLES_EXT:
4993 if (features().use_img_for_multisampled_render_to_texture) {
4994 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
4995 params);
4996 } else {
4997 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
4998 params);
4999 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005000 default:
5001 glGetRenderbufferParameterivEXT(target, pname, params);
5002 break;
5003 }
5004}
5005
5006void GLES2DecoderImpl::DoBlitFramebufferEXT(
5007 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5008 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5009 GLbitfield mask, GLenum filter) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005010 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005011 if (!features().chromium_framebuffer_multisample) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005012 LOCAL_SET_GL_ERROR(
5013 GL_INVALID_OPERATION,
5014 "glBlitFramebufferEXT", "function not available");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005015 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005016
5017 if (!CheckBoundFramebuffersValid("glBlitFramebufferEXT")) {
5018 return;
5019 }
5020
5021 glDisable(GL_SCISSOR_TEST);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005022 if (IsAngle()) {
5023 glBlitFramebufferANGLE(
5024 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5025 } else {
5026 glBlitFramebufferEXT(
5027 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5028 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005029 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005030}
5031
5032void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
5033 GLenum target, GLsizei samples, GLenum internalformat,
5034 GLsizei width, GLsizei height) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01005035 if (!features().chromium_framebuffer_multisample &&
5036 !features().multisampled_render_to_texture) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005037 LOCAL_SET_GL_ERROR(
5038 GL_INVALID_OPERATION,
5039 "glRenderbufferStorageMultisample", "function not available");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005040 return;
5041 }
5042
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005043 Renderbuffer* renderbuffer =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005044 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5045 if (!renderbuffer) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005046 LOCAL_SET_GL_ERROR(
5047 GL_INVALID_OPERATION,
5048 "glRenderbufferStorageMultisample", "no renderbuffer bound");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005049 return;
5050 }
5051
5052 if (samples > renderbuffer_manager()->max_samples()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005053 LOCAL_SET_GL_ERROR(
5054 GL_INVALID_VALUE,
5055 "glRenderbufferStorageMultisample", "samples too large");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005056 return;
5057 }
5058
5059 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5060 height > renderbuffer_manager()->max_renderbuffer_size()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005061 LOCAL_SET_GL_ERROR(
5062 GL_INVALID_VALUE,
5063 "glRenderbufferStorageMultisample", "dimensions too large");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005064 return;
5065 }
5066
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005067 uint32 estimated_size = 0;
5068 if (!RenderbufferManager::ComputeEstimatedRenderbufferSize(
5069 width, height, samples, internalformat, &estimated_size)) {
5070 LOCAL_SET_GL_ERROR(
5071 GL_OUT_OF_MEMORY,
5072 "glRenderbufferStorageMultsample", "dimensions too large");
5073 return;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005074 }
5075
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005076 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5077 LOCAL_SET_GL_ERROR(
5078 GL_OUT_OF_MEMORY,
5079 "glRenderbufferStorageMultsample", "out of memory");
5080 return;
5081 }
5082
5083 GLenum impl_format = RenderbufferManager::
5084 InternalRenderbufferFormatToImplFormat(internalformat);
5085 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisample");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005086 if (IsAngle()) {
5087 glRenderbufferStorageMultisampleANGLE(
5088 target, samples, impl_format, width, height);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01005089 } else if (features().use_img_for_multisampled_render_to_texture) {
5090 glRenderbufferStorageMultisampleIMG(
5091 target, samples, impl_format, width, height);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005092 } else {
5093 glRenderbufferStorageMultisampleEXT(
5094 target, samples, impl_format, width, height);
5095 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005096 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisample");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005097 if (error == GL_NO_ERROR) {
5098 // TODO(gman): If renderbuffers tracked which framebuffers they were
5099 // attached to we could just mark those framebuffers as not complete.
5100 framebuffer_manager()->IncFramebufferStateChangeCount();
5101 renderbuffer_manager()->SetInfo(
5102 renderbuffer, samples, internalformat, width, height);
5103 }
5104}
5105
5106void GLES2DecoderImpl::DoRenderbufferStorage(
5107 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005108 Renderbuffer* renderbuffer =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005109 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5110 if (!renderbuffer) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005111 LOCAL_SET_GL_ERROR(
5112 GL_INVALID_OPERATION,
5113 "glRenderbufferStorage", "no renderbuffer bound");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005114 return;
5115 }
5116
5117 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5118 height > renderbuffer_manager()->max_renderbuffer_size()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005119 LOCAL_SET_GL_ERROR(
5120 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005121 return;
5122 }
5123
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005124 uint32 estimated_size = 0;
5125 if (!RenderbufferManager::ComputeEstimatedRenderbufferSize(
5126 width, height, 1, internalformat, &estimated_size)) {
5127 LOCAL_SET_GL_ERROR(
5128 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
5129 return;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005130 }
5131
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005132 if (!EnsureGPUMemoryAvailable(estimated_size)) {
5133 LOCAL_SET_GL_ERROR(
5134 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
5135 return;
5136 }
5137
5138 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
5139 glRenderbufferStorageEXT(
5140 target, RenderbufferManager::
5141 InternalRenderbufferFormatToImplFormat(internalformat),
5142 width, height);
5143 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005144 if (error == GL_NO_ERROR) {
5145 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5146 // we could just mark those framebuffers as not complete.
5147 framebuffer_manager()->IncFramebufferStateChangeCount();
5148 renderbuffer_manager()->SetInfo(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005149 renderbuffer, 1, internalformat, width, height);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005150 }
5151}
5152
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005153void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005154 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005155 Program* program = GetProgramInfoNotShader(
5156 program_id, "glLinkProgram");
5157 if (!program) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005158 return;
5159 }
5160
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005161 LogClientServiceForInfo(program, program_id, "glLinkProgram");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005162 ShaderTranslator* vertex_translator = NULL;
5163 ShaderTranslator* fragment_translator = NULL;
5164 if (use_shader_translator_) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01005165 vertex_translator = vertex_translator_.get();
5166 fragment_translator = fragment_translator_.get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005167 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005168 if (program->Link(shader_manager(),
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01005169 vertex_translator,
5170 fragment_translator,
5171 feature_info_.get(),
5172 shader_cache_callback_)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005173 if (program == state_.current_program.get()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005174 if (workarounds().use_current_program_after_successful_link) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005175 glUseProgram(program->service_id());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005176 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005177 program_manager()->ClearUniforms(program);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005178 }
5179 }
5180};
5181
5182void GLES2DecoderImpl::DoTexParameterf(
5183 GLenum target, GLenum pname, GLfloat param) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01005184 TextureRef* texture = GetTextureInfoForTarget(target);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005185 if (!texture) {
5186 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005187 return;
5188 }
5189
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005190 texture_manager()->SetParameter(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005191 "glTexParameterf", GetErrorState(), texture, pname,
5192 static_cast<GLint>(param));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005193}
5194
5195void GLES2DecoderImpl::DoTexParameteri(
5196 GLenum target, GLenum pname, GLint param) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01005197 TextureRef* texture = GetTextureInfoForTarget(target);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005198 if (!texture) {
5199 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005200 return;
5201 }
5202
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005203 texture_manager()->SetParameter(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005204 "glTexParameteri", GetErrorState(), texture, pname, param);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005205}
5206
5207void GLES2DecoderImpl::DoTexParameterfv(
5208 GLenum target, GLenum pname, const GLfloat* params) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01005209 TextureRef* texture = GetTextureInfoForTarget(target);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005210 if (!texture) {
5211 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005212 return;
5213 }
5214
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005215 texture_manager()->SetParameter(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005216 "glTexParameterfv", GetErrorState(), texture, pname,
5217 static_cast<GLint>(params[0]));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005218}
5219
5220void GLES2DecoderImpl::DoTexParameteriv(
5221 GLenum target, GLenum pname, const GLint* params) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01005222 TextureRef* texture = GetTextureInfoForTarget(target);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005223 if (!texture) {
5224 LOCAL_SET_GL_ERROR(
5225 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005226 return;
5227 }
5228
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005229 texture_manager()->SetParameter(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005230 "glTexParameteriv", GetErrorState(), texture, pname, *params);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005231}
5232
5233bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01005234 if (!state_.current_program.get()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005235 // The program does not exist.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005236 LOCAL_SET_GL_ERROR(
5237 GL_INVALID_OPERATION, function_name, "no program in use");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005238 return false;
5239 }
5240 if (!state_.current_program->InUse()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005241 LOCAL_SET_GL_ERROR(
5242 GL_INVALID_OPERATION, function_name, "program not linked");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005243 return false;
5244 }
5245 return true;
5246}
5247
5248bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5249 GLint location, const char* function_name) {
5250 if (!CheckCurrentProgram(function_name)) {
5251 return false;
5252 }
5253 return location != -1;
5254}
5255
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005256namespace {
5257
5258static const GLenum valid_int_vec1_types_list[] = {
5259 GL_INT,
5260 GL_BOOL,
5261 GL_SAMPLER_2D,
5262 GL_SAMPLER_2D_RECT_ARB,
5263 GL_SAMPLER_CUBE,
5264 GL_SAMPLER_EXTERNAL_OES,
5265};
5266
5267static const GLenum valid_int_vec2_types_list[] = {
5268 GL_INT_VEC2,
5269 GL_BOOL_VEC2,
5270};
5271
5272static const GLenum valid_int_vec3_types_list[] = {
5273 GL_INT_VEC3,
5274 GL_BOOL_VEC3,
5275};
5276
5277static const GLenum valid_int_vec4_types_list[] = {
5278 GL_INT_VEC4,
5279 GL_BOOL_VEC4,
5280};
5281
5282static const GLenum valid_float_vec1_types_list[] = {
5283 GL_FLOAT,
5284 GL_BOOL,
5285};
5286
5287static const GLenum valid_float_vec2_types_list[] = {
5288 GL_FLOAT_VEC2,
5289 GL_BOOL_VEC2,
5290};
5291
5292static const GLenum valid_float_vec3_types_list[] = {
5293 GL_FLOAT_VEC3,
5294 GL_BOOL_VEC3,
5295};
5296
5297static const GLenum valid_float_vec4_types_list[] = {
5298 GL_FLOAT_VEC4,
5299 GL_BOOL_VEC4,
5300};
5301
5302static const GLenum valid_float_mat2_types_list[] = {
5303 GL_FLOAT_MAT2,
5304};
5305
5306static const GLenum valid_float_mat3_types_list[] = {
5307 GL_FLOAT_MAT3,
5308};
5309
5310static const GLenum valid_float_mat4_types_list[] = {
5311 GL_FLOAT_MAT4,
5312};
5313
5314static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec1_base_info = {
5315 valid_int_vec1_types_list,
5316 arraysize(valid_int_vec1_types_list),
5317};
5318
5319static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec2_base_info = {
5320 valid_int_vec2_types_list,
5321 arraysize(valid_int_vec2_types_list),
5322};
5323
5324static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec3_base_info = {
5325 valid_int_vec3_types_list,
5326 arraysize(valid_int_vec3_types_list),
5327};
5328
5329static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec4_base_info = {
5330 valid_int_vec4_types_list,
5331 arraysize(valid_int_vec4_types_list),
5332};
5333
5334static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec1_base_info = {
5335 valid_float_vec1_types_list,
5336 arraysize(valid_float_vec1_types_list),
5337};
5338
5339static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec2_base_info = {
5340 valid_float_vec2_types_list,
5341 arraysize(valid_float_vec2_types_list),
5342};
5343
5344static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec3_base_info = {
5345 valid_float_vec3_types_list,
5346 arraysize(valid_float_vec3_types_list),
5347};
5348
5349static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec4_base_info = {
5350 valid_float_vec4_types_list,
5351 arraysize(valid_float_vec4_types_list),
5352};
5353
5354static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat2_base_info = {
5355 valid_float_mat2_types_list,
5356 arraysize(valid_float_mat2_types_list),
5357};
5358
5359static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat3_base_info = {
5360 valid_float_mat3_types_list,
5361 arraysize(valid_float_mat3_types_list),
5362};
5363
5364static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat4_base_info = {
5365 valid_float_mat4_types_list,
5366 arraysize(valid_float_mat4_types_list),
5367};
5368
5369} // anonymous namespace.
5370
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005371bool GLES2DecoderImpl::PrepForSetUniformByLocation(
5372 GLint fake_location, const char* function_name,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005373 const GLES2DecoderImpl::BaseUniformInfo& base_info,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005374 GLint* real_location, GLenum* type, GLsizei* count) {
5375 DCHECK(type);
5376 DCHECK(count);
5377 DCHECK(real_location);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005378
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005379 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
5380 return false;
5381 }
5382 GLint array_index = -1;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005383 const Program::UniformInfo* info =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005384 state_.current_program->GetUniformInfoByFakeLocation(
5385 fake_location, real_location, &array_index);
5386 if (!info) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005387 LOCAL_SET_GL_ERROR(
5388 GL_INVALID_OPERATION, function_name, "unknown location");
5389 return false;
5390 }
5391 bool okay = false;
5392 for (size_t ii = 0; ii < base_info.num_valid_types; ++ii) {
5393 if (base_info.valid_types[ii] == info->type) {
5394 okay = true;
5395 break;
5396 }
5397 }
5398 if (!okay) {
5399 LOCAL_SET_GL_ERROR(
5400 GL_INVALID_OPERATION, function_name,
5401 "wrong uniform function for type");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005402 return false;
5403 }
5404 if (*count > 1 && !info->is_array) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005405 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005406 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
5407 return false;
5408 }
5409 *count = std::min(info->size - array_index, *count);
5410 if (*count <= 0) {
5411 return false;
5412 }
5413 *type = info->type;
5414 return true;
5415}
5416
5417void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5418 GLenum type = 0;
5419 GLsizei count = 1;
5420 GLint real_location = -1;
5421 if (!PrepForSetUniformByLocation(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005422 fake_location, "glUniform1iv", valid_int_vec1_base_info,
5423 &real_location, &type, &count)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005424 return;
5425 }
5426 if (!state_.current_program->SetSamplers(
5427 state_.texture_units.size(), fake_location, 1, &v0)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005428 LOCAL_SET_GL_ERROR(
5429 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005430 return;
5431 }
5432 glUniform1i(real_location, v0);
5433}
5434
5435void GLES2DecoderImpl::DoUniform1iv(
5436 GLint fake_location, GLsizei count, const GLint *value) {
5437 GLenum type = 0;
5438 GLint real_location = -1;
5439 if (!PrepForSetUniformByLocation(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005440 fake_location, "glUniform1iv", valid_int_vec1_base_info,
5441 &real_location, &type, &count)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005442 return;
5443 }
5444 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5445 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
5446 if (!state_.current_program->SetSamplers(
5447 state_.texture_units.size(), fake_location, count, value)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005448 LOCAL_SET_GL_ERROR(
5449 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005450 return;
5451 }
5452 }
5453 glUniform1iv(real_location, count, value);
5454}
5455
5456void GLES2DecoderImpl::DoUniform1fv(
5457 GLint fake_location, GLsizei count, const GLfloat* value) {
5458 GLenum type = 0;
5459 GLint real_location = -1;
5460 if (!PrepForSetUniformByLocation(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005461 fake_location, "glUniform1fv", valid_float_vec1_base_info,
5462 &real_location, &type, &count)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005463 return;
5464 }
5465 if (type == GL_BOOL) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005466 scoped_ptr<GLint[]> temp(new GLint[count]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005467 for (GLsizei ii = 0; ii < count; ++ii) {
5468 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5469 }
5470 DoUniform1iv(real_location, count, temp.get());
5471 } else {
5472 glUniform1fv(real_location, count, value);
5473 }
5474}
5475
5476void GLES2DecoderImpl::DoUniform2fv(
5477 GLint fake_location, GLsizei count, const GLfloat* value) {
5478 GLenum type = 0;
5479 GLint real_location = -1;
5480 if (!PrepForSetUniformByLocation(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005481 fake_location, "glUniform2fv", valid_float_vec2_base_info,
5482 &real_location, &type, &count)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005483 return;
5484 }
5485 if (type == GL_BOOL_VEC2) {
5486 GLsizei num_values = count * 2;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005487 scoped_ptr<GLint[]> temp(new GLint[num_values]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005488 for (GLsizei ii = 0; ii < num_values; ++ii) {
5489 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5490 }
5491 glUniform2iv(real_location, count, temp.get());
5492 } else {
5493 glUniform2fv(real_location, count, value);
5494 }
5495}
5496
5497void GLES2DecoderImpl::DoUniform3fv(
5498 GLint fake_location, GLsizei count, const GLfloat* value) {
5499 GLenum type = 0;
5500 GLint real_location = -1;
5501 if (!PrepForSetUniformByLocation(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005502 fake_location, "glUniform3fv", valid_float_vec3_base_info,
5503 &real_location, &type, &count)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005504 return;
5505 }
5506 if (type == GL_BOOL_VEC3) {
5507 GLsizei num_values = count * 3;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005508 scoped_ptr<GLint[]> temp(new GLint[num_values]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005509 for (GLsizei ii = 0; ii < num_values; ++ii) {
5510 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5511 }
5512 glUniform3iv(real_location, count, temp.get());
5513 } else {
5514 glUniform3fv(real_location, count, value);
5515 }
5516}
5517
5518void GLES2DecoderImpl::DoUniform4fv(
5519 GLint fake_location, GLsizei count, const GLfloat* value) {
5520 GLenum type = 0;
5521 GLint real_location = -1;
5522 if (!PrepForSetUniformByLocation(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005523 fake_location, "glUniform4fv", valid_float_vec4_base_info,
5524 &real_location, &type, &count)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005525 return;
5526 }
5527 if (type == GL_BOOL_VEC4) {
5528 GLsizei num_values = count * 4;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005529 scoped_ptr<GLint[]> temp(new GLint[num_values]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005530 for (GLsizei ii = 0; ii < num_values; ++ii) {
5531 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
5532 }
5533 glUniform4iv(real_location, count, temp.get());
5534 } else {
5535 glUniform4fv(real_location, count, value);
5536 }
5537}
5538
5539void GLES2DecoderImpl::DoUniform2iv(
5540 GLint fake_location, GLsizei count, const GLint* value) {
5541 GLenum type = 0;
5542 GLint real_location = -1;
5543 if (!PrepForSetUniformByLocation(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005544 fake_location, "glUniform2iv", valid_int_vec2_base_info,
5545 &real_location, &type, &count)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005546 return;
5547 }
5548 glUniform2iv(real_location, count, value);
5549}
5550
5551void GLES2DecoderImpl::DoUniform3iv(
5552 GLint fake_location, GLsizei count, const GLint* value) {
5553 GLenum type = 0;
5554 GLint real_location = -1;
5555 if (!PrepForSetUniformByLocation(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005556 fake_location, "glUniform3iv", valid_int_vec3_base_info,
5557 &real_location, &type, &count)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005558 return;
5559 }
5560 glUniform3iv(real_location, count, value);
5561}
5562
5563void GLES2DecoderImpl::DoUniform4iv(
5564 GLint fake_location, GLsizei count, const GLint* value) {
5565 GLenum type = 0;
5566 GLint real_location = -1;
5567 if (!PrepForSetUniformByLocation(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005568 fake_location, "glUniform4iv", valid_int_vec4_base_info,
5569 &real_location, &type, &count)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005570 return;
5571 }
5572 glUniform4iv(real_location, count, value);
5573}
5574
5575void GLES2DecoderImpl::DoUniformMatrix2fv(
5576 GLint fake_location, GLsizei count, GLboolean transpose,
5577 const GLfloat* value) {
5578 GLenum type = 0;
5579 GLint real_location = -1;
5580 if (!PrepForSetUniformByLocation(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005581 fake_location, "glUniformMatrix2fv", valid_float_mat2_base_info,
5582 &real_location, &type, &count)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005583 return;
5584 }
5585 glUniformMatrix2fv(real_location, count, transpose, value);
5586}
5587
5588void GLES2DecoderImpl::DoUniformMatrix3fv(
5589 GLint fake_location, GLsizei count, GLboolean transpose,
5590 const GLfloat* value) {
5591 GLenum type = 0;
5592 GLint real_location = -1;
5593 if (!PrepForSetUniformByLocation(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005594 fake_location, "glUniformMatrix3fv", valid_float_mat3_base_info,
5595 &real_location, &type, &count)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005596 return;
5597 }
5598 glUniformMatrix3fv(real_location, count, transpose, value);
5599}
5600
5601void GLES2DecoderImpl::DoUniformMatrix4fv(
5602 GLint fake_location, GLsizei count, GLboolean transpose,
5603 const GLfloat* value) {
5604 GLenum type = 0;
5605 GLint real_location = -1;
5606 if (!PrepForSetUniformByLocation(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005607 fake_location, "glUniformMatrix4fv", valid_float_mat4_base_info,
5608 &real_location, &type, &count)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005609 return;
5610 }
5611 glUniformMatrix4fv(real_location, count, transpose, value);
5612}
5613
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005614void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005615 GLuint service_id = 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005616 Program* program = NULL;
5617 if (program_id) {
5618 program = GetProgramInfoNotShader(program_id, "glUseProgram");
5619 if (!program) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005620 return;
5621 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005622 if (!program->IsValid()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005623 // Program was not linked successfully. (ie, glLinkProgram)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005624 LOCAL_SET_GL_ERROR(
5625 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005626 return;
5627 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005628 service_id = program->service_id();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005629 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01005630 if (state_.current_program.get()) {
5631 program_manager()->UnuseProgram(shader_manager(),
5632 state_.current_program.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005633 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005634 state_.current_program = program;
5635 LogClientServiceMapping("glUseProgram", program_id, service_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005636 glUseProgram(service_id);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01005637 if (state_.current_program.get()) {
5638 program_manager()->UseProgram(state_.current_program.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005639 }
5640}
5641
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005642void GLES2DecoderImpl::RenderWarning(
5643 const char* filename, int line, const std::string& msg) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005644 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005645}
5646
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005647void GLES2DecoderImpl::PerformanceWarning(
5648 const char* filename, int line, const std::string& msg) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005649 logger_.LogMessage(filename, line,
5650 std::string("PERFORMANCE WARNING: ") + msg);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005651}
5652
Ben Murdoch558790d2013-07-30 15:19:42 +01005653void GLES2DecoderImpl::UpdateStreamTextureIfNeeded(Texture* texture) {
5654 if (texture && texture->IsStreamTexture()) {
5655 DCHECK(stream_texture_manager());
5656 StreamTexture* stream_tex =
5657 stream_texture_manager()->LookupStreamTexture(texture->service_id());
5658 if (stream_tex)
5659 stream_tex->Update();
5660 }
5661}
5662
5663bool GLES2DecoderImpl::PrepareTexturesForRender() {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01005664 DCHECK(state_.current_program.get());
Ben Murdoch558790d2013-07-30 15:19:42 +01005665 bool have_unrenderable_textures =
5666 texture_manager()->HaveUnrenderableTextures();
5667 if (!have_unrenderable_textures && !features().oes_egl_image_external) {
5668 return true;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005669 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01005670
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005671 bool textures_set = false;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005672 const Program::SamplerIndices& sampler_indices =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005673 state_.current_program->sampler_indices();
5674 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005675 const Program::UniformInfo* uniform_info =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005676 state_.current_program->GetUniformInfo(sampler_indices[ii]);
5677 DCHECK(uniform_info);
5678 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5679 GLuint texture_unit_index = uniform_info->texture_units[jj];
5680 if (texture_unit_index < state_.texture_units.size()) {
5681 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01005682 TextureRef* texture =
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01005683 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
Ben Murdochfb250652013-07-31 11:42:55 +01005684 if (texture)
5685 UpdateStreamTextureIfNeeded(texture->texture());
Ben Murdoch558790d2013-07-30 15:19:42 +01005686 if (have_unrenderable_textures &&
5687 (!texture || !texture_manager()->CanRender(texture))) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005688 textures_set = true;
5689 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5690 glBindTexture(
5691 GetBindTargetForSamplerType(uniform_info->type),
5692 texture_manager()->black_texture_id(uniform_info->type));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005693 LOCAL_RENDER_WARNING(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005694 std::string("texture bound to texture unit ") +
5695 base::IntToString(texture_unit_index) +
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01005696 " is not renderable. It maybe non-power-of-2 and have"
5697 " incompatible texture filtering or is not"
5698 " 'texture complete'");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005699 }
5700 }
5701 // else: should this be an error?
5702 }
5703 }
Ben Murdoch558790d2013-07-30 15:19:42 +01005704 return !textures_set;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005705}
5706
5707void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01005708 DCHECK(state_.current_program.get());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005709 const Program::SamplerIndices& sampler_indices =
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01005710 state_.current_program->sampler_indices();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005711 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005712 const Program::UniformInfo* uniform_info =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005713 state_.current_program->GetUniformInfo(sampler_indices[ii]);
5714 DCHECK(uniform_info);
5715 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5716 GLuint texture_unit_index = uniform_info->texture_units[jj];
5717 if (texture_unit_index < state_.texture_units.size()) {
5718 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01005719 TextureRef* texture_ref =
5720 uniform_info->type == GL_SAMPLER_2D
5721 ? texture_unit.bound_texture_2d.get()
5722 : texture_unit.bound_texture_cube_map.get();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01005723 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005724 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01005725 // Get the texture_ref info that was previously bound here.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01005726 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
5727 ? texture_unit.bound_texture_2d.get()
5728 : texture_unit.bound_texture_cube_map.get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005729 glBindTexture(texture_unit.bind_target,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01005730 texture_ref ? texture_ref->service_id() : 0);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005731 }
5732 }
5733 }
5734 }
5735 // Set the active texture back to whatever the user had it as.
5736 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
5737}
5738
5739bool GLES2DecoderImpl::ClearUnclearedTextures() {
5740 // Only check if there are some uncleared textures.
5741 if (!texture_manager()->HaveUnsafeTextures()) {
5742 return true;
5743 }
5744
5745 // 1: Check all textures we are about to render with.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01005746 if (state_.current_program.get()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005747 const Program::SamplerIndices& sampler_indices =
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01005748 state_.current_program->sampler_indices();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005749 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005750 const Program::UniformInfo* uniform_info =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005751 state_.current_program->GetUniformInfo(sampler_indices[ii]);
5752 DCHECK(uniform_info);
5753 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5754 GLuint texture_unit_index = uniform_info->texture_units[jj];
5755 if (texture_unit_index < state_.texture_units.size()) {
5756 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01005757 TextureRef* texture_ref =
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01005758 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01005759 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
5760 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005761 return false;
5762 }
5763 }
5764 }
5765 }
5766 }
5767 }
5768 return true;
5769}
5770
5771bool GLES2DecoderImpl::IsDrawValid(
5772 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount) {
5773 // NOTE: We specifically do not check current_program->IsValid() because
5774 // it could never be invalid since glUseProgram would have failed. While
5775 // glLinkProgram could later mark the program as invalid the previous
5776 // valid program will still function if it is still the current program.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01005777 if (!state_.current_program.get()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005778 // The program does not exist.
5779 // But GL says no ERROR.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005780 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005781 return false;
5782 }
5783
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01005784 return state_.vertex_attrib_manager
5785 ->ValidateBindings(function_name,
5786 this,
5787 feature_info_.get(),
5788 state_.current_program.get(),
5789 max_vertex_accessed,
5790 primcount);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005791}
5792
5793bool GLES2DecoderImpl::SimulateAttrib0(
5794 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
5795 DCHECK(simulated);
5796 *simulated = false;
5797
5798 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
5799 return true;
5800
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005801 const VertexAttrib* attrib =
5802 state_.vertex_attrib_manager->GetVertexAttrib(0);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005803 // If it's enabled or it's not used then we don't need to do anything.
5804 bool attrib_0_used =
5805 state_.current_program->GetAttribInfoByLocation(0) != NULL;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005806 if (attrib->enabled() && attrib_0_used) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005807 return true;
5808 }
5809
5810 // Make a buffer with a single repeated vec4 value enough to
5811 // simulate the constant value that is supposed to be here.
5812 // This is required to emulate GLES2 on GL.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005813 GLuint num_vertices = max_vertex_accessed + 1;
5814 uint32 size_needed = 0;
5815
5816 if (num_vertices == 0 ||
5817 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
5818 size_needed > 0x7FFFFFFFU) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005819 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005820 return false;
5821 }
5822
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005823 LOCAL_PERFORMANCE_WARNING(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005824 "Attribute 0 is disabled. This has signficant performance penalty");
5825
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005826 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005827 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
5828
5829 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
5830 if (new_buffer) {
5831 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
5832 GLenum error = glGetError();
5833 if (error != GL_NO_ERROR) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005834 LOCAL_SET_GL_ERROR(
5835 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005836 return false;
5837 }
5838 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005839
5840 const Vec4& value = state_.attrib_values[0];
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005841 if (new_buffer ||
5842 (attrib_0_used &&
5843 (!attrib_0_buffer_matches_value_ ||
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005844 (value.v[0] != attrib_0_value_.v[0] ||
5845 value.v[1] != attrib_0_value_.v[1] ||
5846 value.v[2] != attrib_0_value_.v[2] ||
5847 value.v[3] != attrib_0_value_.v[3])))) {
5848 std::vector<Vec4> temp(num_vertices, value);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005849 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
5850 attrib_0_buffer_matches_value_ = true;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005851 attrib_0_value_ = value;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005852 attrib_0_size_ = size_needed;
5853 }
5854
5855 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5856
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005857 if (attrib->divisor())
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005858 glVertexAttribDivisorANGLE(0, 0);
5859
5860 *simulated = true;
5861 return true;
5862}
5863
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005864void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib_index) {
5865 const VertexAttrib* attrib =
5866 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
5867 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
5868 Buffer* buffer = attrib->buffer();
5869 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005870 glVertexAttribPointer(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005871 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
5872 attrib->gl_stride(), ptr);
5873 if (attrib->divisor())
5874 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005875 glBindBuffer(
5876 GL_ARRAY_BUFFER,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01005877 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
5878 : 0);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005879
5880 // Never touch vertex attribute 0's state (in particular, never
5881 // disable it) when running on desktop GL because it will never be
5882 // re-enabled.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005883 if (attrib_index != 0 ||
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005884 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005885 if (attrib->enabled()) {
5886 glEnableVertexAttribArray(attrib_index);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005887 } else {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005888 glDisableVertexAttribArray(attrib_index);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005889 }
5890 }
5891}
5892
5893bool GLES2DecoderImpl::SimulateFixedAttribs(
5894 const char* function_name,
5895 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
5896 DCHECK(simulated);
5897 *simulated = false;
5898 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
5899 return true;
5900
5901 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
5902 return true;
5903 }
5904
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005905 LOCAL_PERFORMANCE_WARNING(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005906 "GL_FIXED attributes have a signficant performance penalty");
5907
5908 // NOTE: we could be smart and try to check if a buffer is used
5909 // twice in 2 different attribs, find the overlapping parts and therefore
5910 // duplicate the minimum amount of data but this whole code path is not meant
5911 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
5912 // tests so we just add to the buffer attrib used.
5913
5914 GLuint elements_needed = 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005915 const VertexAttribManager::VertexAttribList& enabled_attribs =
5916 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
5917 for (VertexAttribManager::VertexAttribList::const_iterator it =
5918 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
5919 const VertexAttrib* attrib = *it;
5920 const Program::VertexAttrib* attrib_info =
5921 state_.current_program->GetAttribInfoByLocation(attrib->index());
5922 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
5923 max_vertex_accessed);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005924 GLuint num_vertices = max_accessed + 1;
5925 if (num_vertices == 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005926 LOCAL_SET_GL_ERROR(
5927 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005928 return false;
5929 }
5930 if (attrib_info &&
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005931 attrib->CanAccess(max_accessed) &&
5932 attrib->type() == GL_FIXED) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005933 uint32 elements_used = 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005934 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005935 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005936 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005937 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
5938 return false;
5939 }
5940 }
5941 }
5942
5943 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
5944 uint32 size_needed = 0;
5945 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
5946 size_needed > 0x7FFFFFFFU) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005947 LOCAL_SET_GL_ERROR(
5948 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005949 return false;
5950 }
5951
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005952 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005953
5954 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
5955 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
5956 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
5957 GLenum error = glGetError();
5958 if (error != GL_NO_ERROR) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005959 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005960 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
5961 return false;
5962 }
5963 }
5964
5965 // Copy the elements and convert to float
5966 GLintptr offset = 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005967 for (VertexAttribManager::VertexAttribList::const_iterator it =
5968 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
5969 const VertexAttrib* attrib = *it;
5970 const Program::VertexAttrib* attrib_info =
5971 state_.current_program->GetAttribInfoByLocation(attrib->index());
5972 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005973 max_vertex_accessed);
5974 GLuint num_vertices = max_accessed + 1;
5975 if (num_vertices == 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005976 LOCAL_SET_GL_ERROR(
5977 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005978 return false;
5979 }
5980 if (attrib_info &&
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005981 attrib->CanAccess(max_accessed) &&
5982 attrib->type() == GL_FIXED) {
5983 int num_elements = attrib->size() * kSizeOfFloat;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005984 int size = num_elements * num_vertices;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005985 scoped_ptr<float[]> data(new float[size]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005986 const int32* src = reinterpret_cast<const int32 *>(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005987 attrib->buffer()->GetRange(attrib->offset(), size));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005988 const int32* end = src + num_elements;
5989 float* dst = data.get();
5990 while (src != end) {
5991 *dst++ = static_cast<float>(*src++) / 65536.0f;
5992 }
5993 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
5994 glVertexAttribPointer(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005995 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005996 reinterpret_cast<GLvoid*>(offset));
5997 offset += size;
5998 }
5999 }
6000 *simulated = true;
6001 return true;
6002}
6003
6004void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
6005 // There's no need to call glVertexAttribPointer because we shadow all the
6006 // settings and passing GL_FIXED to it will not work.
6007 glBindBuffer(
6008 GL_ARRAY_BUFFER,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01006009 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
6010 : 0);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006011}
6012
6013error::Error GLES2DecoderImpl::DoDrawArrays(
6014 const char* function_name,
6015 bool instanced,
6016 GLenum mode,
6017 GLint first,
6018 GLsizei count,
6019 GLsizei primcount) {
6020 if (ShouldDeferDraws())
6021 return error::kDeferCommandUntilLater;
6022 if (!validators_->draw_mode.IsValid(mode)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006023 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006024 return error::kNoError;
6025 }
6026 if (count < 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006027 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006028 return error::kNoError;
6029 }
6030 if (primcount < 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006031 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006032 return error::kNoError;
6033 }
6034 if (!CheckBoundFramebuffersValid(function_name)) {
6035 return error::kNoError;
6036 }
6037 // We have to check this here because the prototype for glDrawArrays
6038 // is GLint not GLsizei.
6039 if (first < 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006040 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006041 return error::kNoError;
6042 }
6043
6044 if (count == 0 || (instanced && primcount == 0)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006045 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006046 return error::kNoError;
6047 }
6048
6049 GLuint max_vertex_accessed = first + count - 1;
6050 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6051 if (!ClearUnclearedTextures()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006052 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006053 return error::kNoError;
6054 }
6055 bool simulated_attrib_0 = false;
6056 if (!SimulateAttrib0(
6057 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6058 return error::kNoError;
6059 }
6060 bool simulated_fixed_attribs = false;
6061 if (SimulateFixedAttribs(
6062 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6063 primcount)) {
Ben Murdoch558790d2013-07-30 15:19:42 +01006064 bool textures_set = !PrepareTexturesForRender();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006065 ApplyDirtyState();
6066 if (!instanced) {
6067 glDrawArrays(mode, first, count);
6068 } else {
6069 glDrawArraysInstancedANGLE(mode, first, count, primcount);
6070 }
6071 ProcessPendingQueries();
6072 if (textures_set) {
6073 RestoreStateForNonRenderableTextures();
6074 }
6075 if (simulated_fixed_attribs) {
6076 RestoreStateForSimulatedFixedAttribs();
6077 }
6078 }
6079 if (simulated_attrib_0) {
6080 RestoreStateForAttrib(0);
6081 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006082 }
6083 return error::kNoError;
6084}
6085
6086error::Error GLES2DecoderImpl::HandleDrawArrays(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006087 uint32 immediate_data_size, const cmds::DrawArrays& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006088 return DoDrawArrays("glDrawArrays",
6089 false,
6090 static_cast<GLenum>(c.mode),
6091 static_cast<GLint>(c.first),
6092 static_cast<GLsizei>(c.count),
6093 0);
6094}
6095
6096error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006097 uint32 immediate_data_size, const cmds::DrawArraysInstancedANGLE& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006098 if (!features().angle_instanced_arrays) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006099 LOCAL_SET_GL_ERROR(
6100 GL_INVALID_OPERATION,
6101 "glDrawArraysInstancedANGLE", "function not available");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006102 return error::kNoError;
6103 }
6104 return DoDrawArrays("glDrawArraysIntancedANGLE",
6105 true,
6106 static_cast<GLenum>(c.mode),
6107 static_cast<GLint>(c.first),
6108 static_cast<GLsizei>(c.count),
6109 static_cast<GLsizei>(c.primcount));
6110}
6111
6112error::Error GLES2DecoderImpl::DoDrawElements(
6113 const char* function_name,
6114 bool instanced,
6115 GLenum mode,
6116 GLsizei count,
6117 GLenum type,
6118 int32 offset,
6119 GLsizei primcount) {
6120 if (ShouldDeferDraws())
6121 return error::kDeferCommandUntilLater;
6122 if (!state_.vertex_attrib_manager->element_array_buffer()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006123 LOCAL_SET_GL_ERROR(
6124 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006125 return error::kNoError;
6126 }
6127
6128 if (count < 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006129 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006130 return error::kNoError;
6131 }
6132 if (offset < 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006133 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006134 return error::kNoError;
6135 }
6136 if (!validators_->draw_mode.IsValid(mode)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006137 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006138 return error::kNoError;
6139 }
6140 if (!validators_->index_type.IsValid(type)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006141 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006142 return error::kNoError;
6143 }
6144 if (primcount < 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006145 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006146 return error::kNoError;
6147 }
6148
6149 if (!CheckBoundFramebuffersValid(function_name)) {
6150 return error::kNoError;
6151 }
6152
6153 if (count == 0 || (instanced && primcount == 0)) {
6154 return error::kNoError;
6155 }
6156
6157 GLuint max_vertex_accessed;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006158 Buffer* element_array_buffer =
6159 state_.vertex_attrib_manager->element_array_buffer();
6160
6161 if (!element_array_buffer->GetMaxValueForRange(
6162 offset, count, type, &max_vertex_accessed)) {
6163 LOCAL_SET_GL_ERROR(
6164 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006165 return error::kNoError;
6166 }
6167
6168 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
6169 if (!ClearUnclearedTextures()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006170 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006171 return error::kNoError;
6172 }
6173 bool simulated_attrib_0 = false;
6174 if (!SimulateAttrib0(
6175 function_name, max_vertex_accessed, &simulated_attrib_0)) {
6176 return error::kNoError;
6177 }
6178 bool simulated_fixed_attribs = false;
6179 if (SimulateFixedAttribs(
6180 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6181 primcount)) {
Ben Murdoch558790d2013-07-30 15:19:42 +01006182 bool textures_set = !PrepareTexturesForRender();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006183 ApplyDirtyState();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006184 // TODO(gman): Refactor to hide these details in BufferManager or
6185 // VertexAttribManager.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006186 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006187 bool used_client_side_array = false;
6188 if (element_array_buffer->IsClientSideArray()) {
6189 used_client_side_array = true;
6190 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6191 indices = element_array_buffer->GetRange(offset, 0);
6192 }
6193
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006194 if (!instanced) {
6195 glDrawElements(mode, count, type, indices);
6196 } else {
6197 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6198 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006199
6200 if (used_client_side_array) {
6201 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6202 element_array_buffer->service_id());
6203 }
6204
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006205 ProcessPendingQueries();
6206 if (textures_set) {
6207 RestoreStateForNonRenderableTextures();
6208 }
6209 if (simulated_fixed_attribs) {
6210 RestoreStateForSimulatedFixedAttribs();
6211 }
6212 }
6213 if (simulated_attrib_0) {
6214 RestoreStateForAttrib(0);
6215 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006216 }
6217 return error::kNoError;
6218}
6219
6220error::Error GLES2DecoderImpl::HandleDrawElements(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006221 uint32 immediate_data_size, const cmds::DrawElements& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006222 return DoDrawElements("glDrawElements",
6223 false,
6224 static_cast<GLenum>(c.mode),
6225 static_cast<GLsizei>(c.count),
6226 static_cast<GLenum>(c.type),
6227 static_cast<int32>(c.index_offset),
6228 0);
6229}
6230
6231error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006232 uint32 immediate_data_size, const cmds::DrawElementsInstancedANGLE& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006233 if (!features().angle_instanced_arrays) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006234 LOCAL_SET_GL_ERROR(
6235 GL_INVALID_OPERATION,
6236 "glDrawElementsInstancedANGLE", "function not available");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006237 return error::kNoError;
6238 }
6239 return DoDrawElements("glDrawElementsInstancedANGLE",
6240 true,
6241 static_cast<GLenum>(c.mode),
6242 static_cast<GLsizei>(c.count),
6243 static_cast<GLenum>(c.type),
6244 static_cast<int32>(c.index_offset),
6245 static_cast<GLsizei>(c.primcount));
6246}
6247
6248GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
6249 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
6250 GLuint max_vertex_accessed = 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006251 Buffer* buffer = GetBuffer(buffer_id);
6252 if (!buffer) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006253 // TODO(gman): Should this be a GL error or a command buffer error?
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006254 LOCAL_SET_GL_ERROR(
6255 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006256 } else {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006257 if (!buffer->GetMaxValueForRange(
6258 offset, count, type, &max_vertex_accessed)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006259 // TODO(gman): Should this be a GL error or a command buffer error?
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006260 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006261 GL_INVALID_OPERATION,
6262 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
6263 }
6264 }
6265 return max_vertex_accessed;
6266}
6267
6268// Calls glShaderSource for the various versions of the ShaderSource command.
6269// Assumes that data / data_size points to a piece of memory that is in range
6270// of whatever context it came from (shared memory, immediate memory, bucket
6271// memory.)
6272error::Error GLES2DecoderImpl::ShaderSourceHelper(
6273 GLuint client_id, const char* data, uint32 data_size) {
6274 std::string str(data, data + data_size);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006275 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
6276 if (!shader) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006277 return error::kNoError;
6278 }
6279 // Note: We don't actually call glShaderSource here. We wait until
6280 // the call to glCompileShader.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006281 shader->UpdateSource(str.c_str());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006282 return error::kNoError;
6283}
6284
6285error::Error GLES2DecoderImpl::HandleShaderSource(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006286 uint32 immediate_data_size, const cmds::ShaderSource& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006287 uint32 data_size = c.data_size;
6288 const char* data = GetSharedMemoryAs<const char*>(
6289 c.data_shm_id, c.data_shm_offset, data_size);
6290 if (!data) {
6291 return error::kOutOfBounds;
6292 }
6293 return ShaderSourceHelper(c.shader, data, data_size);
6294}
6295
6296error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006297 uint32 immediate_data_size, const cmds::ShaderSourceImmediate& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006298 uint32 data_size = c.data_size;
6299 const char* data = GetImmediateDataAs<const char*>(
6300 c, data_size, immediate_data_size);
6301 if (!data) {
6302 return error::kOutOfBounds;
6303 }
6304 return ShaderSourceHelper(c.shader, data, data_size);
6305}
6306
6307error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006308 uint32 immediate_data_size, const cmds::ShaderSourceBucket& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006309 Bucket* bucket = GetBucket(c.data_bucket_id);
6310 if (!bucket || bucket->size() == 0) {
6311 return error::kInvalidArguments;
6312 }
6313 return ShaderSourceHelper(
6314 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
6315 bucket->size() - 1);
6316}
6317
6318void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
6319 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006320 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
6321 if (!shader) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006322 return;
6323 }
6324 ShaderTranslator* translator = NULL;
6325 if (use_shader_translator_) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006326 translator = shader->shader_type() == GL_VERTEX_SHADER ?
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006327 vertex_translator_.get() : fragment_translator_.get();
6328 }
6329
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01006330 program_manager()->DoCompileShader(shader, translator, feature_info_.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006331};
6332
6333void GLES2DecoderImpl::DoGetShaderiv(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006334 GLuint shader_id, GLenum pname, GLint* params) {
6335 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
6336 if (!shader) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006337 return;
6338 }
6339 switch (pname) {
6340 case GL_SHADER_SOURCE_LENGTH:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006341 *params = shader->source() ? shader->source()->size() + 1 : 0;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006342 return;
6343 case GL_COMPILE_STATUS:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006344 *params = compile_shader_always_succeeds_ ? true : shader->IsValid();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006345 return;
6346 case GL_INFO_LOG_LENGTH:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006347 *params = shader->log_info() ? shader->log_info()->size() + 1 : 0;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006348 return;
6349 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006350 *params = shader->translated_source() ?
6351 shader->translated_source()->size() + 1 : 0;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006352 return;
6353 default:
6354 break;
6355 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006356 glGetShaderiv(shader->service_id(), pname, params);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006357}
6358
6359error::Error GLES2DecoderImpl::HandleGetShaderSource(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006360 uint32 immediate_data_size, const cmds::GetShaderSource& c) {
6361 GLuint shader_id = c.shader;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006362 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6363 Bucket* bucket = CreateBucket(bucket_id);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006364 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
6365 if (!shader || !shader->source()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006366 bucket->SetSize(0);
6367 return error::kNoError;
6368 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006369 bucket->SetFromString(shader->source()->c_str());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006370 return error::kNoError;
6371}
6372
6373error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6374 uint32 immediate_data_size,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006375 const cmds::GetTranslatedShaderSourceANGLE& c) {
6376 GLuint shader_id = c.shader;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006377 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6378 Bucket* bucket = CreateBucket(bucket_id);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006379 Shader* shader = GetShaderInfoNotProgram(
6380 shader_id, "glTranslatedGetShaderSourceANGLE");
6381 if (!shader) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006382 bucket->SetSize(0);
6383 return error::kNoError;
6384 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006385
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006386 bucket->SetFromString(shader->translated_source() ?
6387 shader->translated_source()->c_str() : NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006388 return error::kNoError;
6389}
6390
6391error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006392 uint32 immediate_data_size, const cmds::GetProgramInfoLog& c) {
6393 GLuint program_id = c.program;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006394 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6395 Bucket* bucket = CreateBucket(bucket_id);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006396 Program* program = GetProgramInfoNotShader(
6397 program_id, "glGetProgramInfoLog");
6398 if (!program || !program->log_info()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006399 bucket->SetFromString("");
6400 return error::kNoError;
6401 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006402 bucket->SetFromString(program->log_info()->c_str());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006403 return error::kNoError;
6404}
6405
6406error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006407 uint32 immediate_data_size, const cmds::GetShaderInfoLog& c) {
6408 GLuint shader_id = c.shader;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006409 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6410 Bucket* bucket = CreateBucket(bucket_id);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006411 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
6412 if (!shader || !shader->log_info()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006413 bucket->SetFromString("");
6414 return error::kNoError;
6415 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006416 bucket->SetFromString(shader->log_info()->c_str());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006417 return error::kNoError;
6418}
6419
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006420bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
6421 return state_.GetEnabled(cap);
6422}
6423
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006424bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006425 const Buffer* buffer = GetBuffer(client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006426 return buffer && buffer->IsValid() && !buffer->IsDeleted();
6427}
6428
6429bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006430 const Framebuffer* framebuffer =
6431 GetFramebuffer(client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006432 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
6433}
6434
6435bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
6436 // IsProgram is true for programs as soon as they are created, until they are
6437 // deleted and no longer in use.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006438 const Program* program = GetProgram(client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006439 return program != NULL && !program->IsDeleted();
6440}
6441
6442bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006443 const Renderbuffer* renderbuffer =
6444 GetRenderbuffer(client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006445 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
6446}
6447
6448bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
6449 // IsShader is true for shaders as soon as they are created, until they
6450 // are deleted and not attached to any programs.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006451 const Shader* shader = GetShader(client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006452 return shader != NULL && !shader->IsDeleted();
6453}
6454
6455bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01006456 const TextureRef* texture_ref = GetTexture(client_id);
6457 return texture_ref && texture_ref->texture()->IsValid();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006458}
6459
6460void GLES2DecoderImpl::DoAttachShader(
6461 GLuint program_client_id, GLint shader_client_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006462 Program* program = GetProgramInfoNotShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006463 program_client_id, "glAttachShader");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006464 if (!program) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006465 return;
6466 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006467 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
6468 if (!shader) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006469 return;
6470 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006471 if (!program->AttachShader(shader_manager(), shader)) {
6472 LOCAL_SET_GL_ERROR(
6473 GL_INVALID_OPERATION,
6474 "glAttachShader",
6475 "can not attach more than one shader of the same type.");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006476 return;
6477 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006478 glAttachShader(program->service_id(), shader->service_id());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006479}
6480
6481void GLES2DecoderImpl::DoDetachShader(
6482 GLuint program_client_id, GLint shader_client_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006483 Program* program = GetProgramInfoNotShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006484 program_client_id, "glDetachShader");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006485 if (!program) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006486 return;
6487 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006488 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
6489 if (!shader) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006490 return;
6491 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006492 if (!program->DetachShader(shader_manager(), shader)) {
6493 LOCAL_SET_GL_ERROR(
6494 GL_INVALID_OPERATION,
6495 "glDetachShader", "shader not attached to program");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006496 return;
6497 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006498 glDetachShader(program->service_id(), shader->service_id());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006499}
6500
6501void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006502 Program* program = GetProgramInfoNotShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006503 program_client_id, "glValidateProgram");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006504 if (!program) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006505 return;
6506 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006507 program->Validate();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006508}
6509
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006510void GLES2DecoderImpl::GetVertexAttribHelper(
6511 const VertexAttrib* attrib, GLenum pname, GLint* params) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006512 switch (pname) {
6513 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006514 Buffer* buffer = attrib->buffer();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006515 if (buffer && !buffer->IsDeleted()) {
6516 GLuint client_id;
6517 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
6518 *params = client_id;
6519 }
6520 break;
6521 }
6522 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006523 *params = attrib->enabled();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006524 break;
6525 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006526 *params = attrib->size();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006527 break;
6528 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006529 *params = attrib->gl_stride();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006530 break;
6531 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006532 *params = attrib->type();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006533 break;
6534 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006535 *params = attrib->normalized();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006536 break;
6537 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006538 *params = attrib->divisor();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006539 break;
6540 default:
6541 NOTREACHED();
6542 break;
6543 }
6544}
6545
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006546void GLES2DecoderImpl::DoGetVertexAttribfv(
6547 GLuint index, GLenum pname, GLfloat* params) {
6548 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6549 if (!attrib) {
6550 LOCAL_SET_GL_ERROR(
6551 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006552 return;
6553 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006554 switch (pname) {
6555 case GL_CURRENT_VERTEX_ATTRIB: {
6556 const Vec4& value = state_.attrib_values[index];
6557 params[0] = value.v[0];
6558 params[1] = value.v[1];
6559 params[2] = value.v[2];
6560 params[3] = value.v[3];
6561 break;
6562 }
6563 default: {
6564 GLint value = 0;
6565 GetVertexAttribHelper(attrib, pname, &value);
6566 *params = static_cast<GLfloat>(value);
6567 break;
6568 }
6569 }
6570}
6571
6572void GLES2DecoderImpl::DoGetVertexAttribiv(
6573 GLuint index, GLenum pname, GLint* params) {
6574 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6575 if (!attrib) {
6576 LOCAL_SET_GL_ERROR(
6577 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
6578 return;
6579 }
6580 switch (pname) {
6581 case GL_CURRENT_VERTEX_ATTRIB: {
6582 const Vec4& value = state_.attrib_values[index];
6583 params[0] = static_cast<GLint>(value.v[0]);
6584 params[1] = static_cast<GLint>(value.v[1]);
6585 params[2] = static_cast<GLint>(value.v[2]);
6586 params[3] = static_cast<GLint>(value.v[3]);
6587 break;
6588 }
6589 default:
6590 GetVertexAttribHelper(attrib, pname, params);
6591 break;
6592 }
6593}
6594
6595bool GLES2DecoderImpl::SetVertexAttribValue(
6596 const char* function_name, GLuint index, const GLfloat* value) {
6597 if (index >= state_.attrib_values.size()) {
6598 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
6599 return false;
6600 }
6601 Vec4& v = state_.attrib_values[index];
6602 v.v[0] = value[0];
6603 v.v[1] = value[1];
6604 v.v[2] = value[2];
6605 v.v[3] = value[3];
6606 return true;
6607}
6608
6609void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
6610 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
6611 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
6612 glVertexAttrib1f(index, v0);
6613 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006614}
6615
6616void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006617 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
6618 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
6619 glVertexAttrib2f(index, v0, v1);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006620 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006621}
6622
6623void GLES2DecoderImpl::DoVertexAttrib3f(
6624 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006625 GLfloat v[4] = { v0, v1, v2, 1.0f, };
6626 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
6627 glVertexAttrib3f(index, v0, v1, v2);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006628 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006629}
6630
6631void GLES2DecoderImpl::DoVertexAttrib4f(
6632 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006633 GLfloat v[4] = { v0, v1, v2, v3, };
6634 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
6635 glVertexAttrib4f(index, v0, v1, v2, v3);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006636 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006637}
6638
6639void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006640 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
6641 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
6642 glVertexAttrib1fv(index, v);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006643 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006644}
6645
6646void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006647 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
6648 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
6649 glVertexAttrib2fv(index, v);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006650 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006651}
6652
6653void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006654 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
6655 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
6656 glVertexAttrib3fv(index, v);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006657 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006658}
6659
6660void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006661 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
6662 glVertexAttrib4fv(index, v);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006663 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006664}
6665
6666error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006667 uint32 immediate_data_size, const cmds::VertexAttribPointer& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006668
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01006669 if (!state_.bound_array_buffer.get() ||
6670 state_.bound_array_buffer->IsDeleted()) {
6671 if (state_.vertex_attrib_manager.get() ==
6672 default_vertex_attrib_manager_.get()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006673 LOCAL_SET_GL_ERROR(
6674 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006675 return error::kNoError;
6676 } else if (c.offset != 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006677 LOCAL_SET_GL_ERROR(
6678 GL_INVALID_VALUE,
6679 "glVertexAttribPointer", "client side arrays are not allowed");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006680 return error::kNoError;
6681 }
6682 }
6683
6684 GLuint indx = c.indx;
6685 GLint size = c.size;
6686 GLenum type = c.type;
6687 GLboolean normalized = c.normalized;
6688 GLsizei stride = c.stride;
6689 GLsizei offset = c.offset;
6690 const void* ptr = reinterpret_cast<const void*>(offset);
6691 if (!validators_->vertex_attrib_type.IsValid(type)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006692 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006693 return error::kNoError;
6694 }
6695 if (!validators_->vertex_attrib_size.IsValid(size)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006696 LOCAL_SET_GL_ERROR(
6697 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006698 return error::kNoError;
6699 }
6700 if (indx >= group_->max_vertex_attribs()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006701 LOCAL_SET_GL_ERROR(
6702 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006703 return error::kNoError;
6704 }
6705 if (stride < 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006706 LOCAL_SET_GL_ERROR(
6707 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006708 return error::kNoError;
6709 }
6710 if (stride > 255) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006711 LOCAL_SET_GL_ERROR(
6712 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006713 return error::kNoError;
6714 }
6715 if (offset < 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006716 LOCAL_SET_GL_ERROR(
6717 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006718 return error::kNoError;
6719 }
6720 GLsizei component_size =
6721 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
6722 if (offset % component_size > 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006723 LOCAL_SET_GL_ERROR(
6724 GL_INVALID_OPERATION,
6725 "glVertexAttribPointer", "offset not valid for type");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006726 return error::kNoError;
6727 }
6728 if (stride % component_size > 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006729 LOCAL_SET_GL_ERROR(
6730 GL_INVALID_OPERATION,
6731 "glVertexAttribPointer", "stride not valid for type");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006732 return error::kNoError;
6733 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01006734 state_.vertex_attrib_manager
6735 ->SetAttribInfo(indx,
6736 state_.bound_array_buffer.get(),
6737 size,
6738 type,
6739 normalized,
6740 stride,
6741 stride != 0 ? stride : component_size * size,
6742 offset);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006743 if (type != GL_FIXED) {
6744 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
6745 }
6746 return error::kNoError;
6747}
6748
6749void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
6750 GLsizei height) {
6751 state_.viewport_x = x;
6752 state_.viewport_y = y;
6753 state_.viewport_width = std::min(width, viewport_max_width_);
6754 state_.viewport_height = std::min(height, viewport_max_height_);
6755 glViewport(x, y, width, height);
6756}
6757
6758error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006759 uint32 immediate_data_size, const cmds::VertexAttribDivisorANGLE& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006760 if (!features().angle_instanced_arrays) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006761 LOCAL_SET_GL_ERROR(
6762 GL_INVALID_OPERATION,
6763 "glVertexAttribDivisorANGLE", "function not available");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006764 }
6765 GLuint index = c.index;
6766 GLuint divisor = c.divisor;
6767 if (index >= group_->max_vertex_attribs()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006768 LOCAL_SET_GL_ERROR(
6769 GL_INVALID_VALUE,
6770 "glVertexAttribDivisorANGLE", "index out of range");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006771 return error::kNoError;
6772 }
6773
6774 state_.vertex_attrib_manager->SetDivisor(
6775 index,
6776 divisor);
6777 glVertexAttribDivisorANGLE(index, divisor);
6778 return error::kNoError;
6779}
6780
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01006781void GLES2DecoderImpl::FinishReadPixels(
6782 const cmds::ReadPixels& c,
6783 GLuint buffer) {
6784 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
6785 GLsizei width = c.width;
6786 GLsizei height = c.height;
6787 GLenum format = c.format;
6788 GLenum type = c.type;
6789 typedef cmds::ReadPixels::Result Result;
6790 uint32 pixels_size;
6791 Result* result = NULL;
6792 if (c.result_shm_id != 0) {
6793 result = GetSharedMemoryAs<Result*>(
6794 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6795 if (!result) {
6796 if (buffer != 0) {
6797 glDeleteBuffersARB(1, &buffer);
6798 }
6799 return;
6800 }
6801 }
6802 GLES2Util::ComputeImageDataSizes(
6803 width, height, format, type, state_.pack_alignment, &pixels_size,
6804 NULL, NULL);
6805 void* pixels = GetSharedMemoryAs<void*>(
6806 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
6807 if (!pixels) {
6808 if (buffer != 0) {
6809 glDeleteBuffersARB(1, &buffer);
6810 }
6811 return;
6812 }
6813
6814 if (buffer != 0) {
6815 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
6816 void* data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
6817 memcpy(pixels, data, pixels_size);
6818 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
6819 // have to restore the state.
6820 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
6821 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
6822 glDeleteBuffersARB(1, &buffer);
6823 }
6824
6825 if (result != NULL) {
6826 *result = true;
6827 }
6828
6829 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6830 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6831 if ((channels_exist & 0x0008) == 0 &&
6832 workarounds().clear_alpha_in_readpixels) {
6833 // Set the alpha to 255 because some drivers are buggy in this regard.
6834 uint32 temp_size;
6835
6836 uint32 unpadded_row_size;
6837 uint32 padded_row_size;
6838 if (!GLES2Util::ComputeImageDataSizes(
6839 width, 2, format, type, state_.pack_alignment, &temp_size,
6840 &unpadded_row_size, &padded_row_size)) {
6841 return;
6842 }
6843 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
6844 // of this implementation.
6845 if (type != GL_UNSIGNED_BYTE) {
6846 return;
6847 }
6848 switch (format) {
6849 case GL_RGBA:
6850 case GL_BGRA_EXT:
6851 case GL_ALPHA: {
6852 int offset = (format == GL_ALPHA) ? 0 : 3;
6853 int step = (format == GL_ALPHA) ? 1 : 4;
6854 uint8* dst = static_cast<uint8*>(pixels) + offset;
6855 for (GLint yy = 0; yy < height; ++yy) {
6856 uint8* end = dst + unpadded_row_size;
6857 for (uint8* d = dst; d < end; d += step) {
6858 *d = 255;
6859 }
6860 dst += padded_row_size;
6861 }
6862 break;
6863 }
6864 default:
6865 break;
6866 }
6867 }
6868}
6869
6870
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006871error::Error GLES2DecoderImpl::HandleReadPixels(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006872 uint32 immediate_data_size, const cmds::ReadPixels& c) {
6873 if (ShouldDeferReads())
6874 return error::kDeferCommandUntilLater;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006875 GLint x = c.x;
6876 GLint y = c.y;
6877 GLsizei width = c.width;
6878 GLsizei height = c.height;
6879 GLenum format = c.format;
6880 GLenum type = c.type;
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01006881 GLboolean async = c.async;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006882 if (width < 0 || height < 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006883 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006884 return error::kNoError;
6885 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006886 typedef cmds::ReadPixels::Result Result;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006887 uint32 pixels_size;
6888 if (!GLES2Util::ComputeImageDataSizes(
6889 width, height, format, type, state_.pack_alignment, &pixels_size,
6890 NULL, NULL)) {
6891 return error::kOutOfBounds;
6892 }
6893 void* pixels = GetSharedMemoryAs<void*>(
6894 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006895 if (!pixels) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006896 return error::kOutOfBounds;
6897 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006898 Result* result = NULL;
6899 if (c.result_shm_id != 0) {
6900 result = GetSharedMemoryAs<Result*>(
6901 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6902 if (!result) {
6903 return error::kOutOfBounds;
6904 }
6905 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006906
6907 if (!validators_->read_pixel_format.IsValid(format)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006908 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006909 return error::kNoError;
6910 }
6911 if (!validators_->pixel_type.IsValid(type)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006912 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006913 return error::kNoError;
6914 }
6915 if (width == 0 || height == 0) {
6916 return error::kNoError;
6917 }
6918
6919 // Get the size of the current fbo or backbuffer.
6920 gfx::Size max_size = GetBoundReadFrameBufferSize();
6921
6922 int32 max_x;
6923 int32 max_y;
6924 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006925 LOCAL_SET_GL_ERROR(
6926 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006927 return error::kNoError;
6928 }
6929
6930 if (!CheckBoundFramebuffersValid("glReadPixels")) {
6931 return error::kNoError;
6932 }
6933
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006934 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixel");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006935
6936 ScopedResolvedFrameBufferBinder binder(this, false, true);
6937
6938 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
6939 // The user requested an out of range area. Get the results 1 line
6940 // at a time.
6941 uint32 temp_size;
6942 uint32 unpadded_row_size;
6943 uint32 padded_row_size;
6944 if (!GLES2Util::ComputeImageDataSizes(
6945 width, 2, format, type, state_.pack_alignment, &temp_size,
6946 &unpadded_row_size, &padded_row_size)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006947 LOCAL_SET_GL_ERROR(
6948 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006949 return error::kNoError;
6950 }
6951
6952 GLint dest_x_offset = std::max(-x, 0);
6953 uint32 dest_row_offset;
6954 if (!GLES2Util::ComputeImageDataSizes(
6955 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
6956 NULL, NULL)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006957 LOCAL_SET_GL_ERROR(
6958 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006959 return error::kNoError;
6960 }
6961
6962 // Copy each row into the larger dest rect.
6963 int8* dst = static_cast<int8*>(pixels);
6964 GLint read_x = std::max(0, x);
6965 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
6966 GLint read_width = read_end_x - read_x;
6967 for (GLint yy = 0; yy < height; ++yy) {
6968 GLint ry = y + yy;
6969
6970 // Clear the row.
6971 memset(dst, 0, unpadded_row_size);
6972
6973 // If the row is in range, copy it.
6974 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
6975 glReadPixels(
6976 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
6977 }
6978 dst += padded_row_size;
6979 }
6980 } else {
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01006981 if (async && features().use_async_readpixels) {
6982 GLuint buffer;
6983 glGenBuffersARB(1, &buffer);
6984 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
6985 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
6986 GLenum error = glGetError();
6987 if (error == GL_NO_ERROR) {
6988 glReadPixels(x, y, width, height, format, type, 0);
6989 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
6990 new FenceCallback()));
6991 WaitForReadPixels(base::Bind(
6992 &GLES2DecoderImpl::FinishReadPixels,
6993 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
6994 <GLES2DecoderImpl>(this),
6995 c, buffer));
6996 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
6997 return error::kNoError;
6998 }
6999 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007000 glReadPixels(x, y, width, height, format, type, pixels);
7001 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007002 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007003 if (error == GL_NO_ERROR) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01007004 if (result != NULL) {
7005 *result = true;
7006 }
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01007007 FinishReadPixels(c, 0);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007008 }
7009
7010 return error::kNoError;
7011}
7012
7013error::Error GLES2DecoderImpl::HandlePixelStorei(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007014 uint32 immediate_data_size, const cmds::PixelStorei& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007015 GLenum pname = c.pname;
7016 GLenum param = c.param;
7017 if (!validators_->pixel_store.IsValid(pname)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007018 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007019 return error::kNoError;
7020 }
7021 switch (pname) {
7022 case GL_PACK_ALIGNMENT:
7023 case GL_UNPACK_ALIGNMENT:
7024 if (!validators_->pixel_store_alignment.IsValid(param)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007025 LOCAL_SET_GL_ERROR(
7026 GL_INVALID_VALUE, "glPixelStore", "param GL_INVALID_VALUE");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007027 return error::kNoError;
7028 }
7029 break;
7030 case GL_UNPACK_FLIP_Y_CHROMIUM:
7031 unpack_flip_y_ = (param != 0);
7032 return error::kNoError;
7033 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
7034 unpack_premultiply_alpha_ = (param != 0);
7035 return error::kNoError;
7036 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
7037 unpack_unpremultiply_alpha_ = (param != 0);
7038 return error::kNoError;
7039 default:
7040 break;
7041 }
7042 glPixelStorei(pname, param);
7043 switch (pname) {
7044 case GL_PACK_ALIGNMENT:
7045 state_.pack_alignment = param;
7046 break;
7047 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
7048 state_.pack_reverse_row_order = (param != 0);
7049 break;
7050 case GL_UNPACK_ALIGNMENT:
7051 state_.unpack_alignment = param;
7052 break;
7053 default:
7054 // Validation should have prevented us from getting here.
7055 NOTREACHED();
7056 break;
7057 }
7058 return error::kNoError;
7059}
7060
7061error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007062 uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007063 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
7064 if (!surface_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007065 LOCAL_SET_GL_ERROR(
7066 GL_INVALID_OPERATION,
7067 "glPostSubBufferCHROMIUM", "command not supported by surface");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007068 return error::kNoError;
7069 }
7070 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
7071 return error::kNoError;
7072 } else {
7073 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
7074 return error::kLostContext;
7075 }
7076}
7077
7078error::Error GLES2DecoderImpl::GetAttribLocationHelper(
7079 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7080 const std::string& name_str) {
7081 if (!StringIsValidForGLES(name_str.c_str())) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007082 LOCAL_SET_GL_ERROR(
7083 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007084 return error::kNoError;
7085 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007086 Program* program = GetProgramInfoNotShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007087 client_id, "glGetAttribLocation");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007088 if (!program) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007089 return error::kNoError;
7090 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007091 if (!program->IsValid()) {
7092 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007093 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
7094 return error::kNoError;
7095 }
7096 GLint* location = GetSharedMemoryAs<GLint*>(
7097 location_shm_id, location_shm_offset, sizeof(GLint));
7098 if (!location) {
7099 return error::kOutOfBounds;
7100 }
7101 // Require the client to init this incase the context is lost and we are no
7102 // longer executing commands.
7103 if (*location != -1) {
7104 return error::kGenericError;
7105 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007106 *location = program->GetAttribLocation(name_str);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007107 return error::kNoError;
7108}
7109
7110error::Error GLES2DecoderImpl::HandleGetAttribLocation(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007111 uint32 immediate_data_size, const cmds::GetAttribLocation& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007112 uint32 name_size = c.data_size;
7113 const char* name = GetSharedMemoryAs<const char*>(
7114 c.name_shm_id, c.name_shm_offset, name_size);
7115 if (!name) {
7116 return error::kOutOfBounds;
7117 }
7118 String name_str(name, name_size);
7119 return GetAttribLocationHelper(
7120 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7121}
7122
7123error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007124 uint32 immediate_data_size, const cmds::GetAttribLocationImmediate& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007125 uint32 name_size = c.data_size;
7126 const char* name = GetImmediateDataAs<const char*>(
7127 c, name_size, immediate_data_size);
7128 if (!name) {
7129 return error::kOutOfBounds;
7130 }
7131 String name_str(name, name_size);
7132 return GetAttribLocationHelper(
7133 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7134}
7135
7136error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007137 uint32 immediate_data_size, const cmds::GetAttribLocationBucket& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007138 Bucket* bucket = GetBucket(c.name_bucket_id);
7139 if (!bucket) {
7140 return error::kInvalidArguments;
7141 }
7142 std::string name_str;
7143 if (!bucket->GetAsString(&name_str)) {
7144 return error::kInvalidArguments;
7145 }
7146 return GetAttribLocationHelper(
7147 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7148}
7149
7150error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7151 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7152 const std::string& name_str) {
7153 if (!StringIsValidForGLES(name_str.c_str())) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007154 LOCAL_SET_GL_ERROR(
7155 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007156 return error::kNoError;
7157 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007158 Program* program = GetProgramInfoNotShader(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007159 client_id, "glUniformLocation");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007160 if (!program) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007161 return error::kNoError;
7162 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007163 if (!program->IsValid()) {
7164 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007165 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
7166 return error::kNoError;
7167 }
7168 GLint* location = GetSharedMemoryAs<GLint*>(
7169 location_shm_id, location_shm_offset, sizeof(GLint));
7170 if (!location) {
7171 return error::kOutOfBounds;
7172 }
7173 // Require the client to init this incase the context is lost an we are no
7174 // longer executing commands.
7175 if (*location != -1) {
7176 return error::kGenericError;
7177 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007178 *location = program->GetUniformFakeLocation(name_str);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007179 return error::kNoError;
7180}
7181
7182error::Error GLES2DecoderImpl::HandleGetUniformLocation(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007183 uint32 immediate_data_size, const cmds::GetUniformLocation& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007184 uint32 name_size = c.data_size;
7185 const char* name = GetSharedMemoryAs<const char*>(
7186 c.name_shm_id, c.name_shm_offset, name_size);
7187 if (!name) {
7188 return error::kOutOfBounds;
7189 }
7190 String name_str(name, name_size);
7191 return GetUniformLocationHelper(
7192 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7193}
7194
7195error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007196 uint32 immediate_data_size, const cmds::GetUniformLocationImmediate& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007197 uint32 name_size = c.data_size;
7198 const char* name = GetImmediateDataAs<const char*>(
7199 c, name_size, immediate_data_size);
7200 if (!name) {
7201 return error::kOutOfBounds;
7202 }
7203 String name_str(name, name_size);
7204 return GetUniformLocationHelper(
7205 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7206}
7207
7208error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007209 uint32 immediate_data_size, const cmds::GetUniformLocationBucket& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007210 Bucket* bucket = GetBucket(c.name_bucket_id);
7211 if (!bucket) {
7212 return error::kInvalidArguments;
7213 }
7214 std::string name_str;
7215 if (!bucket->GetAsString(&name_str)) {
7216 return error::kInvalidArguments;
7217 }
7218 return GetUniformLocationHelper(
7219 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7220}
7221
7222error::Error GLES2DecoderImpl::HandleGetString(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007223 uint32 immediate_data_size, const cmds::GetString& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007224 GLenum name = static_cast<GLenum>(c.name);
7225 if (!validators_->string_type.IsValid(name)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007226 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007227 return error::kNoError;
7228 }
7229 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
7230 const char* str = NULL;
7231 std::string extensions;
7232 switch (name) {
7233 case GL_VERSION:
7234 str = "OpenGL ES 2.0 Chromium";
7235 break;
7236 case GL_SHADING_LANGUAGE_VERSION:
7237 str = "OpenGL ES GLSL ES 1.0 Chromium";
7238 break;
7239 case GL_RENDERER:
7240 str = "Chromium";
7241 break;
7242 case GL_VENDOR:
7243 str = "Chromium";
7244 break;
7245 case GL_EXTENSIONS:
7246 {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01007247 // For WebGL contexts, strip out the OES derivatives and
7248 // EXT frag depth extensions if they have not been enabled.
7249 if (force_webgl_glsl_validation_) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007250 extensions = feature_info_->extensions();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01007251 if (!derivatives_explicitly_enabled_) {
7252 size_t offset = extensions.find(kOESDerivativeExtension);
7253 if (std::string::npos != offset) {
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01007254 extensions.replace(offset, arraysize(kOESDerivativeExtension),
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01007255 std::string());
7256 }
7257 }
7258 if (!frag_depth_explicitly_enabled_) {
7259 size_t offset = extensions.find(kEXTFragDepthExtension);
7260 if (std::string::npos != offset) {
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01007261 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01007262 std::string());
7263 }
7264 }
7265 if (!draw_buffers_explicitly_enabled_) {
7266 size_t offset = extensions.find(kEXTDrawBuffersExtension);
7267 if (std::string::npos != offset) {
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01007268 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01007269 std::string());
7270 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007271 }
7272 } else {
7273 extensions = feature_info_->extensions().c_str();
7274 }
7275 std::string surface_extensions = surface_->GetExtensions();
7276 if (!surface_extensions.empty())
7277 extensions += " " + surface_extensions;
7278 str = extensions.c_str();
7279 }
7280 break;
7281 default:
7282 str = gl_str;
7283 break;
7284 }
7285 Bucket* bucket = CreateBucket(c.bucket_id);
7286 bucket->SetFromString(str);
7287 return error::kNoError;
7288}
7289
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007290error::Error GLES2DecoderImpl::HandleBufferData(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007291 uint32 immediate_data_size, const cmds::BufferData& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007292 GLenum target = static_cast<GLenum>(c.target);
7293 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
7294 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7295 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7296 GLenum usage = static_cast<GLenum>(c.usage);
7297 const void* data = NULL;
7298 if (data_shm_id != 0 || data_shm_offset != 0) {
7299 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
7300 if (!data) {
7301 return error::kOutOfBounds;
7302 }
7303 }
Ben Murdoch9ab55632013-07-18 11:57:30 +01007304 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007305 return error::kNoError;
7306}
7307
7308error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007309 uint32 immediate_data_size, const cmds::BufferDataImmediate& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007310 GLenum target = static_cast<GLenum>(c.target);
7311 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
7312 const void* data = GetImmediateDataAs<const void*>(
7313 c, size, immediate_data_size);
7314 if (!data) {
7315 return error::kOutOfBounds;
7316 }
7317 GLenum usage = static_cast<GLenum>(c.usage);
Ben Murdoch9ab55632013-07-18 11:57:30 +01007318 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007319 return error::kNoError;
7320}
7321
7322void GLES2DecoderImpl::DoBufferSubData(
7323 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
Ben Murdoch9ab55632013-07-18 11:57:30 +01007324 // Just delegate it. Some validation is actually done before this.
7325 buffer_manager()->ValidateAndDoBufferSubData(
7326 &state_, target, offset, size, data);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007327}
7328
7329bool GLES2DecoderImpl::ClearLevel(
7330 unsigned service_id,
7331 unsigned bind_target,
7332 unsigned target,
7333 int level,
7334 unsigned format,
7335 unsigned type,
7336 int width,
7337 int height,
7338 bool is_texture_immutable) {
7339 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7340 if (IsAngle() && (channels & GLES2Util::kDepth) != 0) {
7341 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7342 // on depth formats.
7343 GLuint fb = 0;
7344 glGenFramebuffersEXT(1, &fb);
7345 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
7346
7347 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
7348 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
7349 GL_DEPTH_ATTACHMENT;
7350
7351 glFramebufferTexture2DEXT(
7352 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
7353 // ANGLE promises a depth only attachment ok.
7354 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
7355 GL_FRAMEBUFFER_COMPLETE) {
7356 return false;
7357 }
7358 glClearStencil(0);
7359 glStencilMask(-1);
7360 glClearDepth(1.0f);
7361 glDepthMask(true);
7362 glDisable(GL_SCISSOR_TEST);
7363 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
7364
7365 RestoreClearState();
7366
7367 glDeleteFramebuffersEXT(1, &fb);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007368 Framebuffer* framebuffer =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007369 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
7370 GLuint fb_service_id =
7371 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
7372 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
7373 return true;
7374 }
7375
7376 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
7377
7378 uint32 size;
7379 uint32 padded_row_size;
7380 if (!GLES2Util::ComputeImageDataSizes(
7381 width, height, format, type, state_.unpack_alignment, &size,
7382 NULL, &padded_row_size)) {
7383 return false;
7384 }
7385
7386 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
7387
7388 int tile_height;
7389
7390 if (size > kMaxZeroSize) {
7391 if (kMaxZeroSize < padded_row_size) {
7392 // That'd be an awfully large texture.
7393 return false;
7394 }
7395 // We should never have a large total size with a zero row size.
7396 DCHECK_GT(padded_row_size, 0U);
7397 tile_height = kMaxZeroSize / padded_row_size;
7398 if (!GLES2Util::ComputeImageDataSizes(
7399 width, tile_height, format, type, state_.unpack_alignment, &size,
7400 NULL, NULL)) {
7401 return false;
7402 }
7403 } else {
7404 tile_height = height;
7405 }
7406
7407 // Assumes the size has already been checked.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01007408 scoped_ptr<char[]> zero(new char[size]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007409 memset(zero.get(), 0, size);
7410 glBindTexture(bind_target, service_id);
7411
7412 GLint y = 0;
7413 while (y < height) {
7414 GLint h = y + tile_height > height ? height - y : tile_height;
7415 if (is_texture_immutable || h != height) {
7416 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
7417 } else {
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01007418 glTexImage2D(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007419 target, level, format, width, h, 0, format, type, zero.get());
7420 }
7421 y += tile_height;
7422 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01007423 TextureRef* texture = GetTextureInfoForTarget(bind_target);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007424 glBindTexture(bind_target, texture ? texture->service_id() : 0);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007425 return true;
7426}
7427
7428namespace {
7429
7430const int kS3TCBlockWidth = 4;
7431const int kS3TCBlockHeight = 4;
7432const int kS3TCDXT1BlockSize = 8;
7433const int kS3TCDXT3AndDXT5BlockSize = 16;
7434const int kETC1BlockWidth = 4;
7435const int kETC1BlockHeight = 4;
7436const int kETC1BlockSize = 8;
7437
7438bool IsValidDXTSize(GLint level, GLsizei size) {
7439 return (size == 1) ||
7440 (size == 2) || !(size % kS3TCBlockWidth);
7441}
7442
7443} // anonymous namespace.
7444
7445bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
7446 const char* function_name,
7447 GLsizei width, GLsizei height, GLenum format, size_t size) {
7448 unsigned int bytes_required = 0;
7449
7450 switch (format) {
7451 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7452 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: {
7453 int num_blocks_across =
7454 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7455 int num_blocks_down =
7456 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7457 int num_blocks = num_blocks_across * num_blocks_down;
7458 bytes_required = num_blocks * kS3TCDXT1BlockSize;
7459 break;
7460 }
7461 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7462 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7463 int num_blocks_across =
7464 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7465 int num_blocks_down =
7466 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7467 int num_blocks = num_blocks_across * num_blocks_down;
7468 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
7469 break;
7470 }
7471 case GL_ETC1_RGB8_OES: {
7472 int num_blocks_across =
7473 (width + kETC1BlockWidth - 1) / kETC1BlockWidth;
7474 int num_blocks_down =
7475 (height + kETC1BlockHeight - 1) / kETC1BlockHeight;
7476 int num_blocks = num_blocks_across * num_blocks_down;
7477 bytes_required = num_blocks * kETC1BlockSize;
7478 break;
7479 }
7480 default:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007481 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007482 return false;
7483 }
7484
7485 if (size != bytes_required) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007486 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007487 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
7488 return false;
7489 }
7490
7491 return true;
7492}
7493
7494bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7495 const char* function_name,
7496 GLint level, GLsizei width, GLsizei height, GLenum format) {
7497 switch (format) {
7498 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7499 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7500 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7501 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7502 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007503 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007504 GL_INVALID_OPERATION, function_name,
7505 "width or height invalid for level");
7506 return false;
7507 }
7508 return true;
7509 }
7510 case GL_ETC1_RGB8_OES:
7511 if (width <= 0 || height <= 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007512 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007513 GL_INVALID_OPERATION, function_name,
7514 "width or height invalid for level");
7515 return false;
7516 }
7517 return true;
7518 default:
7519 return false;
7520 }
7521}
7522
7523bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
7524 const char* function_name,
7525 GLenum target, GLint level, GLint xoffset, GLint yoffset,
7526 GLsizei width, GLsizei height, GLenum format,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007527 Texture* texture) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007528 if (xoffset < 0 || yoffset < 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007529 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007530 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
7531 return false;
7532 }
7533
7534 switch (format) {
7535 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7536 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7537 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7538 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7539 const int kBlockWidth = 4;
7540 const int kBlockHeight = 4;
7541 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007542 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007543 GL_INVALID_OPERATION, function_name,
7544 "xoffset or yoffset not multiple of 4");
7545 return false;
7546 }
7547 GLsizei tex_width = 0;
7548 GLsizei tex_height = 0;
7549 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
7550 width - xoffset > tex_width ||
7551 height - yoffset > tex_height) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007552 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007553 GL_INVALID_OPERATION, function_name, "dimensions out of range");
7554 return false;
7555 }
7556 return ValidateCompressedTexDimensions(
7557 function_name, level, width, height, format);
7558 }
7559 case GL_ETC1_RGB8_OES: {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007560 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007561 GL_INVALID_OPERATION, function_name,
7562 "TexsubImage2d not supported for ECT1_RGB8_OES textures");
7563 return false;
7564 }
7565 default:
7566 return false;
7567 }
7568}
7569
7570error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
7571 GLenum target,
7572 GLint level,
7573 GLenum internal_format,
7574 GLsizei width,
7575 GLsizei height,
7576 GLint border,
7577 GLsizei image_size,
7578 const void* data) {
7579 // TODO(gman): Validate image_size is correct for width, height and format.
7580 if (!validators_->texture_target.IsValid(target)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007581 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7582 "glCompressedTexImage2D", target, "target");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007583 return error::kNoError;
7584 }
7585 if (!validators_->compressed_texture_format.IsValid(
7586 internal_format)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007587 LOCAL_SET_GL_ERROR_INVALID_ENUM(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007588 "glCompressedTexImage2D", internal_format, "internal_format");
7589 return error::kNoError;
7590 }
7591 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
7592 border != 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007593 LOCAL_SET_GL_ERROR(
7594 GL_INVALID_VALUE,
7595 "glCompressedTexImage2D", "dimensions out of range");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007596 return error::kNoError;
7597 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01007598 TextureRef* texture_ref = GetTextureInfoForTarget(target);
7599 if (!texture_ref) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007600 LOCAL_SET_GL_ERROR(
7601 GL_INVALID_VALUE,
7602 "glCompressedTexImage2D", "unknown texture target");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007603 return error::kNoError;
7604 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01007605 Texture* texture = texture_ref->texture();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007606 if (texture->IsImmutable()) {
7607 LOCAL_SET_GL_ERROR(
7608 GL_INVALID_OPERATION,
7609 "glCompressedTexImage2D", "texture is immutable");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007610 return error::kNoError;
7611 }
7612
7613 if (!ValidateCompressedTexDimensions(
7614 "glCompressedTexImage2D", level, width, height, internal_format) ||
7615 !ValidateCompressedTexFuncData(
7616 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
7617 return error::kNoError;
7618 }
7619
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007620 if (!EnsureGPUMemoryAvailable(image_size)) {
7621 LOCAL_SET_GL_ERROR(
7622 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
7623 return error::kNoError;
7624 }
7625
7626 if (texture->IsAttachedToFramebuffer()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007627 clear_state_dirty_ = true;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007628 }
7629
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01007630 scoped_ptr<int8[]> zero;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007631 if (!data) {
7632 zero.reset(new int8[image_size]);
7633 memset(zero.get(), 0, image_size);
7634 data = zero.get();
7635 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007636 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007637 glCompressedTexImage2D(
7638 target, level, internal_format, width, height, border, image_size, data);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007639 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007640 if (error == GL_NO_ERROR) {
7641 texture_manager()->SetLevelInfo(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01007642 texture_ref, target, level, internal_format,
7643 width, height, 1, border, 0, 0, true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007644 }
7645 return error::kNoError;
7646}
7647
7648error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007649 uint32 immediate_data_size, const cmds::CompressedTexImage2D& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007650 GLenum target = static_cast<GLenum>(c.target);
7651 GLint level = static_cast<GLint>(c.level);
7652 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7653 GLsizei width = static_cast<GLsizei>(c.width);
7654 GLsizei height = static_cast<GLsizei>(c.height);
7655 GLint border = static_cast<GLint>(c.border);
7656 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
7657 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7658 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7659 const void* data = NULL;
7660 if (data_shm_id != 0 || data_shm_offset != 0) {
7661 data = GetSharedMemoryAs<const void*>(
7662 data_shm_id, data_shm_offset, image_size);
7663 if (!data) {
7664 return error::kOutOfBounds;
7665 }
7666 }
7667 return DoCompressedTexImage2D(
7668 target, level, internal_format, width, height, border, image_size, data);
7669}
7670
7671error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007672 uint32 immediate_data_size, const cmds::CompressedTexImage2DImmediate& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007673 GLenum target = static_cast<GLenum>(c.target);
7674 GLint level = static_cast<GLint>(c.level);
7675 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7676 GLsizei width = static_cast<GLsizei>(c.width);
7677 GLsizei height = static_cast<GLsizei>(c.height);
7678 GLint border = static_cast<GLint>(c.border);
7679 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
7680 const void* data = GetImmediateDataAs<const void*>(
7681 c, image_size, immediate_data_size);
7682 if (!data) {
7683 return error::kOutOfBounds;
7684 }
7685 return DoCompressedTexImage2D(
7686 target, level, internal_format, width, height, border, image_size, data);
7687}
7688
7689error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007690 uint32 immediate_data_size, const cmds::CompressedTexImage2DBucket& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007691 GLenum target = static_cast<GLenum>(c.target);
7692 GLint level = static_cast<GLint>(c.level);
7693 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7694 GLsizei width = static_cast<GLsizei>(c.width);
7695 GLsizei height = static_cast<GLsizei>(c.height);
7696 GLint border = static_cast<GLint>(c.border);
7697 Bucket* bucket = GetBucket(c.bucket_id);
7698 if (!bucket) {
7699 return error::kInvalidArguments;
7700 }
7701 uint32 data_size = bucket->size();
7702 GLsizei imageSize = data_size;
7703 const void* data = bucket->GetData(0, data_size);
7704 if (!data) {
7705 return error::kInvalidArguments;
7706 }
7707 return DoCompressedTexImage2D(
7708 target, level, internal_format, width, height, border,
7709 imageSize, data);
7710}
7711
7712error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
7713 uint32 immediate_data_size,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007714 const cmds::CompressedTexSubImage2DBucket& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007715 GLenum target = static_cast<GLenum>(c.target);
7716 GLint level = static_cast<GLint>(c.level);
7717 GLint xoffset = static_cast<GLint>(c.xoffset);
7718 GLint yoffset = static_cast<GLint>(c.yoffset);
7719 GLsizei width = static_cast<GLsizei>(c.width);
7720 GLsizei height = static_cast<GLsizei>(c.height);
7721 GLenum format = static_cast<GLenum>(c.format);
7722 Bucket* bucket = GetBucket(c.bucket_id);
7723 if (!bucket) {
7724 return error::kInvalidArguments;
7725 }
7726 uint32 data_size = bucket->size();
7727 GLsizei imageSize = data_size;
7728 const void* data = bucket->GetData(0, data_size);
7729 if (!data) {
7730 return error::kInvalidArguments;
7731 }
7732 if (!validators_->texture_target.IsValid(target)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007733 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007734 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
7735 return error::kNoError;
7736 }
7737 if (!validators_->compressed_texture_format.IsValid(format)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007738 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7739 "glCompressedTexSubImage2D", format, "format");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007740 return error::kNoError;
7741 }
7742 if (width < 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007743 LOCAL_SET_GL_ERROR(
7744 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007745 return error::kNoError;
7746 }
7747 if (height < 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007748 LOCAL_SET_GL_ERROR(
7749 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007750 return error::kNoError;
7751 }
7752 if (imageSize < 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007753 LOCAL_SET_GL_ERROR(
7754 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007755 return error::kNoError;
7756 }
7757 DoCompressedTexSubImage2D(
7758 target, level, xoffset, yoffset, width, height, format, imageSize, data);
7759 return error::kNoError;
7760}
7761
7762bool GLES2DecoderImpl::ValidateTextureParameters(
7763 const char* function_name,
7764 GLenum target, GLenum format, GLenum type, GLint level) {
7765 if (!feature_info_->GetTextureFormatValidator(format).IsValid(type)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007766 LOCAL_SET_GL_ERROR(
7767 GL_INVALID_OPERATION, function_name,
7768 (std::string("invalid type ") +
7769 GLES2Util::GetStringEnum(type) + " for format " +
7770 GLES2Util::GetStringEnum(format)).c_str());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007771 return false;
7772 }
7773
7774 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7775 if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007776 LOCAL_SET_GL_ERROR(
7777 GL_INVALID_OPERATION, function_name,
7778 (std::string("invalid type ") +
7779 GLES2Util::GetStringEnum(type) + " for format " +
7780 GLES2Util::GetStringEnum(format)).c_str());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007781 return false;
7782 }
7783 return true;
7784}
7785
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007786bool GLES2DecoderImpl::ValidateTexImage2D(
7787 const char* function_name,
7788 GLenum target,
7789 GLint level,
7790 GLenum internal_format,
7791 GLsizei width,
7792 GLsizei height,
7793 GLint border,
7794 GLenum format,
7795 GLenum type,
7796 const void* pixels,
7797 uint32 pixels_size) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007798 if (!validators_->texture_target.IsValid(target)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007799 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
7800 return false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007801 }
7802 if (!validators_->texture_format.IsValid(internal_format)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007803 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7804 function_name, internal_format, "internal_format");
7805 return false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007806 }
7807 if (!validators_->texture_format.IsValid(format)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007808 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
7809 return false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007810 }
7811 if (!validators_->pixel_type.IsValid(type)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007812 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
7813 return false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007814 }
7815 if (format != internal_format) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007816 LOCAL_SET_GL_ERROR(
7817 GL_INVALID_OPERATION, function_name, "format != internalFormat");
7818 return false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007819 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007820 if (!ValidateTextureParameters(function_name, target, format, type, level)) {
7821 return false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007822 }
7823 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
7824 border != 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007825 LOCAL_SET_GL_ERROR(
7826 GL_INVALID_VALUE, function_name, "dimensions out of range");
7827 return false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007828 }
7829 if ((GLES2Util::GetChannelsForFormat(format) &
7830 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && pixels) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007831 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007832 GL_INVALID_OPERATION,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007833 function_name, "can not supply data for depth or stencil textures");
7834 return false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007835 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01007836 TextureRef* texture_ref = GetTextureInfoForTarget(target);
7837 if (!texture_ref) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007838 LOCAL_SET_GL_ERROR(
7839 GL_INVALID_OPERATION, function_name, "unknown texture for target");
7840 return false;
7841 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01007842 if (texture_ref->texture()->IsImmutable()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007843 LOCAL_SET_GL_ERROR(
7844 GL_INVALID_OPERATION, function_name, "texture is immutable");
7845 return false;
7846 }
7847 return true;
7848}
7849
7850void GLES2DecoderImpl::DoTexImage2D(
7851 GLenum target,
7852 GLint level,
7853 GLenum internal_format,
7854 GLsizei width,
7855 GLsizei height,
7856 GLint border,
7857 GLenum format,
7858 GLenum type,
7859 const void* pixels,
7860 uint32 pixels_size) {
7861 if (!ValidateTexImage2D("glTexImage2D", target, level, internal_format,
7862 width, height, border, format, type, pixels, pixels_size)) {
7863 return;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007864 }
7865
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007866 if (!EnsureGPUMemoryAvailable(pixels_size)) {
7867 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexImage2D", "out of memory");
7868 return;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007869 }
7870
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01007871 TextureRef* texture_ref = GetTextureInfoForTarget(target);
7872 Texture* texture = texture_ref->texture();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007873 GLsizei tex_width = 0;
7874 GLsizei tex_height = 0;
7875 GLenum tex_type = 0;
7876 GLenum tex_format = 0;
7877 bool level_is_same =
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007878 texture->GetLevelSize(target, level, &tex_width, &tex_height) &&
7879 texture->GetLevelType(target, level, &tex_type, &tex_format) &&
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007880 width == tex_width && height == tex_height &&
7881 type == tex_type && format == tex_format;
7882
7883 if (level_is_same && !pixels) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007884 // Just set the level texture but mark the texture as uncleared.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007885 texture_manager()->SetLevelInfo(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01007886 texture_ref,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007887 target, level, internal_format, width, height, 1, border, format, type,
7888 false);
7889 tex_image_2d_failed_ = false;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007890 return;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007891 }
7892
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007893 if (texture->IsAttachedToFramebuffer()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007894 clear_state_dirty_ = true;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007895 }
7896
7897 if (!teximage2d_faster_than_texsubimage2d_ && level_is_same && pixels) {
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01007898 {
7899 ScopedTextureUploadTimer timer(this);
7900 glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
7901 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01007902 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007903 tex_image_2d_failed_ = false;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007904 return;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007905 }
7906
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007907 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexImage2D");
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01007908 {
7909 ScopedTextureUploadTimer timer(this);
7910 glTexImage2D(
7911 target, level, internal_format, width, height, border, format, type,
7912 pixels);
7913 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007914 GLenum error = LOCAL_PEEK_GL_ERROR("glTexImage2D");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007915 if (error == GL_NO_ERROR) {
7916 texture_manager()->SetLevelInfo(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01007917 texture_ref,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007918 target, level, internal_format, width, height, 1, border, format, type,
7919 pixels != NULL);
7920 tex_image_2d_failed_ = false;
7921 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007922 return;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007923}
7924
7925error::Error GLES2DecoderImpl::HandleTexImage2D(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007926 uint32 immediate_data_size, const cmds::TexImage2D& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007927 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
7928 tex_image_2d_failed_ = true;
7929 GLenum target = static_cast<GLenum>(c.target);
7930 GLint level = static_cast<GLint>(c.level);
7931 GLint internal_format = static_cast<GLint>(c.internalformat);
7932 GLsizei width = static_cast<GLsizei>(c.width);
7933 GLsizei height = static_cast<GLsizei>(c.height);
7934 GLint border = static_cast<GLint>(c.border);
7935 GLenum format = static_cast<GLenum>(c.format);
7936 GLenum type = static_cast<GLenum>(c.type);
7937 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
7938 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
7939 uint32 pixels_size;
7940 if (!GLES2Util::ComputeImageDataSizes(
7941 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
7942 NULL)) {
7943 return error::kOutOfBounds;
7944 }
7945 const void* pixels = NULL;
7946 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
7947 pixels = GetSharedMemoryAs<const void*>(
7948 pixels_shm_id, pixels_shm_offset, pixels_size);
7949 if (!pixels) {
7950 return error::kOutOfBounds;
7951 }
7952 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007953
7954 DoTexImage2D(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007955 target, level, internal_format, width, height, border, format, type,
7956 pixels, pixels_size);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007957 return error::kNoError;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007958}
7959
7960error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007961 uint32 immediate_data_size, const cmds::TexImage2DImmediate& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007962 GLenum target = static_cast<GLenum>(c.target);
7963 GLint level = static_cast<GLint>(c.level);
7964 GLint internal_format = static_cast<GLint>(c.internalformat);
7965 GLsizei width = static_cast<GLsizei>(c.width);
7966 GLsizei height = static_cast<GLsizei>(c.height);
7967 GLint border = static_cast<GLint>(c.border);
7968 GLenum format = static_cast<GLenum>(c.format);
7969 GLenum type = static_cast<GLenum>(c.type);
7970 uint32 size;
7971 if (!GLES2Util::ComputeImageDataSizes(
7972 width, height, format, type, state_.unpack_alignment, &size,
7973 NULL, NULL)) {
7974 return error::kOutOfBounds;
7975 }
7976 const void* pixels = GetImmediateDataAs<const void*>(
7977 c, size, immediate_data_size);
7978 if (!pixels) {
7979 return error::kOutOfBounds;
7980 }
7981 DoTexImage2D(
7982 target, level, internal_format, width, height, border, format, type,
7983 pixels, size);
7984 return error::kNoError;
7985}
7986
7987void GLES2DecoderImpl::DoCompressedTexSubImage2D(
7988 GLenum target,
7989 GLint level,
7990 GLint xoffset,
7991 GLint yoffset,
7992 GLsizei width,
7993 GLsizei height,
7994 GLenum format,
7995 GLsizei image_size,
7996 const void * data) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01007997 TextureRef* texture_ref = GetTextureInfoForTarget(target);
7998 if (!texture_ref) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007999 LOCAL_SET_GL_ERROR(
8000 GL_INVALID_OPERATION,
8001 "glCompressedTexSubImage2D", "unknown texture for target");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008002 return;
8003 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01008004 Texture* texture = texture_ref->texture();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008005 GLenum type = 0;
8006 GLenum internal_format = 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008007 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
8008 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008009 GL_INVALID_OPERATION,
8010 "glCompressedTexSubImage2D", "level does not exist.");
8011 return;
8012 }
8013 if (internal_format != format) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008014 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008015 GL_INVALID_OPERATION,
8016 "glCompressedTexSubImage2D", "format does not match internal format.");
8017 return;
8018 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008019 if (!texture->ValidForTexture(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008020 target, level, xoffset, yoffset, width, height, format, type)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008021 LOCAL_SET_GL_ERROR(
8022 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008023 return;
8024 }
8025
8026 if (!ValidateCompressedTexFuncData(
8027 "glCompressedTexSubImage2D", width, height, format, image_size) ||
8028 !ValidateCompressedTexSubDimensions(
8029 "glCompressedTexSubImage2D",
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008030 target, level, xoffset, yoffset, width, height, format, texture)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008031 return;
8032 }
8033
8034
8035 // Note: There is no need to deal with texture cleared tracking here
8036 // because the validation above means you can only get here if the level
8037 // is already a matching compressed format and in that case
8038 // CompressedTexImage2D already cleared the texture.
8039 glCompressedTexSubImage2D(
8040 target, level, xoffset, yoffset, width, height, format, image_size, data);
8041}
8042
8043static void Clip(
8044 GLint start, GLint range, GLint sourceRange,
8045 GLint* out_start, GLint* out_range) {
8046 DCHECK(out_start);
8047 DCHECK(out_range);
8048 if (start < 0) {
8049 range += start;
8050 start = 0;
8051 }
8052 GLint end = start + range;
8053 if (end > sourceRange) {
8054 range -= end - sourceRange;
8055 }
8056 *out_start = start;
8057 *out_range = range;
8058}
8059
8060void GLES2DecoderImpl::DoCopyTexImage2D(
8061 GLenum target,
8062 GLint level,
8063 GLenum internal_format,
8064 GLint x,
8065 GLint y,
8066 GLsizei width,
8067 GLsizei height,
8068 GLint border) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008069 DCHECK(!ShouldDeferReads());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01008070 TextureRef* texture_ref = GetTextureInfoForTarget(target);
8071 if (!texture_ref) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008072 LOCAL_SET_GL_ERROR(
8073 GL_INVALID_OPERATION,
8074 "glCopyTexImage2D", "unknown texture for target");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008075 return;
8076 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01008077 Texture* texture = texture_ref->texture();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008078 if (texture->IsImmutable()) {
8079 LOCAL_SET_GL_ERROR(
8080 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008081 }
8082 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
8083 border != 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008084 LOCAL_SET_GL_ERROR(
8085 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008086 return;
8087 }
8088 if (!ValidateTextureParameters(
8089 "glCopyTexImage2D", target, internal_format, GL_UNSIGNED_BYTE, level)) {
8090 return;
8091 }
8092
8093 // Check we have compatible formats.
8094 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8095 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8096 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
8097
8098 if ((channels_needed & channels_exist) != channels_needed) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008099 LOCAL_SET_GL_ERROR(
8100 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008101 return;
8102 }
8103
8104 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008105 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008106 GL_INVALID_OPERATION,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008107 "glCopyTexImage2D", "can not be used with depth or stencil textures");
8108 return;
8109 }
8110
8111 uint32 estimated_size = 0;
8112 if (!GLES2Util::ComputeImageDataSizes(
8113 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
8114 &estimated_size, NULL, NULL)) {
8115 LOCAL_SET_GL_ERROR(
8116 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
8117 return;
8118 }
8119
8120 if (!EnsureGPUMemoryAvailable(estimated_size)) {
8121 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008122 return;
8123 }
8124
8125 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
8126 return;
8127 }
8128
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008129 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008130 ScopedResolvedFrameBufferBinder binder(this, false, true);
8131 gfx::Size size = GetBoundReadFrameBufferSize();
8132
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008133 if (texture->IsAttachedToFramebuffer()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008134 clear_state_dirty_ = true;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008135 }
8136
8137 // Clip to size to source dimensions
8138 GLint copyX = 0;
8139 GLint copyY = 0;
8140 GLint copyWidth = 0;
8141 GLint copyHeight = 0;
8142 Clip(x, width, size.width(), &copyX, &copyWidth);
8143 Clip(y, height, size.height(), &copyY, &copyHeight);
8144
8145 if (copyX != x ||
8146 copyY != y ||
8147 copyWidth != width ||
8148 copyHeight != height) {
8149 // some part was clipped so clear the texture.
8150 if (!ClearLevel(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008151 texture->service_id(), texture->target(),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008152 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008153 texture->IsImmutable())) {
8154 LOCAL_SET_GL_ERROR(
8155 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008156 return;
8157 }
8158 if (copyHeight > 0 && copyWidth > 0) {
8159 GLint dx = copyX - x;
8160 GLint dy = copyY - y;
8161 GLint destX = dx;
8162 GLint destY = dy;
8163 glCopyTexSubImage2D(target, level,
8164 destX, destY, copyX, copyY,
8165 copyWidth, copyHeight);
8166 }
8167 } else {
8168 glCopyTexImage2D(target, level, internal_format,
8169 copyX, copyY, copyWidth, copyHeight, border);
8170 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008171 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008172 if (error == GL_NO_ERROR) {
8173 texture_manager()->SetLevelInfo(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01008174 texture_ref, target, level, internal_format, width, height, 1,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008175 border, internal_format, GL_UNSIGNED_BYTE, true);
8176 }
8177}
8178
8179void GLES2DecoderImpl::DoCopyTexSubImage2D(
8180 GLenum target,
8181 GLint level,
8182 GLint xoffset,
8183 GLint yoffset,
8184 GLint x,
8185 GLint y,
8186 GLsizei width,
8187 GLsizei height) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008188 DCHECK(!ShouldDeferReads());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01008189 TextureRef* texture_ref = GetTextureInfoForTarget(target);
8190 if (!texture_ref) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008191 LOCAL_SET_GL_ERROR(
8192 GL_INVALID_OPERATION,
8193 "glCopyTexSubImage2D", "unknown texture for target");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008194 return;
8195 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01008196 Texture* texture = texture_ref->texture();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008197 GLenum type = 0;
8198 GLenum format = 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008199 if (!texture->GetLevelType(target, level, &type, &format) ||
8200 !texture->ValidForTexture(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008201 target, level, xoffset, yoffset, width, height, format, type)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008202 LOCAL_SET_GL_ERROR(
8203 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
8204 return;
8205 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01008206 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008207 LOCAL_SET_GL_ERROR(
8208 GL_INVALID_OPERATION,
8209 "glCopyTexSubImage2D", "async upload pending for texture");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008210 return;
8211 }
8212
8213 // Check we have compatible formats.
8214 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8215 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8216 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
8217
8218 if (!channels_needed ||
8219 (channels_needed & channels_exist) != channels_needed) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008220 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008221 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
8222 return;
8223 }
8224
8225 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008226 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008227 GL_INVALID_OPERATION,
8228 "glCopySubImage2D", "can not be used with depth or stencil textures");
8229 return;
8230 }
8231
8232 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8233 return;
8234 }
8235
8236 ScopedResolvedFrameBufferBinder binder(this, false, true);
8237 gfx::Size size = GetBoundReadFrameBufferSize();
8238 GLint copyX = 0;
8239 GLint copyY = 0;
8240 GLint copyWidth = 0;
8241 GLint copyHeight = 0;
8242 Clip(x, width, size.width(), &copyX, &copyWidth);
8243 Clip(y, height, size.height(), &copyY, &copyHeight);
8244
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01008245 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008246 LOCAL_SET_GL_ERROR(
8247 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008248 return;
8249 }
8250
8251 if (copyX != x ||
8252 copyY != y ||
8253 copyWidth != width ||
8254 copyHeight != height) {
8255 // some part was clipped so clear the sub rect.
8256 uint32 pixels_size = 0;
8257 if (!GLES2Util::ComputeImageDataSizes(
8258 width, height, format, type, state_.unpack_alignment, &pixels_size,
8259 NULL, NULL)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008260 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008261 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
8262 return;
8263 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01008264 scoped_ptr<char[]> zero(new char[pixels_size]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008265 memset(zero.get(), 0, pixels_size);
8266 glTexSubImage2D(
8267 target, level, xoffset, yoffset, width, height,
8268 format, type, zero.get());
8269 }
8270
8271 if (copyHeight > 0 && copyWidth > 0) {
8272 GLint dx = copyX - x;
8273 GLint dy = copyY - y;
8274 GLint destX = xoffset + dx;
8275 GLint destY = yoffset + dy;
8276 glCopyTexSubImage2D(target, level,
8277 destX, destY, copyX, copyY,
8278 copyWidth, copyHeight);
8279 }
8280}
8281
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008282bool GLES2DecoderImpl::ValidateTexSubImage2D(
8283 error::Error* error,
8284 const char* function_name,
8285 GLenum target,
8286 GLint level,
8287 GLint xoffset,
8288 GLint yoffset,
8289 GLsizei width,
8290 GLsizei height,
8291 GLenum format,
8292 GLenum type,
8293 const void * data) {
8294 (*error) = error::kNoError;
8295 if (!validators_->texture_target.IsValid(target)) {
8296 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
8297 return false;
8298 }
8299 if (width < 0) {
8300 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
8301 return false;
8302 }
8303 if (height < 0) {
8304 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
8305 return false;
8306 }
8307 if (!validators_->texture_format.IsValid(format)) {
8308 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
8309 return false;
8310 }
8311 if (!validators_->pixel_type.IsValid(type)) {
8312 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
8313 return false;
8314 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01008315 TextureRef* texture_ref = GetTextureInfoForTarget(target);
8316 if (!texture_ref) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008317 LOCAL_SET_GL_ERROR(
8318 GL_INVALID_OPERATION,
8319 function_name, "unknown texture for target");
8320 return false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008321 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01008322 Texture* texture = texture_ref->texture();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008323 GLenum current_type = 0;
8324 GLenum internal_format = 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008325 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
8326 LOCAL_SET_GL_ERROR(
8327 GL_INVALID_OPERATION, function_name, "level does not exist.");
8328 return false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008329 }
8330 if (format != internal_format) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008331 LOCAL_SET_GL_ERROR(
8332 GL_INVALID_OPERATION,
8333 function_name, "format does not match internal format.");
8334 return false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008335 }
8336 if (type != current_type) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008337 LOCAL_SET_GL_ERROR(
8338 GL_INVALID_OPERATION,
8339 function_name, "type does not match type of texture.");
8340 return false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008341 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01008342 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008343 LOCAL_SET_GL_ERROR(
8344 GL_INVALID_OPERATION,
8345 function_name, "async upload pending for texture");
8346 return false;
8347 }
8348 if (!texture->ValidForTexture(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008349 target, level, xoffset, yoffset, width, height, format, type)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008350 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
8351 return false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008352 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008353 if ((GLES2Util::GetChannelsForFormat(format) &
8354 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008355 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008356 GL_INVALID_OPERATION,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008357 function_name, "can not supply data for depth or stencil textures");
8358 return false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008359 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008360 if (data == NULL) {
8361 (*error) = error::kOutOfBounds;
8362 return false;
8363 }
8364 return true;
8365}
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008366
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008367error::Error GLES2DecoderImpl::DoTexSubImage2D(
8368 GLenum target,
8369 GLint level,
8370 GLint xoffset,
8371 GLint yoffset,
8372 GLsizei width,
8373 GLsizei height,
8374 GLenum format,
8375 GLenum type,
8376 const void * data) {
8377 error::Error error = error::kNoError;
8378 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
8379 xoffset, yoffset, width, height, format, type, data)) {
8380 return error;
8381 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01008382 TextureRef* texture_ref = GetTextureInfoForTarget(target);
8383 Texture* texture = texture_ref->texture();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008384 GLsizei tex_width = 0;
8385 GLsizei tex_height = 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008386 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008387 DCHECK(ok);
8388 if (xoffset != 0 || yoffset != 0 ||
8389 width != tex_width || height != tex_height) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01008390 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
8391 target, level)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008392 LOCAL_SET_GL_ERROR(
8393 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
8394 return error::kNoError;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008395 }
8396 ScopedTextureUploadTimer timer(this);
8397 glTexSubImage2D(
8398 target, level, xoffset, yoffset, width, height, format, type, data);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008399 return error::kNoError;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008400 }
8401
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008402 if (teximage2d_faster_than_texsubimage2d_ && !texture->IsImmutable()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008403 ScopedTextureUploadTimer timer(this);
8404 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
8405 // same as internal_foramt. If that changes we'll need to look them up.
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01008406 glTexImage2D(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008407 target, level, format, width, height, 0, format, type, data);
8408 } else {
8409 ScopedTextureUploadTimer timer(this);
8410 glTexSubImage2D(
8411 target, level, xoffset, yoffset, width, height, format, type, data);
8412 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01008413 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008414 return error::kNoError;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008415}
8416
8417error::Error GLES2DecoderImpl::HandleTexSubImage2D(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008418 uint32 immediate_data_size, const cmds::TexSubImage2D& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008419 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
8420 GLboolean internal = static_cast<GLboolean>(c.internal);
8421 if (internal == GL_TRUE && tex_image_2d_failed_)
8422 return error::kNoError;
8423
8424 GLenum target = static_cast<GLenum>(c.target);
8425 GLint level = static_cast<GLint>(c.level);
8426 GLint xoffset = static_cast<GLint>(c.xoffset);
8427 GLint yoffset = static_cast<GLint>(c.yoffset);
8428 GLsizei width = static_cast<GLsizei>(c.width);
8429 GLsizei height = static_cast<GLsizei>(c.height);
8430 GLenum format = static_cast<GLenum>(c.format);
8431 GLenum type = static_cast<GLenum>(c.type);
8432 uint32 data_size;
8433 if (!GLES2Util::ComputeImageDataSizes(
8434 width, height, format, type, state_.unpack_alignment, &data_size,
8435 NULL, NULL)) {
8436 return error::kOutOfBounds;
8437 }
8438 const void* pixels = GetSharedMemoryAs<const void*>(
8439 c.pixels_shm_id, c.pixels_shm_offset, data_size);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008440 return DoTexSubImage2D(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008441 target, level, xoffset, yoffset, width, height, format, type, pixels);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008442}
8443
8444error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008445 uint32 immediate_data_size, const cmds::TexSubImage2DImmediate& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008446 GLboolean internal = static_cast<GLboolean>(c.internal);
8447 if (internal == GL_TRUE && tex_image_2d_failed_)
8448 return error::kNoError;
8449
8450 GLenum target = static_cast<GLenum>(c.target);
8451 GLint level = static_cast<GLint>(c.level);
8452 GLint xoffset = static_cast<GLint>(c.xoffset);
8453 GLint yoffset = static_cast<GLint>(c.yoffset);
8454 GLsizei width = static_cast<GLsizei>(c.width);
8455 GLsizei height = static_cast<GLsizei>(c.height);
8456 GLenum format = static_cast<GLenum>(c.format);
8457 GLenum type = static_cast<GLenum>(c.type);
8458 uint32 data_size;
8459 if (!GLES2Util::ComputeImageDataSizes(
8460 width, height, format, type, state_.unpack_alignment, &data_size,
8461 NULL, NULL)) {
8462 return error::kOutOfBounds;
8463 }
8464 const void* pixels = GetImmediateDataAs<const void*>(
8465 c, data_size, immediate_data_size);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008466 return DoTexSubImage2D(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008467 target, level, xoffset, yoffset, width, height, format, type, pixels);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008468}
8469
8470error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008471 uint32 immediate_data_size, const cmds::GetVertexAttribPointerv& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008472 GLuint index = static_cast<GLuint>(c.index);
8473 GLenum pname = static_cast<GLenum>(c.pname);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008474 typedef cmds::GetVertexAttribPointerv::Result Result;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008475 Result* result = GetSharedMemoryAs<Result*>(
8476 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
8477 if (!result) {
8478 return error::kOutOfBounds;
8479 }
8480 // Check that the client initialized the result.
8481 if (result->size != 0) {
8482 return error::kInvalidArguments;
8483 }
8484 if (!validators_->vertex_pointer.IsValid(pname)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008485 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8486 "glGetVertexAttribPointerv", pname, "pname");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008487 return error::kNoError;
8488 }
8489 if (index >= group_->max_vertex_attribs()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008490 LOCAL_SET_GL_ERROR(
8491 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008492 return error::kNoError;
8493 }
8494 result->SetNumResults(1);
8495 *result->GetData() =
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008496 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008497 return error::kNoError;
8498}
8499
8500bool GLES2DecoderImpl::GetUniformSetup(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008501 GLuint program_id, GLint fake_location,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008502 uint32 shm_id, uint32 shm_offset,
8503 error::Error* error, GLint* real_location,
8504 GLuint* service_id, void** result_pointer, GLenum* result_type) {
8505 DCHECK(error);
8506 DCHECK(service_id);
8507 DCHECK(result_pointer);
8508 DCHECK(result_type);
8509 DCHECK(real_location);
8510 *error = error::kNoError;
8511 // Make sure we have enough room for the result on failure.
8512 SizedResult<GLint>* result;
8513 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8514 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
8515 if (!result) {
8516 *error = error::kOutOfBounds;
8517 return false;
8518 }
8519 *result_pointer = result;
8520 // Set the result size to 0 so the client does not have to check for success.
8521 result->SetNumResults(0);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008522 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
8523 if (!program) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008524 return false;
8525 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008526 if (!program->IsValid()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008527 // Program was not linked successfully. (ie, glLinkProgram)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008528 LOCAL_SET_GL_ERROR(
8529 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008530 return false;
8531 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008532 *service_id = program->service_id();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008533 GLint array_index = -1;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008534 const Program::UniformInfo* uniform_info =
8535 program->GetUniformInfoByFakeLocation(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008536 fake_location, real_location, &array_index);
8537 if (!uniform_info) {
8538 // No such location.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008539 LOCAL_SET_GL_ERROR(
8540 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008541 return false;
8542 }
8543 GLenum type = uniform_info->type;
8544 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
8545 if (size == 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008546 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008547 return false;
8548 }
8549 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8550 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
8551 if (!result) {
8552 *error = error::kOutOfBounds;
8553 return false;
8554 }
8555 result->size = size;
8556 *result_type = type;
8557 return true;
8558}
8559
8560error::Error GLES2DecoderImpl::HandleGetUniformiv(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008561 uint32 immediate_data_size, const cmds::GetUniformiv& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008562 GLuint program = c.program;
8563 GLint fake_location = c.location;
8564 GLuint service_id;
8565 GLenum result_type;
8566 GLint real_location = -1;
8567 Error error;
8568 void* result;
8569 if (GetUniformSetup(
8570 program, fake_location, c.params_shm_id, c.params_shm_offset,
8571 &error, &real_location, &service_id, &result, &result_type)) {
8572 glGetUniformiv(
8573 service_id, real_location,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008574 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008575 }
8576 return error;
8577}
8578
8579error::Error GLES2DecoderImpl::HandleGetUniformfv(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008580 uint32 immediate_data_size, const cmds::GetUniformfv& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008581 GLuint program = c.program;
8582 GLint fake_location = c.location;
8583 GLuint service_id;
8584 GLint real_location = -1;
8585 Error error;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008586 typedef cmds::GetUniformfv::Result Result;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008587 Result* result;
8588 GLenum result_type;
8589 if (GetUniformSetup(
8590 program, fake_location, c.params_shm_id, c.params_shm_offset,
8591 &error, &real_location, &service_id,
8592 reinterpret_cast<void**>(&result), &result_type)) {
8593 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
8594 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
8595 GLsizei num_values = result->GetNumResults();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01008596 scoped_ptr<GLint[]> temp(new GLint[num_values]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008597 glGetUniformiv(service_id, real_location, temp.get());
8598 GLfloat* dst = result->GetData();
8599 for (GLsizei ii = 0; ii < num_values; ++ii) {
8600 dst[ii] = (temp[ii] != 0);
8601 }
8602 } else {
8603 glGetUniformfv(service_id, real_location, result->GetData());
8604 }
8605 }
8606 return error;
8607}
8608
8609error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008610 uint32 immediate_data_size, const cmds::GetShaderPrecisionFormat& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008611 GLenum shader_type = static_cast<GLenum>(c.shadertype);
8612 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008613 typedef cmds::GetShaderPrecisionFormat::Result Result;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008614 Result* result = GetSharedMemoryAs<Result*>(
8615 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8616 if (!result) {
8617 return error::kOutOfBounds;
8618 }
8619 // Check that the client initialized the result.
8620 if (result->success != 0) {
8621 return error::kInvalidArguments;
8622 }
8623 if (!validators_->shader_type.IsValid(shader_type)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008624 LOCAL_SET_GL_ERROR_INVALID_ENUM(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008625 "glGetShaderPrecisionFormat", shader_type, "shader_type");
8626 return error::kNoError;
8627 }
8628 if (!validators_->shader_precision.IsValid(precision_type)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008629 LOCAL_SET_GL_ERROR_INVALID_ENUM(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008630 "glGetShaderPrecisionFormat", precision_type, "precision_type");
8631 return error::kNoError;
8632 }
8633
8634 result->success = 1; // true
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008635
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01008636 GLint range[2] = { 0, 0 };
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008637 GLint precision = 0;
8638 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
8639
8640 result->min_range = range[0];
8641 result->max_range = range[1];
8642 result->precision = precision;
8643
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008644 return error::kNoError;
8645}
8646
8647error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008648 uint32 immediate_data_size, const cmds::GetAttachedShaders& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008649 uint32 result_size = c.result_size;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008650 GLuint program_id = static_cast<GLuint>(c.program);
8651 Program* program = GetProgramInfoNotShader(
8652 program_id, "glGetAttachedShaders");
8653 if (!program) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008654 return error::kNoError;
8655 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008656 typedef cmds::GetAttachedShaders::Result Result;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008657 uint32 max_count = Result::ComputeMaxResults(result_size);
8658 Result* result = GetSharedMemoryAs<Result*>(
8659 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
8660 if (!result) {
8661 return error::kOutOfBounds;
8662 }
8663 // Check that the client initialized the result.
8664 if (result->size != 0) {
8665 return error::kInvalidArguments;
8666 }
8667 GLsizei count = 0;
8668 glGetAttachedShaders(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008669 program->service_id(), max_count, &count, result->GetData());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008670 for (GLsizei ii = 0; ii < count; ++ii) {
8671 if (!shader_manager()->GetClientId(result->GetData()[ii],
8672 &result->GetData()[ii])) {
8673 NOTREACHED();
8674 return error::kGenericError;
8675 }
8676 }
8677 result->SetNumResults(count);
8678 return error::kNoError;
8679}
8680
8681error::Error GLES2DecoderImpl::HandleGetActiveUniform(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008682 uint32 immediate_data_size, const cmds::GetActiveUniform& c) {
8683 GLuint program_id = c.program;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008684 GLuint index = c.index;
8685 uint32 name_bucket_id = c.name_bucket_id;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008686 typedef cmds::GetActiveUniform::Result Result;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008687 Result* result = GetSharedMemoryAs<Result*>(
8688 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8689 if (!result) {
8690 return error::kOutOfBounds;
8691 }
8692 // Check that the client initialized the result.
8693 if (result->success != 0) {
8694 return error::kInvalidArguments;
8695 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008696 Program* program = GetProgramInfoNotShader(
8697 program_id, "glGetActiveUniform");
8698 if (!program) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008699 return error::kNoError;
8700 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008701 const Program::UniformInfo* uniform_info =
8702 program->GetUniformInfo(index);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008703 if (!uniform_info) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008704 LOCAL_SET_GL_ERROR(
8705 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008706 return error::kNoError;
8707 }
8708 result->success = 1; // true.
8709 result->size = uniform_info->size;
8710 result->type = uniform_info->type;
8711 Bucket* bucket = CreateBucket(name_bucket_id);
8712 bucket->SetFromString(uniform_info->name.c_str());
8713 return error::kNoError;
8714}
8715
8716error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008717 uint32 immediate_data_size, const cmds::GetActiveAttrib& c) {
8718 GLuint program_id = c.program;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008719 GLuint index = c.index;
8720 uint32 name_bucket_id = c.name_bucket_id;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008721 typedef cmds::GetActiveAttrib::Result Result;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008722 Result* result = GetSharedMemoryAs<Result*>(
8723 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8724 if (!result) {
8725 return error::kOutOfBounds;
8726 }
8727 // Check that the client initialized the result.
8728 if (result->success != 0) {
8729 return error::kInvalidArguments;
8730 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008731 Program* program = GetProgramInfoNotShader(
8732 program_id, "glGetActiveAttrib");
8733 if (!program) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008734 return error::kNoError;
8735 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008736 const Program::VertexAttrib* attrib_info =
8737 program->GetAttribInfo(index);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008738 if (!attrib_info) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008739 LOCAL_SET_GL_ERROR(
8740 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008741 return error::kNoError;
8742 }
8743 result->success = 1; // true.
8744 result->size = attrib_info->size;
8745 result->type = attrib_info->type;
8746 Bucket* bucket = CreateBucket(name_bucket_id);
8747 bucket->SetFromString(attrib_info->name.c_str());
8748 return error::kNoError;
8749}
8750
8751error::Error GLES2DecoderImpl::HandleShaderBinary(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008752 uint32 immediate_data_size, const cmds::ShaderBinary& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008753#if 1 // No binary shader support.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008754 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008755 return error::kNoError;
8756#else
8757 GLsizei n = static_cast<GLsizei>(c.n);
8758 if (n < 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008759 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008760 return error::kNoError;
8761 }
8762 GLsizei length = static_cast<GLsizei>(c.length);
8763 if (length < 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008764 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008765 return error::kNoError;
8766 }
8767 uint32 data_size;
8768 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
8769 return error::kOutOfBounds;
8770 }
8771 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
8772 c.shaders_shm_id, c.shaders_shm_offset, data_size);
8773 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
8774 const void* binary = GetSharedMemoryAs<const void*>(
8775 c.binary_shm_id, c.binary_shm_offset, length);
8776 if (shaders == NULL || binary == NULL) {
8777 return error::kOutOfBounds;
8778 }
8779 scoped_array<GLuint> service_ids(new GLuint[n]);
8780 for (GLsizei ii = 0; ii < n; ++ii) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008781 Shader* shader = GetShader(shaders[ii]);
8782 if (!shader) {
8783 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008784 return error::kNoError;
8785 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008786 service_ids[ii] = shader->service_id();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008787 }
8788 // TODO(gman): call glShaderBinary
8789 return error::kNoError;
8790#endif
8791}
8792
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01008793void GLES2DecoderImpl::DoSwapBuffers() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008794 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008795
8796 int this_frame_number = frame_number_++;
8797 // TRACE_EVENT for gpu tests:
8798 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01008799 TRACE_EVENT_SCOPE_THREAD,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008800 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
8801 "width", (is_offscreen ? offscreen_size_.width() :
8802 surface_->GetSize().width()));
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01008803 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008804 "offscreen", is_offscreen,
8805 "frame", this_frame_number);
8806 // If offscreen then don't actually SwapBuffers to the display. Just copy
8807 // the rendered frame to another frame buffer.
8808 if (is_offscreen) {
8809 TRACE_EVENT2("gpu", "Offscreen",
8810 "width", offscreen_size_.width(), "height", offscreen_size_.height());
8811 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
8812 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
8813 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
8814 // fix this.
8815 if (workarounds().needs_offscreen_buffer_workaround) {
8816 offscreen_saved_frame_buffer_->Create();
8817 glFinish();
8818 }
8819
8820 // Allocate the offscreen saved color texture.
8821 DCHECK(offscreen_saved_color_format_);
8822 offscreen_saved_color_texture_->AllocateStorage(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008823 offscreen_size_, offscreen_saved_color_format_, false);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008824
8825 offscreen_saved_frame_buffer_->AttachRenderTexture(
8826 offscreen_saved_color_texture_.get());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008827 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
8828 if (offscreen_saved_frame_buffer_->CheckStatus() !=
8829 GL_FRAMEBUFFER_COMPLETE) {
8830 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
8831 << "because offscreen saved FBO was incomplete.";
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01008832 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
8833 return;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008834 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008835
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008836 // Clear the offscreen color texture.
8837 // TODO(piman): Is this still necessary?
8838 {
8839 ScopedFrameBufferBinder binder(this,
8840 offscreen_saved_frame_buffer_->id());
8841 glClearColor(0, 0, 0, 0);
8842 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
8843 glDisable(GL_SCISSOR_TEST);
8844 glClear(GL_COLOR_BUFFER_BIT);
8845 RestoreClearState();
8846 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008847 }
8848
8849 UpdateParentTextureInfo();
8850 }
8851
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008852 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01008853 return;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008854 ScopedGLErrorSuppressor suppressor(
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01008855 "GLES2DecoderImpl::DoSwapBuffers", this);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008856
8857 if (IsOffscreenBufferMultisampled()) {
8858 // For multisampled buffers, resolve the frame buffer.
8859 ScopedResolvedFrameBufferBinder binder(this, true, false);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008860 } else {
8861 ScopedFrameBufferBinder binder(this,
8862 offscreen_target_frame_buffer_->id());
8863
8864 if (offscreen_target_buffer_preserved_) {
8865 // Copy the target frame buffer to the saved offscreen texture.
8866 offscreen_saved_color_texture_->Copy(
8867 offscreen_saved_color_texture_->size(),
8868 offscreen_saved_color_format_);
8869 } else {
8870 // Flip the textures in the parent context via the texture manager.
8871 if (!!offscreen_saved_color_texture_info_.get())
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01008872 offscreen_saved_color_texture_info_->texture()->
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008873 SetServiceId(offscreen_target_color_texture_->id());
8874
8875 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
8876 offscreen_target_frame_buffer_->AttachRenderTexture(
8877 offscreen_target_color_texture_.get());
8878 }
8879
8880 // Ensure the side effects of the copy are visible to the parent
8881 // context. There is no need to do this for ANGLE because it uses a
8882 // single D3D device for all contexts.
8883 if (!IsAngle())
8884 glFlush();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008885 }
8886 } else {
8887 TRACE_EVENT2("gpu", "Onscreen",
8888 "width", surface_->GetSize().width(),
8889 "height", surface_->GetSize().height());
8890 if (!surface_->SwapBuffers()) {
8891 LOG(ERROR) << "Context lost because SwapBuffers failed.";
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01008892 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008893 }
8894 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008895}
8896
8897error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008898 uint32 immediate_data_size, const cmds::EnableFeatureCHROMIUM& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008899 Bucket* bucket = GetBucket(c.bucket_id);
8900 if (!bucket || bucket->size() == 0) {
8901 return error::kInvalidArguments;
8902 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008903 typedef cmds::EnableFeatureCHROMIUM::Result Result;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008904 Result* result = GetSharedMemoryAs<Result*>(
8905 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8906 if (!result) {
8907 return error::kOutOfBounds;
8908 }
8909 // Check that the client initialized the result.
8910 if (*result != 0) {
8911 return error::kInvalidArguments;
8912 }
8913 std::string feature_str;
8914 if (!bucket->GetAsString(&feature_str)) {
8915 return error::kInvalidArguments;
8916 }
8917
8918 // TODO(gman): make this some kind of table to function pointer thingy.
8919 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
8920 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
8921 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
8922 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
8923 // TODO(gman): decide how to remove the need for this const_cast.
8924 // I could make validators_ non const but that seems bad as this is the only
8925 // place it is needed. I could make some special friend class of validators
8926 // just to allow this to set them. That seems silly. I could refactor this
8927 // code to use the extension mechanism or the initialization attributes to
8928 // turn this feature on. Given that the only real point of this is to make
8929 // the conformance tests pass and given that there is lots of real work that
8930 // needs to be done it seems like refactoring for one to one of those
8931 // methods is a very low priority.
8932 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
8933 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
8934 force_webgl_glsl_validation_ = true;
8935 InitializeShaderTranslator();
8936 } else {
8937 return error::kNoError;
8938 }
8939
8940 *result = 1; // true.
8941 return error::kNoError;
8942}
8943
8944error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
8945 uint32 immediate_data_size,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008946 const cmds::GetRequestableExtensionsCHROMIUM& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008947 Bucket* bucket = CreateBucket(c.bucket_id);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008948 scoped_refptr<FeatureInfo> info(new FeatureInfo());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008949 info->Initialize(disallowed_features_, NULL);
8950 bucket->SetFromString(info->extensions().c_str());
8951 return error::kNoError;
8952}
8953
8954error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008955 uint32 immediate_data_size, const cmds::RequestExtensionCHROMIUM& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008956 Bucket* bucket = GetBucket(c.bucket_id);
8957 if (!bucket || bucket->size() == 0) {
8958 return error::kInvalidArguments;
8959 }
8960 std::string feature_str;
8961 if (!bucket->GetAsString(&feature_str)) {
8962 return error::kInvalidArguments;
8963 }
8964
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008965 bool desire_webgl_glsl_validation =
8966 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
8967 bool desire_standard_derivatives = false;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01008968 bool desire_frag_depth = false;
8969 bool desire_draw_buffers = false;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008970 if (force_webgl_glsl_validation_) {
8971 desire_standard_derivatives =
8972 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01008973 desire_frag_depth =
8974 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
8975 desire_draw_buffers =
8976 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008977 }
8978
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008979 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01008980 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
8981 desire_frag_depth != frag_depth_explicitly_enabled_ ||
8982 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
8983 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
8984 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
8985 frag_depth_explicitly_enabled_ |= desire_frag_depth;
8986 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008987 InitializeShaderTranslator();
8988 }
8989
8990 UpdateCapabilities();
8991
8992 return error::kNoError;
8993}
8994
8995error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00008996 uint32 immediate_data_size, const cmds::GetMultipleIntegervCHROMIUM& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008997 GLuint count = c.count;
8998 uint32 pnames_size;
8999 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
9000 return error::kOutOfBounds;
9001 }
9002 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
9003 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
9004 if (pnames == NULL) {
9005 return error::kOutOfBounds;
9006 }
9007
9008 // We have to copy them since we use them twice so the client
9009 // can't change them between the time we validate them and the time we use
9010 // them.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01009011 scoped_ptr<GLenum[]> enums(new GLenum[count]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009012 memcpy(enums.get(), pnames, pnames_size);
9013
9014 // Count up the space needed for the result.
9015 uint32 num_results = 0;
9016 for (GLuint ii = 0; ii < count; ++ii) {
9017 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
9018 if (num == 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009019 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9020 "glGetMulitpleCHROMIUM", enums[ii], "pname");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009021 return error::kNoError;
9022 }
9023 // Num will never be more than 4.
9024 DCHECK_LE(num, 4u);
9025 if (!SafeAddUint32(num_results, num, &num_results)) {
9026 return error::kOutOfBounds;
9027 }
9028 }
9029
9030 uint32 result_size = 0;
9031 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
9032 return error::kOutOfBounds;
9033 }
9034
9035 if (result_size != static_cast<uint32>(c.size)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009036 LOCAL_SET_GL_ERROR(
9037 GL_INVALID_VALUE,
9038 "glGetMulitpleCHROMIUM", "bad size GL_INVALID_VALUE");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009039 return error::kNoError;
9040 }
9041
9042 GLint* results = GetSharedMemoryAs<GLint*>(
9043 c.results_shm_id, c.results_shm_offset, result_size);
9044 if (results == NULL) {
9045 return error::kOutOfBounds;
9046 }
9047
9048 // Check the results have been cleared in case the context was lost.
9049 for (uint32 ii = 0; ii < num_results; ++ii) {
9050 if (results[ii]) {
9051 return error::kInvalidArguments;
9052 }
9053 }
9054
9055 // Get each result.
9056 GLint* start = results;
9057 for (GLuint ii = 0; ii < count; ++ii) {
9058 GLsizei num_written = 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009059 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009060 !GetHelper(enums[ii], results, &num_written)) {
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01009061 DoGetIntegerv(enums[ii], results);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009062 }
9063 results += num_written;
9064 }
9065
9066 // Just to verify. Should this be a DCHECK?
9067 if (static_cast<uint32>(results - start) != num_results) {
9068 return error::kOutOfBounds;
9069 }
9070
9071 return error::kNoError;
9072}
9073
9074error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009075 uint32 immediate_data_size, const cmds::GetProgramInfoCHROMIUM& c) {
9076 GLuint program_id = static_cast<GLuint>(c.program);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009077 uint32 bucket_id = c.bucket_id;
9078 Bucket* bucket = CreateBucket(bucket_id);
9079 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009080 Program* program = NULL;
9081 program = GetProgram(program_id);
9082 if (!program || !program->IsValid()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009083 return error::kNoError;
9084 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009085 program->GetProgramInfo(program_manager(), bucket);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009086 return error::kNoError;
9087}
9088
9089error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
9090 switch (reset_status_) {
9091 case GL_NO_ERROR:
9092 // TODO(kbr): improve the precision of the error code in this case.
9093 // Consider delegating to context for error code if MakeCurrent fails.
9094 return error::kUnknown;
9095 case GL_GUILTY_CONTEXT_RESET_ARB:
9096 return error::kGuilty;
9097 case GL_INNOCENT_CONTEXT_RESET_ARB:
9098 return error::kInnocent;
9099 case GL_UNKNOWN_CONTEXT_RESET_ARB:
9100 return error::kUnknown;
9101 }
9102
9103 NOTREACHED();
9104 return error::kUnknown;
9105}
9106
9107bool GLES2DecoderImpl::WasContextLost() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009108 if (reset_status_ != GL_NO_ERROR) {
9109 return true;
9110 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009111 if (context_->WasAllocatedUsingRobustnessExtension()) {
9112 GLenum status = GL_NO_ERROR;
9113 if (has_robustness_extension_)
9114 status = glGetGraphicsResetStatusARB();
9115 if (status != GL_NO_ERROR) {
9116 // The graphics card was reset. Signal a lost context to the application.
9117 reset_status_ = status;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01009118 reset_by_robustness_extension_ = true;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009119 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009120 << " context lost via ARB/EXT_robustness. Reset status = "
9121 << GLES2Util::GetStringEnum(status);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009122 return true;
9123 }
9124 }
9125 return false;
9126}
9127
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01009128bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
9129 return WasContextLost() && reset_by_robustness_extension_;
9130}
9131
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009132void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
9133 // Only loses the context once.
9134 if (reset_status_ != GL_NO_ERROR) {
9135 return;
9136 }
9137
9138 // Marks this context as lost.
9139 reset_status_ = reset_status;
9140 current_decoder_error_ = error::kLostContext;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009141}
9142
9143error::Error GLES2DecoderImpl::HandleLoseContextCHROMIUM(
9144 uint32 immediate_data_size, const cmds::LoseContextCHROMIUM& c) {
9145 GLenum current = static_cast<GLenum>(c.current);
9146 GLenum other = static_cast<GLenum>(c.other);
9147 if (!validators_->reset_status.IsValid(current)) {
9148 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9149 "glLoseContextCHROMIUM", current, "current");
9150 }
9151 if (!validators_->reset_status.IsValid(other)) {
9152 LOCAL_SET_GL_ERROR_INVALID_ENUM("glLoseContextCHROMIUM", other, "other");
9153 }
9154 group_->LoseContexts(other);
9155 reset_status_ = current;
9156 current_decoder_error_ = error::kLostContext;
9157 return error::kLostContext;
9158}
9159
9160error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
9161 uint32 immediate_data_size, const cmds::InsertSyncPointCHROMIUM& c) {
9162 return error::kUnknownCommand;
9163}
9164
9165error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
9166 uint32 immediate_data_size, const cmds::WaitSyncPointCHROMIUM& c) {
9167 if (wait_sync_point_callback_.is_null())
9168 return error::kNoError;
9169
9170 return wait_sync_point_callback_.Run(c.sync_point) ?
9171 error::kNoError : error::kDeferCommandUntilLater;
9172}
9173
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009174bool GLES2DecoderImpl::GenQueriesEXTHelper(
9175 GLsizei n, const GLuint* client_ids) {
9176 for (GLsizei ii = 0; ii < n; ++ii) {
9177 if (query_manager_->GetQuery(client_ids[ii])) {
9178 return false;
9179 }
9180 }
9181 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
9182 return true;
9183}
9184
9185void GLES2DecoderImpl::DeleteQueriesEXTHelper(
9186 GLsizei n, const GLuint* client_ids) {
9187 for (GLsizei ii = 0; ii < n; ++ii) {
9188 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
9189 if (query && !query->IsDeleted()) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01009190 if (query == state_.current_query.get()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009191 state_.current_query = NULL;
9192 }
9193 query->Destroy(true);
9194 query_manager_->RemoveQuery(client_ids[ii]);
9195 }
9196 }
9197}
9198
9199bool GLES2DecoderImpl::ProcessPendingQueries() {
9200 if (query_manager_.get() == NULL) {
9201 return false;
9202 }
9203 if (!query_manager_->ProcessPendingQueries()) {
9204 current_decoder_error_ = error::kOutOfBounds;
9205 }
9206 return query_manager_->HavePendingQueries();
9207}
9208
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01009209// Note that if there are no pending readpixels right now,
9210// this function will call the callback immediately.
9211void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
9212 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
9213 pending_readpixel_fences_.back()->callbacks.push_back(callback);
9214 } else {
9215 callback.Run();
9216 }
9217}
9218
9219void GLES2DecoderImpl::ProcessPendingReadPixels() {
9220 while (!pending_readpixel_fences_.empty() &&
9221 pending_readpixel_fences_.front()->fence->HasCompleted()) {
9222 std::vector<base::Closure> callbacks =
9223 pending_readpixel_fences_.front()->callbacks;
9224 pending_readpixel_fences_.pop();
9225 for (size_t i = 0; i < callbacks.size(); i++) {
9226 callbacks[i].Run();
9227 }
9228 }
9229}
9230
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009231bool GLES2DecoderImpl::HasMoreIdleWork() {
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01009232 return !pending_readpixel_fences_.empty() ||
9233 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009234}
9235
9236void GLES2DecoderImpl::PerformIdleWork() {
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01009237 ProcessPendingReadPixels();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01009238 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009239 return;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01009240 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009241 ProcessFinishedAsyncTransfers();
9242}
9243
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009244error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009245 uint32 immediate_data_size, const cmds::BeginQueryEXT& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009246 GLenum target = static_cast<GLenum>(c.target);
9247 GLuint client_id = static_cast<GLuint>(c.id);
9248 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
9249 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
9250
9251 switch (target) {
9252 case GL_COMMANDS_ISSUED_CHROMIUM:
9253 case GL_LATENCY_QUERY_CHROMIUM:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009254 case GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM:
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01009255 case GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009256 case GL_GET_ERROR_QUERY_CHROMIUM:
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009257 break;
9258 default:
9259 if (!features().occlusion_query_boolean) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009260 LOCAL_SET_GL_ERROR(
9261 GL_INVALID_OPERATION, "glBeginQueryEXT",
9262 "not enabled for occlusion queries");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009263 return error::kNoError;
9264 }
9265 break;
9266 }
9267
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01009268 // TODO(hubbe): Make it possible to have one query per type running at the
9269 // same time.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01009270 if (state_.current_query.get()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009271 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009272 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
9273 return error::kNoError;
9274 }
9275
9276 if (client_id == 0) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009277 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009278 return error::kNoError;
9279 }
9280
9281 QueryManager::Query* query = query_manager_->GetQuery(client_id);
9282 if (!query) {
9283 // TODO(gman): Decide if we need this check.
9284 //
9285 // Checks id was made by glGenQueries
9286 //
9287 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
9288 // for all Query ids but from the POV of the command buffer service maybe
9289 // you don't.
9290 //
9291 // The client can enforce this. I don't think the service cares.
9292 //
9293 // IdAllocatorInterface* id_allocator =
9294 // group_->GetIdAllocator(id_namespaces::kQueries);
9295 // if (!id_allocator->InUse(client_id)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009296 // LOCAL_SET_GL_ERROR(
9297 // GL_INVALID_OPERATION,
9298 // "glBeginQueryEXT", "id not made by glGenQueriesEXT");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009299 // return error::kNoError;
9300 // }
9301 query = query_manager_->CreateQuery(
9302 target, client_id, sync_shm_id, sync_shm_offset);
9303 }
9304
9305 if (query->target() != target) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009306 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009307 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
9308 return error::kNoError;
9309 } else if (query->shm_id() != sync_shm_id ||
9310 query->shm_offset() != sync_shm_offset) {
9311 DLOG(ERROR) << "Shared memory used by query not the same as before";
9312 return error::kInvalidArguments;
9313 }
9314
9315 if (!query_manager_->BeginQuery(query)) {
9316 return error::kOutOfBounds;
9317 }
9318
9319 state_.current_query = query;
9320 return error::kNoError;
9321}
9322
9323error::Error GLES2DecoderImpl::HandleEndQueryEXT(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009324 uint32 immediate_data_size, const cmds::EndQueryEXT& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009325 GLenum target = static_cast<GLenum>(c.target);
9326 uint32 submit_count = static_cast<GLuint>(c.submit_count);
9327
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01009328 if (!state_.current_query.get()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009329 LOCAL_SET_GL_ERROR(
9330 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009331 return error::kNoError;
9332 }
9333 if (state_.current_query->target() != target) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009334 LOCAL_SET_GL_ERROR(
9335 GL_INVALID_OPERATION,
9336 "glEndQueryEXT", "target does not match active query");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009337 return error::kNoError;
9338 }
9339
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01009340 if (!query_manager_->EndQuery(state_.current_query.get(), submit_count)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009341 return error::kOutOfBounds;
9342 }
9343
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009344 query_manager_->ProcessPendingTransferQueries();
9345
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009346 state_.current_query = NULL;
9347 return error::kNoError;
9348}
9349
9350bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9351 GLsizei n, const GLuint* client_ids) {
9352 for (GLsizei ii = 0; ii < n; ++ii) {
9353 if (GetVertexAttribManager(client_ids[ii])) {
9354 return false;
9355 }
9356 }
9357
9358 if (!features().native_vertex_array_object) {
9359 // Emulated VAO
9360 for (GLsizei ii = 0; ii < n; ++ii) {
9361 CreateVertexAttribManager(client_ids[ii], 0);
9362 }
9363 } else {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01009364 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009365
9366 glGenVertexArraysOES(n, service_ids.get());
9367 for (GLsizei ii = 0; ii < n; ++ii) {
9368 CreateVertexAttribManager(client_ids[ii], service_ids[ii]);
9369 }
9370 }
9371
9372 return true;
9373}
9374
9375void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9376 GLsizei n, const GLuint* client_ids) {
9377 for (GLsizei ii = 0; ii < n; ++ii) {
9378 VertexAttribManager* vao =
9379 GetVertexAttribManager(client_ids[ii]);
9380 if (vao && !vao->IsDeleted()) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01009381 if (state_.vertex_attrib_manager.get() == vao) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009382 state_.vertex_attrib_manager = default_vertex_attrib_manager_;
9383 }
9384 RemoveVertexAttribManager(client_ids[ii]);
9385 }
9386 }
9387}
9388
9389void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
9390 VertexAttribManager* vao = NULL;
9391 GLuint service_id = 0;
9392 if (client_id != 0) {
9393 vao = GetVertexAttribManager(client_id);
9394 if (!vao) {
9395 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9396 // only allows names that have been previously generated. As such, we do
9397 // not generate new names here.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009398 LOCAL_SET_GL_ERROR(
9399 GL_INVALID_OPERATION,
9400 "glBindVertexArrayOES", "bad vertex array id.");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009401 current_decoder_error_ = error::kNoError;
9402 return;
9403 } else {
9404 service_id = vao->service_id();
9405 }
9406 } else {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01009407 vao = default_vertex_attrib_manager_.get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009408 }
9409
9410 // Only set the VAO state if it's changed
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01009411 if (state_.vertex_attrib_manager.get() != vao) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009412 state_.vertex_attrib_manager = vao;
9413 if (!features().native_vertex_array_object) {
9414 EmulateVertexArrayState();
9415 } else {
9416 glBindVertexArrayOES(service_id);
9417 }
9418 }
9419}
9420
9421// Used when OES_vertex_array_object isn't natively supported
9422void GLES2DecoderImpl::EmulateVertexArrayState() {
9423 // Setup the Vertex attribute state
9424 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
9425 RestoreStateForAttrib(vv);
9426 }
9427
9428 // Setup the element buffer
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009429 Buffer* element_array_buffer =
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009430 state_.vertex_attrib_manager->element_array_buffer();
9431 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
9432 element_array_buffer ? element_array_buffer->service_id() : 0);
9433}
9434
9435bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
9436 const VertexAttribManager* vao =
9437 GetVertexAttribManager(client_id);
9438 return vao && vao->IsValid() && !vao->IsDeleted();
9439}
9440
9441error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
9442 uint32 immediate_data_size,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009443 const cmds::CreateStreamTextureCHROMIUM& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009444 if (!features().chromium_stream_texture) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009445 LOCAL_SET_GL_ERROR(
9446 GL_INVALID_OPERATION,
9447 "glOpenStreamTextureCHROMIUM", "not supported.");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009448 return error::kNoError;
9449 }
9450
9451 uint32 client_id = c.client_id;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009452 typedef cmds::CreateStreamTextureCHROMIUM::Result Result;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009453 Result* result = GetSharedMemoryAs<Result*>(
9454 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9455
9456 if (!result)
9457 return error::kOutOfBounds;
9458 *result = GL_ZERO;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009459 TextureRef* texture_ref = texture_manager()->GetTexture(client_id);
9460 if (!texture_ref) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009461 LOCAL_SET_GL_ERROR(
9462 GL_INVALID_VALUE,
9463 "glCreateStreamTextureCHROMIUM", "bad texture id.");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009464 return error::kNoError;
9465 }
9466
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009467 Texture* texture = texture_ref->texture();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009468 if (texture->IsStreamTexture()) {
9469 LOCAL_SET_GL_ERROR(
9470 GL_INVALID_OPERATION,
9471 "glCreateStreamTextureCHROMIUM", "is already a stream texture.");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009472 return error::kNoError;
9473 }
9474
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009475 if (texture->target() && texture->target() != GL_TEXTURE_EXTERNAL_OES) {
9476 LOCAL_SET_GL_ERROR(
9477 GL_INVALID_OPERATION,
9478 "glCreateStreamTextureCHROMIUM",
9479 "is already bound to incompatible target.");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009480 return error::kNoError;
9481 }
9482
Ben Murdocheb525c52013-07-10 11:40:50 +01009483 if (!stream_texture_manager())
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009484 return error::kInvalidArguments;
9485
Ben Murdocheb525c52013-07-10 11:40:50 +01009486 GLuint object_id = stream_texture_manager()->CreateStreamTexture(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009487 texture->service_id(), client_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009488
9489 if (object_id) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009490 texture_manager()->SetStreamTexture(texture_ref, true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009491 } else {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009492 LOCAL_SET_GL_ERROR(
9493 GL_OUT_OF_MEMORY,
9494 "glCreateStreamTextureCHROMIUM", "failed to create platform texture.");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009495 }
9496
9497 *result = object_id;
9498 return error::kNoError;
9499}
9500
9501error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
9502 uint32 immediate_data_size,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009503 const cmds::DestroyStreamTextureCHROMIUM& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009504 GLuint client_id = c.texture;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009505 TextureRef* texture_ref = texture_manager()->GetTexture(client_id);
Ben Murdocheb525c52013-07-10 11:40:50 +01009506 if (texture_ref && texture_manager()->IsStreamTextureOwner(texture_ref)) {
9507 if (!stream_texture_manager())
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009508 return error::kInvalidArguments;
9509
Ben Murdocheb525c52013-07-10 11:40:50 +01009510 stream_texture_manager()->DestroyStreamTexture(texture_ref->service_id());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009511 texture_manager()->SetStreamTexture(texture_ref, false);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009512 } else {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009513 LOCAL_SET_GL_ERROR(
9514 GL_INVALID_VALUE,
9515 "glDestroyStreamTextureCHROMIUM", "bad texture id.");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009516 }
9517
9518 return error::kNoError;
9519}
9520
9521#if defined(OS_MACOSX)
9522void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
9523 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
9524 texture_id);
9525 if (it != texture_to_io_surface_map_.end()) {
9526 // Found a previous IOSurface bound to this texture; release it.
9527 CFTypeRef surface = it->second;
9528 CFRelease(surface);
9529 texture_to_io_surface_map_.erase(it);
9530 }
9531}
9532#endif
9533
9534void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9535 GLenum target, GLsizei width, GLsizei height,
9536 GLuint io_surface_id, GLuint plane) {
9537#if defined(OS_MACOSX)
9538 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009539 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009540 GL_INVALID_OPERATION,
9541 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
9542 return;
9543 }
9544
9545 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
9546 if (!surface_support) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009547 LOCAL_SET_GL_ERROR(
9548 GL_INVALID_OPERATION,
9549 "glTexImageIOSurface2DCHROMIUM", "only supported on 10.6.");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009550 return;
9551 }
9552
9553 if (target != GL_TEXTURE_RECTANGLE_ARB) {
9554 // This might be supported in the future, and if we could require
9555 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9556 // could delete a lot of code. For now, perform strict validation so we
9557 // know what's going on.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009558 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009559 GL_INVALID_OPERATION,
9560 "glTexImageIOSurface2DCHROMIUM",
9561 "requires TEXTURE_RECTANGLE_ARB target");
9562 return;
9563 }
9564
9565 // Default target might be conceptually valid, but disallow it to avoid
9566 // accidents.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009567 TextureRef* texture_ref = GetTextureInfoForTargetUnlessDefault(target);
9568 if (!texture_ref) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009569 LOCAL_SET_GL_ERROR(
9570 GL_INVALID_OPERATION,
9571 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009572 return;
9573 }
9574
9575 // Look up the new IOSurface. Note that because of asynchrony
9576 // between processes this might fail; during live resizing the
9577 // plugin process might allocate and release an IOSurface before
9578 // this process gets a chance to look it up. Hold on to any old
9579 // IOSurface in this case.
9580 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
9581 if (!surface) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009582 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009583 GL_INVALID_OPERATION,
9584 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
9585 return;
9586 }
9587
9588 // Release any IOSurface previously bound to this texture.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009589 ReleaseIOSurfaceForTexture(texture_ref->service_id());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009590
9591 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9592 texture_to_io_surface_map_.insert(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009593 std::make_pair(texture_ref->service_id(), surface));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009594
9595 CGLContextObj context =
9596 static_cast<CGLContextObj>(context_->GetHandle());
9597
9598 CGLError err = surface_support->CGLTexImageIOSurface2D(
9599 context,
9600 target,
9601 GL_RGBA,
9602 width,
9603 height,
9604 GL_BGRA,
9605 GL_UNSIGNED_INT_8_8_8_8_REV,
9606 surface,
9607 plane);
9608
9609 if (err != kCGLNoError) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009610 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009611 GL_INVALID_OPERATION,
9612 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
9613 return;
9614 }
9615
9616 texture_manager()->SetLevelInfo(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009617 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009618 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
9619
9620#else
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009621 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009622 "glTexImageIOSurface2DCHROMIUM", "not supported.");
9623#endif
9624}
9625
9626static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
9627 switch (internalformat) {
9628 case GL_RGB565:
9629 return GL_RGB;
9630 case GL_RGBA4:
9631 return GL_RGBA;
9632 case GL_RGB5_A1:
9633 return GL_RGBA;
9634 case GL_RGB8_OES:
9635 return GL_RGB;
9636 case GL_RGBA8_OES:
9637 return GL_RGBA;
9638 case GL_LUMINANCE8_ALPHA8_EXT:
9639 return GL_LUMINANCE_ALPHA;
9640 case GL_LUMINANCE8_EXT:
9641 return GL_LUMINANCE;
9642 case GL_ALPHA8_EXT:
9643 return GL_ALPHA;
9644 case GL_RGBA32F_EXT:
9645 return GL_RGBA;
9646 case GL_RGB32F_EXT:
9647 return GL_RGB;
9648 case GL_ALPHA32F_EXT:
9649 return GL_ALPHA;
9650 case GL_LUMINANCE32F_EXT:
9651 return GL_LUMINANCE;
9652 case GL_LUMINANCE_ALPHA32F_EXT:
9653 return GL_LUMINANCE_ALPHA;
9654 case GL_RGBA16F_EXT:
9655 return GL_RGBA;
9656 case GL_RGB16F_EXT:
9657 return GL_RGB;
9658 case GL_ALPHA16F_EXT:
9659 return GL_ALPHA;
9660 case GL_LUMINANCE16F_EXT:
9661 return GL_LUMINANCE;
9662 case GL_LUMINANCE_ALPHA16F_EXT:
9663 return GL_LUMINANCE_ALPHA;
9664 case GL_BGRA8_EXT:
9665 return GL_BGRA_EXT;
9666 default:
9667 return GL_NONE;
9668 }
9669}
9670
9671void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
9672 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01009673 GLenum internal_format, GLenum dest_type) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009674 TextureRef* dest_texture_ref = GetTexture(dest_id);
9675 TextureRef* source_texture_ref = GetTexture(source_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009676
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009677 if (!source_texture_ref || !dest_texture_ref) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009678 LOCAL_SET_GL_ERROR(
9679 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009680 return;
9681 }
9682
9683 if (GL_TEXTURE_2D != target) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009684 LOCAL_SET_GL_ERROR(
9685 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009686 return;
9687 }
9688
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009689 Texture* source_texture = source_texture_ref->texture();
9690 Texture* dest_texture = dest_texture_ref->texture();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009691 if (dest_texture->target() != GL_TEXTURE_2D ||
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01009692 (source_texture->target() != GL_TEXTURE_2D &&
9693 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009694 LOCAL_SET_GL_ERROR(
9695 GL_INVALID_VALUE,
9696 "glCopyTextureCHROMIUM", "invalid texture target binding");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009697 return;
9698 }
9699
9700 int source_width, source_height, dest_width, dest_height;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009701
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01009702 if (source_texture->target() == GL_TEXTURE_2D) {
9703 if (!source_texture->GetLevelSize(GL_TEXTURE_2D, 0, &source_width,
9704 &source_height)) {
9705 LOCAL_SET_GL_ERROR(
9706 GL_INVALID_VALUE,
9707 "glCopyTextureChromium", "source texture has no level 0");
9708 return;
9709 }
9710
9711 // Check that this type of texture is allowed.
9712 if (!texture_manager()->ValidForTarget(GL_TEXTURE_2D, level, source_width,
9713 source_height, 1)) {
9714 LOCAL_SET_GL_ERROR(
9715 GL_INVALID_VALUE,
9716 "glCopyTextureCHROMIUM", "Bad dimensions");
9717 return;
9718 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009719 }
9720
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01009721 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
Ben Murdoch558790d2013-07-30 15:19:42 +01009722 UpdateStreamTextureIfNeeded(source_texture);
Ben Murdocheb525c52013-07-10 11:40:50 +01009723 DCHECK(stream_texture_manager());
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01009724 StreamTexture* stream_tex =
Ben Murdocheb525c52013-07-10 11:40:50 +01009725 stream_texture_manager()->LookupStreamTexture(
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01009726 source_texture->service_id());
9727 if (!stream_tex) {
9728 LOCAL_SET_GL_ERROR(
9729 GL_INVALID_VALUE,
9730 "glCopyTextureChromium", "Stream texture lookup failed");
9731 return;
9732 }
9733 gfx::Size size = stream_tex->GetSize();
9734 source_width = size.width();
9735 source_height = size.height();
9736 if (source_width <= 0 || source_height <= 0) {
9737 LOCAL_SET_GL_ERROR(
9738 GL_INVALID_VALUE,
9739 "glCopyTextureChromium", "invalid streamtexture size");
9740 return;
9741 }
9742 }
9743
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009744 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
9745 // needed because it takes 10s of milliseconds to initialize.
9746 if (!copy_texture_CHROMIUM_.get()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009747 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009748 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009749 copy_texture_CHROMIUM_->Initialize(this);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009750 RestoreCurrentFramebufferBindings();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009751 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009752 return;
9753 }
9754
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01009755 GLenum dest_type_previous;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009756 GLenum dest_internal_format;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009757 bool dest_level_defined = dest_texture->GetLevelSize(
9758 GL_TEXTURE_2D, level, &dest_width, &dest_height);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009759
9760 if (dest_level_defined) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01009761 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009762 &dest_internal_format);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01009763 }
9764
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009765 // Resize the destination texture to the dimensions of the source texture.
9766 if (!dest_level_defined || dest_width != source_width ||
9767 dest_height != source_height ||
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01009768 dest_internal_format != internal_format ||
9769 dest_type_previous != dest_type) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009770 // Ensure that the glTexImage2D succeeds.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009771 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
9772 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01009773 glTexImage2D(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009774 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
9775 0, internal_format, dest_type, NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009776 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009777 if (error != GL_NO_ERROR) {
9778 RestoreCurrentTexture2DBindings();
9779 return;
9780 }
9781
9782 texture_manager()->SetLevelInfo(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009783 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009784 source_height, 1, 0, internal_format, dest_type, true);
9785 } else {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009786 texture_manager()->SetLevelCleared(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009787 dest_texture_ref, GL_TEXTURE_2D, level, true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009788 }
9789
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01009790 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
9791 // before presenting.
9792 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
9793 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
9794 // instead of using default matrix crbug.com/226218.
9795 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
9796 0.0f, 1.0f, 0.0f, 0.0f,
9797 0.0f, 0.0f, 1.0f, 0.0f,
9798 0.0f, 0.0f, 0.0f, 1.0f};
9799 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
9800 this,
9801 source_texture->target(),
9802 dest_texture->target(),
9803 source_texture->service_id(),
9804 dest_texture->service_id(), level,
9805 source_width, source_height,
9806 unpack_flip_y_,
9807 unpack_premultiply_alpha_,
9808 unpack_unpremultiply_alpha_,
9809 default_matrix);
9810 } else {
9811 copy_texture_CHROMIUM_->DoCopyTexture(
9812 this,
9813 source_texture->target(),
9814 dest_texture->target(),
9815 source_texture->service_id(),
9816 dest_texture->service_id(), level,
9817 source_width, source_height,
9818 unpack_flip_y_,
9819 unpack_premultiply_alpha_,
9820 unpack_unpremultiply_alpha_);
9821 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009822}
9823
9824static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
9825 switch (internalformat) {
9826 case GL_RGB565:
9827 return GL_UNSIGNED_SHORT_5_6_5;
9828 case GL_RGBA4:
9829 return GL_UNSIGNED_SHORT_4_4_4_4;
9830 case GL_RGB5_A1:
9831 return GL_UNSIGNED_SHORT_5_5_5_1;
9832 case GL_RGB8_OES:
9833 return GL_UNSIGNED_BYTE;
9834 case GL_RGBA8_OES:
9835 return GL_UNSIGNED_BYTE;
9836 case GL_LUMINANCE8_ALPHA8_EXT:
9837 return GL_UNSIGNED_BYTE;
9838 case GL_LUMINANCE8_EXT:
9839 return GL_UNSIGNED_BYTE;
9840 case GL_ALPHA8_EXT:
9841 return GL_UNSIGNED_BYTE;
9842 case GL_RGBA32F_EXT:
9843 return GL_FLOAT;
9844 case GL_RGB32F_EXT:
9845 return GL_FLOAT;
9846 case GL_ALPHA32F_EXT:
9847 return GL_FLOAT;
9848 case GL_LUMINANCE32F_EXT:
9849 return GL_FLOAT;
9850 case GL_LUMINANCE_ALPHA32F_EXT:
9851 return GL_FLOAT;
9852 case GL_RGBA16F_EXT:
9853 return GL_HALF_FLOAT_OES;
9854 case GL_RGB16F_EXT:
9855 return GL_HALF_FLOAT_OES;
9856 case GL_ALPHA16F_EXT:
9857 return GL_HALF_FLOAT_OES;
9858 case GL_LUMINANCE16F_EXT:
9859 return GL_HALF_FLOAT_OES;
9860 case GL_LUMINANCE_ALPHA16F_EXT:
9861 return GL_HALF_FLOAT_OES;
9862 case GL_BGRA8_EXT:
9863 return GL_UNSIGNED_BYTE;
9864 default:
9865 return GL_NONE;
9866 }
9867}
9868
9869void GLES2DecoderImpl::DoTexStorage2DEXT(
9870 GLenum target,
9871 GLint levels,
9872 GLenum internal_format,
9873 GLsizei width,
9874 GLsizei height) {
9875 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
9876 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
9877 TextureManager::ComputeMipMapCount(width, height, 1) < levels) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009878 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009879 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
9880 return;
9881 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009882 TextureRef* texture_ref = GetTextureInfoForTarget(target);
9883 if (!texture_ref) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009884 LOCAL_SET_GL_ERROR(
9885 GL_INVALID_OPERATION,
9886 "glTexStorage2DEXT", "unknown texture for target");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009887 return;
9888 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009889 Texture* texture = texture_ref->texture();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009890 if (texture->IsAttachedToFramebuffer()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009891 clear_state_dirty_ = true;
9892 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009893 if (texture->IsImmutable()) {
9894 LOCAL_SET_GL_ERROR(
9895 GL_INVALID_OPERATION,
9896 "glTexStorage2DEXT", "texture is immutable");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009897 return;
9898 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009899
9900 GLenum format = ExtractFormatFromStorageFormat(internal_format);
9901 GLenum type = ExtractTypeFromStorageFormat(internal_format);
9902
9903 {
9904 GLsizei level_width = width;
9905 GLsizei level_height = height;
9906 uint32 estimated_size = 0;
9907 for (int ii = 0; ii < levels; ++ii) {
9908 uint32 level_size = 0;
9909 if (!GLES2Util::ComputeImageDataSizes(
9910 level_width, level_height, format, type, state_.unpack_alignment,
9911 &estimated_size, NULL, NULL) ||
9912 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
9913 LOCAL_SET_GL_ERROR(
9914 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
9915 return;
9916 }
9917 level_width = std::max(1, level_width >> 1);
9918 level_height = std::max(1, level_height >> 1);
9919 }
9920 if (!EnsureGPUMemoryAvailable(estimated_size)) {
9921 LOCAL_SET_GL_ERROR(
9922 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
9923 return;
9924 }
9925 }
9926
9927 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01009928 glTexStorage2DEXT(target, levels, internal_format, width, height);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009929 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009930 if (error == GL_NO_ERROR) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009931 GLsizei level_width = width;
9932 GLsizei level_height = height;
9933 for (int ii = 0; ii < levels; ++ii) {
9934 texture_manager()->SetLevelInfo(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009935 texture_ref, target, ii, format,
9936 level_width, level_height, 1, 0, format, type, false);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009937 level_width = std::max(1, level_width >> 1);
9938 level_height = std::max(1, level_height >> 1);
9939 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009940 texture->SetImmutable(true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009941 }
9942}
9943
9944error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009945 uint32 immediate_data_size, const cmds::GenMailboxCHROMIUM& c) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009946 MailboxName name;
9947 mailbox_manager()->GenerateMailboxName(&name);
9948 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
9949 Bucket* bucket = CreateBucket(bucket_id);
9950
9951 bucket->SetSize(GL_MAILBOX_SIZE_CHROMIUM);
9952 bucket->SetData(&name, 0, GL_MAILBOX_SIZE_CHROMIUM);
9953
9954 return error::kNoError;
9955}
9956
9957void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
9958 const GLbyte* mailbox) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009959 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01009960 "context", logger_.GetLogPrefix(),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009961 "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
9962
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009963 TextureRef* texture_ref = GetTextureInfoForTarget(target);
9964 if (!texture_ref) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009965 LOCAL_SET_GL_ERROR(
9966 GL_INVALID_OPERATION,
9967 "glProduceTextureCHROMIUM", "unknown texture for target");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009968 return;
9969 }
9970
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01009971 Texture* produced = texture_manager()->Produce(texture_ref);
9972 if (!produced) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009973 LOCAL_SET_GL_ERROR(
9974 GL_INVALID_OPERATION,
9975 "glProduceTextureCHROMIUM", "invalid texture");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009976 return;
9977 }
9978
9979 if (!group_->mailbox_manager()->ProduceTexture(
9980 target,
9981 *reinterpret_cast<const MailboxName*>(mailbox),
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01009982 produced)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009983 LOCAL_SET_GL_ERROR(
9984 GL_INVALID_OPERATION,
9985 "glProduceTextureCHROMIUM", "invalid mailbox name");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009986 return;
9987 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00009988}
9989
9990void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
9991 const GLbyte* mailbox) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009992 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01009993 "context", logger_.GetLogPrefix(),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009994 "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
9995
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01009996 scoped_refptr<TextureRef> texture_ref =
9997 GetTextureInfoForTargetUnlessDefault(target);
9998 if (!texture_ref.get()) {
9999 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10000 "glConsumeTextureCHROMIUM",
10001 "unknown texture for target");
10002 return;
10003 }
10004 GLuint client_id = texture_ref->client_id();
10005 if (!client_id) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010006 LOCAL_SET_GL_ERROR(
10007 GL_INVALID_OPERATION,
10008 "glConsumeTextureCHROMIUM", "unknown texture for target");
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010009 return;
10010 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010010011 Texture* texture =
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010012 group_->mailbox_manager()->ConsumeTexture(
10013 target,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010010014 *reinterpret_cast<const MailboxName*>(mailbox));
10015 if (!texture) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010016 LOCAL_SET_GL_ERROR(
10017 GL_INVALID_OPERATION,
10018 "glConsumeTextureCHROMIUM", "invalid mailbox name");
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010019 return;
10020 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010010021 if (texture->target() != target) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010022 LOCAL_SET_GL_ERROR(
10023 GL_INVALID_OPERATION,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010010024 "glConsumeTextureCHROMIUM", "invalid target");
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010025 return;
10026 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010010027
10028 DeleteTexturesHelper(1, &client_id);
10029 texture_ref = texture_manager()->Consume(client_id, texture);
10030 glBindTexture(target, texture_ref->service_id());
10031
10032 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
10033 unit.bind_target = target;
10034 switch (target) {
10035 case GL_TEXTURE_2D:
10036 unit.bound_texture_2d = texture_ref;
10037 break;
10038 case GL_TEXTURE_CUBE_MAP:
10039 unit.bound_texture_cube_map = texture_ref;
10040 break;
10041 case GL_TEXTURE_EXTERNAL_OES:
10042 unit.bound_texture_external_oes = texture_ref;
10043 break;
10044 case GL_TEXTURE_RECTANGLE_ARB:
10045 unit.bound_texture_rectangle_arb = texture_ref;
10046 break;
10047 default:
10048 NOTREACHED(); // Validation should prevent us getting here.
10049 break;
10050 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010051}
10052
10053void GLES2DecoderImpl::DoInsertEventMarkerEXT(
10054 GLsizei length, const GLchar* marker) {
10055 if (!marker) {
10056 marker = "";
10057 }
10058 debug_marker_manager_.SetMarker(
10059 length ? std::string(marker, length) : std::string(marker));
10060}
10061
10062void GLES2DecoderImpl::DoPushGroupMarkerEXT(
10063 GLsizei length, const GLchar* marker) {
10064 if (!marker) {
10065 marker = "";
10066 }
10067 debug_marker_manager_.PushGroup(
10068 length ? std::string(marker, length) : std::string(marker));
10069}
10070
10071void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
10072 debug_marker_manager_.PopGroup();
10073}
10074
10075void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
10076 GLenum target, GLint image_id) {
10077 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
10078 if (target != GL_TEXTURE_2D) {
10079 // This might be supported in the future.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010080 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010081 GL_INVALID_OPERATION,
10082 "glBindTexImage2DCHROMIUM", "requires TEXTURE_2D target");
10083 return;
10084 }
10085
10086 // Default target might be conceptually valid, but disallow it to avoid
10087 // accidents.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010010088 TextureRef* texture_ref = GetTextureInfoForTargetUnlessDefault(target);
10089 if (!texture_ref) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010090 LOCAL_SET_GL_ERROR(
10091 GL_INVALID_OPERATION,
10092 "glBindTexImage2DCHROMIUM", "no texture bound");
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010093 return;
10094 }
10095
10096 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10097 if (!gl_image) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010098 LOCAL_SET_GL_ERROR(
10099 GL_INVALID_OPERATION,
10100 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010101 return;
10102 }
10103
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010010104 {
10105 ScopedGLErrorSuppressor suppressor(
10106 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", this);
10107 if (!gl_image->BindTexImage()) {
10108 LOCAL_SET_GL_ERROR(
10109 GL_INVALID_OPERATION,
10110 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
10111 return;
10112 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010113 }
10114
10115 gfx::Size size = gl_image->GetSize();
10116 texture_manager()->SetLevelInfo(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010010117 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010118 GL_RGBA, GL_UNSIGNED_BYTE, true);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010010119 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010120}
10121
10122void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
10123 GLenum target, GLint image_id) {
10124 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
10125 if (target != GL_TEXTURE_2D) {
10126 // This might be supported in the future.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010127 LOCAL_SET_GL_ERROR(
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010128 GL_INVALID_OPERATION,
10129 "glReleaseTexImage2DCHROMIUM", "requires TEXTURE_2D target");
10130 return;
10131 }
10132
10133 // Default target might be conceptually valid, but disallow it to avoid
10134 // accidents.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010010135 TextureRef* texture_ref = GetTextureInfoForTargetUnlessDefault(target);
10136 if (!texture_ref) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010137 LOCAL_SET_GL_ERROR(
10138 GL_INVALID_OPERATION,
10139 "glReleaseTexImage2DCHROMIUM", "no texture bound");
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010140 return;
10141 }
10142
10143 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
10144 if (!gl_image) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010145 LOCAL_SET_GL_ERROR(
10146 GL_INVALID_OPERATION,
10147 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010148 return;
10149 }
10150
10151 // Do nothing when image is not currently bound.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010010152 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010153 return;
10154
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010010155 {
10156 ScopedGLErrorSuppressor suppressor(
10157 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", this);
10158 gl_image->ReleaseTexImage();
10159 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010160
10161 texture_manager()->SetLevelInfo(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010010162 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010163 GL_RGBA, GL_UNSIGNED_BYTE, false);
10164}
10165
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010166error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
10167 uint32 immediate_data_size, const cmds::TraceBeginCHROMIUM& c) {
10168 Bucket* bucket = GetBucket(c.bucket_id);
10169 if (!bucket || bucket->size() == 0) {
10170 return error::kInvalidArguments;
10171 }
10172 std::string command_name;
10173 if (!bucket->GetAsString(&command_name)) {
10174 return error::kInvalidArguments;
10175 }
10176 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
10177 if (!gpu_tracer_->Begin(command_name)) {
10178 LOCAL_SET_GL_ERROR(
10179 GL_INVALID_OPERATION,
10180 "glTraceBeginCHROMIUM", "unable to create begin trace");
10181 return error::kNoError;
10182 }
10183 return error::kNoError;
10184}
10185
10186void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
10187 if (gpu_tracer_->CurrentName().empty()) {
10188 LOCAL_SET_GL_ERROR(
10189 GL_INVALID_OPERATION,
10190 "glTraceEndCHROMIUM", "no trace begin found");
10191 return;
10192 }
10193 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
10194 gpu_tracer_->End();
10195}
10196
10197void GLES2DecoderImpl::DoDrawBuffersEXT(
10198 GLsizei count, const GLenum* bufs) {
10199 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
10200 LOCAL_SET_GL_ERROR(
10201 GL_INVALID_VALUE,
10202 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
10203 return;
10204 }
10205
10206 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
10207 if (framebuffer) {
10208 for (GLsizei i = 0; i < count; ++i) {
10209 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
10210 bufs[i] != GL_NONE) {
10211 LOCAL_SET_GL_ERROR(
10212 GL_INVALID_OPERATION,
10213 "glDrawBuffersEXT",
10214 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
10215 return;
10216 }
10217 }
10218 glDrawBuffersARB(count, bufs);
10219 framebuffer->SetDrawBuffers(count, bufs);
10220 } else { // backbuffer
10221 if (count > 1 ||
10222 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
10223 LOCAL_SET_GL_ERROR(
10224 GL_INVALID_OPERATION,
10225 "glDrawBuffersEXT",
10226 "more than one buffer or bufs not GL_NONE or GL_BACK");
10227 return;
10228 }
10229 GLenum mapped_buf = bufs[0];
10230 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10231 bufs[0] == GL_BACK) {
10232 mapped_buf = GL_COLOR_ATTACHMENT0;
10233 }
10234 glDrawBuffersARB(count, &mapped_buf);
10235 group_->set_draw_buffer(bufs[0]);
10236 }
10237}
10238
10239bool GLES2DecoderImpl::ValidateAsyncTransfer(
10240 const char* function_name,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010010241 TextureRef* texture_ref,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010242 GLenum target,
10243 GLint level,
10244 const void * data) {
10245 // We only support async uploads to 2D textures for now.
10246 if (GL_TEXTURE_2D != target) {
10247 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10248 return false;
10249 }
10250 // We only support uploads to level zero for now.
10251 if (level != 0) {
10252 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
10253 return false;
10254 }
10255 // A transfer buffer must be bound, even for asyncTexImage2D.
10256 if (data == NULL) {
10257 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
10258 return false;
10259 }
10260 // We only support one async transfer in progress.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010010261 if (!texture_ref ||
10262 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010263 LOCAL_SET_GL_ERROR(
10264 GL_INVALID_OPERATION,
10265 function_name, "transfer already in progress");
10266 return false;
10267 }
10268 return true;
10269}
10270
10271error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
10272 uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) {
10273 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
10274 GLenum target = static_cast<GLenum>(c.target);
10275 GLint level = static_cast<GLint>(c.level);
10276 GLint internal_format = static_cast<GLint>(c.internalformat);
10277 GLsizei width = static_cast<GLsizei>(c.width);
10278 GLsizei height = static_cast<GLsizei>(c.height);
10279 GLint border = static_cast<GLint>(c.border);
10280 GLenum format = static_cast<GLenum>(c.format);
10281 GLenum type = static_cast<GLenum>(c.type);
10282 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10283 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10284 uint32 pixels_size;
10285
10286 // TODO(epenner): Move this and copies of this memory validation
10287 // into ValidateTexImage2D step.
10288 if (!GLES2Util::ComputeImageDataSizes(
10289 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
10290 NULL)) {
10291 return error::kOutOfBounds;
10292 }
10293 const void* pixels = NULL;
10294 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10295 pixels = GetSharedMemoryAs<const void*>(
10296 pixels_shm_id, pixels_shm_offset, pixels_size);
10297 if (!pixels) {
10298 return error::kOutOfBounds;
10299 }
10300 }
10301
10302 // All the normal glTexSubImage2D validation.
10303 if (!ValidateTexImage2D(
10304 "glAsyncTexImage2DCHROMIUM", target, level, internal_format,
10305 width, height, border, format, type, pixels, pixels_size)) {
10306 return error::kNoError;
10307 }
10308
10309 // Extra async validation.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010010310 TextureRef* texture_ref = GetTextureInfoForTarget(target);
10311 Texture* texture = texture_ref->texture();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010312 if (!ValidateAsyncTransfer(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010010313 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010314 return error::kNoError;
10315
10316 // Don't allow async redefinition of a textures.
10317 if (texture->IsDefined()) {
10318 LOCAL_SET_GL_ERROR(
10319 GL_INVALID_OPERATION,
10320 "glAsyncTexImage2DCHROMIUM", "already defined");
10321 return error::kNoError;
10322 }
10323
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010324 if (!EnsureGPUMemoryAvailable(pixels_size)) {
10325 LOCAL_SET_GL_ERROR(
10326 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
10327 return error::kNoError;
10328 }
10329
10330 // We know the memory/size is safe, so get the real shared memory since
10331 // it might need to be duped to prevent use-after-free of the memory.
10332 gpu::Buffer buffer = GetSharedMemoryBuffer(c.pixels_shm_id);
10333 base::SharedMemory* shared_memory = buffer.shared_memory;
10334 uint32 shm_size = buffer.size;
10335 uint32 shm_data_offset = c.pixels_shm_offset;
10336 uint32 shm_data_size = pixels_size;
10337
10338 // Setup the parameters.
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010010339 AsyncTexImage2DParams tex_params = {
10340 target, level, static_cast<GLenum>(internal_format),
10341 width, height, border, format, type};
10342 AsyncMemoryParams mem_params = {
10343 shared_memory, shm_size, shm_data_offset, shm_data_size};
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010344
10345 // Set up the async state if needed, and make the texture
10346 // immutable so the async state stays valid. The level info
10347 // is set up lazily when the transfer completes.
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010010348 AsyncPixelTransferDelegate* delegate =
10349 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
10350 tex_params);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010351 texture->SetImmutable(true);
10352
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010010353 delegate->AsyncTexImage2D(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010354 tex_params,
10355 mem_params,
10356 base::Bind(&TextureManager::SetLevelInfoFromParams,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010010357 // The callback is only invoked if the transfer delegate still
10358 // exists, which implies through manager->texture_ref->state
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010359 // ownership that both of these pointers are valid.
10360 base::Unretained(texture_manager()),
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010010361 base::Unretained(texture_ref),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010362 tex_params));
10363 return error::kNoError;
10364}
10365
10366error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
10367 uint32 immediate_data_size, const cmds::AsyncTexSubImage2DCHROMIUM& c) {
10368 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
10369 GLenum target = static_cast<GLenum>(c.target);
10370 GLint level = static_cast<GLint>(c.level);
10371 GLint xoffset = static_cast<GLint>(c.xoffset);
10372 GLint yoffset = static_cast<GLint>(c.yoffset);
10373 GLsizei width = static_cast<GLsizei>(c.width);
10374 GLsizei height = static_cast<GLsizei>(c.height);
10375 GLenum format = static_cast<GLenum>(c.format);
10376 GLenum type = static_cast<GLenum>(c.type);
10377
10378 // TODO(epenner): Move this and copies of this memory validation
10379 // into ValidateTexSubImage2D step.
10380 uint32 data_size;
10381 if (!GLES2Util::ComputeImageDataSizes(
10382 width, height, format, type, state_.unpack_alignment, &data_size,
10383 NULL, NULL)) {
10384 return error::kOutOfBounds;
10385 }
10386 const void* pixels = GetSharedMemoryAs<const void*>(
10387 c.data_shm_id, c.data_shm_offset, data_size);
10388
10389 // All the normal glTexSubImage2D validation.
10390 error::Error error = error::kNoError;
10391 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
10392 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
10393 return error;
10394 }
10395
10396 // Extra async validation.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010010397 TextureRef* texture_ref = GetTextureInfoForTarget(target);
10398 Texture* texture = texture_ref->texture();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010399 if (!ValidateAsyncTransfer(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010010400 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010401 return error::kNoError;
10402
10403 // Guarantee async textures are always 'cleared' as follows:
10404 // - AsyncTexImage2D can not redefine an existing texture
10405 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10406 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10407 // - Textures become immutable after an async call.
10408 // This way we know in all cases that an async texture is always clear.
10409 if (!texture->SafeToRenderFrom()) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010010410 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10411 target, level)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010412 LOCAL_SET_GL_ERROR(
10413 GL_OUT_OF_MEMORY,
10414 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
10415 return error::kNoError;
10416 }
10417 }
10418
10419 // We know the memory/size is safe, so get the real shared memory since
10420 // it might need to be duped to prevent use-after-free of the memory.
10421 gpu::Buffer buffer = GetSharedMemoryBuffer(c.data_shm_id);
10422 base::SharedMemory* shared_memory = buffer.shared_memory;
10423 uint32 shm_size = buffer.size;
10424 uint32 shm_data_offset = c.data_shm_offset;
10425 uint32 shm_data_size = data_size;
10426
10427 // Setup the parameters.
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010010428 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010429 width, height, format, type};
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010010430 AsyncMemoryParams mem_params = {shared_memory, shm_size,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010431 shm_data_offset, shm_data_size};
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010010432 AsyncPixelTransferDelegate* delegate =
10433 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10434 if (!delegate) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010435 // TODO(epenner): We may want to enforce exclusive use
10436 // of async APIs in which case this should become an error,
10437 // (the texture should have been async defined).
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010010438 AsyncTexImage2DParams define_params = {target, level,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010439 0, 0, 0, 0, 0, 0};
10440 texture->GetLevelSize(target, level, &define_params.width,
10441 &define_params.height);
10442 texture->GetLevelType(target, level, &define_params.type,
10443 &define_params.internal_format);
10444 // Set up the async state if needed, and make the texture
10445 // immutable so the async state stays valid.
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010010446 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010010447 texture_ref, define_params);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010448 texture->SetImmutable(true);
10449 }
10450
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010010451 delegate->AsyncTexSubImage2D(tex_params, mem_params);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010452 return error::kNoError;
10453}
10454
10455error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10456 uint32 immediate_data_size, const cmds::WaitAsyncTexImage2DCHROMIUM& c) {
10457 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10458 GLenum target = static_cast<GLenum>(c.target);
10459
10460 if (GL_TEXTURE_2D != target) {
10461 LOCAL_SET_GL_ERROR(
10462 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
10463 return error::kNoError;
10464 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010010465 TextureRef* texture_ref = GetTextureInfoForTarget(target);
10466 if (!texture_ref) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010467 LOCAL_SET_GL_ERROR(
10468 GL_INVALID_OPERATION,
10469 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
10470 return error::kNoError;
10471 }
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010010472 AsyncPixelTransferDelegate* delegate =
10473 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10474 if (!delegate) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010010475 LOCAL_SET_GL_ERROR(
10476 GL_INVALID_OPERATION,
10477 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10478 return error::kNoError;
10479 }
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010010480 delegate->WaitForTransferCompletion();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010481 ProcessFinishedAsyncTransfers();
10482 return error::kNoError;
10483}
10484
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010485// Include the auto-generated part of this file. We split this because it means
10486// we can easily edit the non-auto generated parts right here in this file
10487// instead of having to edit some template or the code generator.
10488#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
10489
10490} // namespace gles2
10491} // namespace gpu