blob: 1489fc64ab1abe497db73b4b6bf6ea626c07cc09 [file] [log] [blame]
[email protected]529c6672012-01-04 02:18:261// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]96449d2c2009-11-25 00:01:322// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]8a837bb2010-01-05 00:21:245#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
[email protected]74470702010-01-06 18:51:166
7#include <stdio.h>
8
[email protected]1aef98132010-02-23 18:00:079#include <algorithm>
[email protected]f39f4b3f2010-05-12 17:04:0810#include <list>
[email protected]96449d2c2009-11-25 00:01:3211#include <map>
[email protected]94307712012-11-16 23:26:1112#include <stack>
[email protected]f39f4b3f2010-05-12 17:04:0813#include <string>
14#include <vector>
[email protected]5a6db6c2010-04-22 18:32:0615
[email protected]00eb49a2010-08-12 20:46:5716#include "base/at_exit.h"
[email protected]d353541f2012-05-03 22:45:4117#include "base/atomicops.h"
[email protected]9d37f062011-11-22 01:24:5218#include "base/bind.h"
[email protected]e844ae22012-01-14 03:36:2619#include "base/command_line.h"
[email protected]1078f912011-12-23 13:12:1420#include "base/debug/trace_event.h"
[email protected]e51bdf32011-11-23 22:21:4621#if defined(OS_MACOSX)
22#include "base/mac/scoped_cftyperef.h"
23#endif
[email protected]3b63f8f42011-03-28 01:54:1524#include "base/memory/scoped_ptr.h"
[email protected]f4390962013-06-11 07:29:2225#include "base/strings/string_number_conversions.h"
[email protected]d37231fa2010-04-09 21:16:0226#include "build/build_config.h"
[email protected]96449d2c2009-11-25 00:01:3227#define GLES2_GPU_SERVICE 1
[email protected]f4390962013-06-11 07:29:2228#include "gpu/command_buffer/common/debug_marker_manager.h"
[email protected]96449d2c2009-11-25 00:01:3229#include "gpu/command_buffer/common/gles2_cmd_format.h"
30#include "gpu/command_buffer/common/gles2_cmd_utils.h"
[email protected]066849e32010-05-03 19:14:1031#include "gpu/command_buffer/common/id_allocator.h"
[email protected]2ad674132013-06-05 07:48:5132#include "gpu/command_buffer/common/mailbox.h"
[email protected]f4390962013-06-11 07:29:2233#include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
34#include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
[email protected]3916c97e2010-02-25 03:20:5035#include "gpu/command_buffer/service/buffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3236#include "gpu/command_buffer/service/cmd_buffer_engine.h"
[email protected]3916c97e2010-02-25 03:20:5037#include "gpu/command_buffer/service/context_group.h"
[email protected]e259eb412012-10-13 05:47:2438#include "gpu/command_buffer/service/context_state.h"
[email protected]d3eba342013-04-18 21:11:5039#include "gpu/command_buffer/service/error_state.h"
[email protected]915a59a12010-09-30 21:29:1140#include "gpu/command_buffer/service/feature_info.h"
[email protected]a25fa872010-03-25 02:57:5841#include "gpu/command_buffer/service/framebuffer_manager.h"
[email protected]96449d2c2009-11-25 00:01:3242#include "gpu/command_buffer/service/gl_utils.h"
[email protected]43410e92012-04-20 17:06:2843#include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
[email protected]ba3176a2009-12-16 18:19:4644#include "gpu/command_buffer/service/gles2_cmd_validation.h"
[email protected]e844ae22012-01-14 03:36:2645#include "gpu/command_buffer/service/gpu_switches.h"
[email protected]fb97b662013-02-20 23:02:1446#include "gpu/command_buffer/service/gpu_tracer.h"
[email protected]09d50362012-10-18 20:54:3747#include "gpu/command_buffer/service/image_manager.h"
[email protected]78b514b2012-05-01 21:50:5948#include "gpu/command_buffer/service/mailbox_manager.h"
[email protected]ff6493f2012-07-31 19:52:2549#include "gpu/command_buffer/service/memory_tracking.h"
[email protected]a93bb842010-02-16 23:03:4750#include "gpu/command_buffer/service/program_manager.h"
[email protected]882ba1e22012-03-08 19:02:5351#include "gpu/command_buffer/service/query_manager.h"
[email protected]a25fa872010-03-25 02:57:5852#include "gpu/command_buffer/service/renderbuffer_manager.h"
[email protected]a93bb842010-02-16 23:03:4753#include "gpu/command_buffer/service/shader_manager.h"
[email protected]a550584e2010-09-17 18:01:4554#include "gpu/command_buffer/service/shader_translator.h"
[email protected]87fb6ab2012-06-13 22:28:0455#include "gpu/command_buffer/service/shader_translator_cache.h"
[email protected]b0af4f52011-09-28 22:04:4256#include "gpu/command_buffer/service/stream_texture.h"
57#include "gpu/command_buffer/service/stream_texture_manager.h"
[email protected]a93bb842010-02-16 23:03:4758#include "gpu/command_buffer/service/texture_manager.h"
[email protected]944b62f32012-09-27 02:20:4659#include "gpu/command_buffer/service/vertex_array_manager.h"
[email protected]f4390962013-06-11 07:29:2260#include "gpu/command_buffer/service/vertex_attrib_manager.h"
[email protected]d8bc3ec2013-03-07 06:28:4061#include "ui/gl/gl_bindings.h"
[email protected]5a36dc132013-07-23 23:17:5562#include "ui/gl/gl_fence.h"
[email protected]09d50362012-10-18 20:54:3763#include "ui/gl/gl_image.h"
[email protected]c9e2cbbb2012-05-12 21:17:2764#include "ui/gl/gl_implementation.h"
65#include "ui/gl/gl_surface.h"
[email protected]423e644f2013-06-19 00:48:2766
[email protected]e51bdf32011-11-23 22:21:4667#if defined(OS_MACOSX)
[email protected]423e644f2013-06-19 00:48:2768#include "ui/gl/io_surface_support_mac.h"
[email protected]e51bdf32011-11-23 22:21:4669#endif
[email protected]de17df392010-04-23 21:09:4170
[email protected]6eb775352013-08-27 05:57:1671#if defined(OS_WIN)
72#include "base/win/win_util.h"
73#endif
74
[email protected]693ca512012-11-13 18:09:1375// TODO(zmo): we can't include "City.h" due to type def conflicts.
76extern uint64 CityHash64(const char*, size_t);
77
[email protected]a7a27ace2009-12-12 00:11:2578namespace gpu {
[email protected]96449d2c2009-11-25 00:01:3279namespace gles2 {
80
[email protected]f0d74742011-10-03 16:31:0481namespace {
[email protected]693ca512012-11-13 18:09:1382
[email protected]f0d74742011-10-03 16:31:0483static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
[email protected]70dc60932013-06-04 03:33:4984static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
[email protected]aff39ac82013-06-08 04:53:1385static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
[email protected]693ca512012-11-13 18:09:1386
[email protected]3d944a82013-02-12 19:09:0287#if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
[email protected]693ca512012-11-13 18:09:1388khronos_uint64_t CityHashForAngle(const char* name, unsigned int len) {
89 return static_cast<khronos_uint64_t>(
90 CityHash64(name, static_cast<size_t>(len)));
91}
[email protected]3d944a82013-02-12 19:09:0292#endif
[email protected]693ca512012-11-13 18:09:1393
[email protected]448e459e2013-06-12 17:00:4194static bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
95 GLint rangeMax,
96 GLint precision) {
97 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
98}
99
[email protected]8dc1bf92013-03-12 03:58:21100static void GetShaderPrecisionFormatImpl(GLenum shader_type,
101 GLenum precision_type,
102 GLint *range, GLint *precision) {
103 switch (precision_type) {
104 case GL_LOW_INT:
105 case GL_MEDIUM_INT:
106 case GL_HIGH_INT:
107 // These values are for a 32-bit twos-complement integer format.
108 range[0] = 31;
109 range[1] = 30;
110 *precision = 0;
111 break;
112 case GL_LOW_FLOAT:
113 case GL_MEDIUM_FLOAT:
114 case GL_HIGH_FLOAT:
115 // These values are for an IEEE single-precision floating-point format.
116 range[0] = 127;
117 range[1] = 127;
118 *precision = 23;
119 break;
120 default:
121 NOTREACHED();
122 break;
123 }
124
[email protected]8af4d5e2013-03-15 23:55:33125 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
126 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
[email protected]8dc1bf92013-03-12 03:58:21127 // This function is sometimes defined even though it's really just
128 // a stub, so we need to set range and precision as if it weren't
129 // defined before calling it.
[email protected]501b57402013-03-14 22:21:44130 // On Mac OS with some GPUs, calling this generates a
131 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
132 // platforms.
[email protected]8dc1bf92013-03-12 03:58:21133 glGetShaderPrecisionFormat(shader_type, precision_type,
134 range, precision);
[email protected]448e459e2013-06-12 17:00:41135
136 // TODO(brianderson): Make the following official workarounds.
137
138 // Some drivers have bugs where they report the ranges as a negative number.
139 // Taking the absolute value here shouldn't hurt because negative numbers
140 // aren't expected anyway.
141 range[0] = abs(range[0]);
142 range[1] = abs(range[1]);
143
144 // If the driver reports a precision for highp float that isn't actually
145 // highp, don't pretend like it's supported because shader compilation will
146 // fail anyway.
147 if (precision_type == GL_HIGH_FLOAT &&
148 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
149 range[0] = 0;
150 range[1] = 0;
151 *precision = 0;
152 }
[email protected]8dc1bf92013-03-12 03:58:21153 }
154}
155
[email protected]b04e24c2013-01-08 18:35:25156} // namespace
[email protected]f0d74742011-10-03 16:31:04157
[email protected]6217d392010-03-25 22:08:35158class GLES2DecoderImpl;
159
[email protected]ab09b612013-03-11 22:11:51160// Local versions of the SET_GL_ERROR macros
161#define LOCAL_SET_GL_ERROR(error, function_name, msg) \
[email protected]d3eba342013-04-18 21:11:50162 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
[email protected]ab09b612013-03-11 22:11:51163#define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
[email protected]d3eba342013-04-18 21:11:50164 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
165 function_name, value, label)
[email protected]ab09b612013-03-11 22:11:51166#define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
[email protected]d3eba342013-04-18 21:11:50167 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
168 function_name, pname)
[email protected]ab09b612013-03-11 22:11:51169#define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
[email protected]d3eba342013-04-18 21:11:50170 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
171 function_name)
[email protected]ab09b612013-03-11 22:11:51172#define LOCAL_PEEK_GL_ERROR(function_name) \
[email protected]d3eba342013-04-18 21:11:50173 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
[email protected]ab09b612013-03-11 22:11:51174#define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
[email protected]d3eba342013-04-18 21:11:50175 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
[email protected]ab09b612013-03-11 22:11:51176#define LOCAL_PERFORMANCE_WARNING(msg) \
177 PerformanceWarning(__FILE__, __LINE__, msg)
178#define LOCAL_RENDER_WARNING(msg) \
179 RenderWarning(__FILE__, __LINE__, msg)
180
[email protected]07f54fcc2009-12-22 02:46:30181// Check that certain assumptions the code makes are true. There are places in
182// the code where shared memory is passed direclty to GL. Example, glUniformiv,
183// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
184// a few others) are 32bits. If they are not 32bits the code will have to change
185// to call those GL functions with service side memory and then copy the results
186// to shared memory, converting the sizes.
187COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
188 GLint_not_same_size_as_uint32);
189COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
190 GLint_not_same_size_as_uint32);
[email protected]f7b85372010-02-03 01:11:37191COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
192 GLfloat_not_same_size_as_float);
[email protected]07f54fcc2009-12-22 02:46:30193
[email protected]43f28f832010-02-03 02:28:48194// TODO(kbr): the use of this anonymous namespace core dumps the
195// linker on Mac OS X 10.6 when the symbol ordering file is used
196// namespace {
[email protected]96449d2c2009-11-25 00:01:32197
198// Returns the address of the first byte after a struct.
199template <typename T>
200const void* AddressAfterStruct(const T& pod) {
201 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
202}
203
[email protected]07f54fcc2009-12-22 02:46:30204// Returns the address of the frst byte after the struct or NULL if size >
205// immediate_data_size.
[email protected]96449d2c2009-11-25 00:01:32206template <typename RETURN_TYPE, typename COMMAND_TYPE>
[email protected]07f54fcc2009-12-22 02:46:30207RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
208 uint32 size,
209 uint32 immediate_data_size) {
210 return (size <= immediate_data_size) ?
211 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
212 NULL;
[email protected]96449d2c2009-11-25 00:01:32213}
214
[email protected]07f54fcc2009-12-22 02:46:30215// Computes the data size for certain gl commands like glUniform.
[email protected]a76b0052010-03-05 00:33:18216bool ComputeDataSize(
[email protected]96449d2c2009-11-25 00:01:32217 GLuint count,
218 size_t size,
[email protected]a76b0052010-03-05 00:33:18219 unsigned int elements_per_unit,
220 uint32* dst) {
221 uint32 value;
222 if (!SafeMultiplyUint32(count, size, &value)) {
223 return false;
224 }
225 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
226 return false;
227 }
228 *dst = value;
229 return true;
[email protected]96449d2c2009-11-25 00:01:32230}
231
232// A struct to hold info about each command.
233struct CommandInfo {
234 int arg_flags; // How to handle the arguments for this command
235 int arg_count; // How many arguments are expected for this command.
236};
237
238// A table of CommandInfo for all the commands.
239const CommandInfo g_command_info[] = {
[email protected]ed9f9cd2013-02-27 21:12:35240 #define GLES2_CMD_OP(name) { \
241 cmds::name::kArgFlags, \
242 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ \
[email protected]96449d2c2009-11-25 00:01:32243
244 GLES2_COMMAND_LIST(GLES2_CMD_OP)
245
246 #undef GLES2_CMD_OP
247};
248
[email protected]258a3313f2011-10-18 20:13:57249// Return true if a character belongs to the ASCII subset as defined in
250// GLSL ES 1.0 spec section 3.1.
251static bool CharacterIsValidForGLES(unsigned char c) {
252 // Printing characters are valid except " $ ` @ \ ' DEL.
253 if (c >= 32 && c <= 126 &&
254 c != '"' &&
255 c != '$' &&
256 c != '`' &&
257 c != '@' &&
258 c != '\\' &&
259 c != '\'') {
260 return true;
261 }
262 // Horizontal tab, line feed, vertical tab, form feed, carriage return
263 // are also valid.
264 if (c >= 9 && c <= 13) {
265 return true;
266 }
267
268 return false;
269}
270
271static bool StringIsValidForGLES(const char* str) {
272 for (; *str; ++str) {
273 if (!CharacterIsValidForGLES(*str)) {
274 return false;
275 }
276 }
277 return true;
278}
279
[email protected]297ca1c2011-06-20 23:08:46280// Wrapper for glEnable/glDisable that doesn't suck.
281static void EnableDisable(GLenum pname, bool enable) {
282 if (enable) {
283 glEnable(pname);
284 } else {
285 glDisable(pname);
286 }
287}
288
[email protected]6217d392010-03-25 22:08:35289// This class prevents any GL errors that occur when it is in scope from
290// being reported to the client.
291class ScopedGLErrorSuppressor {
292 public:
[email protected]ab09b612013-03-11 22:11:51293 explicit ScopedGLErrorSuppressor(
294 const char* function_name, GLES2DecoderImpl* decoder);
[email protected]6217d392010-03-25 22:08:35295 ~ScopedGLErrorSuppressor();
296 private:
[email protected]ab09b612013-03-11 22:11:51297 const char* function_name_;
[email protected]6217d392010-03-25 22:08:35298 GLES2DecoderImpl* decoder_;
299 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
300};
301
302// Temporarily changes a decoder's bound 2D texture and restore it when this
303// object goes out of scope. Also temporarily switches to using active texture
304// unit zero in case the client has changed that to something invalid.
305class ScopedTexture2DBinder {
306 public:
307 ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
308 ~ScopedTexture2DBinder();
309
310 private:
311 GLES2DecoderImpl* decoder_;
312 DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
313};
314
315// Temporarily changes a decoder's bound render buffer and restore it when this
316// object goes out of scope.
317class ScopedRenderBufferBinder {
318 public:
319 ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
320 ~ScopedRenderBufferBinder();
321
322 private:
323 GLES2DecoderImpl* decoder_;
324 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
325};
326
327// Temporarily changes a decoder's bound frame buffer and restore it when this
328// object goes out of scope.
329class ScopedFrameBufferBinder {
330 public:
331 ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
332 ~ScopedFrameBufferBinder();
333
334 private:
335 GLES2DecoderImpl* decoder_;
336 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
337};
338
[email protected]34ff8b0c2010-10-01 20:06:02339// Temporarily changes a decoder's bound frame buffer to a resolved version of
[email protected]c0701082011-04-20 00:34:52340// the multisampled offscreen render buffer if that buffer is multisampled, and,
[email protected]de26b3c2011-08-03 21:54:27341// if it is bound or enforce_internal_framebuffer is true. If internal is
342// true, the resolved framebuffer is not visible to the parent.
[email protected]34ff8b0c2010-10-01 20:06:02343class ScopedResolvedFrameBufferBinder {
344 public:
[email protected]e7e38032011-07-26 17:25:25345 ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
[email protected]de26b3c2011-08-03 21:54:27346 bool enforce_internal_framebuffer,
347 bool internal);
[email protected]34ff8b0c2010-10-01 20:06:02348 ~ScopedResolvedFrameBufferBinder();
349
350 private:
351 GLES2DecoderImpl* decoder_;
352 bool resolve_and_bind_;
353 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
354};
355
[email protected]6217d392010-03-25 22:08:35356// Encapsulates an OpenGL texture.
[email protected]ed9f9cd2013-02-27 21:12:35357class BackTexture {
[email protected]6217d392010-03-25 22:08:35358 public:
[email protected]ed9f9cd2013-02-27 21:12:35359 explicit BackTexture(GLES2DecoderImpl* decoder);
360 ~BackTexture();
[email protected]6217d392010-03-25 22:08:35361
362 // Create a new render texture.
363 void Create();
364
365 // Set the initial size and format of a render texture or resize it.
[email protected]678a73f2012-12-19 19:22:09366 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
[email protected]6217d392010-03-25 22:08:35367
368 // Copy the contents of the currently bound frame buffer.
[email protected]3a4d0c52011-06-29 23:11:58369 void Copy(const gfx::Size& size, GLenum format);
[email protected]6217d392010-03-25 22:08:35370
371 // Destroy the render texture. This must be explicitly called before
372 // destroying this object.
373 void Destroy();
374
[email protected]97872062010-11-03 19:07:05375 // Invalidate the texture. This can be used when a context is lost and it is
376 // not possible to make it current in order to free the resource.
377 void Invalidate();
378
[email protected]6217d392010-03-25 22:08:35379 GLuint id() const {
380 return id_;
381 }
382
[email protected]d37231fa2010-04-09 21:16:02383 gfx::Size size() const {
384 return size_;
385 }
386
[email protected]1078f912011-12-23 13:12:14387 size_t estimated_size() const {
[email protected]ff6493f2012-07-31 19:52:25388 return memory_tracker_.GetMemRepresented();
[email protected]1078f912011-12-23 13:12:14389 }
390
[email protected]6217d392010-03-25 22:08:35391 private:
392 GLES2DecoderImpl* decoder_;
[email protected]ff6493f2012-07-31 19:52:25393 MemoryTypeTracker memory_tracker_;
[email protected]68e81a4a62012-12-13 01:16:48394 size_t bytes_allocated_;
[email protected]6217d392010-03-25 22:08:35395 GLuint id_;
[email protected]d37231fa2010-04-09 21:16:02396 gfx::Size size_;
[email protected]ed9f9cd2013-02-27 21:12:35397 DISALLOW_COPY_AND_ASSIGN(BackTexture);
[email protected]6217d392010-03-25 22:08:35398};
399
400// Encapsulates an OpenGL render buffer of any format.
[email protected]ed9f9cd2013-02-27 21:12:35401class BackRenderbuffer {
[email protected]6217d392010-03-25 22:08:35402 public:
[email protected]ed9f9cd2013-02-27 21:12:35403 explicit BackRenderbuffer(GLES2DecoderImpl* decoder);
404 ~BackRenderbuffer();
[email protected]6217d392010-03-25 22:08:35405
406 // Create a new render buffer.
407 void Create();
408
409 // Set the initial size and format of a render buffer or resize it.
[email protected]34ff8b0c2010-10-01 20:06:02410 bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
[email protected]6217d392010-03-25 22:08:35411
412 // Destroy the render buffer. This must be explicitly called before destroying
413 // this object.
414 void Destroy();
415
[email protected]97872062010-11-03 19:07:05416 // Invalidate the render buffer. This can be used when a context is lost and
417 // it is not possible to make it current in order to free the resource.
418 void Invalidate();
419
[email protected]6217d392010-03-25 22:08:35420 GLuint id() const {
421 return id_;
422 }
423
[email protected]1078f912011-12-23 13:12:14424 size_t estimated_size() const {
[email protected]ff6493f2012-07-31 19:52:25425 return memory_tracker_.GetMemRepresented();
[email protected]1078f912011-12-23 13:12:14426 }
427
[email protected]6217d392010-03-25 22:08:35428 private:
429 GLES2DecoderImpl* decoder_;
[email protected]ff6493f2012-07-31 19:52:25430 MemoryTypeTracker memory_tracker_;
[email protected]68e81a4a62012-12-13 01:16:48431 size_t bytes_allocated_;
[email protected]6217d392010-03-25 22:08:35432 GLuint id_;
[email protected]ed9f9cd2013-02-27 21:12:35433 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
[email protected]6217d392010-03-25 22:08:35434};
435
436// Encapsulates an OpenGL frame buffer.
[email protected]ed9f9cd2013-02-27 21:12:35437class BackFramebuffer {
[email protected]6217d392010-03-25 22:08:35438 public:
[email protected]ed9f9cd2013-02-27 21:12:35439 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
440 ~BackFramebuffer();
[email protected]6217d392010-03-25 22:08:35441
442 // Create a new frame buffer.
443 void Create();
444
445 // Attach a color render buffer to a frame buffer.
[email protected]ed9f9cd2013-02-27 21:12:35446 void AttachRenderTexture(BackTexture* texture);
[email protected]6217d392010-03-25 22:08:35447
[email protected]b9363b22010-06-09 22:06:15448 // Attach a render buffer to a frame buffer. Note that this unbinds any
449 // currently bound frame buffer.
[email protected]ed9f9cd2013-02-27 21:12:35450 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
[email protected]6217d392010-03-25 22:08:35451
[email protected]6217d392010-03-25 22:08:35452 // Destroy the frame buffer. This must be explicitly called before destroying
453 // this object.
454 void Destroy();
455
[email protected]97872062010-11-03 19:07:05456 // Invalidate the frame buffer. This can be used when a context is lost and it
457 // is not possible to make it current in order to free the resource.
458 void Invalidate();
459
[email protected]6217d392010-03-25 22:08:35460 // See glCheckFramebufferStatusEXT.
461 GLenum CheckStatus();
462
463 GLuint id() const {
464 return id_;
465 }
466
467 private:
468 GLES2DecoderImpl* decoder_;
469 GLuint id_;
[email protected]ed9f9cd2013-02-27 21:12:35470 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
[email protected]6217d392010-03-25 22:08:35471};
[email protected]34ff8b0c2010-10-01 20:06:02472
[email protected]5a36dc132013-07-23 23:17:55473struct FenceCallback {
474 explicit FenceCallback()
475 : fence(gfx::GLFence::Create()) {
476 DCHECK(fence);
477 }
478 void AddCallback(base::Closure cb) {
479 callbacks.push_back(cb);
480 }
481 std::vector<base::Closure> callbacks;
482 scoped_ptr<gfx::GLFence> fence;
483};
484
485
[email protected]43f28f832010-02-03 02:28:48486// } // anonymous namespace.
[email protected]96449d2c2009-11-25 00:01:32487
[email protected]ddb1e5a2010-12-13 20:10:45488bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
489 uint32* service_texture_id) {
490 return false;
491}
492
[email protected]a3ded6d2010-10-19 06:44:39493GLES2Decoder::GLES2Decoder()
[email protected]55e136f2013-04-03 18:50:06494 : initialized_(false),
495 debug_(false),
[email protected]1d82e822013-04-10 21:32:32496 log_commands_(false) {
[email protected]96449d2c2009-11-25 00:01:32497}
498
[email protected]3916c97e2010-02-25 03:20:50499GLES2Decoder::~GLES2Decoder() {
500}
501
[email protected]57edfdad2012-02-07 04:57:15502bool GLES2Decoder::testing_force_is_angle_;
503
504void GLES2Decoder::set_testing_force_is_angle(bool force) {
505 testing_force_is_angle_ = force;
506}
507
508bool GLES2Decoder::IsAngle() {
509#if defined(OS_WIN)
510 return testing_force_is_angle_ ||
511 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
512#else
513 return testing_force_is_angle_;
514#endif
515}
516
[email protected]f39f4b3f2010-05-12 17:04:08517// This class implements GLES2Decoder so we don't have to expose all the GLES2
518// cmd stuff to outside this class.
[email protected]ee1e6aa2012-11-29 09:24:10519class GLES2DecoderImpl : public GLES2Decoder {
[email protected]f39f4b3f2010-05-12 17:04:08520 public:
[email protected]476ccb72012-12-06 15:52:52521 // Used by PrepForSetUniformByLocation to validate types.
522 struct BaseUniformInfo {
523 const GLenum* const valid_types;
524 size_t num_valid_types;
525 };
526
[email protected]aa7666122011-09-02 19:45:52527 explicit GLES2DecoderImpl(ContextGroup* group);
[email protected]b8e97b62012-09-30 15:09:00528 virtual ~GLES2DecoderImpl();
[email protected]f39f4b3f2010-05-12 17:04:08529
[email protected]96449d2c2009-11-25 00:01:32530 // Overridden from AsyncAPIInterface.
[email protected]f7a64ee2010-02-01 22:24:14531 virtual Error DoCommand(unsigned int command,
[email protected]3916c97e2010-02-25 03:20:50532 unsigned int arg_count,
[email protected]b8e97b62012-09-30 15:09:00533 const void* args) OVERRIDE;
[email protected]96449d2c2009-11-25 00:01:32534
535 // Overridden from AsyncAPIInterface.
[email protected]b8e97b62012-09-30 15:09:00536 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE;
[email protected]96449d2c2009-11-25 00:01:32537
538 // Overridden from GLES2Decoder.
[email protected]fbe20372011-06-01 01:46:38539 virtual bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
540 const scoped_refptr<gfx::GLContext>& context,
[email protected]069944672012-04-25 20:52:23541 bool offscreen,
[email protected]6217d392010-03-25 22:08:35542 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:29543 const DisallowedFeatures& disallowed_features,
[email protected]a3ded6d2010-10-19 06:44:39544 const char* allowed_extensions,
[email protected]b8e97b62012-09-30 15:09:00545 const std::vector<int32>& attribs) OVERRIDE;
546 virtual void Destroy(bool have_context) OVERRIDE;
[email protected]63c9b052012-05-17 18:27:38547 virtual void SetSurface(
548 const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
[email protected]2ad674132013-06-05 07:48:51549 virtual bool ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
[email protected]b8e97b62012-09-30 15:09:00550 virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
[email protected]9a5afa432011-07-22 18:16:39551 void UpdateParentTextureInfo();
[email protected]b8e97b62012-09-30 15:09:00552 virtual bool MakeCurrent() OVERRIDE;
553 virtual void ReleaseCurrent() OVERRIDE;
554 virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
555 virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
556 virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
[email protected]1868a342012-11-07 15:56:02557 virtual void RestoreState() const OVERRIDE;
[email protected]29a4d902013-02-26 20:18:06558
559 virtual void RestoreActiveTexture() const OVERRIDE {
560 state_.RestoreActiveTexture();
561 }
[email protected]217004512013-05-10 21:25:55562 virtual void RestoreAllTextureUnitBindings() const OVERRIDE {
563 state_.RestoreAllTextureUnitBindings();
564 }
[email protected]29a4d902013-02-26 20:18:06565 virtual void RestoreAttribute(unsigned index) const OVERRIDE {
566 state_.RestoreAttribute(index);
567 }
568 virtual void RestoreBufferBindings() const OVERRIDE {
569 state_.RestoreBufferBindings();
570 }
571 virtual void RestoreGlobalState() const OVERRIDE {
572 state_.RestoreGlobalState();
573 }
574 virtual void RestoreProgramBindings() const OVERRIDE {
575 state_.RestoreProgramBindings();
576 }
577 virtual void RestoreRenderbufferBindings() const OVERRIDE {
578 state_.RestoreRenderbufferBindings();
579 }
580 virtual void RestoreTextureUnitBindings(unsigned unit) const OVERRIDE {
581 state_.RestoreTextureUnitBindings(unit);
582 }
583 virtual void RestoreFramebufferBindings() const OVERRIDE;
584 virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
585
[email protected]b8e97b62012-09-30 15:09:00586 virtual QueryManager* GetQueryManager() OVERRIDE {
587 return query_manager_.get();
588 }
589 virtual VertexArrayManager* GetVertexArrayManager() OVERRIDE {
[email protected]944b62f32012-09-27 02:20:46590 return vertex_array_manager_.get();
591 }
[email protected]b8e97b62012-09-30 15:09:00592 virtual bool ProcessPendingQueries() OVERRIDE;
[email protected]2b1767cf2013-03-16 09:25:05593 virtual bool HasMoreIdleWork() OVERRIDE;
594 virtual void PerformIdleWork() OVERRIDE;
[email protected]43f28f832010-02-03 02:28:48595
[email protected]5a36dc132013-07-23 23:17:55596 virtual void WaitForReadPixels(base::Closure callback) OVERRIDE;
597
[email protected]9d37f062011-11-22 01:24:52598 virtual void SetResizeCallback(
[email protected]729c0b42013-05-26 02:05:07599 const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
[email protected]22f320a2011-08-30 01:17:00600
[email protected]1d82e822013-04-10 21:32:32601 virtual Logger* GetLogger() OVERRIDE;
[email protected]d3eba342013-04-18 21:11:50602 virtual ErrorState* GetErrorState() OVERRIDE;
[email protected]1d82e822013-04-10 21:32:32603
[email protected]e3932abb2013-03-13 00:01:37604 virtual void SetShaderCacheCallback(
605 const ShaderCacheCallback& callback) OVERRIDE;
[email protected]840a7e462013-02-27 01:29:51606 virtual void SetWaitSyncPointCallback(
607 const WaitSyncPointCallback& callback) OVERRIDE;
[email protected]22f320a2011-08-30 01:17:00608
[email protected]85a4ac22013-05-31 01:58:47609 virtual AsyncPixelTransferManager*
610 GetAsyncPixelTransferManager() OVERRIDE;
611 virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
[email protected]498b5c072013-06-04 19:30:07612 virtual void SetAsyncPixelTransferManagerForTest(
613 AsyncPixelTransferManager* manager) OVERRIDE;
[email protected]69a8701e2013-03-07 21:31:09614 void ProcessFinishedAsyncTransfers();
[email protected]32145a92012-12-17 09:01:59615
[email protected]1318e922010-09-17 22:03:16616 virtual bool GetServiceTextureId(uint32 client_texture_id,
[email protected]b8e97b62012-09-30 15:09:00617 uint32* service_texture_id) OVERRIDE;
[email protected]43f28f832010-02-03 02:28:48618
[email protected]63b465922012-09-06 02:04:52619 virtual uint32 GetTextureUploadCount() OVERRIDE;
620 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE;
621 virtual base::TimeDelta GetTotalProcessingCommandsTime() OVERRIDE;
[email protected]dc25dda2012-09-27 21:36:30622 virtual void AddProcessingCommandsTime(base::TimeDelta) OVERRIDE;
[email protected]63b465922012-09-06 02:04:52623
[email protected]8e3e0662010-08-23 18:46:30624 // Restores the current state to the user's settings.
625 void RestoreCurrentFramebufferBindings();
626 void RestoreCurrentRenderbufferBindings();
627 void RestoreCurrentTexture2DBindings();
628
[email protected]297ca1c2011-06-20 23:08:46629 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
630 void ApplyDirtyState();
631
632 // These check the state of the currently bound framebuffer or the
633 // backbuffer if no framebuffer is bound.
[email protected]f3b191b2013-06-19 03:43:54634 // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise
635 // check with all attached and enabled color attachments.
636 bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers);
[email protected]297ca1c2011-06-20 23:08:46637 bool BoundFramebufferHasDepthAttachment();
638 bool BoundFramebufferHasStencilAttachment();
639
[email protected]b8e97b62012-09-30 15:09:00640 virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
[email protected]38d139d2011-07-14 00:38:43641
[email protected]96449d2c2009-11-25 00:01:32642 private:
[email protected]70d34263c2013-01-09 00:27:45643 friend class ScopedFrameBufferBinder;
[email protected]6217d392010-03-25 22:08:35644 friend class ScopedGLErrorSuppressor;
[email protected]34ff8b0c2010-10-01 20:06:02645 friend class ScopedResolvedFrameBufferBinder;
[email protected]ed9f9cd2013-02-27 21:12:35646 friend class BackTexture;
647 friend class BackRenderbuffer;
648 friend class BackFramebuffer;
[email protected]6217d392010-03-25 22:08:35649
[email protected]c2f8c8402010-12-06 18:07:24650 // Initialize or re-initialize the shader translator.
651 bool InitializeShaderTranslator();
652
[email protected]302ce6d2011-07-07 23:28:11653 void UpdateCapabilities();
654
[email protected]ae51d192010-04-27 00:48:03655 // Helpers for the glGen and glDelete functions.
656 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
657 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
658 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
659 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
660 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
661 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
662 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
663 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
[email protected]882ba1e22012-03-08 19:02:53664 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
665 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
[email protected]944b62f32012-09-27 02:20:46666 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
667 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
[email protected]a93bb842010-02-16 23:03:47668
[email protected]70d34263c2013-01-09 00:27:45669 // Workarounds
670 void OnFboChanged() const;
[email protected]28718a92013-04-04 12:12:51671 void OnUseFramebuffer() const;
[email protected]70d34263c2013-01-09 00:27:45672
[email protected]3916c97e2010-02-25 03:20:50673 // TODO(gman): Cache these pointers?
[email protected]3916c97e2010-02-25 03:20:50674 BufferManager* buffer_manager() {
675 return group_->buffer_manager();
676 }
677
[email protected]a25fa872010-03-25 02:57:58678 RenderbufferManager* renderbuffer_manager() {
679 return group_->renderbuffer_manager();
680 }
681
682 FramebufferManager* framebuffer_manager() {
683 return group_->framebuffer_manager();
684 }
685
[email protected]3916c97e2010-02-25 03:20:50686 ProgramManager* program_manager() {
687 return group_->program_manager();
688 }
689
690 ShaderManager* shader_manager() {
691 return group_->shader_manager();
692 }
693
[email protected]29a4d902013-02-26 20:18:06694 const TextureManager* texture_manager() const {
695 return group_->texture_manager();
696 }
697
[email protected]3916c97e2010-02-25 03:20:50698 TextureManager* texture_manager() {
699 return group_->texture_manager();
700 }
701
[email protected]78b514b2012-05-01 21:50:59702 MailboxManager* mailbox_manager() {
703 return group_->mailbox_manager();
704 }
705
[email protected]09d50362012-10-18 20:54:37706 ImageManager* image_manager() {
707 return group_->image_manager();
708 }
709
[email protected]944b62f32012-09-27 02:20:46710 VertexArrayManager* vertex_array_manager() {
711 return vertex_array_manager_.get();
712 }
713
[email protected]7989c9e2013-01-23 06:39:26714 MemoryTracker* memory_tracker() {
715 return group_->memory_tracker();
716 }
717
[email protected]4f9958142013-07-02 03:58:07718 StreamTextureManager* stream_texture_manager() const {
719 return group_->stream_texture_manager();
720 }
721
[email protected]7989c9e2013-01-23 06:39:26722 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
723 MemoryTracker* tracker = memory_tracker();
724 if (tracker) {
725 return tracker->EnsureGPUMemoryAvailable(estimated_size);
726 }
727 return true;
728 }
729
[email protected]34ff8b0c2010-10-01 20:06:02730 bool IsOffscreenBufferMultisampled() const {
731 return offscreen_target_samples_ > 1;
732 }
733
[email protected]ed9f9cd2013-02-27 21:12:35734 // Creates a Texture for the given texture.
[email protected]370eaf12013-05-18 09:19:49735 TextureRef* CreateTexture(
[email protected]ae51d192010-04-27 00:48:03736 GLuint client_id, GLuint service_id) {
[email protected]ed9f9cd2013-02-27 21:12:35737 return texture_manager()->CreateTexture(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47738 }
739
740 // Gets the texture info for the given texture. Returns NULL if none exists.
[email protected]370eaf12013-05-18 09:19:49741 TextureRef* GetTexture(GLuint client_id) const {
[email protected]02965c22013-03-09 02:40:07742 return texture_manager()->GetTexture(client_id);
[email protected]a93bb842010-02-16 23:03:47743 }
744
745 // Deletes the texture info for the given texture.
[email protected]ed9f9cd2013-02-27 21:12:35746 void RemoveTexture(GLuint client_id) {
747 texture_manager()->RemoveTexture(client_id);
[email protected]3916c97e2010-02-25 03:20:50748 }
[email protected]a93bb842010-02-16 23:03:47749
[email protected]d37231fa2010-04-09 21:16:02750 // Get the size (in pixels) of the currently bound frame buffer (either FBO
751 // or regular back buffer).
[email protected]8e3e0662010-08-23 18:46:30752 gfx::Size GetBoundReadFrameBufferSize();
[email protected]d37231fa2010-04-09 21:16:02753
[email protected]9edc6b22010-12-23 02:00:26754 // Get the format of the currently bound frame buffer (either FBO or regular
755 // back buffer)
756 GLenum GetBoundReadFrameBufferInternalFormat();
[email protected]297ca1c2011-06-20 23:08:46757 GLenum GetBoundDrawFrameBufferInternalFormat();
[email protected]9edc6b22010-12-23 02:00:26758
[email protected]a93bb842010-02-16 23:03:47759 // Wrapper for CompressedTexImage2D commands.
760 error::Error DoCompressedTexImage2D(
[email protected]09d50362012-10-18 20:54:37761 GLenum target,
762 GLint level,
763 GLenum internal_format,
764 GLsizei width,
765 GLsizei height,
766 GLint border,
767 GLsizei image_size,
768 const void* data);
[email protected]a93bb842010-02-16 23:03:47769
[email protected]cadde4a2010-07-31 17:10:43770 // Wrapper for CompressedTexSubImage2D.
771 void DoCompressedTexSubImage2D(
[email protected]09d50362012-10-18 20:54:37772 GLenum target,
773 GLint level,
774 GLint xoffset,
775 GLint yoffset,
776 GLsizei width,
777 GLsizei height,
778 GLenum format,
779 GLsizei imageSize,
780 const void * data);
[email protected]cadde4a2010-07-31 17:10:43781
782 // Wrapper for CopyTexImage2D.
783 void DoCopyTexImage2D(
[email protected]09d50362012-10-18 20:54:37784 GLenum target,
785 GLint level,
786 GLenum internal_format,
787 GLint x,
788 GLint y,
789 GLsizei width,
790 GLsizei height,
791 GLint border);
[email protected]cadde4a2010-07-31 17:10:43792
[email protected]6d792ee12013-05-15 00:40:56793 // Wrapper for SwapBuffers.
794 void DoSwapBuffers();
795
[email protected]cadde4a2010-07-31 17:10:43796 // Wrapper for CopyTexSubImage2D.
797 void DoCopyTexSubImage2D(
[email protected]09d50362012-10-18 20:54:37798 GLenum target,
799 GLint level,
800 GLint xoffset,
801 GLint yoffset,
802 GLint x,
803 GLint y,
804 GLsizei width,
805 GLsizei height);
[email protected]cadde4a2010-07-31 17:10:43806
[email protected]f598f422012-12-07 08:30:03807 // Validation for TexSubImage2D.
808 bool ValidateTexSubImage2D(
809 error::Error* error,
810 const char* function_name,
811 GLenum target,
812 GLint level,
813 GLint xoffset,
814 GLint yoffset,
815 GLsizei width,
816 GLsizei height,
817 GLenum format,
818 GLenum type,
819 const void * data);
820
[email protected]cadde4a2010-07-31 17:10:43821 // Wrapper for TexSubImage2D.
[email protected]f598f422012-12-07 08:30:03822 error::Error DoTexSubImage2D(
[email protected]09d50362012-10-18 20:54:37823 GLenum target,
824 GLint level,
825 GLint xoffset,
826 GLint yoffset,
827 GLsizei width,
828 GLsizei height,
829 GLenum format,
830 GLenum type,
831 const void * data);
[email protected]cadde4a2010-07-31 17:10:43832
[email protected]32145a92012-12-17 09:01:59833 // Extra validation for async tex(Sub)Image2D.
834 bool ValidateAsyncTransfer(
835 const char* function_name,
[email protected]85a4ac22013-05-31 01:58:47836 TextureRef* texture_ref,
[email protected]32145a92012-12-17 09:01:59837 GLenum target,
838 GLint level,
839 const void * data);
840
[email protected]e51bdf32011-11-23 22:21:46841 // Wrapper for TexImageIOSurface2DCHROMIUM.
842 void DoTexImageIOSurface2DCHROMIUM(
[email protected]09d50362012-10-18 20:54:37843 GLenum target,
844 GLsizei width,
845 GLsizei height,
846 GLuint io_surface_id,
847 GLuint plane);
[email protected]e51bdf32011-11-23 22:21:46848
[email protected]43410e92012-04-20 17:06:28849 void DoCopyTextureCHROMIUM(
[email protected]09d50362012-10-18 20:54:37850 GLenum target,
851 GLuint source_id,
852 GLuint target_id,
853 GLint level,
[email protected]a4a6bdd12013-04-19 20:46:54854 GLenum internal_format,
855 GLenum dest_type);
[email protected]43410e92012-04-20 17:06:28856
[email protected]97dc7cbe2011-12-06 17:26:17857 // Wrapper for TexStorage2DEXT.
858 void DoTexStorage2DEXT(
[email protected]09d50362012-10-18 20:54:37859 GLenum target,
860 GLint levels,
861 GLenum internal_format,
862 GLsizei width,
863 GLsizei height);
[email protected]97dc7cbe2011-12-06 17:26:17864
[email protected]78b514b2012-05-01 21:50:59865 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
866 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
867
[email protected]09d50362012-10-18 20:54:37868 void DoBindTexImage2DCHROMIUM(
869 GLenum target,
870 GLint image_id);
871 void DoReleaseTexImage2DCHROMIUM(
872 GLenum target,
873 GLint image_id);
874
[email protected]94307712012-11-16 23:26:11875 void DoTraceEndCHROMIUM(void);
876
[email protected]2f143d482013-03-14 18:04:49877 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
878
[email protected]ed9f9cd2013-02-27 21:12:35879 // Creates a Program for the given program.
880 Program* CreateProgram(
[email protected]d685a682011-04-29 16:19:57881 GLuint client_id, GLuint service_id) {
[email protected]ed9f9cd2013-02-27 21:12:35882 return program_manager()->CreateProgram(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47883 }
884
[email protected]07f54fcc2009-12-22 02:46:30885 // Gets the program info for the given program. Returns NULL if none exists.
[email protected]ed9f9cd2013-02-27 21:12:35886 Program* GetProgram(GLuint client_id) {
887 return program_manager()->GetProgram(client_id);
[email protected]1d32bc82010-01-13 22:06:46888 }
[email protected]07f54fcc2009-12-22 02:46:30889
[email protected]cae20172012-12-07 00:06:19890#if defined(NDEBUG)
891 void LogClientServiceMapping(
892 const char* /* function_name */,
893 GLuint /* client_id */,
894 GLuint /* service_id */) {
895 }
896 template<typename T>
897 void LogClientServiceForInfo(
898 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
899 }
900#else
901 void LogClientServiceMapping(
902 const char* function_name, GLuint client_id, GLuint service_id) {
[email protected]2a22fe72012-12-07 04:21:26903 if (service_logging_) {
[email protected]1d82e822013-04-10 21:32:32904 DLOG(INFO) << "[" << logger_.GetLogPrefix() << "] " << function_name
[email protected]2a22fe72012-12-07 04:21:26905 << ": client_id = " << client_id
906 << ", service_id = " << service_id;
907 }
[email protected]cae20172012-12-07 00:06:19908 }
909 template<typename T>
910 void LogClientServiceForInfo(
911 T* info, GLuint client_id, const char* function_name) {
[email protected]2a22fe72012-12-07 04:21:26912 if (info) {
[email protected]cae20172012-12-07 00:06:19913 LogClientServiceMapping(function_name, client_id, info->service_id());
914 }
915 }
916#endif
917
[email protected]6b8cf1a2010-05-06 16:13:58918 // Gets the program info for the given program. If it's not a program
919 // generates a GL error. Returns NULL if not program.
[email protected]ed9f9cd2013-02-27 21:12:35920 Program* GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:58921 GLuint client_id, const char* function_name) {
[email protected]df37b9932013-03-08 05:21:42922 Program* program = GetProgram(client_id);
923 if (!program) {
[email protected]ed9f9cd2013-02-27 21:12:35924 if (GetShader(client_id)) {
[email protected]ab09b612013-03-11 22:11:51925 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:43926 GL_INVALID_OPERATION, function_name, "shader passed for program");
[email protected]6b8cf1a2010-05-06 16:13:58927 } else {
[email protected]ab09b612013-03-11 22:11:51928 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
[email protected]6b8cf1a2010-05-06 16:13:58929 }
930 }
[email protected]df37b9932013-03-08 05:21:42931 LogClientServiceForInfo(program, client_id, function_name);
932 return program;
[email protected]6b8cf1a2010-05-06 16:13:58933 }
934
935
[email protected]ed9f9cd2013-02-27 21:12:35936 // Creates a Shader for the given shader.
937 Shader* CreateShader(
[email protected]d685a682011-04-29 16:19:57938 GLuint client_id,
939 GLuint service_id,
940 GLenum shader_type) {
[email protected]ed9f9cd2013-02-27 21:12:35941 return shader_manager()->CreateShader(
[email protected]d685a682011-04-29 16:19:57942 client_id, service_id, shader_type);
[email protected]45bf5152010-02-12 00:11:31943 }
944
945 // Gets the shader info for the given shader. Returns NULL if none exists.
[email protected]ed9f9cd2013-02-27 21:12:35946 Shader* GetShader(GLuint client_id) {
947 return shader_manager()->GetShader(client_id);
[email protected]45bf5152010-02-12 00:11:31948 }
949
[email protected]6b8cf1a2010-05-06 16:13:58950 // Gets the shader info for the given shader. If it's not a shader generates a
951 // GL error. Returns NULL if not shader.
[email protected]ed9f9cd2013-02-27 21:12:35952 Shader* GetShaderInfoNotProgram(
[email protected]6b8cf1a2010-05-06 16:13:58953 GLuint client_id, const char* function_name) {
[email protected]df37b9932013-03-08 05:21:42954 Shader* shader = GetShader(client_id);
955 if (!shader) {
[email protected]ed9f9cd2013-02-27 21:12:35956 if (GetProgram(client_id)) {
[email protected]ab09b612013-03-11 22:11:51957 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:43958 GL_INVALID_OPERATION, function_name, "program passed for shader");
[email protected]6b8cf1a2010-05-06 16:13:58959 } else {
[email protected]ab09b612013-03-11 22:11:51960 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:43961 GL_INVALID_VALUE, function_name, "unknown shader");
[email protected]6b8cf1a2010-05-06 16:13:58962 }
963 }
[email protected]df37b9932013-03-08 05:21:42964 LogClientServiceForInfo(shader, client_id, function_name);
965 return shader;
[email protected]6b8cf1a2010-05-06 16:13:58966 }
967
[email protected]a93bb842010-02-16 23:03:47968 // Creates a buffer info for the given buffer.
[email protected]ed9f9cd2013-02-27 21:12:35969 void CreateBuffer(GLuint client_id, GLuint service_id) {
970 return buffer_manager()->CreateBuffer(client_id, service_id);
[email protected]a93bb842010-02-16 23:03:47971 }
972
[email protected]07f54fcc2009-12-22 02:46:30973 // Gets the buffer info for the given buffer.
[email protected]16ccec12013-02-28 03:40:21974 Buffer* GetBuffer(GLuint client_id) {
[email protected]b10492f2013-03-08 05:24:07975 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
976 return buffer;
[email protected]1d32bc82010-01-13 22:06:46977 }
[email protected]07f54fcc2009-12-22 02:46:30978
[email protected]a93bb842010-02-16 23:03:47979 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
980 // on glDeleteBuffers so we can make sure the user does not try to render
981 // with deleted buffers.
[email protected]ed9f9cd2013-02-27 21:12:35982 void RemoveBuffer(GLuint client_id);
[email protected]a93bb842010-02-16 23:03:47983
[email protected]a25fa872010-03-25 02:57:58984 // Creates a framebuffer info for the given framebuffer.
[email protected]ed9f9cd2013-02-27 21:12:35985 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
986 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
[email protected]a25fa872010-03-25 02:57:58987 }
988
989 // Gets the framebuffer info for the given framebuffer.
[email protected]4d8f0dd2013-03-09 14:37:06990 Framebuffer* GetFramebuffer(GLuint client_id) {
991 return framebuffer_manager()->GetFramebuffer(client_id);
[email protected]a25fa872010-03-25 02:57:58992 }
993
994 // Removes the framebuffer info for the given framebuffer.
[email protected]ed9f9cd2013-02-27 21:12:35995 void RemoveFramebuffer(GLuint client_id) {
996 framebuffer_manager()->RemoveFramebuffer(client_id);
[email protected]a25fa872010-03-25 02:57:58997 }
998
999 // Creates a renderbuffer info for the given renderbuffer.
[email protected]ed9f9cd2013-02-27 21:12:351000 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1001 return renderbuffer_manager()->CreateRenderbuffer(
[email protected]ae51d192010-04-27 00:48:031002 client_id, service_id);
[email protected]a25fa872010-03-25 02:57:581003 }
1004
1005 // Gets the renderbuffer info for the given renderbuffer.
[email protected]ee2a79c32013-03-10 03:50:271006 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1007 return renderbuffer_manager()->GetRenderbuffer(client_id);
[email protected]a25fa872010-03-25 02:57:581008 }
1009
1010 // Removes the renderbuffer info for the given renderbuffer.
[email protected]ed9f9cd2013-02-27 21:12:351011 void RemoveRenderbuffer(GLuint client_id) {
1012 renderbuffer_manager()->RemoveRenderbuffer(client_id);
[email protected]a25fa872010-03-25 02:57:581013 }
1014
[email protected]944b62f32012-09-27 02:20:461015 // Gets the vertex attrib manager for the given vertex array.
1016 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1017 VertexAttribManager* info =
1018 vertex_array_manager()->GetVertexAttribManager(client_id);
1019 return info;
1020 }
1021
1022 // Removes the vertex attrib manager for the given vertex array.
1023 void RemoveVertexAttribManager(GLuint client_id) {
1024 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1025 }
1026
1027 // Creates a vertex attrib manager for the given vertex array.
1028 void CreateVertexAttribManager(GLuint client_id, GLuint service_id) {
1029 return vertex_array_manager()->CreateVertexAttribManager(
1030 client_id, service_id, group_->max_vertex_attribs());
1031 }
1032
[email protected]258a3313f2011-10-18 20:13:571033 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
[email protected]2be6abf32012-06-26 00:28:331034 void DoBindUniformLocationCHROMIUM(
1035 GLuint client_id, GLint location, const char* name);
[email protected]258a3313f2011-10-18 20:13:571036
[email protected]558847a2010-03-24 07:02:541037 error::Error GetAttribLocationHelper(
1038 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1039 const std::string& name_str);
1040
1041 error::Error GetUniformLocationHelper(
1042 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1043 const std::string& name_str);
1044
[email protected]3916c97e2010-02-25 03:20:501045 // Helper for glShaderSource.
1046 error::Error ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:031047 GLuint client_id, const char* data, uint32 data_size);
[email protected]07f54fcc2009-12-22 02:46:301048
[email protected]0d6bfdc2011-11-02 01:32:201049 // Clear any textures used by the current program.
1050 bool ClearUnclearedTextures();
1051
1052 // Clear any uncleared level in texture.
1053 // Returns false if there was a generated GL error.
[email protected]02965c22013-03-09 02:40:071054 bool ClearTexture(Texture* texture);
[email protected]0d6bfdc2011-11-02 01:32:201055
1056 // Clears any uncleared attachments attached to the given frame buffer.
1057 // Returns false if there was a generated GL error.
[email protected]4d8f0dd2013-03-09 14:37:061058 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
[email protected]3a2e7c7b2010-08-06 01:12:281059
[email protected]0d6bfdc2011-11-02 01:32:201060 // overridden from GLES2Decoder
[email protected]b8e97b62012-09-30 15:09:001061 virtual bool ClearLevel(unsigned service_id,
1062 unsigned bind_target,
1063 unsigned target,
1064 int level,
1065 unsigned format,
1066 unsigned type,
1067 int width,
1068 int height,
1069 bool is_texture_immutable) OVERRIDE;
[email protected]0d6bfdc2011-11-02 01:32:201070
[email protected]c007aa02010-09-02 22:22:401071 // Restore all GL state that affects clearing.
1072 void RestoreClearState();
1073
[email protected]3a2e7c7b2010-08-06 01:12:281074 // Remembers the state of some capabilities.
[email protected]297ca1c2011-06-20 23:08:461075 // Returns: true if glEnable/glDisable should actually be called.
1076 bool SetCapabilityState(GLenum cap, bool enabled);
[email protected]3a2e7c7b2010-08-06 01:12:281077
[email protected]0d6bfdc2011-11-02 01:32:201078 // Check that the currently bound framebuffers are valid.
1079 // Generates GL error if not.
1080 bool CheckBoundFramebuffersValid(const char* func_name);
1081
1082 // Check if a framebuffer meets our requirements.
1083 bool CheckFramebufferValid(
[email protected]ed9f9cd2013-02-27 21:12:351084 Framebuffer* framebuffer,
[email protected]0d6bfdc2011-11-02 01:32:201085 GLenum target,
1086 const char* func_name);
[email protected]3a03a8f2011-03-19 00:51:271087
[email protected]939e7362010-05-13 20:49:101088 // Checks if the current program exists and is valid. If not generates the
1089 // appropriate GL error. Returns true if the current program is in a usable
1090 // state.
1091 bool CheckCurrentProgram(const char* function_name);
1092
1093 // Checks if the current program exists and is valid and that location is not
1094 // -1. If the current program is not valid generates the appropriate GL
1095 // error. Returns true if the current program is in a usable state and
1096 // location is not -1.
1097 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1098
1099 // Gets the type of a uniform for a location in the current program. Sets GL
1100 // errors if the current program is not valid. Returns true if the current
[email protected]43c2f1f2011-03-25 18:35:361101 // program is valid and the location exists. Adjusts count so it
1102 // does not overflow the uniform.
1103 bool PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:121104 GLint fake_location, const char* function_name,
[email protected]476ccb72012-12-06 15:52:521105 const BaseUniformInfo& base_info,
[email protected]1b0a6752012-02-22 03:44:121106 GLint* real_location, GLenum* type, GLsizei* count);
[email protected]939e7362010-05-13 20:49:101107
[email protected]b177ae22011-11-01 03:29:111108 // Gets the service id for any simulated backbuffer fbo.
[email protected]1868a342012-11-07 15:56:021109 GLuint GetBackbufferServiceId() const;
[email protected]b177ae22011-11-01 03:29:111110
[email protected]b273e432010-04-12 17:23:581111 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1112 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1113
[email protected]ac77603c72013-03-08 13:52:061114 // Helper for glGetVertexAttrib
1115 void GetVertexAttribHelper(
1116 const VertexAttrib* attrib, GLenum pname, GLint* param);
1117
[email protected]96449d2c2009-11-25 00:01:321118 // Wrapper for glCreateProgram
[email protected]ae51d192010-04-27 00:48:031119 bool CreateProgramHelper(GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:321120
1121 // Wrapper for glCreateShader
[email protected]ae51d192010-04-27 00:48:031122 bool CreateShaderHelper(GLenum type, GLuint client_id);
[email protected]96449d2c2009-11-25 00:01:321123
[email protected]3916c97e2010-02-25 03:20:501124 // Wrapper for glActiveTexture
1125 void DoActiveTexture(GLenum texture_unit);
1126
[email protected]ae51d192010-04-27 00:48:031127 // Wrapper for glAttachShader
1128 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1129
[email protected]96449d2c2009-11-25 00:01:321130 // Wrapper for glBindBuffer since we need to track the current targets.
1131 void DoBindBuffer(GLenum target, GLuint buffer);
1132
[email protected]86093972010-03-11 00:13:561133 // Wrapper for glBindFramebuffer since we need to track the current targets.
1134 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1135
1136 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1137 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1138
[email protected]a93bb842010-02-16 23:03:471139 // Wrapper for glBindTexture since we need to track the current targets.
1140 void DoBindTexture(GLenum target, GLuint texture);
1141
[email protected]944b62f32012-09-27 02:20:461142 // Wrapper for glBindVertexArrayOES
1143 void DoBindVertexArrayOES(GLuint array);
[email protected]ab4fd7282012-10-12 16:25:571144 void EmulateVertexArrayState();
[email protected]944b62f32012-09-27 02:20:461145
[email protected]8e3e0662010-08-23 18:46:301146 // Wrapper for glBlitFramebufferEXT.
1147 void DoBlitFramebufferEXT(
1148 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1149 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1150 GLbitfield mask, GLenum filter);
1151
[email protected]36cef8ce2010-03-16 07:34:451152 // Wrapper for glBufferSubData.
[email protected]0c86dbf2010-03-05 08:14:111153 void DoBufferSubData(
1154 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1155
[email protected]36cef8ce2010-03-16 07:34:451156 // Wrapper for glCheckFramebufferStatus
1157 GLenum DoCheckFramebufferStatus(GLenum target);
1158
[email protected]3a03a8f2011-03-19 00:51:271159 // Wrapper for glClear
[email protected]a7266a92012-06-28 02:11:081160 error::Error DoClear(GLbitfield mask);
[email protected]3a03a8f2011-03-19 00:51:271161
[email protected]88a61bf2012-10-27 13:00:421162 // Wrappers for various state.
[email protected]88a61bf2012-10-27 13:00:421163 void DoDepthRangef(GLclampf znear, GLclampf zfar);
[email protected]b04e24c2013-01-08 18:35:251164 void DoSampleCoverage(GLclampf value, GLboolean invert);
[email protected]3a2e7c7b2010-08-06 01:12:281165
[email protected]45bf5152010-02-12 00:11:311166 // Wrapper for glCompileShader.
1167 void DoCompileShader(GLuint shader);
1168
[email protected]269200b12010-11-18 22:53:061169 // Helper for DeleteSharedIdsCHROMIUM commands.
1170 void DoDeleteSharedIdsCHROMIUM(
1171 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101172
[email protected]ae51d192010-04-27 00:48:031173 // Wrapper for glDetachShader
1174 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1175
[email protected]3a2e7c7b2010-08-06 01:12:281176 // Wrapper for glDisable
1177 void DoDisable(GLenum cap);
1178
[email protected]07f54fcc2009-12-22 02:46:301179 // Wrapper for glDisableVertexAttribArray.
1180 void DoDisableVertexAttribArray(GLuint index);
1181
[email protected]60f22d32012-12-12 00:31:581182 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1183 // attachments.
1184 void DoDiscardFramebufferEXT(GLenum target,
1185 GLsizei numAttachments,
1186 const GLenum* attachments);
1187
[email protected]3a2e7c7b2010-08-06 01:12:281188 // Wrapper for glEnable
1189 void DoEnable(GLenum cap);
1190
[email protected]07f54fcc2009-12-22 02:46:301191 // Wrapper for glEnableVertexAttribArray.
1192 void DoEnableVertexAttribArray(GLuint index);
1193
[email protected]882ba1e22012-03-08 19:02:531194 // Wrapper for glFinish.
1195 void DoFinish();
1196
1197 // Wrapper for glFlush.
1198 void DoFlush();
1199
[email protected]36cef8ce2010-03-16 07:34:451200 // Wrapper for glFramebufferRenderbufffer.
1201 void DoFramebufferRenderbuffer(
1202 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1203 GLuint renderbuffer);
1204
1205 // Wrapper for glFramebufferTexture2D.
1206 void DoFramebufferTexture2D(
1207 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1208 GLint level);
1209
[email protected]7d3c36e2013-07-12 14:13:161210 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1211 void DoFramebufferTexture2DMultisample(
1212 GLenum target, GLenum attachment, GLenum textarget,
1213 GLuint texture, GLint level, GLsizei samples);
1214
1215 // Common implementation for both DoFramebufferTexture2D wrappers.
1216 void DoFramebufferTexture2DCommon(const char* name,
1217 GLenum target, GLenum attachment, GLenum textarget,
1218 GLuint texture, GLint level, GLsizei samples);
1219
[email protected]a93bb842010-02-16 23:03:471220 // Wrapper for glGenerateMipmap
1221 void DoGenerateMipmap(GLenum target);
1222
[email protected]269200b12010-11-18 22:53:061223 // Helper for GenSharedIdsCHROMIUM commands.
1224 void DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:101225 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids);
1226
[email protected]7d3c36e2013-07-12 14:13:161227 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1228 // to account for different pname values defined in different extension
1229 // variants.
1230 GLenum AdjustGetPname(GLenum pname);
1231
[email protected]b273e432010-04-12 17:23:581232 // Wrapper for DoGetBooleanv.
1233 void DoGetBooleanv(GLenum pname, GLboolean* params);
1234
1235 // Wrapper for DoGetFloatv.
1236 void DoGetFloatv(GLenum pname, GLfloat* params);
1237
[email protected]36cef8ce2010-03-16 07:34:451238 // Wrapper for glGetFramebufferAttachmentParameteriv.
1239 void DoGetFramebufferAttachmentParameteriv(
1240 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1241
[email protected]a0c3e972010-04-21 00:49:131242 // Wrapper for glGetIntegerv.
[email protected]b273e432010-04-12 17:23:581243 void DoGetIntegerv(GLenum pname, GLint* params);
1244
[email protected]29a9eb52010-04-13 09:04:231245 // Gets the max value in a range in a buffer.
[email protected]269200b12010-11-18 22:53:061246 GLuint DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:231247 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1248
[email protected]17cfbe0e2013-03-07 01:26:081249 // Wrapper for glGetBufferParameteriv.
1250 void DoGetBufferParameteriv(
1251 GLenum target, GLenum pname, GLint* params);
1252
[email protected]a0c3e972010-04-21 00:49:131253 // Wrapper for glGetProgramiv.
1254 void DoGetProgramiv(
1255 GLuint program_id, GLenum pname, GLint* params);
1256
[email protected]36cef8ce2010-03-16 07:34:451257 // Wrapper for glRenderbufferParameteriv.
1258 void DoGetRenderbufferParameteriv(
1259 GLenum target, GLenum pname, GLint* params);
1260
[email protected]ddd968b82010-03-02 00:44:291261 // Wrapper for glGetShaderiv
1262 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1263
[email protected]b1122982010-05-17 23:04:241264 // Wrappers for glGetVertexAttrib.
1265 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
1266 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
1267
[email protected]1958e0e2010-04-22 05:17:151268 // Wrappers for glIsXXX functions.
[email protected]3dc69c42012-05-12 02:29:241269 bool DoIsEnabled(GLenum cap);
[email protected]1958e0e2010-04-22 05:17:151270 bool DoIsBuffer(GLuint client_id);
1271 bool DoIsFramebuffer(GLuint client_id);
1272 bool DoIsProgram(GLuint client_id);
1273 bool DoIsRenderbuffer(GLuint client_id);
1274 bool DoIsShader(GLuint client_id);
1275 bool DoIsTexture(GLuint client_id);
[email protected]944b62f32012-09-27 02:20:461276 bool DoIsVertexArrayOES(GLuint client_id);
[email protected]1958e0e2010-04-22 05:17:151277
[email protected]07f54fcc2009-12-22 02:46:301278 // Wrapper for glLinkProgram
1279 void DoLinkProgram(GLuint program);
1280
[email protected]269200b12010-11-18 22:53:061281 // Helper for RegisterSharedIdsCHROMIUM.
1282 void DoRegisterSharedIdsCHROMIUM(
1283 GLuint namespace_id, GLsizei n, const GLuint* ids);
[email protected]066849e32010-05-03 19:14:101284
[email protected]36cef8ce2010-03-16 07:34:451285 // Wrapper for glRenderbufferStorage.
1286 void DoRenderbufferStorage(
[email protected]ae51d192010-04-27 00:48:031287 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
[email protected]36cef8ce2010-03-16 07:34:451288
[email protected]8e3e0662010-08-23 18:46:301289 // Wrapper for glRenderbufferStorageMultisampleEXT.
1290 void DoRenderbufferStorageMultisample(
1291 GLenum target, GLsizei samples, GLenum internalformat,
1292 GLsizei width, GLsizei height);
1293
[email protected]b273e432010-04-12 17:23:581294 // Wrapper for glReleaseShaderCompiler.
1295 void DoReleaseShaderCompiler() { }
1296
[email protected]3916c97e2010-02-25 03:20:501297 // Wrappers for glTexParameter functions.
1298 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1299 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1300 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1301 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1302
1303 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1304 // spec only these 2 functions can be used to set sampler uniforms.
[email protected]1b0a6752012-02-22 03:44:121305 void DoUniform1i(GLint fake_location, GLint v0);
1306 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1307 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1308 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1309 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
[email protected]939e7362010-05-13 20:49:101310
1311 // Wrappers for glUniformfv because some drivers don't correctly accept
1312 // bool uniforms.
[email protected]1b0a6752012-02-22 03:44:121313 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1314 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1315 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1316 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
[email protected]3916c97e2010-02-25 03:20:501317
[email protected]43c2f1f2011-03-25 18:35:361318 void DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:121319 GLint fake_location, GLsizei count, GLboolean transpose,
1320 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361321 void DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:121322 GLint fake_location, GLsizei count, GLboolean transpose,
1323 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361324 void DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:121325 GLint fake_location, GLsizei count, GLboolean transpose,
1326 const GLfloat* value);
[email protected]43c2f1f2011-03-25 18:35:361327
[email protected]af6380962012-11-29 23:24:131328 bool SetVertexAttribValue(
1329 const char* function_name, GLuint index, const GLfloat* value);
1330
[email protected]b1122982010-05-17 23:04:241331 // Wrappers for glVertexAttrib??
1332 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1333 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1334 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1335 void DoVertexAttrib4f(
1336 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1337 void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
1338 void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
1339 void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
1340 void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
1341
[email protected]43410e92012-04-20 17:06:281342 // Wrapper for glViewport
1343 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1344
[email protected]07f54fcc2009-12-22 02:46:301345 // Wrapper for glUseProgram
1346 void DoUseProgram(GLuint program);
1347
[email protected]ae51d192010-04-27 00:48:031348 // Wrapper for glValidateProgram.
1349 void DoValidateProgram(GLuint program_client_id);
1350
[email protected]d2a0e1a2012-08-12 02:25:011351 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1352 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1353 void DoPopGroupMarkerEXT(void);
1354
[email protected]4e8a5b122010-05-08 22:00:101355 // Gets the number of values that will be returned by glGetXXX. Returns
1356 // false if pname is unknown.
1357 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1358
[email protected]07f54fcc2009-12-22 02:46:301359 // Checks if the current program and vertex attributes are valid for drawing.
[email protected]ad84a3a2012-06-08 21:42:431360 bool IsDrawValid(
1361 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount);
[email protected]07f54fcc2009-12-22 02:46:301362
[email protected]c13e1da62011-09-09 21:48:301363 // Returns true if successful, simulated will be true if attrib0 was
1364 // simulated.
[email protected]c6aef902012-02-14 03:31:421365 bool SimulateAttrib0(
[email protected]ad84a3a2012-06-08 21:42:431366 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
[email protected]43410e92012-04-20 17:06:281367 void RestoreStateForAttrib(GLuint attrib);
[email protected]b1122982010-05-17 23:04:241368
[email protected]e56131d22013-07-28 16:14:111369 // If texture is a stream texture, this will update the stream to the newest
1370 // buffer.
1371 void UpdateStreamTextureIfNeeded(Texture* texture);
1372
1373 // Returns false if unrenderable textures were replaced.
1374 bool PrepareTexturesForRender();
[email protected]3916c97e2010-02-25 03:20:501375 void RestoreStateForNonRenderableTextures();
1376
[email protected]8fbedc02010-11-18 18:43:401377 // Returns true if GL_FIXED attribs were simulated.
[email protected]c6aef902012-02-14 03:31:421378 bool SimulateFixedAttribs(
[email protected]ad84a3a2012-06-08 21:42:431379 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421380 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
[email protected]8fbedc02010-11-18 18:43:401381 void RestoreStateForSimulatedFixedAttribs();
1382
[email protected]c6aef902012-02-14 03:31:421383 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1384 // cases (primcount is 0 for non-instanced).
1385 error::Error DoDrawArrays(
[email protected]ad84a3a2012-06-08 21:42:431386 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421387 bool instanced, GLenum mode, GLint first, GLsizei count,
1388 GLsizei primcount);
1389 error::Error DoDrawElements(
[email protected]ad84a3a2012-06-08 21:42:431390 const char* function_name,
[email protected]c6aef902012-02-14 03:31:421391 bool instanced, GLenum mode, GLsizei count, GLenum type,
1392 int32 offset, GLsizei primcount);
1393
[email protected]61eeb33f2011-07-26 15:30:311394 GLenum GetBindTargetForSamplerType(GLenum type) {
1395 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
[email protected]e51bdf32011-11-23 22:21:461396 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1397 switch (type) {
1398 case GL_SAMPLER_2D:
1399 return GL_TEXTURE_2D;
1400 case GL_SAMPLER_CUBE:
1401 return GL_TEXTURE_CUBE_MAP;
1402 case GL_SAMPLER_EXTERNAL_OES:
1403 return GL_TEXTURE_EXTERNAL_OES;
1404 case GL_SAMPLER_2D_RECT_ARB:
1405 return GL_TEXTURE_RECTANGLE_ARB;
1406 }
1407
1408 NOTREACHED();
1409 return 0;
[email protected]61eeb33f2011-07-26 15:30:311410 }
1411
[email protected]8e3e0662010-08-23 18:46:301412 // Gets the framebuffer info for a particular target.
[email protected]4d8f0dd2013-03-09 14:37:061413 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1414 Framebuffer* framebuffer = NULL;
[email protected]8e3e0662010-08-23 18:46:301415 switch (target) {
1416 case GL_FRAMEBUFFER:
[email protected]ebfb73c2012-08-15 02:37:451417 case GL_DRAW_FRAMEBUFFER_EXT:
[email protected]7cd76fd2013-06-02 21:11:111418 framebuffer = state_.bound_draw_framebuffer.get();
[email protected]8e3e0662010-08-23 18:46:301419 break;
[email protected]ebfb73c2012-08-15 02:37:451420 case GL_READ_FRAMEBUFFER_EXT:
[email protected]7cd76fd2013-06-02 21:11:111421 framebuffer = state_.bound_read_framebuffer.get();
[email protected]8e3e0662010-08-23 18:46:301422 break;
1423 default:
1424 NOTREACHED();
1425 break;
1426 }
[email protected]4d8f0dd2013-03-09 14:37:061427 return framebuffer;
[email protected]8e3e0662010-08-23 18:46:301428 }
1429
[email protected]ed9f9cd2013-02-27 21:12:351430 Renderbuffer* GetRenderbufferInfoForTarget(
[email protected]0d6bfdc2011-11-02 01:32:201431 GLenum target) {
[email protected]ee2a79c32013-03-10 03:50:271432 Renderbuffer* renderbuffer = NULL;
[email protected]0d6bfdc2011-11-02 01:32:201433 switch (target) {
1434 case GL_RENDERBUFFER:
[email protected]7cd76fd2013-06-02 21:11:111435 renderbuffer = state_.bound_renderbuffer.get();
[email protected]0d6bfdc2011-11-02 01:32:201436 break;
1437 default:
1438 NOTREACHED();
1439 break;
1440 }
[email protected]ee2a79c32013-03-10 03:50:271441 return renderbuffer;
[email protected]0d6bfdc2011-11-02 01:32:201442 }
1443
[email protected]f7b85372010-02-03 01:11:371444 // Validates the program and location for a glGetUniform call and returns
1445 // a SizeResult setup to receive the result. Returns true if glGetUniform
1446 // should be called.
1447 bool GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:121448 GLuint program, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:371449 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:121450 error::Error* error, GLint* real_location, GLuint* service_id,
1451 void** result, GLenum* result_type);
[email protected]f7b85372010-02-03 01:11:371452
[email protected]1078f912011-12-23 13:12:141453 // Computes the estimated memory used for the backbuffer and passes it to
1454 // the tracing system.
[email protected]260ddc4e2012-06-28 00:01:531455 size_t GetBackbufferMemoryTotal();
[email protected]1078f912011-12-23 13:12:141456
[email protected]a10b4a02012-11-26 23:09:501457 virtual bool WasContextLost() OVERRIDE;
[email protected]93a7d98f2013-07-11 00:04:221458 virtual bool WasContextLostByRobustnessExtension() OVERRIDE;
[email protected]c4485aad62012-12-17 10:19:091459 virtual void LoseContext(uint32 reset_status) OVERRIDE;
[email protected]38d139d2011-07-14 00:38:431460
[email protected]e51bdf32011-11-23 22:21:461461#if defined(OS_MACOSX)
1462 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1463#endif
1464
[email protected]81375742012-06-08 00:04:001465 // Validates the combination of texture parameters. For example validates that
1466 // for a given format the specific type, level and targets are valid.
1467 // Synthesizes the correct GL error if invalid. Returns true if valid.
1468 bool ValidateTextureParameters(
1469 const char* function_name,
1470 GLenum target, GLenum format, GLenum type, GLint level);
1471
[email protected]ad84a3a2012-06-08 21:42:431472 bool ValidateCompressedTexDimensions(
1473 const char* function_name,
1474 GLint level, GLsizei width, GLsizei height, GLenum format);
1475 bool ValidateCompressedTexFuncData(
1476 const char* function_name,
1477 GLsizei width, GLsizei height, GLenum format, size_t size);
1478 bool ValidateCompressedTexSubDimensions(
1479 const char* function_name,
1480 GLenum target, GLint level, GLint xoffset, GLint yoffset,
1481 GLsizei width, GLsizei height, GLenum format,
[email protected]ed9f9cd2013-02-27 21:12:351482 Texture* texture);
[email protected]ad84a3a2012-06-08 21:42:431483
[email protected]ab09b612013-03-11 22:11:511484 void RenderWarning(const char* filename, int line, const std::string& msg);
1485 void PerformanceWarning(
1486 const char* filename, int line, const std::string& msg);
[email protected]0f8afe82012-05-14 23:43:011487
[email protected]62e155e2012-10-23 22:43:151488 const FeatureInfo::FeatureFlags& features() const {
1489 return feature_info_->feature_flags();
1490 }
1491
1492 const FeatureInfo::Workarounds& workarounds() const {
1493 return feature_info_->workarounds();
1494 }
1495
[email protected]a7266a92012-06-28 02:11:081496 bool ShouldDeferDraws() {
1497 return !offscreen_target_frame_buffer_.get() &&
[email protected]7cd76fd2013-06-02 21:11:111498 state_.bound_draw_framebuffer.get() == NULL &&
[email protected]a7266a92012-06-28 02:11:081499 surface_->DeferDraws();
1500 }
1501
[email protected]09e17272012-11-30 10:30:441502 bool ShouldDeferReads() {
1503 return !offscreen_target_frame_buffer_.get() &&
[email protected]7cd76fd2013-06-02 21:11:111504 state_.bound_read_framebuffer.get() == NULL &&
[email protected]09e17272012-11-30 10:30:441505 surface_->DeferDraws();
1506 }
1507
[email protected]5a36dc132013-07-23 23:17:551508 void ProcessPendingReadPixels();
1509 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1510
[email protected]96449d2c2009-11-25 00:01:321511 // Generate a member function prototype for each command in an automated and
1512 // typesafe way.
1513 #define GLES2_CMD_OP(name) \
[email protected]f7a64ee2010-02-01 22:24:141514 Error Handle ## name( \
[email protected]ed9f9cd2013-02-27 21:12:351515 uint32 immediate_data_size, \
1516 const cmds::name& args); \
[email protected]96449d2c2009-11-25 00:01:321517
1518 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1519
1520 #undef GLES2_CMD_OP
1521
[email protected]2f2d7042010-04-14 21:45:581522 // The GL context this decoder renders to on behalf of the client.
[email protected]fbe20372011-06-01 01:46:381523 scoped_refptr<gfx::GLSurface> surface_;
1524 scoped_refptr<gfx::GLContext> context_;
[email protected]d37231fa2010-04-09 21:16:021525
[email protected]a3ded6d2010-10-19 06:44:391526 // The ContextGroup for this decoder uses to track resources.
[email protected]ed9f9cd2013-02-27 21:12:351527 scoped_refptr<ContextGroup> group_;
[email protected]a3ded6d2010-10-19 06:44:391528
[email protected]1d82e822013-04-10 21:32:321529 DebugMarkerManager debug_marker_manager_;
1530 Logger logger_;
1531
[email protected]e259eb412012-10-13 05:47:241532 // All the state for this context.
1533 ContextState state_;
1534
[email protected]34ff8b0c2010-10-01 20:06:021535 // Current width and height of the offscreen frame buffer.
1536 gfx::Size offscreen_size_;
1537
[email protected]96449d2c2009-11-25 00:01:321538 // Util to help with GL.
1539 GLES2Util util_;
1540
[email protected]43410e92012-04-20 17:06:281541 // unpack flip y as last set by glPixelStorei
1542 bool unpack_flip_y_;
1543
[email protected]6c75c712012-06-19 15:43:171544 // unpack (un)premultiply alpha as last set by glPixelStorei
[email protected]43410e92012-04-20 17:06:281545 bool unpack_premultiply_alpha_;
[email protected]6c75c712012-06-19 15:43:171546 bool unpack_unpremultiply_alpha_;
[email protected]43410e92012-04-20 17:06:281547
[email protected]944b62f32012-09-27 02:20:461548 // Default vertex attribs manager, used when no VAOs are bound.
[email protected]ed9f9cd2013-02-27 21:12:351549 scoped_refptr<VertexAttribManager> default_vertex_attrib_manager_;
[email protected]07f54fcc2009-12-22 02:46:301550
[email protected]b1122982010-05-17 23:04:241551 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1552 GLuint attrib_0_buffer_id_;
1553
1554 // The value currently in attrib_0.
[email protected]af6380962012-11-29 23:24:131555 Vec4 attrib_0_value_;
[email protected]b1122982010-05-17 23:04:241556
[email protected]fc753442011-02-04 19:49:491557 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1558 bool attrib_0_buffer_matches_value_;
1559
[email protected]b1122982010-05-17 23:04:241560 // The size of attrib 0.
1561 GLsizei attrib_0_size_;
1562
[email protected]8fbedc02010-11-18 18:43:401563 // The buffer used to simulate GL_FIXED attribs.
1564 GLuint fixed_attrib_buffer_id_;
1565
1566 // The size of fiixed attrib buffer.
1567 GLsizei fixed_attrib_buffer_size_;
1568
[email protected]b9363b22010-06-09 22:06:151569 // The offscreen frame buffer that the client renders to. With EGL, the
1570 // depth and stencil buffers are separate. With regular GL there is a single
1571 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1572 // offscreen_target_stencil_render_buffer_ is unused.
[email protected]ed9f9cd2013-02-27 21:12:351573 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1574 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1575 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1576 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1577 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
[email protected]34ff8b0c2010-10-01 20:06:021578 GLenum offscreen_target_color_format_;
1579 GLenum offscreen_target_depth_format_;
1580 GLenum offscreen_target_stencil_format_;
1581 GLsizei offscreen_target_samples_;
[email protected]8a61d872012-01-20 12:43:561582 GLboolean offscreen_target_buffer_preserved_;
[email protected]6217d392010-03-25 22:08:351583
[email protected]de26b3c2011-08-03 21:54:271584 // The copy that is saved when SwapBuffers is called.
[email protected]ed9f9cd2013-02-27 21:12:351585 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1586 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
[email protected]370eaf12013-05-18 09:19:491587 scoped_refptr<TextureRef>
[email protected]ed9f9cd2013-02-27 21:12:351588 offscreen_saved_color_texture_info_;
[email protected]de26b3c2011-08-03 21:54:271589
1590 // The copy that is used as the destination for multi-sample resolves.
[email protected]ed9f9cd2013-02-27 21:12:351591 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1592 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
[email protected]97872062010-11-03 19:07:051593 GLenum offscreen_saved_color_format_;
[email protected]6217d392010-03-25 22:08:351594
[email protected]882ba1e22012-03-08 19:02:531595 scoped_ptr<QueryManager> query_manager_;
[email protected]882ba1e22012-03-08 19:02:531596
[email protected]944b62f32012-09-27 02:20:461597 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1598
[email protected]729c0b42013-05-26 02:05:071599 base::Callback<void(gfx::Size, float)> resize_callback_;
[email protected]22f320a2011-08-30 01:17:001600
[email protected]840a7e462013-02-27 01:29:511601 WaitSyncPointCallback wait_sync_point_callback_;
[email protected]43f28f832010-02-03 02:28:481602
[email protected]e3932abb2013-03-13 00:01:371603 ShaderCacheCallback shader_cache_callback_;
1604
[email protected]85a4ac22013-05-31 01:58:471605 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
[email protected]b0af4f52011-09-28 22:04:421606
[email protected]32fe9aa2011-01-21 23:47:131607 // The format of the back buffer_
1608 GLenum back_buffer_color_format_;
[email protected]297ca1c2011-06-20 23:08:461609 bool back_buffer_has_depth_;
1610 bool back_buffer_has_stencil_;
[email protected]32fe9aa2011-01-21 23:47:131611
[email protected]60f22d32012-12-12 00:31:581612 // Backbuffer attachments that are currently undefined.
1613 uint32 backbuffer_needs_clear_bits_;
1614
[email protected]a3a93e7b2010-08-28 00:48:561615 // The current decoder error.
1616 error::Error current_decoder_error_;
1617
[email protected]b1d2dcb2010-05-17 19:24:181618 bool use_shader_translator_;
[email protected]87fb6ab2012-06-13 22:28:041619 scoped_refptr<ShaderTranslator> vertex_translator_;
1620 scoped_refptr<ShaderTranslator> fragment_translator_;
[email protected]b1d2dcb2010-05-17 19:24:181621
[email protected]e82fb792011-09-22 00:33:291622 DisallowedFeatures disallowed_features_;
[email protected]c410da802011-03-14 19:17:411623
[email protected]915a59a12010-09-30 21:29:111624 // Cached from ContextGroup
[email protected]9438b012010-06-15 22:55:051625 const Validators* validators_;
[email protected]ed9f9cd2013-02-27 21:12:351626 scoped_refptr<FeatureInfo> feature_info_;
[email protected]9438b012010-06-15 22:55:051627
[email protected]65225772011-05-12 21:10:241628 int frame_number_;
1629
[email protected]706b69f2012-07-27 04:59:301630 bool has_robustness_extension_;
[email protected]38d139d2011-07-14 00:38:431631 GLenum reset_status_;
[email protected]93a7d98f2013-07-11 00:04:221632 bool reset_by_robustness_extension_;
[email protected]38d139d2011-07-14 00:38:431633
[email protected]f0d74742011-10-03 16:31:041634 // These flags are used to override the state of the shared feature_info_
1635 // member. Because the same FeatureInfo instance may be shared among many
1636 // contexts, the assumptions on the availablity of extensions in WebGL
1637 // contexts may be broken. These flags override the shared state to preserve
1638 // WebGL semantics.
1639 bool force_webgl_glsl_validation_;
1640 bool derivatives_explicitly_enabled_;
[email protected]70dc60932013-06-04 03:33:491641 bool frag_depth_explicitly_enabled_;
[email protected]aff39ac82013-06-08 04:53:131642 bool draw_buffers_explicitly_enabled_;
[email protected]f0d74742011-10-03 16:31:041643
[email protected]062c38b2012-01-18 03:25:101644 bool compile_shader_always_succeeds_;
1645
[email protected]cae20172012-12-07 00:06:191646 // Log extra info.
1647 bool service_logging_;
1648
[email protected]e51bdf32011-11-23 22:21:461649#if defined(OS_MACOSX)
1650 typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap;
1651 TextureToIOSurfaceMap texture_to_io_surface_map_;
1652#endif
1653
[email protected]43410e92012-04-20 17:06:281654 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
1655
[email protected]1868a342012-11-07 15:56:021656 // Cached values of the currently assigned viewport dimensions.
1657 GLsizei viewport_max_width_;
1658 GLsizei viewport_max_height_;
1659
[email protected]63b465922012-09-06 02:04:521660 // Command buffer stats.
[email protected]63b465922012-09-06 02:04:521661 base::TimeDelta total_processing_commands_time_;
1662
[email protected]c986af502013-08-14 01:04:441663 // States related to each manager.
1664 DecoderTextureState texture_state_;
1665 DecoderFramebufferState framebuffer_state_;
1666
[email protected]fb97b662013-02-20 23:02:141667 scoped_ptr<GPUTracer> gpu_tracer_;
[email protected]94307712012-11-16 23:26:111668
[email protected]5a36dc132013-07-23 23:17:551669 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
1670
[email protected]96449d2c2009-11-25 00:01:321671 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
1672};
1673
[email protected]ab09b612013-03-11 22:11:511674ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
1675 const char* function_name, GLES2DecoderImpl* decoder)
1676 : function_name_(function_name),
1677 decoder_(decoder) {
[email protected]d3eba342013-04-18 21:11:501678 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(decoder_->GetErrorState(),
1679 function_name_);
[email protected]6217d392010-03-25 22:08:351680}
1681
1682ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
[email protected]d3eba342013-04-18 21:11:501683 ERRORSTATE_CLEAR_REAL_GL_ERRORS(decoder_->GetErrorState(), function_name_);
[email protected]6217d392010-03-25 22:08:351684}
1685
1686ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
1687 GLuint id)
1688 : decoder_(decoder) {
[email protected]ab09b612013-03-11 22:11:511689 ScopedGLErrorSuppressor suppressor(
1690 "ScopedTexture2DBinder::ctor", decoder_);
[email protected]6217d392010-03-25 22:08:351691
1692 // TODO(apatrick): Check if there are any other states that need to be reset
1693 // before binding a new texture.
1694 glActiveTexture(GL_TEXTURE0);
1695 glBindTexture(GL_TEXTURE_2D, id);
1696}
1697
1698ScopedTexture2DBinder::~ScopedTexture2DBinder() {
[email protected]ab09b612013-03-11 22:11:511699 ScopedGLErrorSuppressor suppressor(
1700 "ScopedTexture2DBinder::dtor", decoder_);
[email protected]8e3e0662010-08-23 18:46:301701 decoder_->RestoreCurrentTexture2DBindings();
[email protected]6217d392010-03-25 22:08:351702}
1703
1704ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
1705 GLuint id)
1706 : decoder_(decoder) {
[email protected]ab09b612013-03-11 22:11:511707 ScopedGLErrorSuppressor suppressor(
1708 "ScopedRenderBufferBinder::ctor", decoder_);
[email protected]6217d392010-03-25 22:08:351709 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
1710}
1711
1712ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
[email protected]ab09b612013-03-11 22:11:511713 ScopedGLErrorSuppressor suppressor(
1714 "ScopedRenderBufferBinder::dtor", decoder_);
[email protected]8e3e0662010-08-23 18:46:301715 decoder_->RestoreCurrentRenderbufferBindings();
[email protected]6217d392010-03-25 22:08:351716}
1717
1718ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
1719 GLuint id)
1720 : decoder_(decoder) {
[email protected]ab09b612013-03-11 22:11:511721 ScopedGLErrorSuppressor suppressor(
1722 "ScopedFrameBufferBinder::ctor", decoder_);
[email protected]6217d392010-03-25 22:08:351723 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
[email protected]70d34263c2013-01-09 00:27:451724 decoder->OnFboChanged();
[email protected]6217d392010-03-25 22:08:351725}
1726
1727ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
[email protected]ab09b612013-03-11 22:11:511728 ScopedGLErrorSuppressor suppressor(
1729 "ScopedFrameBufferBinder::dtor", decoder_);
[email protected]8e3e0662010-08-23 18:46:301730 decoder_->RestoreCurrentFramebufferBindings();
[email protected]6217d392010-03-25 22:08:351731}
1732
[email protected]34ff8b0c2010-10-01 20:06:021733ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
[email protected]de26b3c2011-08-03 21:54:271734 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
[email protected]c0701082011-04-20 00:34:521735 : decoder_(decoder) {
[email protected]34ff8b0c2010-10-01 20:06:021736 resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
1737 decoder_->IsOffscreenBufferMultisampled() &&
[email protected]e259eb412012-10-13 05:47:241738 (!decoder_->state_.bound_read_framebuffer.get() ||
[email protected]c0701082011-04-20 00:34:521739 enforce_internal_framebuffer));
[email protected]34ff8b0c2010-10-01 20:06:021740 if (!resolve_and_bind_)
1741 return;
1742
[email protected]ab09b612013-03-11 22:11:511743 ScopedGLErrorSuppressor suppressor(
1744 "ScopedResolvedFrameBufferBinder::ctor", decoder_);
[email protected]34ff8b0c2010-10-01 20:06:021745 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
1746 decoder_->offscreen_target_frame_buffer_->id());
[email protected]de26b3c2011-08-03 21:54:271747 GLuint targetid;
1748 if (internal) {
1749 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
1750 decoder_->offscreen_resolved_frame_buffer_.reset(
[email protected]ed9f9cd2013-02-27 21:12:351751 new BackFramebuffer(decoder_));
[email protected]de26b3c2011-08-03 21:54:271752 decoder_->offscreen_resolved_frame_buffer_->Create();
[email protected]ed9f9cd2013-02-27 21:12:351753 decoder_->offscreen_resolved_color_texture_.reset(
1754 new BackTexture(decoder_));
[email protected]de26b3c2011-08-03 21:54:271755 decoder_->offscreen_resolved_color_texture_->Create();
1756
1757 DCHECK(decoder_->offscreen_saved_color_format_);
1758 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
[email protected]678a73f2012-12-19 19:22:091759 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
1760 false);
[email protected]de26b3c2011-08-03 21:54:271761 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
1762 decoder_->offscreen_resolved_color_texture_.get());
1763 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
1764 GL_FRAMEBUFFER_COMPLETE) {
1765 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
1766 << "because offscreen resolved FBO was incomplete.";
1767 return;
1768 }
1769 }
1770 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
1771 } else {
1772 targetid = decoder_->offscreen_saved_frame_buffer_->id();
1773 }
1774 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021775 const int width = decoder_->offscreen_size_.width();
1776 const int height = decoder_->offscreen_size_.height();
[email protected]8c3e68782010-10-27 16:41:181777 glDisable(GL_SCISSOR_TEST);
[email protected]57edfdad2012-02-07 04:57:151778 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021779 glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
1780 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1781 } else {
1782 glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
1783 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1784 }
[email protected]de26b3c2011-08-03 21:54:271785 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
[email protected]34ff8b0c2010-10-01 20:06:021786}
1787
1788ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
1789 if (!resolve_and_bind_)
1790 return;
1791
[email protected]ab09b612013-03-11 22:11:511792 ScopedGLErrorSuppressor suppressor(
1793 "ScopedResolvedFrameBufferBinder::dtor", decoder_);
[email protected]34ff8b0c2010-10-01 20:06:021794 decoder_->RestoreCurrentFramebufferBindings();
[email protected]f731b9462012-10-30 00:35:221795 if (decoder_->state_.enable_flags.scissor_test) {
[email protected]8c3e68782010-10-27 16:41:181796 glEnable(GL_SCISSOR_TEST);
1797 }
[email protected]34ff8b0c2010-10-01 20:06:021798}
1799
[email protected]ed9f9cd2013-02-27 21:12:351800BackTexture::BackTexture(GLES2DecoderImpl* decoder)
[email protected]6217d392010-03-25 22:08:351801 : decoder_(decoder),
[email protected]7989c9e2013-01-23 06:39:261802 memory_tracker_(decoder->memory_tracker(), MemoryTracker::kUnmanaged),
[email protected]68e81a4a62012-12-13 01:16:481803 bytes_allocated_(0),
[email protected]ff6493f2012-07-31 19:52:251804 id_(0) {
[email protected]6217d392010-03-25 22:08:351805}
1806
[email protected]ed9f9cd2013-02-27 21:12:351807BackTexture::~BackTexture() {
[email protected]6217d392010-03-25 22:08:351808 // This does not destroy the render texture because that would require that
1809 // the associated GL context was current. Just check that it was explicitly
1810 // destroyed.
1811 DCHECK_EQ(id_, 0u);
1812}
1813
[email protected]ed9f9cd2013-02-27 21:12:351814void BackTexture::Create() {
[email protected]ab09b612013-03-11 22:11:511815 ScopedGLErrorSuppressor suppressor("BackTexture::Create", decoder_);
[email protected]6217d392010-03-25 22:08:351816 Destroy();
1817 glGenTextures(1, &id_);
[email protected]3a4d0c52011-06-29 23:11:581818 ScopedTexture2DBinder binder(decoder_, id_);
1819 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1820 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1821 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1822 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
[email protected]62788802011-10-03 17:57:161823
1824 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
1825 // never called on an offscreen context, no data will ever be uploaded to the
1826 // saved offscreen color texture (it is deferred until to when SwapBuffers
1827 // is called). My idea is that some nvidia drivers might have a bug where
1828 // deleting a texture that has never been populated might cause a
1829 // crash.
1830 glTexImage2D(
1831 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
[email protected]68e81a4a62012-12-13 01:16:481832
1833 bytes_allocated_ = 16u * 16u * 4u;
1834 memory_tracker_.TrackMemAlloc(bytes_allocated_);
[email protected]6217d392010-03-25 22:08:351835}
1836
[email protected]ed9f9cd2013-02-27 21:12:351837bool BackTexture::AllocateStorage(
1838 const gfx::Size& size, GLenum format, bool zero) {
[email protected]6217d392010-03-25 22:08:351839 DCHECK_NE(id_, 0u);
[email protected]ab09b612013-03-11 22:11:511840 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage", decoder_);
[email protected]6217d392010-03-25 22:08:351841 ScopedTexture2DBinder binder(decoder_, id_);
[email protected]678a73f2012-12-19 19:22:091842 uint32 image_size = 0;
1843 GLES2Util::ComputeImageDataSizes(
1844 size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
1845 NULL, NULL);
1846
[email protected]7989c9e2013-01-23 06:39:261847 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
1848 return false;
1849 }
1850
[email protected]40d90a22013-04-09 03:39:551851 scoped_ptr<char[]> zero_data;
[email protected]678a73f2012-12-19 19:22:091852 if (zero) {
1853 zero_data.reset(new char[image_size]);
1854 memset(zero_data.get(), 0, image_size);
1855 }
[email protected]6217d392010-03-25 22:08:351856
[email protected]8f1d2aa2013-05-10 23:45:381857 glTexImage2D(GL_TEXTURE_2D,
1858 0, // mip level
1859 format,
1860 size.width(),
1861 size.height(),
1862 0, // border
1863 format,
1864 GL_UNSIGNED_BYTE,
1865 zero_data.get());
[email protected]6217d392010-03-25 22:08:351866
[email protected]d37231fa2010-04-09 21:16:021867 size_ = size;
1868
[email protected]1078f912011-12-23 13:12:141869 bool success = glGetError() == GL_NO_ERROR;
1870 if (success) {
[email protected]68e81a4a62012-12-13 01:16:481871 memory_tracker_.TrackMemFree(bytes_allocated_);
1872 bytes_allocated_ = image_size;
1873 memory_tracker_.TrackMemAlloc(bytes_allocated_);
[email protected]1078f912011-12-23 13:12:141874 }
1875 return success;
[email protected]6217d392010-03-25 22:08:351876}
1877
[email protected]ed9f9cd2013-02-27 21:12:351878void BackTexture::Copy(const gfx::Size& size, GLenum format) {
[email protected]6217d392010-03-25 22:08:351879 DCHECK_NE(id_, 0u);
[email protected]ab09b612013-03-11 22:11:511880 ScopedGLErrorSuppressor suppressor("BackTexture::Copy", decoder_);
[email protected]6217d392010-03-25 22:08:351881 ScopedTexture2DBinder binder(decoder_, id_);
1882 glCopyTexImage2D(GL_TEXTURE_2D,
1883 0, // level
[email protected]3a4d0c52011-06-29 23:11:581884 format,
[email protected]6217d392010-03-25 22:08:351885 0, 0,
1886 size.width(),
1887 size.height(),
1888 0); // border
1889}
1890
[email protected]ed9f9cd2013-02-27 21:12:351891void BackTexture::Destroy() {
[email protected]6217d392010-03-25 22:08:351892 if (id_ != 0) {
[email protected]ab09b612013-03-11 22:11:511893 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy", decoder_);
[email protected]6217d392010-03-25 22:08:351894 glDeleteTextures(1, &id_);
1895 id_ = 0;
1896 }
[email protected]68e81a4a62012-12-13 01:16:481897 memory_tracker_.TrackMemFree(bytes_allocated_);
1898 bytes_allocated_ = 0;
[email protected]6217d392010-03-25 22:08:351899}
1900
[email protected]ed9f9cd2013-02-27 21:12:351901void BackTexture::Invalidate() {
[email protected]97872062010-11-03 19:07:051902 id_ = 0;
1903}
1904
[email protected]ed9f9cd2013-02-27 21:12:351905BackRenderbuffer::BackRenderbuffer(GLES2DecoderImpl* decoder)
[email protected]6217d392010-03-25 22:08:351906 : decoder_(decoder),
[email protected]7989c9e2013-01-23 06:39:261907 memory_tracker_(decoder->memory_tracker(), MemoryTracker::kUnmanaged),
[email protected]68e81a4a62012-12-13 01:16:481908 bytes_allocated_(0),
[email protected]ff6493f2012-07-31 19:52:251909 id_(0) {
[email protected]6217d392010-03-25 22:08:351910}
1911
[email protected]ed9f9cd2013-02-27 21:12:351912BackRenderbuffer::~BackRenderbuffer() {
[email protected]6217d392010-03-25 22:08:351913 // This does not destroy the render buffer because that would require that
1914 // the associated GL context was current. Just check that it was explicitly
1915 // destroyed.
1916 DCHECK_EQ(id_, 0u);
1917}
1918
[email protected]ed9f9cd2013-02-27 21:12:351919void BackRenderbuffer::Create() {
[email protected]ab09b612013-03-11 22:11:511920 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create", decoder_);
[email protected]6217d392010-03-25 22:08:351921 Destroy();
1922 glGenRenderbuffersEXT(1, &id_);
1923}
1924
[email protected]ed9f9cd2013-02-27 21:12:351925bool BackRenderbuffer::AllocateStorage(const gfx::Size& size, GLenum format,
1926 GLsizei samples) {
[email protected]ab09b612013-03-11 22:11:511927 ScopedGLErrorSuppressor suppressor(
1928 "BackRenderbuffer::AllocateStorage", decoder_);
[email protected]6217d392010-03-25 22:08:351929 ScopedRenderBufferBinder binder(decoder_, id_);
[email protected]7989c9e2013-01-23 06:39:261930
1931 uint32 estimated_size = 0;
1932 if (!RenderbufferManager::ComputeEstimatedRenderbufferSize(
1933 size.width(), size.height(), samples, format, &estimated_size)) {
1934 return false;
1935 }
1936
1937 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
1938 return false;
1939 }
1940
[email protected]34ff8b0c2010-10-01 20:06:021941 if (samples <= 1) {
1942 glRenderbufferStorageEXT(GL_RENDERBUFFER,
1943 format,
1944 size.width(),
1945 size.height());
1946 } else {
[email protected]57edfdad2012-02-07 04:57:151947 if (GLES2Decoder::IsAngle()) {
[email protected]34ff8b0c2010-10-01 20:06:021948 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
1949 samples,
1950 format,
1951 size.width(),
1952 size.height());
1953 } else {
1954 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
1955 samples,
1956 format,
1957 size.width(),
1958 size.height());
1959 }
1960 }
[email protected]1078f912011-12-23 13:12:141961 bool success = glGetError() == GL_NO_ERROR;
1962 if (success) {
[email protected]68e81a4a62012-12-13 01:16:481963 memory_tracker_.TrackMemFree(bytes_allocated_);
[email protected]7989c9e2013-01-23 06:39:261964 bytes_allocated_ = estimated_size;
[email protected]68e81a4a62012-12-13 01:16:481965 memory_tracker_.TrackMemAlloc(bytes_allocated_);
[email protected]1078f912011-12-23 13:12:141966 }
1967 return success;
[email protected]6217d392010-03-25 22:08:351968}
1969
[email protected]ed9f9cd2013-02-27 21:12:351970void BackRenderbuffer::Destroy() {
[email protected]6217d392010-03-25 22:08:351971 if (id_ != 0) {
[email protected]ab09b612013-03-11 22:11:511972 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy", decoder_);
[email protected]6217d392010-03-25 22:08:351973 glDeleteRenderbuffersEXT(1, &id_);
1974 id_ = 0;
1975 }
[email protected]68e81a4a62012-12-13 01:16:481976 memory_tracker_.TrackMemFree(bytes_allocated_);
1977 bytes_allocated_ = 0;
[email protected]6217d392010-03-25 22:08:351978}
1979
[email protected]ed9f9cd2013-02-27 21:12:351980void BackRenderbuffer::Invalidate() {
[email protected]97872062010-11-03 19:07:051981 id_ = 0;
1982}
1983
[email protected]ed9f9cd2013-02-27 21:12:351984BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
[email protected]6217d392010-03-25 22:08:351985 : decoder_(decoder),
1986 id_(0) {
1987}
1988
[email protected]ed9f9cd2013-02-27 21:12:351989BackFramebuffer::~BackFramebuffer() {
[email protected]6217d392010-03-25 22:08:351990 // This does not destroy the frame buffer because that would require that
1991 // the associated GL context was current. Just check that it was explicitly
1992 // destroyed.
1993 DCHECK_EQ(id_, 0u);
1994}
1995
[email protected]ed9f9cd2013-02-27 21:12:351996void BackFramebuffer::Create() {
[email protected]ab09b612013-03-11 22:11:511997 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create", decoder_);
[email protected]6217d392010-03-25 22:08:351998 Destroy();
1999 glGenFramebuffersEXT(1, &id_);
2000}
2001
[email protected]ed9f9cd2013-02-27 21:12:352002void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
[email protected]6217d392010-03-25 22:08:352003 DCHECK_NE(id_, 0u);
[email protected]ab09b612013-03-11 22:11:512004 ScopedGLErrorSuppressor suppressor(
2005 "BackFramebuffer::AttachRenderTexture", decoder_);
[email protected]6217d392010-03-25 22:08:352006 ScopedFrameBufferBinder binder(decoder_, id_);
2007 GLuint attach_id = texture ? texture->id() : 0;
2008 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2009 GL_COLOR_ATTACHMENT0,
2010 GL_TEXTURE_2D,
2011 attach_id,
2012 0);
2013}
2014
[email protected]ed9f9cd2013-02-27 21:12:352015void BackFramebuffer::AttachRenderBuffer(GLenum target,
2016 BackRenderbuffer* render_buffer) {
[email protected]6217d392010-03-25 22:08:352017 DCHECK_NE(id_, 0u);
[email protected]ab09b612013-03-11 22:11:512018 ScopedGLErrorSuppressor suppressor(
2019 "BackFramebuffer::AttachRenderBuffer", decoder_);
[email protected]6217d392010-03-25 22:08:352020 ScopedFrameBufferBinder binder(decoder_, id_);
2021 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2022 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
[email protected]b9363b22010-06-09 22:06:152023 target,
[email protected]6217d392010-03-25 22:08:352024 GL_RENDERBUFFER,
2025 attach_id);
2026}
2027
[email protected]ed9f9cd2013-02-27 21:12:352028void BackFramebuffer::Destroy() {
[email protected]6217d392010-03-25 22:08:352029 if (id_ != 0) {
[email protected]ab09b612013-03-11 22:11:512030 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy", decoder_);
[email protected]6217d392010-03-25 22:08:352031 glDeleteFramebuffersEXT(1, &id_);
2032 id_ = 0;
2033 }
2034}
2035
[email protected]ed9f9cd2013-02-27 21:12:352036void BackFramebuffer::Invalidate() {
[email protected]97872062010-11-03 19:07:052037 id_ = 0;
2038}
2039
[email protected]ed9f9cd2013-02-27 21:12:352040GLenum BackFramebuffer::CheckStatus() {
[email protected]6217d392010-03-25 22:08:352041 DCHECK_NE(id_, 0u);
[email protected]ab09b612013-03-11 22:11:512042 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus", decoder_);
[email protected]6217d392010-03-25 22:08:352043 ScopedFrameBufferBinder binder(decoder_, id_);
2044 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2045}
2046
[email protected]aa7666122011-09-02 19:45:522047GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2048 return new GLES2DecoderImpl(group);
[email protected]96449d2c2009-11-25 00:01:322049}
2050
[email protected]aa7666122011-09-02 19:45:522051GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
[email protected]a3ded6d2010-10-19 06:44:392052 : GLES2Decoder(),
[email protected]3b1ecc262011-08-03 22:49:572053 group_(group),
[email protected]1d82e822013-04-10 21:32:322054 logger_(&debug_marker_manager_),
[email protected]d3eba342013-04-18 21:11:502055 state_(group_->feature_info(), &logger_),
[email protected]43410e92012-04-20 17:06:282056 unpack_flip_y_(false),
2057 unpack_premultiply_alpha_(false),
[email protected]6c75c712012-06-19 15:43:172058 unpack_unpremultiply_alpha_(false),
[email protected]b1122982010-05-17 23:04:242059 attrib_0_buffer_id_(0),
[email protected]fc753442011-02-04 19:49:492060 attrib_0_buffer_matches_value_(true),
[email protected]b1122982010-05-17 23:04:242061 attrib_0_size_(0),
[email protected]8fbedc02010-11-18 18:43:402062 fixed_attrib_buffer_id_(0),
2063 fixed_attrib_buffer_size_(0),
[email protected]34ff8b0c2010-10-01 20:06:022064 offscreen_target_color_format_(0),
2065 offscreen_target_depth_format_(0),
2066 offscreen_target_stencil_format_(0),
2067 offscreen_target_samples_(0),
[email protected]8a61d872012-01-20 12:43:562068 offscreen_target_buffer_preserved_(true),
[email protected]97872062010-11-03 19:07:052069 offscreen_saved_color_format_(0),
[email protected]32fe9aa2011-01-21 23:47:132070 back_buffer_color_format_(0),
[email protected]297ca1c2011-06-20 23:08:462071 back_buffer_has_depth_(false),
2072 back_buffer_has_stencil_(false),
[email protected]60f22d32012-12-12 00:31:582073 backbuffer_needs_clear_bits_(0),
[email protected]a3a93e7b2010-08-28 00:48:562074 current_decoder_error_(error::kNoError),
[email protected]9438b012010-06-15 22:55:052075 use_shader_translator_(true),
[email protected]915a59a12010-09-30 21:29:112076 validators_(group_->feature_info()->validators()),
[email protected]b493ee622011-04-13 23:52:002077 feature_info_(group_->feature_info()),
[email protected]38d139d2011-07-14 00:38:432078 frame_number_(0),
[email protected]706b69f2012-07-27 04:59:302079 has_robustness_extension_(false),
[email protected]75c023c2011-08-22 23:54:512080 reset_status_(GL_NO_ERROR),
[email protected]93a7d98f2013-07-11 00:04:222081 reset_by_robustness_extension_(false),
[email protected]f0d74742011-10-03 16:31:042082 force_webgl_glsl_validation_(false),
[email protected]062c38b2012-01-18 03:25:102083 derivatives_explicitly_enabled_(false),
[email protected]70dc60932013-06-04 03:33:492084 frag_depth_explicitly_enabled_(false),
[email protected]aff39ac82013-06-08 04:53:132085 draw_buffers_explicitly_enabled_(false),
[email protected]43410e92012-04-20 17:06:282086 compile_shader_always_succeeds_(false),
[email protected]cae20172012-12-07 00:06:192087 service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
2088 switches::kEnableGPUServiceLoggingGPU)),
[email protected]1868a342012-11-07 15:56:022089 viewport_max_width_(0),
[email protected]c986af502013-08-14 01:04:442090 viewport_max_height_(0) {
[email protected]3b1ecc262011-08-03 22:49:572091 DCHECK(group);
2092
[email protected]b1122982010-05-17 23:04:242093 attrib_0_value_.v[0] = 0.0f;
2094 attrib_0_value_.v[1] = 0.0f;
2095 attrib_0_value_.v[2] = 0.0f;
2096 attrib_0_value_.v[3] = 1.0f;
[email protected]b9363b22010-06-09 22:06:152097
[email protected]c2f8c8402010-12-06 18:07:242098 // The shader translator is used for WebGL even when running on EGL
2099 // because additional restrictions are needed (like only enabling
2100 // GL_OES_standard_derivatives on demand). It is used for the unit
[email protected]4b7eba92013-01-08 02:23:562101 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2102 // the empty string to CompileShader and this is not a valid shader.
2103 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
[email protected]39ba4f02012-03-26 01:16:002104 CommandLine::ForCurrentProcess()->HasSwitch(
2105 switches::kDisableGLSLTranslator)) {
[email protected]b9363b22010-06-09 22:06:152106 use_shader_translator_ = false;
2107 }
[email protected]473c01ccb2011-06-07 01:33:302108
[email protected]a39370652012-09-25 21:52:132109 // TODO(gman): Consider setting this based on GPU and/or driver.
[email protected]473c01ccb2011-06-07 01:33:302110 if (IsAngle()) {
[email protected]c986af502013-08-14 01:04:442111 texture_state_.teximage2d_faster_than_texsubimage2d = false;
[email protected]473c01ccb2011-06-07 01:33:302112 }
[email protected]96449d2c2009-11-25 00:01:322113}
2114
[email protected]80eb6b52012-01-19 00:14:412115GLES2DecoderImpl::~GLES2DecoderImpl() {
2116}
2117
[email protected]c410da802011-03-14 19:17:412118bool GLES2DecoderImpl::Initialize(
[email protected]fbe20372011-06-01 01:46:382119 const scoped_refptr<gfx::GLSurface>& surface,
2120 const scoped_refptr<gfx::GLContext>& context,
[email protected]069944672012-04-25 20:52:232121 bool offscreen,
[email protected]c410da802011-03-14 19:17:412122 const gfx::Size& size,
[email protected]e82fb792011-09-22 00:33:292123 const DisallowedFeatures& disallowed_features,
[email protected]c410da802011-03-14 19:17:412124 const char* allowed_extensions,
[email protected]3c644d82011-06-20 19:58:242125 const std::vector<int32>& attribs) {
[email protected]3551cb202012-05-24 10:55:322126 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
[email protected]63c9b052012-05-17 18:27:382127 DCHECK(context->IsCurrent(surface.get()));
[email protected]66791e382010-07-14 20:48:302128 DCHECK(!context_.get());
2129
[email protected]55e136f2013-04-03 18:50:062130 set_initialized();
[email protected]fb97b662013-02-20 23:02:142131 gpu_tracer_ = GPUTracer::Create();
2132
[email protected]e844ae22012-01-14 03:36:262133 if (CommandLine::ForCurrentProcess()->HasSwitch(
2134 switches::kEnableGPUDebugging)) {
2135 set_debug(true);
2136 }
2137
[email protected]39ba4f02012-03-26 01:16:002138 if (CommandLine::ForCurrentProcess()->HasSwitch(
2139 switches::kEnableGPUCommandLogging)) {
2140 set_log_commands(true);
2141 }
2142
[email protected]062c38b2012-01-18 03:25:102143 compile_shader_always_succeeds_ = CommandLine::ForCurrentProcess()->HasSwitch(
2144 switches::kCompileShaderAlwaysSucceeds);
2145
[email protected]f62a5ab2011-05-23 20:34:152146
[email protected]63c9b052012-05-17 18:27:382147 // Take ownership of the context and surface. The surface can be replaced with
2148 // SetSurface.
[email protected]fbe20372011-06-01 01:46:382149 context_ = context;
[email protected]63c9b052012-05-17 18:27:382150 surface_ = surface;
[email protected]eb54a562010-01-20 21:55:182151
[email protected]c4485aad62012-12-17 10:19:092152 if (!group_->Initialize(this, disallowed_features, allowed_extensions)) {
[email protected]09ddb91f2011-04-14 23:16:222153 LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
[email protected]a3ded6d2010-10-19 06:44:392154 << "failed to initialize.";
[email protected]1871a092011-10-10 21:46:422155 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
[email protected]63c9b052012-05-17 18:27:382156 Destroy(true);
[email protected]ae1741092010-11-17 19:16:032157 return false;
[email protected]a3ded6d2010-10-19 06:44:392158 }
[email protected]b64c24952012-04-19 03:20:272159 CHECK_GL_ERROR();
[email protected]43410e92012-04-20 17:06:282160
[email protected]e82fb792011-09-22 00:33:292161 disallowed_features_ = disallowed_features;
[email protected]246a70452010-03-05 21:53:502162
[email protected]af6380962012-11-29 23:24:132163 state_.attrib_values.resize(group_->max_vertex_attribs());
[email protected]944b62f32012-09-27 02:20:462164 default_vertex_attrib_manager_ = new VertexAttribManager();
2165 default_vertex_attrib_manager_->Initialize(group_->max_vertex_attribs());
2166
[email protected]ab4fd7282012-10-12 16:25:572167 // vertex_attrib_manager is set to default_vertex_attrib_manager_ by this call
2168 DoBindVertexArrayOES(0);
[email protected]876f6fee2010-08-02 23:10:322169
[email protected]7cd76fd2013-06-02 21:11:112170 query_manager_.reset(new QueryManager(this, feature_info_.get()));
[email protected]944b62f32012-09-27 02:20:462171 vertex_array_manager_.reset(new VertexArrayManager());
[email protected]882ba1e22012-03-08 19:02:532172
[email protected]302ce6d2011-07-07 23:28:112173 util_.set_num_compressed_texture_formats(
2174 validators_->compressed_texture_format.GetValues().size());
2175
[email protected]1071e572011-02-09 20:00:122176 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2177 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2178 // OpenGL ES 2.0 does not have this issue.
2179 glEnableVertexAttribArray(0);
2180 }
[email protected]b1122982010-05-17 23:04:242181 glGenBuffersARB(1, &attrib_0_buffer_id_);
2182 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2183 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2184 glBindBuffer(GL_ARRAY_BUFFER, 0);
[email protected]8fbedc02010-11-18 18:43:402185 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
[email protected]f39f4b3f2010-05-12 17:04:082186
[email protected]1868a342012-11-07 15:56:022187 state_.texture_units.resize(group_->max_texture_units());
2188 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
[email protected]00f893d2010-08-24 18:55:492189 glActiveTexture(GL_TEXTURE0 + tt);
[email protected]61eeb33f2011-07-26 15:30:312190 // We want the last bind to be 2D.
[email protected]370eaf12013-05-18 09:19:492191 TextureRef* ref;
[email protected]62e155e2012-10-23 22:43:152192 if (features().oes_egl_image_external) {
[email protected]370eaf12013-05-18 09:19:492193 ref = texture_manager()->GetDefaultTextureInfo(
[email protected]02965c22013-03-09 02:40:072194 GL_TEXTURE_EXTERNAL_OES);
[email protected]370eaf12013-05-18 09:19:492195 state_.texture_units[tt].bound_texture_external_oes = ref;
2196 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref->service_id());
[email protected]61eeb33f2011-07-26 15:30:312197 }
[email protected]62e155e2012-10-23 22:43:152198 if (features().arb_texture_rectangle) {
[email protected]370eaf12013-05-18 09:19:492199 ref = texture_manager()->GetDefaultTextureInfo(
[email protected]02965c22013-03-09 02:40:072200 GL_TEXTURE_RECTANGLE_ARB);
[email protected]370eaf12013-05-18 09:19:492201 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2202 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref->service_id());
[email protected]e51bdf32011-11-23 22:21:462203 }
[email protected]370eaf12013-05-18 09:19:492204 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2205 state_.texture_units[tt].bound_texture_cube_map = ref;
2206 glBindTexture(GL_TEXTURE_CUBE_MAP, ref->service_id());
2207 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2208 state_.texture_units[tt].bound_texture_2d = ref;
2209 glBindTexture(GL_TEXTURE_2D, ref->service_id());
[email protected]1958e0e2010-04-22 05:17:152210 }
[email protected]00f893d2010-08-24 18:55:492211 glActiveTexture(GL_TEXTURE0);
[email protected]246a70452010-03-05 21:53:502212 CHECK_GL_ERROR();
2213
[email protected]763eaf72013-08-16 00:58:562214 ContextCreationAttribHelper attrib_parser;
[email protected]297ca1c2011-06-20 23:08:462215 if (!attrib_parser.Parse(attribs))
2216 return false;
[email protected]41c56362011-06-14 16:47:432217
[email protected]069944672012-04-25 20:52:232218 if (offscreen) {
[email protected]34ff8b0c2010-10-01 20:06:022219 if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
[email protected]b0609652012-12-14 07:24:542220 features().chromium_framebuffer_multisample) {
[email protected]34ff8b0c2010-10-01 20:06:022221 // Per ext_framebuffer_multisample spec, need max bound on sample count.
[email protected]0b1e9d72010-11-11 16:29:432222 // max_sample_count must be initialized to a sane value. If
2223 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2224 GLint max_sample_count = 1;
[email protected]34ff8b0c2010-10-01 20:06:022225 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2226 offscreen_target_samples_ = std::min(attrib_parser.samples_,
2227 max_sample_count);
2228 } else {
2229 offscreen_target_samples_ = 1;
2230 }
[email protected]8a61d872012-01-20 12:43:562231 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved_;
[email protected]34ff8b0c2010-10-01 20:06:022232
2233 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2234 const bool rgb8_supported =
2235 context_->HasExtension("GL_OES_rgb8_rgba8");
2236 // The only available default render buffer formats in GLES2 have very
2237 // little precision. Don't enable multisampling unless 8-bit render
2238 // buffer formats are available--instead fall back to 8-bit textures.
2239 if (rgb8_supported && offscreen_target_samples_ > 1) {
2240 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2241 GL_RGBA8 : GL_RGB8;
2242 } else {
2243 offscreen_target_samples_ = 1;
2244 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2245 GL_RGBA : GL_RGB;
2246 }
2247
2248 // ANGLE only supports packed depth/stencil formats, so use it if it is
2249 // available.
2250 const bool depth24_stencil8_supported =
2251 context_->HasExtension("GL_OES_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272252 VLOG(1) << "GL_OES_packed_depth_stencil "
2253 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]71ee3642010-10-14 18:08:002254 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2255 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022256 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2257 offscreen_target_stencil_format_ = 0;
2258 } else {
2259 // It may be the case that this depth/stencil combination is not
2260 // supported, but this will be checked later by CheckFramebufferStatus.
2261 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2262 GL_DEPTH_COMPONENT16 : 0;
2263 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2264 GL_STENCIL_INDEX8 : 0;
2265 }
2266 } else {
2267 offscreen_target_color_format_ = attrib_parser.alpha_size_ > 0 ?
2268 GL_RGBA : GL_RGB;
2269
2270 // If depth is requested at all, use the packed depth stencil format if
2271 // it's available, as some desktop GL drivers don't support any non-packed
2272 // formats for depth attachments.
2273 const bool depth24_stencil8_supported =
2274 context_->HasExtension("GL_EXT_packed_depth_stencil");
[email protected]d366c482010-10-20 00:11:272275 VLOG(1) << "GL_EXT_packed_depth_stencil "
2276 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
[email protected]34ff8b0c2010-10-01 20:06:022277
[email protected]71ee3642010-10-14 18:08:002278 if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
2279 depth24_stencil8_supported) {
[email protected]34ff8b0c2010-10-01 20:06:022280 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2281 offscreen_target_stencil_format_ = 0;
2282 } else {
2283 offscreen_target_depth_format_ = attrib_parser.depth_size_ > 0 ?
2284 GL_DEPTH_COMPONENT : 0;
2285 offscreen_target_stencil_format_ = attrib_parser.stencil_size_ > 0 ?
2286 GL_STENCIL_INDEX : 0;
2287 }
2288 }
2289
[email protected]97872062010-11-03 19:07:052290 offscreen_saved_color_format_ = attrib_parser.alpha_size_ > 0 ?
2291 GL_RGBA : GL_RGB;
2292
[email protected]6217d392010-03-25 22:08:352293 // Create the target frame buffer. This is the one that the client renders
2294 // directly to.
[email protected]ed9f9cd2013-02-27 21:12:352295 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
[email protected]6217d392010-03-25 22:08:352296 offscreen_target_frame_buffer_->Create();
[email protected]34ff8b0c2010-10-01 20:06:022297 // Due to GLES2 format limitations, either the color texture (for
2298 // non-multisampling) or the color render buffer (for multisampling) will be
2299 // attached to the offscreen frame buffer. The render buffer has more
2300 // limited formats available to it, but the texture can't do multisampling.
2301 if (IsOffscreenBufferMultisampled()) {
[email protected]ed9f9cd2013-02-27 21:12:352302 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(this));
[email protected]34ff8b0c2010-10-01 20:06:022303 offscreen_target_color_render_buffer_->Create();
2304 } else {
[email protected]ed9f9cd2013-02-27 21:12:352305 offscreen_target_color_texture_.reset(new BackTexture(this));
[email protected]34ff8b0c2010-10-01 20:06:022306 offscreen_target_color_texture_->Create();
2307 }
[email protected]ed9f9cd2013-02-27 21:12:352308 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(this));
[email protected]b9363b22010-06-09 22:06:152309 offscreen_target_depth_render_buffer_->Create();
[email protected]ed9f9cd2013-02-27 21:12:352310 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(this));
[email protected]b9363b22010-06-09 22:06:152311 offscreen_target_stencil_render_buffer_->Create();
[email protected]6217d392010-03-25 22:08:352312
2313 // Create the saved offscreen texture. The target frame buffer is copied
2314 // here when SwapBuffers is called.
[email protected]ed9f9cd2013-02-27 21:12:352315 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
[email protected]34ff8b0c2010-10-01 20:06:022316 offscreen_saved_frame_buffer_->Create();
2317 //
[email protected]ed9f9cd2013-02-27 21:12:352318 offscreen_saved_color_texture_.reset(new BackTexture(this));
[email protected]6217d392010-03-25 22:08:352319 offscreen_saved_color_texture_->Create();
2320
[email protected]6217d392010-03-25 22:08:352321 // Allocate the render buffers at their initial size and check the status
2322 // of the frame buffers is okay.
[email protected]799b4b22011-08-22 17:09:592323 if (!ResizeOffscreenFrameBuffer(size)) {
[email protected]d0498742010-09-20 20:27:012324 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
[email protected]63c9b052012-05-17 18:27:382325 Destroy(true);
[email protected]6217d392010-03-25 22:08:352326 return false;
2327 }
2328
[email protected]678a73f2012-12-19 19:22:092329 // Allocate the offscreen saved color texture.
2330 DCHECK(offscreen_saved_color_format_);
2331 offscreen_saved_color_texture_->AllocateStorage(
2332 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2333
2334 offscreen_saved_frame_buffer_->AttachRenderTexture(
2335 offscreen_saved_color_texture_.get());
2336 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2337 GL_FRAMEBUFFER_COMPLETE) {
2338 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2339 Destroy(true);
2340 return false;
2341 }
2342
[email protected]6217d392010-03-25 22:08:352343 // Bind to the new default frame buffer (the offscreen target frame buffer).
2344 // This should now be associated with ID zero.
2345 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
[email protected]62e65f02013-05-29 22:28:102346 } else {
2347 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2348 // These are NOT if the back buffer has these proprorties. They are
2349 // if we want the command buffer to enforce them regardless of what
2350 // the real backbuffer is assuming the real back buffer gives us more than
2351 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2352 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2353 // can't do anything about that.
2354
2355 GLint v = 0;
2356 glGetIntegerv(GL_ALPHA_BITS, &v);
2357 // This checks if the user requested RGBA and we have RGBA then RGBA. If the
2358 // user requested RGB then RGB. If the user did not specify a preference
2359 // than use whatever we were given. Same for DEPTH and STENCIL.
2360 back_buffer_color_format_ =
2361 (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
2362 glGetIntegerv(GL_DEPTH_BITS, &v);
2363 back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
2364 glGetIntegerv(GL_STENCIL_BITS, &v);
2365 back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
[email protected]6217d392010-03-25 22:08:352366 }
2367
[email protected]76a0ee102010-04-07 21:03:042368 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2369 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2370 // isn't well documented; it was discovered in the Khronos OpenGL ES
[email protected]c1d82b62010-09-20 22:43:372371 // mailing list archives. It also implicitly enables the desktop GL
2372 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2373 // variable in fragment shaders.
[email protected]b9363b22010-06-09 22:06:152374 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2375 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
[email protected]c1d82b62010-09-20 22:43:372376 glEnable(GL_POINT_SPRITE);
[email protected]b9363b22010-06-09 22:06:152377 }
[email protected]de17df392010-04-23 21:09:412378
[email protected]706b69f2012-07-27 04:59:302379 has_robustness_extension_ =
2380 context->HasExtension("GL_ARB_robustness") ||
2381 context->HasExtension("GL_EXT_robustness");
[email protected]38d139d2011-07-14 00:38:432382
[email protected]c2f8c8402010-12-06 18:07:242383 if (!InitializeShaderTranslator()) {
2384 return false;
[email protected]de17df392010-04-23 21:09:412385 }
[email protected]76a0ee102010-04-07 21:03:042386
[email protected]e259eb412012-10-13 05:47:242387 state_.viewport_width = size.width();
2388 state_.viewport_height = size.height();
[email protected]43410e92012-04-20 17:06:282389
[email protected]5904806b2012-05-08 18:10:222390 GLint viewport_params[4] = { 0 };
[email protected]43410e92012-04-20 17:06:282391 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
[email protected]1868a342012-11-07 15:56:022392 viewport_max_width_ = viewport_params[0];
2393 viewport_max_height_ = viewport_params[1];
[email protected]43410e92012-04-20 17:06:282394
[email protected]88a61bf2012-10-27 13:00:422395 state_.scissor_width = state_.viewport_width;
2396 state_.scissor_height = state_.viewport_height;
2397
[email protected]11f3e702012-06-19 19:00:012398 // Set all the default state because some GL drivers get it wrong.
[email protected]f731b9462012-10-30 00:35:222399 state_.InitCapabilities();
2400 state_.InitState();
[email protected]e259eb412012-10-13 05:47:242401 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
[email protected]11f3e702012-06-19 19:00:012402
2403 DoBindBuffer(GL_ARRAY_BUFFER, 0);
2404 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2405 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2406 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
2407
[email protected]88cfd132013-07-11 00:59:002408 bool call_gl_clear = true;
2409#if defined(OS_ANDROID)
2410 // Temporary workaround for Android WebView because this clear ignores the
2411 // clip and corrupts that external UI of the App. Not calling glClear is ok
2412 // because the system already clears the buffer before each draw. Proper
2413 // fix might be setting the scissor clip properly before initialize. See
2414 // crbug.com/259023 for details.
2415 call_gl_clear = surface_->GetHandle();
2416#endif
2417 if (call_gl_clear) {
2418 // Clear the backbuffer.
2419 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2420 }
[email protected]561cc0a62013-05-07 18:34:452421
[email protected]62e155e2012-10-23 22:43:152422 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
[email protected]dd289a5d62012-06-30 22:05:462423 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
2424 }
[email protected]dd289a5d62012-06-30 22:05:462425
[email protected]9b753992013-04-27 02:04:412426 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
2427 context_->SetUnbindFboOnMakeCurrent();
[email protected]85cb4682013-04-20 00:54:242428 }
[email protected]85cb4682013-04-20 00:54:242429
[email protected]97419c02013-04-10 02:52:382430 // Only compositor contexts are known to use only the subset of GL
2431 // that can be safely migrated between the iGPU and the dGPU. Mark
2432 // those contexts as safe to forcibly transition between the GPUs.
2433 // http://crbug.com/180876, http://crbug.com/227228
2434 if (!offscreen)
2435 context_->SetSafeToForceGpuSwitch();
2436
[email protected]85a4ac22013-05-31 01:58:472437 async_pixel_transfer_manager_.reset(
[email protected]498b5c072013-06-04 19:30:072438 AsyncPixelTransferManager::Create(context.get()));
2439 async_pixel_transfer_manager_->Initialize(texture_manager());
[email protected]32145a92012-12-17 09:01:592440
[email protected]246a70452010-03-05 21:53:502441 return true;
[email protected]96449d2c2009-11-25 00:01:322442}
2443
[email protected]302ce6d2011-07-07 23:28:112444void GLES2DecoderImpl::UpdateCapabilities() {
2445 util_.set_num_compressed_texture_formats(
2446 validators_->compressed_texture_format.GetValues().size());
2447 util_.set_num_shader_binary_formats(
2448 validators_->shader_binary_format.GetValues().size());
2449}
2450
[email protected]c2f8c8402010-12-06 18:07:242451bool GLES2DecoderImpl::InitializeShaderTranslator() {
[email protected]a5d3dad2012-05-26 04:34:442452 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
2453
[email protected]c2f8c8402010-12-06 18:07:242454 if (!use_shader_translator_) {
2455 return true;
2456 }
2457 ShBuiltInResources resources;
2458 ShInitBuiltInResources(&resources);
2459 resources.MaxVertexAttribs = group_->max_vertex_attribs();
2460 resources.MaxVertexUniformVectors =
2461 group_->max_vertex_uniform_vectors();
2462 resources.MaxVaryingVectors = group_->max_varying_vectors();
2463 resources.MaxVertexTextureImageUnits =
2464 group_->max_vertex_texture_image_units();
2465 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
2466 resources.MaxTextureImageUnits = group_->max_texture_image_units();
2467 resources.MaxFragmentUniformVectors =
2468 group_->max_fragment_uniform_vectors();
[email protected]2f143d482013-03-14 18:04:492469 resources.MaxDrawBuffers = group_->max_draw_buffers();
[email protected]a0b78142013-05-23 00:47:242470 resources.MaxExpressionComplexity = 256;
2471 resources.MaxCallStackDepth = 256;
[email protected]f0d74742011-10-03 16:31:042472
[email protected]9e98f61b2013-03-05 02:21:142473#if (ANGLE_SH_VERSION >= 110)
[email protected]46c86752013-05-21 05:08:392474 GLint range[2] = { 0, 0 };
[email protected]8dc1bf92013-03-12 03:58:212475 GLint precision = 0;
2476 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
2477 range, &precision);
[email protected]448e459e2013-06-12 17:00:412478 resources.FragmentPrecisionHigh =
2479 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
[email protected]9e98f61b2013-03-05 02:21:142480#endif
2481
[email protected]f0d74742011-10-03 16:31:042482 if (force_webgl_glsl_validation_) {
2483 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
[email protected]70dc60932013-06-04 03:33:492484 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
[email protected]aff39ac82013-06-08 04:53:132485 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
[email protected]cd8f1892013-09-05 00:14:442486 if (!draw_buffers_explicitly_enabled_)
2487 resources.MaxDrawBuffers = 1;
[email protected]f0d74742011-10-03 16:31:042488 } else {
2489 resources.OES_standard_derivatives =
[email protected]62e155e2012-10-23 22:43:152490 features().oes_standard_derivatives ? 1 : 0;
[email protected]e51bdf32011-11-23 22:21:462491 resources.ARB_texture_rectangle =
[email protected]62e155e2012-10-23 22:43:152492 features().arb_texture_rectangle ? 1 : 0;
[email protected]70e7bb12012-09-29 14:01:062493 resources.OES_EGL_image_external =
[email protected]62e155e2012-10-23 22:43:152494 features().oes_egl_image_external ? 1 : 0;
[email protected]2f143d482013-03-14 18:04:492495 resources.EXT_draw_buffers =
2496 features().ext_draw_buffers ? 1 : 0;
[email protected]70dc60932013-06-04 03:33:492497 resources.EXT_frag_depth =
2498 features().ext_frag_depth ? 1 : 0;
[email protected]f0d74742011-10-03 16:31:042499 }
2500
[email protected]26b61442013-03-17 16:12:012501 ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
2502 : SH_GLES2_SPEC;
[email protected]6aedcdc2013-01-24 01:25:052503 if (shader_spec == SH_WEBGL_SPEC && features().enable_shader_name_hashing)
[email protected]3d944a82013-02-12 19:09:022504#if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
[email protected]6aedcdc2013-01-24 01:25:052505 resources.HashFunction = &CityHashForAngle;
[email protected]3d944a82013-02-12 19:09:022506#else
2507 resources.HashFunction = &CityHash64;
2508#endif
[email protected]6aedcdc2013-01-24 01:25:052509 else
2510 resources.HashFunction = NULL;
[email protected]a2a0fe762011-09-20 00:59:122511 ShaderTranslatorInterface::GlslImplementationType implementation_type =
2512 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 ?
2513 ShaderTranslatorInterface::kGlslES : ShaderTranslatorInterface::kGlsl;
2514 ShaderTranslatorInterface::GlslBuiltInFunctionBehavior function_behavior =
[email protected]62e155e2012-10-23 22:43:152515 workarounds().needs_glsl_built_in_function_emulation ?
[email protected]a2a0fe762011-09-20 00:59:122516 ShaderTranslatorInterface::kGlslBuiltInFunctionEmulated :
2517 ShaderTranslatorInterface::kGlslBuiltInFunctionOriginal;
[email protected]87fb6ab2012-06-13 22:28:042518
2519 ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
2520 vertex_translator_ = cache->GetTranslator(
2521 SH_VERTEX_SHADER, shader_spec, &resources,
2522 implementation_type, function_behavior);
2523 if (!vertex_translator_.get()) {
[email protected]c2f8c8402010-12-06 18:07:242524 LOG(ERROR) << "Could not initialize vertex shader translator.";
[email protected]63c9b052012-05-17 18:27:382525 Destroy(true);
[email protected]c2f8c8402010-12-06 18:07:242526 return false;
2527 }
[email protected]87fb6ab2012-06-13 22:28:042528
2529 fragment_translator_ = cache->GetTranslator(
2530 SH_FRAGMENT_SHADER, shader_spec, &resources,
2531 implementation_type, function_behavior);
2532 if (!fragment_translator_.get()) {
[email protected]c2f8c8402010-12-06 18:07:242533 LOG(ERROR) << "Could not initialize fragment shader translator.";
[email protected]63c9b052012-05-17 18:27:382534 Destroy(true);
[email protected]c2f8c8402010-12-06 18:07:242535 return false;
2536 }
2537 return true;
2538}
2539
[email protected]ae51d192010-04-27 00:48:032540bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
[email protected]a93bb842010-02-16 23:03:472541 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352542 if (GetBuffer(client_ids[ii])) {
[email protected]ae51d192010-04-27 00:48:032543 return false;
2544 }
2545 }
[email protected]40d90a22013-04-09 03:39:552546 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ae51d192010-04-27 00:48:032547 glGenBuffersARB(n, service_ids.get());
2548 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352549 CreateBuffer(client_ids[ii], service_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032550 }
2551 return true;
2552}
2553
2554bool GLES2DecoderImpl::GenFramebuffersHelper(
2555 GLsizei n, const GLuint* client_ids) {
2556 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352557 if (GetFramebuffer(client_ids[ii])) {
[email protected]ae51d192010-04-27 00:48:032558 return false;
2559 }
2560 }
[email protected]40d90a22013-04-09 03:39:552561 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ae51d192010-04-27 00:48:032562 glGenFramebuffersEXT(n, service_ids.get());
2563 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352564 CreateFramebuffer(client_ids[ii], service_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032565 }
2566 return true;
2567}
2568
2569bool GLES2DecoderImpl::GenRenderbuffersHelper(
2570 GLsizei n, const GLuint* client_ids) {
2571 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352572 if (GetRenderbuffer(client_ids[ii])) {
[email protected]ae51d192010-04-27 00:48:032573 return false;
2574 }
2575 }
[email protected]40d90a22013-04-09 03:39:552576 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ae51d192010-04-27 00:48:032577 glGenRenderbuffersEXT(n, service_ids.get());
2578 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352579 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032580 }
2581 return true;
2582}
2583
2584bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
2585 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352586 if (GetTexture(client_ids[ii])) {
[email protected]ae51d192010-04-27 00:48:032587 return false;
2588 }
2589 }
[email protected]40d90a22013-04-09 03:39:552590 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ae51d192010-04-27 00:48:032591 glGenTextures(n, service_ids.get());
2592 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352593 CreateTexture(client_ids[ii], service_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032594 }
2595 return true;
2596}
2597
2598void GLES2DecoderImpl::DeleteBuffersHelper(
2599 GLsizei n, const GLuint* client_ids) {
2600 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]16ccec12013-02-28 03:40:212601 Buffer* buffer = GetBuffer(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102602 if (buffer && !buffer->IsDeleted()) {
[email protected]e259eb412012-10-13 05:47:242603 state_.vertex_attrib_manager->Unbind(buffer);
[email protected]7cd76fd2013-06-02 21:11:112604 if (state_.bound_array_buffer.get() == buffer) {
[email protected]e259eb412012-10-13 05:47:242605 state_.bound_array_buffer = NULL;
[email protected]a0b78dc2011-11-11 10:43:102606 }
[email protected]ed9f9cd2013-02-27 21:12:352607 RemoveBuffer(client_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032608 }
[email protected]a93bb842010-02-16 23:03:472609 }
[email protected]07f54fcc2009-12-22 02:46:302610}
2611
[email protected]ae51d192010-04-27 00:48:032612void GLES2DecoderImpl::DeleteFramebuffersHelper(
2613 GLsizei n, const GLuint* client_ids) {
[email protected]ebfb73c2012-08-15 02:37:452614 bool supports_separate_framebuffer_binds =
[email protected]62e155e2012-10-23 22:43:152615 features().chromium_framebuffer_multisample;
[email protected]b177ae22011-11-01 03:29:112616
[email protected]a25fa872010-03-25 02:57:582617 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352618 Framebuffer* framebuffer =
2619 GetFramebuffer(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102620 if (framebuffer && !framebuffer->IsDeleted()) {
[email protected]7cd76fd2013-06-02 21:11:112621 if (framebuffer == state_.bound_draw_framebuffer.get()) {
[email protected]e259eb412012-10-13 05:47:242622 state_.bound_draw_framebuffer = NULL;
[email protected]c986af502013-08-14 01:04:442623 framebuffer_state_.clear_state_dirty = true;
[email protected]ebfb73c2012-08-15 02:37:452624 GLenum target = supports_separate_framebuffer_binds ?
2625 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
[email protected]b177ae22011-11-01 03:29:112626 glBindFramebufferEXT(target, GetBackbufferServiceId());
2627 }
[email protected]7cd76fd2013-06-02 21:11:112628 if (framebuffer == state_.bound_read_framebuffer.get()) {
[email protected]e259eb412012-10-13 05:47:242629 state_.bound_read_framebuffer = NULL;
[email protected]ebfb73c2012-08-15 02:37:452630 GLenum target = supports_separate_framebuffer_binds ?
2631 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
[email protected]b177ae22011-11-01 03:29:112632 glBindFramebufferEXT(target, GetBackbufferServiceId());
[email protected]297ca1c2011-06-20 23:08:462633 }
[email protected]70d34263c2013-01-09 00:27:452634 OnFboChanged();
[email protected]ed9f9cd2013-02-27 21:12:352635 RemoveFramebuffer(client_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032636 }
[email protected]a25fa872010-03-25 02:57:582637 }
[email protected]07f54fcc2009-12-22 02:46:302638}
2639
[email protected]ae51d192010-04-27 00:48:032640void GLES2DecoderImpl::DeleteRenderbuffersHelper(
2641 GLsizei n, const GLuint* client_ids) {
[email protected]ebfb73c2012-08-15 02:37:452642 bool supports_separate_framebuffer_binds =
[email protected]62e155e2012-10-23 22:43:152643 features().chromium_framebuffer_multisample;
[email protected]a25fa872010-03-25 02:57:582644 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:352645 Renderbuffer* renderbuffer =
2646 GetRenderbuffer(client_ids[ii]);
[email protected]a0b78dc2011-11-11 10:43:102647 if (renderbuffer && !renderbuffer->IsDeleted()) {
[email protected]7cd76fd2013-06-02 21:11:112648 if (state_.bound_renderbuffer.get() == renderbuffer) {
[email protected]e259eb412012-10-13 05:47:242649 state_.bound_renderbuffer = NULL;
[email protected]a0b78dc2011-11-11 10:43:102650 }
2651 // Unbind from current framebuffers.
[email protected]ebfb73c2012-08-15 02:37:452652 if (supports_separate_framebuffer_binds) {
[email protected]7cd76fd2013-06-02 21:11:112653 if (state_.bound_read_framebuffer.get()) {
2654 state_.bound_read_framebuffer
2655 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
[email protected]a0b78dc2011-11-11 10:43:102656 }
[email protected]7cd76fd2013-06-02 21:11:112657 if (state_.bound_draw_framebuffer.get()) {
2658 state_.bound_draw_framebuffer
2659 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
[email protected]a0b78dc2011-11-11 10:43:102660 }
2661 } else {
[email protected]7cd76fd2013-06-02 21:11:112662 if (state_.bound_draw_framebuffer.get()) {
2663 state_.bound_draw_framebuffer
2664 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
[email protected]a0b78dc2011-11-11 10:43:102665 }
2666 }
[email protected]c986af502013-08-14 01:04:442667 framebuffer_state_.clear_state_dirty = true;
[email protected]ed9f9cd2013-02-27 21:12:352668 RemoveRenderbuffer(client_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032669 }
[email protected]a25fa872010-03-25 02:57:582670 }
[email protected]07f54fcc2009-12-22 02:46:302671}
2672
[email protected]ae51d192010-04-27 00:48:032673void GLES2DecoderImpl::DeleteTexturesHelper(
2674 GLsizei n, const GLuint* client_ids) {
[email protected]ebfb73c2012-08-15 02:37:452675 bool supports_separate_framebuffer_binds =
[email protected]62e155e2012-10-23 22:43:152676 features().chromium_framebuffer_multisample;
[email protected]a93bb842010-02-16 23:03:472677 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]370eaf12013-05-18 09:19:492678 TextureRef* texture_ref = GetTexture(client_ids[ii]);
2679 if (texture_ref) {
2680 Texture* texture = texture_ref->texture();
[email protected]a0b78dc2011-11-11 10:43:102681 if (texture->IsAttachedToFramebuffer()) {
[email protected]c986af502013-08-14 01:04:442682 framebuffer_state_.clear_state_dirty = true;
[email protected]297ca1c2011-06-20 23:08:462683 }
[email protected]370eaf12013-05-18 09:19:492684 // Unbind texture_ref from texture_ref units.
[email protected]1868a342012-11-07 15:56:022685 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
[email protected]370eaf12013-05-18 09:19:492686 state_.texture_units[jj].Unbind(texture_ref);
[email protected]a0b78dc2011-11-11 10:43:102687 }
2688 // Unbind from current framebuffers.
[email protected]ebfb73c2012-08-15 02:37:452689 if (supports_separate_framebuffer_binds) {
[email protected]7cd76fd2013-06-02 21:11:112690 if (state_.bound_read_framebuffer.get()) {
2691 state_.bound_read_framebuffer
2692 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
[email protected]a0b78dc2011-11-11 10:43:102693 }
[email protected]7cd76fd2013-06-02 21:11:112694 if (state_.bound_draw_framebuffer.get()) {
2695 state_.bound_draw_framebuffer
2696 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
[email protected]a0b78dc2011-11-11 10:43:102697 }
2698 } else {
[email protected]7cd76fd2013-06-02 21:11:112699 if (state_.bound_draw_framebuffer.get()) {
2700 state_.bound_draw_framebuffer
2701 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
[email protected]a0b78dc2011-11-11 10:43:102702 }
2703 }
[email protected]e51bdf32011-11-23 22:21:462704#if defined(OS_MACOSX)
[email protected]4f9958142013-07-02 03:58:072705 GLuint service_id = texture->service_id();
[email protected]e51bdf32011-11-23 22:21:462706 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
2707 ReleaseIOSurfaceForTexture(service_id);
2708 }
2709#endif
[email protected]ed9f9cd2013-02-27 21:12:352710 RemoveTexture(client_ids[ii]);
[email protected]ae51d192010-04-27 00:48:032711 }
[email protected]a93bb842010-02-16 23:03:472712 }
[email protected]07f54fcc2009-12-22 02:46:302713}
2714
[email protected]43f28f832010-02-03 02:28:482715// } // anonymous namespace
[email protected]96449d2c2009-11-25 00:01:322716
[email protected]eb54a562010-01-20 21:55:182717bool GLES2DecoderImpl::MakeCurrent() {
[email protected]63c9b052012-05-17 18:27:382718 if (!context_.get() || !context_->MakeCurrent(surface_.get()))
2719 return false;
2720
2721 if (WasContextLost()) {
[email protected]38d139d2011-07-14 00:38:432722 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
[email protected]e9f0ca82013-04-01 23:52:292723
2724 // Some D3D drivers cannot recover from device lost in the GPU process
2725 // sandbox. Allow a new GPU process to launch.
2726 if (workarounds().exit_on_context_lost) {
2727 LOG(ERROR) << "Exiting GPU process because some drivers cannot reset"
2728 << " a D3D device in the Chrome GPU process sandbox.";
[email protected]6eb775352013-08-27 05:57:162729#if defined(OS_WIN)
2730 base::win::SetShouldCrashOnProcessDetach(false);
2731#endif
[email protected]e9f0ca82013-04-01 23:52:292732 exit(0);
2733 }
2734
[email protected]63c9b052012-05-17 18:27:382735 return false;
[email protected]38d139d2011-07-14 00:38:432736 }
2737
[email protected]69a8701e2013-03-07 21:31:092738 ProcessFinishedAsyncTransfers();
[email protected]69a8701e2013-03-07 21:31:092739
[email protected]9b753992013-04-27 02:04:412740 // Rebind the FBO if it was unbound by the context.
2741 if (workarounds().unbind_fbo_on_context_switch)
2742 RestoreFramebufferBindings();
2743
[email protected]c986af502013-08-14 01:04:442744 framebuffer_state_.clear_state_dirty = true;
[email protected]370eaf12013-05-18 09:19:492745
[email protected]69a8701e2013-03-07 21:31:092746 return true;
2747}
2748
2749void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
[email protected]5a36dc132013-07-23 23:17:552750 ProcessPendingReadPixels();
[email protected]fe8d73c2013-02-16 22:37:322751 if (engine() && query_manager_.get())
2752 query_manager_->ProcessPendingTransferQueries();
2753
[email protected]5b3a8e02013-03-13 05:36:442754 // TODO(epenner): Is there a better place to do this?
2755 // This needs to occur before we execute any batch of commands
2756 // from the client, as the client may have recieved an async
2757 // completion while issuing those commands.
2758 // "DidFlushStart" would be ideal if we had such a callback.
[email protected]b68b100752013-06-05 08:34:482759 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
[email protected]eb54a562010-01-20 21:55:182760}
2761
[email protected]a96a6022011-11-04 00:58:122762void GLES2DecoderImpl::ReleaseCurrent() {
2763 if (context_.get())
2764 context_->ReleaseCurrent(surface_.get());
2765}
2766
[email protected]8e3e0662010-08-23 18:46:302767void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
[email protected]ed9f9cd2013-02-27 21:12:352768 Renderbuffer* renderbuffer =
[email protected]0d6bfdc2011-11-02 01:32:202769 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
[email protected]8e3e0662010-08-23 18:46:302770 glBindRenderbufferEXT(
[email protected]0d6bfdc2011-11-02 01:32:202771 GL_RENDERBUFFER, renderbuffer ? renderbuffer->service_id() : 0);
[email protected]8e3e0662010-08-23 18:46:302772}
2773
2774static void RebindCurrentFramebuffer(
2775 GLenum target,
[email protected]4d8f0dd2013-03-09 14:37:062776 Framebuffer* framebuffer,
[email protected]a3783712012-01-20 22:18:242777 GLuint back_buffer_service_id) {
[email protected]4d8f0dd2013-03-09 14:37:062778 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
[email protected]297ca1c2011-06-20 23:08:462779
[email protected]a3783712012-01-20 22:18:242780 if (framebuffer_id == 0) {
2781 framebuffer_id = back_buffer_service_id;
[email protected]8e3e0662010-08-23 18:46:302782 }
[email protected]297ca1c2011-06-20 23:08:462783
[email protected]8e3e0662010-08-23 18:46:302784 glBindFramebufferEXT(target, framebuffer_id);
2785}
2786
2787void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
[email protected]c986af502013-08-14 01:04:442788 framebuffer_state_.clear_state_dirty = true;
[email protected]297ca1c2011-06-20 23:08:462789
[email protected]62e155e2012-10-23 22:43:152790 if (!features().chromium_framebuffer_multisample) {
[email protected]8e3e0662010-08-23 18:46:302791 RebindCurrentFramebuffer(
2792 GL_FRAMEBUFFER,
[email protected]e259eb412012-10-13 05:47:242793 state_.bound_draw_framebuffer.get(),
[email protected]a3783712012-01-20 22:18:242794 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302795 } else {
2796 RebindCurrentFramebuffer(
2797 GL_READ_FRAMEBUFFER_EXT,
[email protected]e259eb412012-10-13 05:47:242798 state_.bound_read_framebuffer.get(),
[email protected]a3783712012-01-20 22:18:242799 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302800 RebindCurrentFramebuffer(
2801 GL_DRAW_FRAMEBUFFER_EXT,
[email protected]e259eb412012-10-13 05:47:242802 state_.bound_draw_framebuffer.get(),
[email protected]a3783712012-01-20 22:18:242803 GetBackbufferServiceId());
[email protected]8e3e0662010-08-23 18:46:302804 }
[email protected]70d34263c2013-01-09 00:27:452805 OnFboChanged();
[email protected]8e3e0662010-08-23 18:46:302806}
2807
2808void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
[email protected]e259eb412012-10-13 05:47:242809 TextureUnit& info = state_.texture_units[0];
[email protected]8e3e0662010-08-23 18:46:302810 GLuint last_id;
[email protected]7cd76fd2013-06-02 21:11:112811 if (info.bound_texture_2d.get()) {
[email protected]8e3e0662010-08-23 18:46:302812 last_id = info.bound_texture_2d->service_id();
2813 } else {
2814 last_id = 0;
2815 }
2816
2817 glBindTexture(GL_TEXTURE_2D, last_id);
[email protected]e259eb412012-10-13 05:47:242818 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
[email protected]8e3e0662010-08-23 18:46:302819}
2820
[email protected]0d6bfdc2011-11-02 01:32:202821bool GLES2DecoderImpl::CheckFramebufferValid(
[email protected]ed9f9cd2013-02-27 21:12:352822 Framebuffer* framebuffer,
[email protected]0d6bfdc2011-11-02 01:32:202823 GLenum target, const char* func_name) {
[email protected]a0b78dc2011-11-11 10:43:102824 if (!framebuffer) {
[email protected]60f22d32012-12-12 00:31:582825 if (backbuffer_needs_clear_bits_) {
2826 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
2827 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
2828 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2829 glClearStencil(0);
2830 glStencilMask(-1);
2831 glClearDepth(1.0f);
2832 glDepthMask(true);
2833 glDisable(GL_SCISSOR_TEST);
2834 glClear(backbuffer_needs_clear_bits_);
2835 backbuffer_needs_clear_bits_ = 0;
2836 RestoreClearState();
2837 }
[email protected]0d6bfdc2011-11-02 01:32:202838 return true;
2839 }
2840
[email protected]968351b2011-12-20 08:26:512841 if (framebuffer_manager()->IsComplete(framebuffer)) {
2842 return true;
2843 }
2844
[email protected]0d6bfdc2011-11-02 01:32:202845 GLenum completeness = framebuffer->IsPossiblyComplete();
2846 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
[email protected]ab09b612013-03-11 22:11:512847 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:432848 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
[email protected]3a03a8f2011-03-19 00:51:272849 return false;
2850 }
[email protected]0d6bfdc2011-11-02 01:32:202851
2852 // Are all the attachments cleared?
2853 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
2854 texture_manager()->HaveUnclearedMips()) {
2855 if (!framebuffer->IsCleared()) {
2856 // Can we clear them?
[email protected]73276522012-11-09 05:50:202857 if (framebuffer->GetStatus(texture_manager(), target) !=
2858 GL_FRAMEBUFFER_COMPLETE) {
[email protected]ab09b612013-03-11 22:11:512859 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:432860 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2861 "framebuffer incomplete (clear)");
[email protected]0d6bfdc2011-11-02 01:32:202862 return false;
2863 }
2864 ClearUnclearedAttachments(target, framebuffer);
2865 }
2866 }
2867
[email protected]968351b2011-12-20 08:26:512868 if (!framebuffer_manager()->IsComplete(framebuffer)) {
[email protected]73276522012-11-09 05:50:202869 if (framebuffer->GetStatus(texture_manager(), target) !=
2870 GL_FRAMEBUFFER_COMPLETE) {
[email protected]ab09b612013-03-11 22:11:512871 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:432872 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
2873 "framebuffer incomplete (check)");
[email protected]968351b2011-12-20 08:26:512874 return false;
2875 }
2876 framebuffer_manager()->MarkAsComplete(framebuffer);
2877 }
2878
[email protected]0d6bfdc2011-11-02 01:32:202879 // NOTE: At this point we don't know if the framebuffer is complete but
2880 // we DO know that everything that needs to be cleared has been cleared.
[email protected]3a03a8f2011-03-19 00:51:272881 return true;
2882}
2883
[email protected]0d6bfdc2011-11-02 01:32:202884bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
[email protected]62e155e2012-10-23 22:43:152885 if (!features().chromium_framebuffer_multisample) {
[email protected]28718a92013-04-04 12:12:512886 bool valid = CheckFramebufferValid(
[email protected]7cd76fd2013-06-02 21:11:112887 state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT, func_name);
[email protected]28718a92013-04-04 12:12:512888
2889 if (valid)
2890 OnUseFramebuffer();
2891
2892 return valid;
[email protected]0d6bfdc2011-11-02 01:32:202893 }
[email protected]7cd76fd2013-06-02 21:11:112894 return CheckFramebufferValid(state_.bound_draw_framebuffer.get(),
2895 GL_DRAW_FRAMEBUFFER_EXT,
2896 func_name) &&
2897 CheckFramebufferValid(state_.bound_read_framebuffer.get(),
2898 GL_READ_FRAMEBUFFER_EXT,
2899 func_name);
[email protected]0d6bfdc2011-11-02 01:32:202900}
2901
[email protected]8e3e0662010-08-23 18:46:302902gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
[email protected]ed9f9cd2013-02-27 21:12:352903 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:452904 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:202905 if (framebuffer != NULL) {
[email protected]ed9f9cd2013-02-27 21:12:352906 const Framebuffer::Attachment* attachment =
[email protected]0d6bfdc2011-11-02 01:32:202907 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
[email protected]9edc6b22010-12-23 02:00:262908 if (attachment) {
2909 return gfx::Size(attachment->width(), attachment->height());
[email protected]246a70452010-03-05 21:53:502910 }
[email protected]9edc6b22010-12-23 02:00:262911 return gfx::Size(0, 0);
[email protected]34ff8b0c2010-10-01 20:06:022912 } else if (offscreen_target_frame_buffer_.get()) {
2913 return offscreen_size_;
[email protected]6217d392010-03-25 22:08:352914 } else {
[email protected]f62a5ab2011-05-23 20:34:152915 return surface_->GetSize();
[email protected]d37231fa2010-04-09 21:16:022916 }
[email protected]246a70452010-03-05 21:53:502917}
2918
[email protected]9edc6b22010-12-23 02:00:262919GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
[email protected]ed9f9cd2013-02-27 21:12:352920 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:452921 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:202922 if (framebuffer != NULL) {
2923 return framebuffer->GetColorAttachmentFormat();
[email protected]297ca1c2011-06-20 23:08:462924 } else if (offscreen_target_frame_buffer_.get()) {
2925 return offscreen_target_color_format_;
2926 } else {
2927 return back_buffer_color_format_;
2928 }
2929}
2930
2931GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
[email protected]ed9f9cd2013-02-27 21:12:352932 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:452933 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:202934 if (framebuffer != NULL) {
2935 return framebuffer->GetColorAttachmentFormat();
[email protected]9edc6b22010-12-23 02:00:262936 } else if (offscreen_target_frame_buffer_.get()) {
2937 return offscreen_target_color_format_;
2938 } else {
[email protected]32fe9aa2011-01-21 23:47:132939 return back_buffer_color_format_;
[email protected]9edc6b22010-12-23 02:00:262940 }
2941}
2942
[email protected]9a5afa432011-07-22 18:16:392943void GLES2DecoderImpl::UpdateParentTextureInfo() {
[email protected]2ad674132013-06-05 07:48:512944 if (!offscreen_saved_color_texture_info_.get())
2945 return;
2946 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
2947 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
2948 texture_manager()->SetLevelInfo(
2949 offscreen_saved_color_texture_info_.get(),
2950 GL_TEXTURE_2D,
2951 0, // level
2952 GL_RGBA,
2953 offscreen_size_.width(),
2954 offscreen_size_.height(),
2955 1, // depth
2956 0, // border
2957 GL_RGBA,
2958 GL_UNSIGNED_BYTE,
2959 true);
2960 texture_manager()->SetParameter(
2961 "UpdateParentTextureInfo",
2962 GetErrorState(),
2963 offscreen_saved_color_texture_info_.get(),
2964 GL_TEXTURE_MAG_FILTER,
2965 GL_NEAREST);
2966 texture_manager()->SetParameter(
2967 "UpdateParentTextureInfo",
2968 GetErrorState(),
2969 offscreen_saved_color_texture_info_.get(),
2970 GL_TEXTURE_MIN_FILTER,
2971 GL_NEAREST);
2972 texture_manager()->SetParameter(
2973 "UpdateParentTextureInfo",
2974 GetErrorState(),
2975 offscreen_saved_color_texture_info_.get(),
2976 GL_TEXTURE_WRAP_S,
2977 GL_CLAMP_TO_EDGE);
2978 texture_manager()->SetParameter(
2979 "UpdateParentTextureInfo",
2980 GetErrorState(),
2981 offscreen_saved_color_texture_info_.get(),
2982 GL_TEXTURE_WRAP_T,
2983 GL_CLAMP_TO_EDGE);
[email protected]c986af502013-08-14 01:04:442984 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
2985 &state_, target);
[email protected]2ad674132013-06-05 07:48:512986 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
[email protected]6217d392010-03-25 22:08:352987}
2988
[email protected]799b4b22011-08-22 17:09:592989void GLES2DecoderImpl::SetResizeCallback(
[email protected]729c0b42013-05-26 02:05:072990 const base::Callback<void(gfx::Size, float)>& callback) {
[email protected]9d37f062011-11-22 01:24:522991 resize_callback_ = callback;
[email protected]7ff86b92010-11-25 17:50:002992}
2993
[email protected]1d82e822013-04-10 21:32:322994Logger* GLES2DecoderImpl::GetLogger() {
2995 return &logger_;
[email protected]6b6e7ee2011-12-13 08:04:522996}
2997
[email protected]d3eba342013-04-18 21:11:502998ErrorState* GLES2DecoderImpl::GetErrorState() {
2999 return state_.GetErrorState();
3000}
3001
[email protected]e3932abb2013-03-13 00:01:373002void GLES2DecoderImpl::SetShaderCacheCallback(
3003 const ShaderCacheCallback& callback) {
3004 shader_cache_callback_ = callback;
3005}
3006
[email protected]840a7e462013-02-27 01:29:513007void GLES2DecoderImpl::SetWaitSyncPointCallback(
3008 const WaitSyncPointCallback& callback) {
3009 wait_sync_point_callback_ = callback;
3010}
3011
[email protected]85a4ac22013-05-31 01:58:473012AsyncPixelTransferManager*
3013 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3014 return async_pixel_transfer_manager_.get();
3015}
3016
3017void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3018 async_pixel_transfer_manager_.reset();
[email protected]32145a92012-12-17 09:01:593019}
3020
[email protected]498b5c072013-06-04 19:30:073021void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3022 AsyncPixelTransferManager* manager) {
3023 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3024}
3025
[email protected]1318e922010-09-17 22:03:163026bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3027 uint32* service_texture_id) {
[email protected]370eaf12013-05-18 09:19:493028 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3029 if (texture_ref) {
3030 *service_texture_id = texture_ref->service_id();
[email protected]1318e922010-09-17 22:03:163031 return true;
3032 }
3033 return false;
3034}
3035
[email protected]63b465922012-09-06 02:04:523036uint32 GLES2DecoderImpl::GetTextureUploadCount() {
[email protected]c986af502013-08-14 01:04:443037 return texture_state_.texture_upload_count +
[email protected]b68b100752013-06-05 08:34:483038 async_pixel_transfer_manager_->GetTextureUploadCount();
[email protected]63b465922012-09-06 02:04:523039}
3040
3041base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
[email protected]c986af502013-08-14 01:04:443042 return texture_state_.total_texture_upload_time +
[email protected]b68b100752013-06-05 08:34:483043 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
[email protected]63b465922012-09-06 02:04:523044}
3045
3046base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3047 return total_processing_commands_time_;
3048}
3049
[email protected]dc25dda2012-09-27 21:36:303050void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3051 total_processing_commands_time_ += time;
3052}
3053
[email protected]63c9b052012-05-17 18:27:383054void GLES2DecoderImpl::Destroy(bool have_context) {
[email protected]55e136f2013-04-03 18:50:063055 if (!initialized())
3056 return;
3057
[email protected]63c9b052012-05-17 18:27:383058 DCHECK(!have_context || context_->IsCurrent(NULL));
[email protected]97872062010-11-03 19:07:053059
[email protected]80eb6b52012-01-19 00:14:413060 // Unbind everything.
[email protected]e259eb412012-10-13 05:47:243061 state_.vertex_attrib_manager = NULL;
[email protected]944b62f32012-09-27 02:20:463062 default_vertex_attrib_manager_ = NULL;
[email protected]1868a342012-11-07 15:56:023063 state_.texture_units.clear();
[email protected]e259eb412012-10-13 05:47:243064 state_.bound_array_buffer = NULL;
3065 state_.current_query = NULL;
[email protected]e259eb412012-10-13 05:47:243066 state_.bound_read_framebuffer = NULL;
3067 state_.bound_draw_framebuffer = NULL;
3068 state_.bound_renderbuffer = NULL;
[email protected]80eb6b52012-01-19 00:14:413069
[email protected]cadac622013-06-11 16:46:363070 if (offscreen_saved_color_texture_info_.get()) {
[email protected]2ad674132013-06-05 07:48:513071 DCHECK(offscreen_target_color_texture_);
3072 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3073 offscreen_saved_color_texture_->id());
3074 offscreen_saved_color_texture_->Invalidate();
3075 offscreen_saved_color_texture_info_ = NULL;
3076 }
[email protected]eadc96792010-10-27 19:39:393077 if (have_context) {
[email protected]c322e882012-05-23 18:06:183078 if (copy_texture_CHROMIUM_.get()) {
3079 copy_texture_CHROMIUM_->Destroy();
3080 copy_texture_CHROMIUM_.reset();
3081 }
[email protected]43410e92012-04-20 17:06:283082
[email protected]7cd76fd2013-06-02 21:11:113083 if (state_.current_program.get()) {
3084 program_manager()->UnuseProgram(shader_manager(),
3085 state_.current_program.get());
[email protected]ca488e12010-12-13 20:06:143086 }
3087
[email protected]b1122982010-05-17 23:04:243088 if (attrib_0_buffer_id_) {
3089 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3090 }
[email protected]8fbedc02010-11-18 18:43:403091 if (fixed_attrib_buffer_id_) {
3092 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3093 }
[email protected]b1122982010-05-17 23:04:243094
[email protected]97872062010-11-03 19:07:053095 if (offscreen_target_frame_buffer_.get())
[email protected]4bedba72010-04-20 22:08:543096 offscreen_target_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053097 if (offscreen_target_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:543098 offscreen_target_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:053099 if (offscreen_target_color_render_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:023100 offscreen_target_color_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053101 if (offscreen_target_depth_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:153102 offscreen_target_depth_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053103 if (offscreen_target_stencil_render_buffer_.get())
[email protected]b9363b22010-06-09 22:06:153104 offscreen_target_stencil_render_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053105 if (offscreen_saved_frame_buffer_.get())
[email protected]34ff8b0c2010-10-01 20:06:023106 offscreen_saved_frame_buffer_->Destroy();
[email protected]97872062010-11-03 19:07:053107 if (offscreen_saved_color_texture_.get())
[email protected]4bedba72010-04-20 22:08:543108 offscreen_saved_color_texture_->Destroy();
[email protected]de26b3c2011-08-03 21:54:273109 if (offscreen_resolved_frame_buffer_.get())
3110 offscreen_resolved_frame_buffer_->Destroy();
3111 if (offscreen_resolved_color_texture_.get())
3112 offscreen_resolved_color_texture_->Destroy();
[email protected]97872062010-11-03 19:07:053113 } else {
3114 if (offscreen_target_frame_buffer_.get())
3115 offscreen_target_frame_buffer_->Invalidate();
3116 if (offscreen_target_color_texture_.get())
3117 offscreen_target_color_texture_->Invalidate();
3118 if (offscreen_target_color_render_buffer_.get())
3119 offscreen_target_color_render_buffer_->Invalidate();
3120 if (offscreen_target_depth_render_buffer_.get())
3121 offscreen_target_depth_render_buffer_->Invalidate();
3122 if (offscreen_target_stencil_render_buffer_.get())
3123 offscreen_target_stencil_render_buffer_->Invalidate();
3124 if (offscreen_saved_frame_buffer_.get())
3125 offscreen_saved_frame_buffer_->Invalidate();
3126 if (offscreen_saved_color_texture_.get())
3127 offscreen_saved_color_texture_->Invalidate();
[email protected]de26b3c2011-08-03 21:54:273128 if (offscreen_resolved_frame_buffer_.get())
3129 offscreen_resolved_frame_buffer_->Invalidate();
3130 if (offscreen_resolved_color_texture_.get())
3131 offscreen_resolved_color_texture_->Invalidate();
[email protected]d37231fa2010-04-09 21:16:023132 }
[email protected]83a52d032013-07-24 10:30:373133
3134 // Current program must be cleared after calling ProgramManager::UnuseProgram.
3135 // Otherwise, we can leak objects. http://crbug.com/258772.
3136 // state_.current_program must be reset before group_ is reset because
3137 // the later deletes the ProgramManager object that referred by
3138 // state_.current_program object.
3139 state_.current_program = NULL;
3140
[email protected]43410e92012-04-20 17:06:283141 copy_texture_CHROMIUM_.reset();
[email protected]97872062010-11-03 19:07:053142
[email protected]882ba1e22012-03-08 19:02:533143 if (query_manager_.get()) {
3144 query_manager_->Destroy(have_context);
3145 query_manager_.reset();
3146 }
3147
[email protected]944b62f32012-09-27 02:20:463148 if (vertex_array_manager_ .get()) {
3149 vertex_array_manager_->Destroy(have_context);
3150 vertex_array_manager_.reset();
3151 }
3152
[email protected]97872062010-11-03 19:07:053153 offscreen_target_frame_buffer_.reset();
3154 offscreen_target_color_texture_.reset();
3155 offscreen_target_color_render_buffer_.reset();
3156 offscreen_target_depth_render_buffer_.reset();
3157 offscreen_target_stencil_render_buffer_.reset();
3158 offscreen_saved_frame_buffer_.reset();
3159 offscreen_saved_color_texture_.reset();
[email protected]de26b3c2011-08-03 21:54:273160 offscreen_resolved_frame_buffer_.reset();
3161 offscreen_resolved_color_texture_.reset();
[email protected]e51bdf32011-11-23 22:21:463162
[email protected]85a4ac22013-05-31 01:58:473163 // Should destroy the transfer manager before the texture manager held
3164 // by the context group.
3165 async_pixel_transfer_manager_.reset();
3166
[email protected]7cd76fd2013-06-02 21:11:113167 if (group_.get()) {
[email protected]2d9d3b92013-01-18 01:07:233168 group_->Destroy(this, have_context);
3169 group_ = NULL;
3170 }
3171
3172 if (context_.get()) {
3173 context_->ReleaseCurrent(NULL);
3174 context_ = NULL;
3175 }
3176
[email protected]e51bdf32011-11-23 22:21:463177#if defined(OS_MACOSX)
3178 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
3179 it != texture_to_io_surface_map_.end(); ++it) {
3180 CFRelease(it->second);
3181 }
3182 texture_to_io_surface_map_.clear();
3183#endif
[email protected]96449d2c2009-11-25 00:01:323184}
3185
[email protected]63c9b052012-05-17 18:27:383186void GLES2DecoderImpl::SetSurface(
3187 const scoped_refptr<gfx::GLSurface>& surface) {
3188 DCHECK(context_->IsCurrent(NULL));
3189 DCHECK(surface_.get());
3190 surface_ = surface;
3191 RestoreCurrentFramebufferBindings();
3192}
3193
[email protected]2ad674132013-06-05 07:48:513194bool GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
[email protected]9a5afa432011-07-22 18:16:393195 if (!offscreen_saved_color_texture_.get())
3196 return false;
[email protected]2ad674132013-06-05 07:48:513197 if (!offscreen_saved_color_texture_info_.get()) {
[email protected]3c644d82011-06-20 19:58:243198 GLuint service_id = offscreen_saved_color_texture_->id();
[email protected]f46476932013-06-08 05:36:073199 offscreen_saved_color_texture_info_ = TextureRef::Create(
3200 texture_manager(), 0, service_id);
[email protected]2ad674132013-06-05 07:48:513201 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
3202 GL_TEXTURE_2D);
[email protected]9a5afa432011-07-22 18:16:393203 UpdateParentTextureInfo();
[email protected]3c644d82011-06-20 19:58:243204 }
[email protected]2ad674132013-06-05 07:48:513205 gpu::gles2::MailboxName name;
3206 memcpy(name.key, mailbox.name, sizeof(mailbox.name));
3207 return mailbox_manager()->ProduceTexture(
3208 GL_TEXTURE_2D, name, offscreen_saved_color_texture_info_->texture());
[email protected]3c644d82011-06-20 19:58:243209}
3210
[email protected]260ddc4e2012-06-28 00:01:533211size_t GLES2DecoderImpl::GetBackbufferMemoryTotal() {
[email protected]1078f912011-12-23 13:12:143212 size_t total = 0;
3213 if (offscreen_target_frame_buffer_.get()) {
3214 if (offscreen_target_color_texture_.get()) {
3215 total += offscreen_target_color_texture_->estimated_size();
3216 }
3217 if (offscreen_target_color_render_buffer_.get()) {
3218 total += offscreen_target_color_render_buffer_->estimated_size();
3219 }
3220 if (offscreen_target_depth_render_buffer_.get()) {
3221 total += offscreen_target_depth_render_buffer_->estimated_size();
3222 }
3223 if (offscreen_target_stencil_render_buffer_.get()) {
3224 total += offscreen_target_stencil_render_buffer_->estimated_size();
3225 }
3226 if (offscreen_saved_color_texture_.get()) {
3227 total += offscreen_saved_color_texture_->estimated_size();
3228 }
3229 if (offscreen_resolved_color_texture_.get()) {
3230 total += offscreen_resolved_color_texture_->estimated_size();
3231 }
3232 } else {
3233 gfx::Size size = surface_->GetSize();
3234 total += size.width() * size.height() *
3235 GLES2Util::RenderbufferBytesPerPixel(back_buffer_color_format_);
3236 }
[email protected]260ddc4e2012-06-28 00:01:533237 return total;
[email protected]1078f912011-12-23 13:12:143238}
3239
[email protected]799b4b22011-08-22 17:09:593240bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
3241 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3242 if (!is_offscreen) {
3243 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
3244 << " with an onscreen framebuffer.";
3245 return false;
3246 }
3247
3248 if (offscreen_size_ == size)
3249 return true;
3250
3251 offscreen_size_ = size;
3252 int w = offscreen_size_.width();
3253 int h = offscreen_size_.height();
3254 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
3255 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3256 << "to allocate storage due to excessive dimensions.";
3257 return false;
3258 }
3259
3260 // Reallocate the offscreen target buffers.
3261 DCHECK(offscreen_target_color_format_);
3262 if (IsOffscreenBufferMultisampled()) {
3263 if (!offscreen_target_color_render_buffer_->AllocateStorage(
3264 offscreen_size_, offscreen_target_color_format_,
3265 offscreen_target_samples_)) {
3266 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3267 << "to allocate storage for offscreen target color buffer.";
3268 return false;
3269 }
3270 } else {
3271 if (!offscreen_target_color_texture_->AllocateStorage(
[email protected]678a73f2012-12-19 19:22:093272 offscreen_size_, offscreen_target_color_format_, false)) {
[email protected]799b4b22011-08-22 17:09:593273 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3274 << "to allocate storage for offscreen target color texture.";
3275 return false;
3276 }
3277 }
3278 if (offscreen_target_depth_format_ &&
3279 !offscreen_target_depth_render_buffer_->AllocateStorage(
3280 offscreen_size_, offscreen_target_depth_format_,
3281 offscreen_target_samples_)) {
3282 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3283 << "to allocate storage for offscreen target depth buffer.";
3284 return false;
3285 }
3286 if (offscreen_target_stencil_format_ &&
3287 !offscreen_target_stencil_render_buffer_->AllocateStorage(
3288 offscreen_size_, offscreen_target_stencil_format_,
3289 offscreen_target_samples_)) {
3290 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3291 << "to allocate storage for offscreen target stencil buffer.";
3292 return false;
3293 }
3294
3295 // Attach the offscreen target buffers to the target frame buffer.
3296 if (IsOffscreenBufferMultisampled()) {
3297 offscreen_target_frame_buffer_->AttachRenderBuffer(
3298 GL_COLOR_ATTACHMENT0,
3299 offscreen_target_color_render_buffer_.get());
3300 } else {
3301 offscreen_target_frame_buffer_->AttachRenderTexture(
3302 offscreen_target_color_texture_.get());
3303 }
3304 if (offscreen_target_depth_format_) {
3305 offscreen_target_frame_buffer_->AttachRenderBuffer(
3306 GL_DEPTH_ATTACHMENT,
3307 offscreen_target_depth_render_buffer_.get());
3308 }
3309 const bool packed_depth_stencil =
3310 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3311 if (packed_depth_stencil) {
3312 offscreen_target_frame_buffer_->AttachRenderBuffer(
3313 GL_STENCIL_ATTACHMENT,
3314 offscreen_target_depth_render_buffer_.get());
3315 } else if (offscreen_target_stencil_format_) {
3316 offscreen_target_frame_buffer_->AttachRenderBuffer(
3317 GL_STENCIL_ATTACHMENT,
3318 offscreen_target_stencil_render_buffer_.get());
3319 }
3320
3321 if (offscreen_target_frame_buffer_->CheckStatus() !=
3322 GL_FRAMEBUFFER_COMPLETE) {
3323 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
3324 << "because offscreen FBO was incomplete.";
3325 return false;
3326 }
3327
3328 // Clear the target frame buffer.
3329 {
3330 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
3331 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3332 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
3333 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3334 glClearStencil(0);
3335 glStencilMaskSeparate(GL_FRONT, -1);
3336 glStencilMaskSeparate(GL_BACK, -1);
3337 glClearDepth(0);
3338 glDepthMask(GL_TRUE);
3339 glDisable(GL_SCISSOR_TEST);
3340 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3341 RestoreClearState();
3342 }
[email protected]d85ef76d2011-09-08 22:21:433343
3344 // Destroy the offscreen resolved framebuffers.
3345 if (offscreen_resolved_frame_buffer_.get())
3346 offscreen_resolved_frame_buffer_->Destroy();
3347 if (offscreen_resolved_color_texture_.get())
3348 offscreen_resolved_color_texture_->Destroy();
3349 offscreen_resolved_color_texture_.reset();
3350 offscreen_resolved_frame_buffer_.reset();
3351
[email protected]799b4b22011-08-22 17:09:593352 return true;
[email protected]6217d392010-03-25 22:08:353353}
3354
[email protected]799b4b22011-08-22 17:09:593355error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:353356 uint32 immediate_data_size, const cmds::ResizeCHROMIUM& c) {
[email protected]09e17272012-11-30 10:30:443357 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
[email protected]452120872012-09-27 15:21:023358 return error::kDeferCommandUntilLater;
3359
[email protected]799b4b22011-08-22 17:09:593360 GLuint width = static_cast<GLuint>(c.width);
3361 GLuint height = static_cast<GLuint>(c.height);
[email protected]729c0b42013-05-26 02:05:073362 GLfloat scale_factor = c.scale_factor;
[email protected]799b4b22011-08-22 17:09:593363 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
[email protected]d16aa4b2013-02-14 22:35:413364
3365 width = std::max(1U, width);
3366 height = std::max(1U, height);
3367
[email protected]a0d989162011-11-22 13:15:073368#if defined(OS_POSIX) && !defined(OS_MACOSX) && \
3369 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
[email protected]7ff86b92010-11-25 17:50:003370 // Make sure that we are done drawing to the back buffer before resizing.
3371 glFinish();
3372#endif
[email protected]799b4b22011-08-22 17:09:593373 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
3374 if (is_offscreen) {
[email protected]7794d512012-04-17 20:36:493375 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
3376 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
3377 << "ResizeOffscreenFrameBuffer failed.";
[email protected]799b4b22011-08-22 17:09:593378 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:493379 }
[email protected]7ff86b92010-11-25 17:50:003380 }
[email protected]799b4b22011-08-22 17:09:593381
[email protected]9d37f062011-11-22 01:24:523382 if (!resize_callback_.is_null()) {
[email protected]729c0b42013-05-26 02:05:073383 resize_callback_.Run(gfx::Size(width, height), scale_factor);
[email protected]0e9346b2013-03-16 16:35:443384 DCHECK(context_->IsCurrent(surface_.get()));
[email protected]7794d512012-04-17 20:36:493385 if (!context_->IsCurrent(surface_.get())) {
3386 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
3387 << "current after resize callback.";
[email protected]658f7562011-09-09 05:24:053388 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:493389 }
[email protected]658f7562011-09-09 05:24:053390 }
[email protected]799b4b22011-08-22 17:09:593391
3392 return error::kNoError;
[email protected]43ecf372010-11-16 19:19:393393}
3394
[email protected]96449d2c2009-11-25 00:01:323395const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
3396 if (command_id > kStartPoint && command_id < kNumCommands) {
3397 return gles2::GetCommandName(static_cast<CommandId>(command_id));
3398 }
3399 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
3400}
3401
3402// Decode command with its arguments, and call the corresponding GL function.
3403// Note: args is a pointer to the command buffer. As such, it could be changed
3404// by a (malicious) client at any time, so if validation has to happen, it
3405// should operate on a copy of them.
[email protected]f7a64ee2010-02-01 22:24:143406error::Error GLES2DecoderImpl::DoCommand(
[email protected]96449d2c2009-11-25 00:01:323407 unsigned int command,
3408 unsigned int arg_count,
3409 const void* cmd_data) {
[email protected]f7a64ee2010-02-01 22:24:143410 error::Error result = error::kNoError;
[email protected]e844ae22012-01-14 03:36:263411 if (log_commands()) {
[email protected]39ba4f02012-03-26 01:16:003412 // TODO(notme): Change this to a LOG/VLOG that works in release. Tried
3413 // LOG(INFO), tried VLOG(1), no luck.
[email protected]1d82e822013-04-10 21:32:323414 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" << "cmd: "
[email protected]d2a0e1a2012-08-12 02:25:013415 << GetCommandName(command);
[email protected]b9849abf2009-11-25 19:13:193416 }
[email protected]96449d2c2009-11-25 00:01:323417 unsigned int command_index = command - kStartPoint - 1;
3418 if (command_index < arraysize(g_command_info)) {
3419 const CommandInfo& info = g_command_info[command_index];
3420 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
3421 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
3422 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
[email protected]b9849abf2009-11-25 19:13:193423 uint32 immediate_data_size =
3424 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
[email protected]96449d2c2009-11-25 00:01:323425 switch (command) {
3426 #define GLES2_CMD_OP(name) \
[email protected]ed9f9cd2013-02-27 21:12:353427 case cmds::name::kCmdId: \
[email protected]b9849abf2009-11-25 19:13:193428 result = Handle ## name( \
3429 immediate_data_size, \
[email protected]ed9f9cd2013-02-27 21:12:353430 *static_cast<const gles2::cmds::name*>(cmd_data)); \
[email protected]b9849abf2009-11-25 19:13:193431 break; \
[email protected]96449d2c2009-11-25 00:01:323432
3433 GLES2_COMMAND_LIST(GLES2_CMD_OP)
[email protected]96449d2c2009-11-25 00:01:323434 #undef GLES2_CMD_OP
[email protected]bf0985e2009-12-17 03:04:383435 }
3436 if (debug()) {
[email protected]07f54fcc2009-12-22 02:46:303437 GLenum error;
3438 while ((error = glGetError()) != GL_NO_ERROR) {
[email protected]1d82e822013-04-10 21:32:323439 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
[email protected]39ba4f02012-03-26 01:16:003440 << "GL ERROR: " << GLES2Util::GetStringEnum(error) << " : "
3441 << GetCommandName(command);
[email protected]ab09b612013-03-11 22:11:513442 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
[email protected]b9849abf2009-11-25 19:13:193443 }
[email protected]96449d2c2009-11-25 00:01:323444 }
3445 } else {
[email protected]f7a64ee2010-02-01 22:24:143446 result = error::kInvalidArguments;
[email protected]96449d2c2009-11-25 00:01:323447 }
[email protected]b9849abf2009-11-25 19:13:193448 } else {
3449 result = DoCommonCommand(command, arg_count, cmd_data);
[email protected]96449d2c2009-11-25 00:01:323450 }
[email protected]a3a93e7b2010-08-28 00:48:563451 if (result == error::kNoError && current_decoder_error_ != error::kNoError) {
3452 result = current_decoder_error_;
3453 current_decoder_error_ = error::kNoError;
3454 }
[email protected]b9849abf2009-11-25 19:13:193455 return result;
[email protected]96449d2c2009-11-25 00:01:323456}
3457
[email protected]ed9f9cd2013-02-27 21:12:353458void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
3459 buffer_manager()->RemoveBuffer(client_id);
[email protected]3916c97e2010-02-25 03:20:503460}
3461
[email protected]ae51d192010-04-27 00:48:033462bool GLES2DecoderImpl::CreateProgramHelper(GLuint client_id) {
[email protected]ed9f9cd2013-02-27 21:12:353463 if (GetProgram(client_id)) {
[email protected]ae51d192010-04-27 00:48:033464 return false;
3465 }
[email protected]96449d2c2009-11-25 00:01:323466 GLuint service_id = glCreateProgram();
[email protected]ae51d192010-04-27 00:48:033467 if (service_id != 0) {
[email protected]ed9f9cd2013-02-27 21:12:353468 CreateProgram(client_id, service_id);
[email protected]96449d2c2009-11-25 00:01:323469 }
[email protected]ae51d192010-04-27 00:48:033470 return true;
[email protected]96449d2c2009-11-25 00:01:323471}
3472
[email protected]ae51d192010-04-27 00:48:033473bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
[email protected]ed9f9cd2013-02-27 21:12:353474 if (GetShader(client_id)) {
[email protected]ae51d192010-04-27 00:48:033475 return false;
[email protected]96449d2c2009-11-25 00:01:323476 }
[email protected]ae51d192010-04-27 00:48:033477 GLuint service_id = glCreateShader(type);
3478 if (service_id != 0) {
[email protected]ed9f9cd2013-02-27 21:12:353479 CreateShader(client_id, service_id, type);
[email protected]ae51d192010-04-27 00:48:033480 }
3481 return true;
[email protected]96449d2c2009-11-25 00:01:323482}
3483
[email protected]882ba1e22012-03-08 19:02:533484void GLES2DecoderImpl::DoFinish() {
3485 glFinish();
[email protected]5a36dc132013-07-23 23:17:553486 ProcessPendingReadPixels();
[email protected]22e3f552012-03-13 01:54:193487 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533488}
3489
3490void GLES2DecoderImpl::DoFlush() {
3491 glFlush();
[email protected]22e3f552012-03-13 01:54:193492 ProcessPendingQueries();
[email protected]882ba1e22012-03-08 19:02:533493}
3494
[email protected]3916c97e2010-02-25 03:20:503495void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
[email protected]36cef8ce2010-03-16 07:34:453496 GLuint texture_index = texture_unit - GL_TEXTURE0;
[email protected]1868a342012-11-07 15:56:023497 if (texture_index >= state_.texture_units.size()) {
[email protected]ab09b612013-03-11 22:11:513498 LOCAL_SET_GL_ERROR_INVALID_ENUM(
[email protected]f80e6e12012-08-31 00:43:533499 "glActiveTexture", texture_unit, "texture_unit");
[email protected]3916c97e2010-02-25 03:20:503500 return;
3501 }
[email protected]e259eb412012-10-13 05:47:243502 state_.active_texture_unit = texture_index;
[email protected]36cef8ce2010-03-16 07:34:453503 glActiveTexture(texture_unit);
[email protected]3916c97e2010-02-25 03:20:503504}
3505
[email protected]051b1372010-04-12 02:42:083506void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
[email protected]b10492f2013-03-08 05:24:073507 Buffer* buffer = NULL;
[email protected]051b1372010-04-12 02:42:083508 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033509 if (client_id != 0) {
[email protected]b10492f2013-03-08 05:24:073510 buffer = GetBuffer(client_id);
3511 if (!buffer) {
[email protected]bf5a8d132011-08-16 08:39:353512 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153513 LOG(ERROR) << "glBindBuffer: id not generated by glGenBuffers";
3514 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353515 return;
3516 }
3517
[email protected]b10492f2013-03-08 05:24:073518 // It's a new id so make a buffer buffer for it.
[email protected]ae51d192010-04-27 00:48:033519 glGenBuffersARB(1, &service_id);
[email protected]ed9f9cd2013-02-27 21:12:353520 CreateBuffer(client_id, service_id);
[email protected]b10492f2013-03-08 05:24:073521 buffer = GetBuffer(client_id);
[email protected]3b1ecc262011-08-03 22:49:573522 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103523 group_->GetIdAllocator(id_namespaces::kBuffers);
3524 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033525 }
[email protected]051b1372010-04-12 02:42:083526 }
[email protected]b10492f2013-03-08 05:24:073527 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
3528 if (buffer) {
3529 if (!buffer_manager()->SetTarget(buffer, target)) {
[email protected]ab09b612013-03-11 22:11:513530 LOCAL_SET_GL_ERROR(
3531 GL_INVALID_OPERATION,
3532 "glBindBuffer", "buffer bound to more than 1 target");
[email protected]a93bb842010-02-16 23:03:473533 return;
3534 }
[email protected]b10492f2013-03-08 05:24:073535 service_id = buffer->service_id();
[email protected]a93bb842010-02-16 23:03:473536 }
[email protected]96449d2c2009-11-25 00:01:323537 switch (target) {
3538 case GL_ARRAY_BUFFER:
[email protected]b10492f2013-03-08 05:24:073539 state_.bound_array_buffer = buffer;
[email protected]96449d2c2009-11-25 00:01:323540 break;
3541 case GL_ELEMENT_ARRAY_BUFFER:
[email protected]b10492f2013-03-08 05:24:073542 state_.vertex_attrib_manager->SetElementArrayBuffer(buffer);
[email protected]96449d2c2009-11-25 00:01:323543 break;
3544 default:
[email protected]a93bb842010-02-16 23:03:473545 NOTREACHED(); // Validation should prevent us getting here.
[email protected]96449d2c2009-11-25 00:01:323546 break;
3547 }
[email protected]051b1372010-04-12 02:42:083548 glBindBuffer(target, service_id);
[email protected]96449d2c2009-11-25 00:01:323549}
3550
[email protected]f3b191b2013-06-19 03:43:543551bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha(
3552 bool all_draw_buffers) {
3553 Framebuffer* framebuffer =
3554 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
3555 if (!all_draw_buffers || !framebuffer) {
3556 return (GLES2Util::GetChannelsForFormat(
3557 GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
3558 }
3559 return framebuffer->HasAlphaMRT();
[email protected]297ca1c2011-06-20 23:08:463560}
3561
3562bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
[email protected]ed9f9cd2013-02-27 21:12:353563 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:453564 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:203565 if (framebuffer) {
3566 return framebuffer->HasDepthAttachment();
[email protected]297ca1c2011-06-20 23:08:463567 }
3568 if (offscreen_target_frame_buffer_.get()) {
3569 return offscreen_target_depth_format_ != 0;
3570 }
3571 return back_buffer_has_depth_;
3572}
3573
3574bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
[email protected]ed9f9cd2013-02-27 21:12:353575 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:453576 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:203577 if (framebuffer) {
3578 return framebuffer->HasStencilAttachment();
[email protected]297ca1c2011-06-20 23:08:463579 }
3580 if (offscreen_target_frame_buffer_.get()) {
3581 return offscreen_target_stencil_format_ != 0 ||
3582 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
3583 }
3584 return back_buffer_has_stencil_;
3585}
3586
3587void GLES2DecoderImpl::ApplyDirtyState() {
[email protected]c986af502013-08-14 01:04:443588 if (framebuffer_state_.clear_state_dirty) {
[email protected]297ca1c2011-06-20 23:08:463589 glColorMask(
[email protected]e259eb412012-10-13 05:47:243590 state_.color_mask_red, state_.color_mask_green, state_.color_mask_blue,
3591 state_.color_mask_alpha &&
[email protected]f3b191b2013-06-19 03:43:543592 BoundFramebufferHasColorAttachmentWithAlpha(true));
[email protected]297ca1c2011-06-20 23:08:463593 bool have_depth = BoundFramebufferHasDepthAttachment();
[email protected]e259eb412012-10-13 05:47:243594 glDepthMask(state_.depth_mask && have_depth);
[email protected]f731b9462012-10-30 00:35:223595 EnableDisable(GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
[email protected]297ca1c2011-06-20 23:08:463596 bool have_stencil = BoundFramebufferHasStencilAttachment();
[email protected]e259eb412012-10-13 05:47:243597 glStencilMaskSeparate(
[email protected]88a61bf2012-10-27 13:00:423598 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
[email protected]e259eb412012-10-13 05:47:243599 glStencilMaskSeparate(
[email protected]88a61bf2012-10-27 13:00:423600 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
[email protected]f731b9462012-10-30 00:35:223601 EnableDisable(
3602 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
3603 EnableDisable(GL_CULL_FACE, state_.enable_flags.cull_face);
3604 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
3605 EnableDisable(GL_BLEND, state_.enable_flags.blend);
[email protected]c986af502013-08-14 01:04:443606 framebuffer_state_.clear_state_dirty = false;
[email protected]297ca1c2011-06-20 23:08:463607 }
3608}
3609
[email protected]1868a342012-11-07 15:56:023610GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
[email protected]7cd76fd2013-06-02 21:11:113611 return (offscreen_target_frame_buffer_.get())
3612 ? offscreen_target_frame_buffer_->id()
3613 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
[email protected]1868a342012-11-07 15:56:023614}
3615
3616void GLES2DecoderImpl::RestoreState() const {
[email protected]962bfbe72013-05-24 11:16:143617 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
3618 "context", logger_.GetLogPrefix());
[email protected]29a4d902013-02-26 20:18:063619 // Restore the Framebuffer first because of bugs in Intel drivers.
3620 // Intel drivers incorrectly clip the viewport settings to
3621 // the size of the current framebuffer object.
3622 RestoreFramebufferBindings();
3623 state_.RestoreState();
3624}
3625
3626void GLES2DecoderImpl::RestoreFramebufferBindings() const {
[email protected]7cd76fd2013-06-02 21:11:113627 GLuint service_id = state_.bound_draw_framebuffer.get()
3628 ? state_.bound_draw_framebuffer->service_id()
3629 : GetBackbufferServiceId();
[email protected]29a4d902013-02-26 20:18:063630 if (!features().chromium_framebuffer_multisample) {
3631 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
3632 } else {
3633 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
[email protected]7cd76fd2013-06-02 21:11:113634 service_id = state_.bound_read_framebuffer.get()
3635 ? state_.bound_read_framebuffer->service_id()
3636 : GetBackbufferServiceId();
[email protected]29a4d902013-02-26 20:18:063637 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
3638 }
[email protected]70d34263c2013-01-09 00:27:453639 OnFboChanged();
[email protected]29a4d902013-02-26 20:18:063640}
3641
3642void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
[email protected]62e65f02013-05-29 22:28:103643 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
3644 if (texture) {
[email protected]9bc9a2e82013-04-03 03:56:253645 GLenum target = texture->target();
3646 glBindTexture(target, service_id);
[email protected]29a4d902013-02-26 20:18:063647 glTexParameteri(
[email protected]9bc9a2e82013-04-03 03:56:253648 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
[email protected]29a4d902013-02-26 20:18:063649 glTexParameteri(
[email protected]9bc9a2e82013-04-03 03:56:253650 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
[email protected]29a4d902013-02-26 20:18:063651 glTexParameteri(
[email protected]9bc9a2e82013-04-03 03:56:253652 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
[email protected]29a4d902013-02-26 20:18:063653 glTexParameteri(
[email protected]9bc9a2e82013-04-03 03:56:253654 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
[email protected]29a4d902013-02-26 20:18:063655 RestoreTextureUnitBindings(state_.active_texture_unit);
3656 }
[email protected]70d34263c2013-01-09 00:27:453657}
3658
3659void GLES2DecoderImpl::OnFboChanged() const {
3660 if (workarounds().restore_scissor_on_fbo_change)
[email protected]28718a92013-04-04 12:12:513661 state_.fbo_binding_for_scissor_workaround_dirty_ = true;
3662}
3663
3664// Called after the FBO is checked for completeness.
3665void GLES2DecoderImpl::OnUseFramebuffer() const {
3666 if (state_.fbo_binding_for_scissor_workaround_dirty_) {
3667 state_.fbo_binding_for_scissor_workaround_dirty_ = false;
[email protected]81fc9d02013-03-14 23:53:323668 // The driver forgets the correct scissor when modifying the FBO binding.
[email protected]28718a92013-04-04 12:12:513669 glScissor(state_.scissor_x,
3670 state_.scissor_y,
3671 state_.scissor_width,
3672 state_.scissor_height);
3673
3674 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
3675 // it's unclear how this bug works.
3676 glFlush();
3677 }
[email protected]b177ae22011-11-01 03:29:113678}
3679
[email protected]051b1372010-04-12 02:42:083680void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
[email protected]4d8f0dd2013-03-09 14:37:063681 Framebuffer* framebuffer = NULL;
[email protected]051b1372010-04-12 02:42:083682 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033683 if (client_id != 0) {
[email protected]4d8f0dd2013-03-09 14:37:063684 framebuffer = GetFramebuffer(client_id);
3685 if (!framebuffer) {
[email protected]bf5a8d132011-08-16 08:39:353686 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153687 LOG(ERROR)
3688 << "glBindFramebuffer: id not generated by glGenFramebuffers";
3689 current_decoder_error_ = error::kGenericError;
3690 return;
[email protected]bf5a8d132011-08-16 08:39:353691 }
3692
[email protected]4d8f0dd2013-03-09 14:37:063693 // It's a new id so make a framebuffer framebuffer for it.
[email protected]ae51d192010-04-27 00:48:033694 glGenFramebuffersEXT(1, &service_id);
[email protected]ed9f9cd2013-02-27 21:12:353695 CreateFramebuffer(client_id, service_id);
[email protected]4d8f0dd2013-03-09 14:37:063696 framebuffer = GetFramebuffer(client_id);
[email protected]3b1ecc262011-08-03 22:49:573697 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103698 group_->GetIdAllocator(id_namespaces::kFramebuffers);
3699 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033700 } else {
[email protected]4d8f0dd2013-03-09 14:37:063701 service_id = framebuffer->service_id();
[email protected]051b1372010-04-12 02:42:083702 }
[email protected]4d8f0dd2013-03-09 14:37:063703 framebuffer->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083704 }
[email protected]4d8f0dd2013-03-09 14:37:063705 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
[email protected]8e3e0662010-08-23 18:46:303706
3707 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
[email protected]4d8f0dd2013-03-09 14:37:063708 state_.bound_draw_framebuffer = framebuffer;
[email protected]8e3e0662010-08-23 18:46:303709 }
3710 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]4d8f0dd2013-03-09 14:37:063711 state_.bound_read_framebuffer = framebuffer;
[email protected]8e3e0662010-08-23 18:46:303712 }
[email protected]6217d392010-03-25 22:08:353713
[email protected]c986af502013-08-14 01:04:443714 framebuffer_state_.clear_state_dirty = true;
[email protected]297ca1c2011-06-20 23:08:463715
[email protected]b177ae22011-11-01 03:29:113716 // If we are rendering to the backbuffer get the FBO id for any simulated
3717 // backbuffer.
[email protected]4d8f0dd2013-03-09 14:37:063718 if (framebuffer == NULL) {
[email protected]b177ae22011-11-01 03:29:113719 service_id = GetBackbufferServiceId();
[email protected]297ca1c2011-06-20 23:08:463720 }
[email protected]6217d392010-03-25 22:08:353721
[email protected]051b1372010-04-12 02:42:083722 glBindFramebufferEXT(target, service_id);
[email protected]70d34263c2013-01-09 00:27:453723 OnFboChanged();
[email protected]86093972010-03-11 00:13:563724}
3725
[email protected]051b1372010-04-12 02:42:083726void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
[email protected]ee2a79c32013-03-10 03:50:273727 Renderbuffer* renderbuffer = NULL;
[email protected]051b1372010-04-12 02:42:083728 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033729 if (client_id != 0) {
[email protected]ee2a79c32013-03-10 03:50:273730 renderbuffer = GetRenderbuffer(client_id);
3731 if (!renderbuffer) {
[email protected]bf5a8d132011-08-16 08:39:353732 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153733 LOG(ERROR)
3734 << "glBindRenderbuffer: id not generated by glGenRenderbuffers";
3735 current_decoder_error_ = error::kGenericError;
[email protected]bf5a8d132011-08-16 08:39:353736 return;
3737 }
3738
[email protected]ee2a79c32013-03-10 03:50:273739 // It's a new id so make a renderbuffer renderbuffer for it.
[email protected]ae51d192010-04-27 00:48:033740 glGenRenderbuffersEXT(1, &service_id);
[email protected]ed9f9cd2013-02-27 21:12:353741 CreateRenderbuffer(client_id, service_id);
[email protected]ee2a79c32013-03-10 03:50:273742 renderbuffer = GetRenderbuffer(client_id);
[email protected]3b1ecc262011-08-03 22:49:573743 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103744 group_->GetIdAllocator(id_namespaces::kRenderbuffers);
3745 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033746 } else {
[email protected]ee2a79c32013-03-10 03:50:273747 service_id = renderbuffer->service_id();
[email protected]051b1372010-04-12 02:42:083748 }
[email protected]ee2a79c32013-03-10 03:50:273749 renderbuffer->MarkAsValid();
[email protected]051b1372010-04-12 02:42:083750 }
[email protected]ee2a79c32013-03-10 03:50:273751 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenerbuffer");
3752 state_.bound_renderbuffer = renderbuffer;
[email protected]051b1372010-04-12 02:42:083753 glBindRenderbufferEXT(target, service_id);
[email protected]86093972010-03-11 00:13:563754}
3755
[email protected]051b1372010-04-12 02:42:083756void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
[email protected]370eaf12013-05-18 09:19:493757 TextureRef* texture_ref = NULL;
[email protected]051b1372010-04-12 02:42:083758 GLuint service_id = 0;
[email protected]ae51d192010-04-27 00:48:033759 if (client_id != 0) {
[email protected]370eaf12013-05-18 09:19:493760 texture_ref = GetTexture(client_id);
3761 if (!texture_ref) {
[email protected]bf5a8d132011-08-16 08:39:353762 if (!group_->bind_generates_resource()) {
[email protected]f4eac0702012-03-30 17:55:153763 LOG(ERROR) << "glBindTexture: id not generated by glGenTextures";
3764 current_decoder_error_ = error::kGenericError;
3765 return;
[email protected]bf5a8d132011-08-16 08:39:353766 }
3767
[email protected]02965c22013-03-09 02:40:073768 // It's a new id so make a texture texture for it.
[email protected]ae51d192010-04-27 00:48:033769 glGenTextures(1, &service_id);
[email protected]80eb6b52012-01-19 00:14:413770 DCHECK_NE(0u, service_id);
[email protected]ed9f9cd2013-02-27 21:12:353771 CreateTexture(client_id, service_id);
[email protected]370eaf12013-05-18 09:19:493772 texture_ref = GetTexture(client_id);
[email protected]3b1ecc262011-08-03 22:49:573773 IdAllocatorInterface* id_allocator =
[email protected]066849e32010-05-03 19:14:103774 group_->GetIdAllocator(id_namespaces::kTextures);
3775 id_allocator->MarkAsUsed(client_id);
[email protected]ae51d192010-04-27 00:48:033776 }
3777 } else {
[email protected]370eaf12013-05-18 09:19:493778 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
[email protected]051b1372010-04-12 02:42:083779 }
[email protected]370eaf12013-05-18 09:19:493780 Texture* texture = texture_ref->texture();
[email protected]ae51d192010-04-27 00:48:033781
[email protected]1958e0e2010-04-22 05:17:153782 // Check the texture exists
3783 // Check that we are not trying to bind it to a different target.
[email protected]02965c22013-03-09 02:40:073784 if (texture->target() != 0 && texture->target() != target) {
[email protected]ab09b612013-03-11 22:11:513785 LOCAL_SET_GL_ERROR(
3786 GL_INVALID_OPERATION,
3787 "glBindTexture", "texture bound to more than 1 target.");
[email protected]1958e0e2010-04-22 05:17:153788 return;
3789 }
[email protected]02965c22013-03-09 02:40:073790 if (texture->IsStreamTexture() && target != GL_TEXTURE_EXTERNAL_OES) {
[email protected]ab09b612013-03-11 22:11:513791 LOCAL_SET_GL_ERROR(
3792 GL_INVALID_OPERATION,
3793 "glBindTexture", "illegal target for stream texture.");
[email protected]b0af4f52011-09-28 22:04:423794 return;
3795 }
[email protected]02965c22013-03-09 02:40:073796 LogClientServiceForInfo(texture, client_id, "glBindTexture");
3797 if (texture->target() == 0) {
[email protected]370eaf12013-05-18 09:19:493798 texture_manager()->SetTarget(texture_ref, target);
[email protected]a93bb842010-02-16 23:03:473799 }
[email protected]02965c22013-03-09 02:40:073800 glBindTexture(target, texture->service_id());
[email protected]32145a92012-12-17 09:01:593801
[email protected]e259eb412012-10-13 05:47:243802 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]3916c97e2010-02-25 03:20:503803 unit.bind_target = target;
[email protected]a93bb842010-02-16 23:03:473804 switch (target) {
3805 case GL_TEXTURE_2D:
[email protected]370eaf12013-05-18 09:19:493806 unit.bound_texture_2d = texture_ref;
[email protected]a93bb842010-02-16 23:03:473807 break;
3808 case GL_TEXTURE_CUBE_MAP:
[email protected]370eaf12013-05-18 09:19:493809 unit.bound_texture_cube_map = texture_ref;
[email protected]a93bb842010-02-16 23:03:473810 break;
[email protected]61eeb33f2011-07-26 15:30:313811 case GL_TEXTURE_EXTERNAL_OES:
[email protected]370eaf12013-05-18 09:19:493812 unit.bound_texture_external_oes = texture_ref;
[email protected]61eeb33f2011-07-26 15:30:313813 break;
[email protected]e51bdf32011-11-23 22:21:463814 case GL_TEXTURE_RECTANGLE_ARB:
[email protected]370eaf12013-05-18 09:19:493815 unit.bound_texture_rectangle_arb = texture_ref;
[email protected]e51bdf32011-11-23 22:21:463816 break;
[email protected]a93bb842010-02-16 23:03:473817 default:
3818 NOTREACHED(); // Validation should prevent us getting here.
3819 break;
3820 }
3821}
3822
[email protected]07f54fcc2009-12-22 02:46:303823void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
[email protected]e259eb412012-10-13 05:47:243824 if (state_.vertex_attrib_manager->Enable(index, false)) {
[email protected]1071e572011-02-09 20:00:123825 if (index != 0 ||
3826 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]b1122982010-05-17 23:04:243827 glDisableVertexAttribArray(index);
3828 }
[email protected]07f54fcc2009-12-22 02:46:303829 } else {
[email protected]ab09b612013-03-11 22:11:513830 LOCAL_SET_GL_ERROR(
3831 GL_INVALID_VALUE,
3832 "glDisableVertexAttribArray", "index out of range");
[email protected]07f54fcc2009-12-22 02:46:303833 }
3834}
3835
[email protected]60f22d32012-12-12 00:31:583836void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
3837 GLsizei numAttachments,
3838 const GLenum* attachments) {
[email protected]ed9f9cd2013-02-27 21:12:353839 Framebuffer* framebuffer =
[email protected]60f22d32012-12-12 00:31:583840 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
3841
3842 // Validates the attachments. If one of them fails
3843 // the whole command fails.
3844 for (GLsizei i = 0; i < numAttachments; ++i) {
3845 if ((framebuffer &&
3846 !validators_->attachment.IsValid(attachments[i])) ||
3847 (!framebuffer &&
3848 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
[email protected]ab09b612013-03-11 22:11:513849 LOCAL_SET_GL_ERROR_INVALID_ENUM(
3850 "glDiscardFramebufferEXT", attachments[i], "attachments");
[email protected]60f22d32012-12-12 00:31:583851 return;
3852 }
3853 }
3854
3855 // Marks each one of them as not cleared
3856 for (GLsizei i = 0; i < numAttachments; ++i) {
3857 if (framebuffer) {
3858 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
3859 texture_manager(),
3860 attachments[i],
3861 false);
3862 } else {
3863 switch (attachments[i]) {
3864 case GL_COLOR_EXT:
3865 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
3866 break;
3867 case GL_DEPTH_EXT:
3868 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
3869 case GL_STENCIL_EXT:
3870 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
3871 break;
3872 default:
3873 NOTREACHED();
3874 break;
3875 }
3876 }
3877 }
3878
3879 glDiscardFramebufferEXT(target, numAttachments, attachments);
3880}
3881
[email protected]07f54fcc2009-12-22 02:46:303882void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
[email protected]e259eb412012-10-13 05:47:243883 if (state_.vertex_attrib_manager->Enable(index, true)) {
[email protected]07f54fcc2009-12-22 02:46:303884 glEnableVertexAttribArray(index);
3885 } else {
[email protected]ab09b612013-03-11 22:11:513886 LOCAL_SET_GL_ERROR(
3887 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
[email protected]07f54fcc2009-12-22 02:46:303888 }
3889}
3890
[email protected]a93bb842010-02-16 23:03:473891void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
[email protected]c986af502013-08-14 01:04:443892 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3893 &state_, target);
[email protected]370eaf12013-05-18 09:19:493894 if (!texture_ref ||
3895 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
[email protected]ab09b612013-03-11 22:11:513896 LOCAL_SET_GL_ERROR(
3897 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
[email protected]a93bb842010-02-16 23:03:473898 return;
3899 }
[email protected]38c0a972012-05-12 00:48:023900
[email protected]12d95352012-12-14 07:23:543901 if (target == GL_TEXTURE_CUBE_MAP) {
3902 for (int i = 0; i < 6; ++i) {
3903 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
[email protected]370eaf12013-05-18 09:19:493904 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
[email protected]ab09b612013-03-11 22:11:513905 LOCAL_SET_GL_ERROR(
3906 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
[email protected]12d95352012-12-14 07:23:543907 return;
3908 }
3909 }
3910 } else {
[email protected]370eaf12013-05-18 09:19:493911 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
[email protected]ab09b612013-03-11 22:11:513912 LOCAL_SET_GL_ERROR(
3913 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
[email protected]12d95352012-12-14 07:23:543914 return;
3915 }
[email protected]7687479c2012-05-14 23:54:043916 }
3917
[email protected]ab09b612013-03-11 22:11:513918 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
[email protected]59f3ca02011-03-26 22:24:193919 // Workaround for Mac driver bug. In the large scheme of things setting
3920 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
[email protected]a8bad262011-10-21 18:28:563921 // hit so there's probably no need to make this conditional. The bug appears
3922 // to be that if the filtering mode is set to something that doesn't require
3923 // mipmaps for rendering, or is never set to something other than the default,
3924 // then glGenerateMipmap misbehaves.
[email protected]62e155e2012-10-23 22:43:153925 if (workarounds().set_texture_filter_before_generating_mipmap) {
[email protected]c892a4e12012-05-08 18:20:193926 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3927 }
[email protected]a93bb842010-02-16 23:03:473928 glGenerateMipmapEXT(target);
[email protected]62e155e2012-10-23 22:43:153929 if (workarounds().set_texture_filter_before_generating_mipmap) {
[email protected]370eaf12013-05-18 09:19:493930 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
3931 texture_ref->texture()->min_filter());
[email protected]c892a4e12012-05-08 18:20:193932 }
[email protected]ab09b612013-03-11 22:11:513933 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
[email protected]38c0a972012-05-12 00:48:023934 if (error == GL_NO_ERROR) {
[email protected]370eaf12013-05-18 09:19:493935 texture_manager()->MarkMipmapsGenerated(texture_ref);
[email protected]38c0a972012-05-12 00:48:023936 }
[email protected]a93bb842010-02-16 23:03:473937}
3938
[email protected]b273e432010-04-12 17:23:583939bool GLES2DecoderImpl::GetHelper(
3940 GLenum pname, GLint* params, GLsizei* num_written) {
[email protected]b273e432010-04-12 17:23:583941 DCHECK(num_written);
[email protected]b9363b22010-06-09 22:06:153942 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
3943 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:433944 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
3945 *num_written = 1;
3946 if (params) {
3947 *params = GL_RGBA; // We don't support other formats.
3948 }
3949 return true;
3950 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3951 *num_written = 1;
3952 if (params) {
3953 *params = GL_UNSIGNED_BYTE; // We don't support other types.
3954 }
3955 return true;
3956 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
3957 *num_written = 1;
3958 if (params) {
3959 *params = group_->max_fragment_uniform_vectors();
3960 }
3961 return true;
3962 case GL_MAX_VARYING_VECTORS:
3963 *num_written = 1;
3964 if (params) {
3965 *params = group_->max_varying_vectors();
3966 }
3967 return true;
3968 case GL_MAX_VERTEX_UNIFORM_VECTORS:
3969 *num_written = 1;
3970 if (params) {
3971 *params = group_->max_vertex_uniform_vectors();
3972 }
3973 return true;
[email protected]4e8a5b122010-05-08 22:00:103974 }
[email protected]5cb735d2011-10-13 01:37:233975 }
3976 switch (pname) {
[email protected]5094b0f2010-11-09 19:45:243977 case GL_MAX_VIEWPORT_DIMS:
3978 if (offscreen_target_frame_buffer_.get()) {
3979 *num_written = 2;
3980 if (params) {
3981 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3982 params[1] = renderbuffer_manager()->max_renderbuffer_size();
3983 }
3984 return true;
3985 }
[email protected]5cb735d2011-10-13 01:37:233986 return false;
[email protected]84afefa2011-10-19 21:45:533987 case GL_MAX_SAMPLES:
3988 *num_written = 1;
3989 if (params) {
3990 params[0] = renderbuffer_manager()->max_samples();
3991 }
3992 return true;
3993 case GL_MAX_RENDERBUFFER_SIZE:
3994 *num_written = 1;
3995 if (params) {
3996 params[0] = renderbuffer_manager()->max_renderbuffer_size();
3997 }
3998 return true;
[email protected]5cb735d2011-10-13 01:37:233999 case GL_MAX_TEXTURE_SIZE:
4000 *num_written = 1;
4001 if (params) {
4002 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
4003 }
4004 return true;
4005 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
4006 *num_written = 1;
4007 if (params) {
4008 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
4009 }
4010 return true;
[email protected]2f143d482013-03-14 18:04:494011 case GL_MAX_COLOR_ATTACHMENTS_EXT:
4012 *num_written = 1;
4013 if (params) {
4014 params[0] = group_->max_color_attachments();
4015 }
4016 return true;
4017 case GL_MAX_DRAW_BUFFERS_ARB:
4018 *num_written = 1;
4019 if (params) {
4020 params[0] = group_->max_draw_buffers();
4021 }
4022 return true;
[email protected]297ca1c2011-06-20 23:08:464023 case GL_ALPHA_BITS:
4024 *num_written = 1;
4025 if (params) {
4026 GLint v = 0;
4027 glGetIntegerv(GL_ALPHA_BITS, &v);
[email protected]f3b191b2013-06-19 03:43:544028 params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0;
[email protected]297ca1c2011-06-20 23:08:464029 }
4030 return true;
4031 case GL_DEPTH_BITS:
4032 *num_written = 1;
4033 if (params) {
4034 GLint v = 0;
4035 glGetIntegerv(GL_DEPTH_BITS, &v);
4036 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
4037 }
4038 return true;
4039 case GL_STENCIL_BITS:
4040 *num_written = 1;
4041 if (params) {
4042 GLint v = 0;
4043 glGetIntegerv(GL_STENCIL_BITS, &v);
4044 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
4045 }
4046 return true;
[email protected]656dcaad2010-05-07 17:18:374047 case GL_COMPRESSED_TEXTURE_FORMATS:
[email protected]302ce6d2011-07-07 23:28:114048 *num_written = validators_->compressed_texture_format.GetValues().size();
4049 if (params) {
4050 for (GLint ii = 0; ii < *num_written; ++ii) {
4051 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
4052 }
4053 }
[email protected]656dcaad2010-05-07 17:18:374054 return true;
[email protected]b273e432010-04-12 17:23:584055 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
4056 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104057 if (params) {
[email protected]302ce6d2011-07-07 23:28:114058 *params = validators_->compressed_texture_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:104059 }
[email protected]b273e432010-04-12 17:23:584060 return true;
4061 case GL_NUM_SHADER_BINARY_FORMATS:
4062 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104063 if (params) {
[email protected]302ce6d2011-07-07 23:28:114064 *params = validators_->shader_binary_format.GetValues().size();
[email protected]4e8a5b122010-05-08 22:00:104065 }
[email protected]b273e432010-04-12 17:23:584066 return true;
4067 case GL_SHADER_BINARY_FORMATS:
[email protected]302ce6d2011-07-07 23:28:114068 *num_written = validators_->shader_binary_format.GetValues().size();
4069 if (params) {
4070 for (GLint ii = 0; ii < *num_written; ++ii) {
4071 params[ii] = validators_->shader_binary_format.GetValues()[ii];
4072 }
4073 }
4074 return true;
[email protected]b273e432010-04-12 17:23:584075 case GL_SHADER_COMPILER:
4076 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104077 if (params) {
4078 *params = GL_TRUE;
4079 }
[email protected]b273e432010-04-12 17:23:584080 return true;
[email protected]6b8cf1a2010-05-06 16:13:584081 case GL_ARRAY_BUFFER_BINDING:
4082 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104083 if (params) {
[email protected]7cd76fd2013-06-02 21:11:114084 if (state_.bound_array_buffer.get()) {
[email protected]4e8a5b122010-05-08 22:00:104085 GLuint client_id = 0;
[email protected]e259eb412012-10-13 05:47:244086 buffer_manager()->GetClientId(state_.bound_array_buffer->service_id(),
[email protected]4e8a5b122010-05-08 22:00:104087 &client_id);
4088 *params = client_id;
4089 } else {
4090 *params = 0;
4091 }
[email protected]6b8cf1a2010-05-06 16:13:584092 }
4093 return true;
4094 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
4095 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104096 if (params) {
[email protected]e259eb412012-10-13 05:47:244097 if (state_.vertex_attrib_manager->element_array_buffer()) {
[email protected]4e8a5b122010-05-08 22:00:104098 GLuint client_id = 0;
4099 buffer_manager()->GetClientId(
[email protected]b04e24c2013-01-08 18:35:254100 state_.vertex_attrib_manager->element_array_buffer()->
4101 service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:104102 *params = client_id;
4103 } else {
4104 *params = 0;
4105 }
[email protected]6b8cf1a2010-05-06 16:13:584106 }
4107 return true;
4108 case GL_FRAMEBUFFER_BINDING:
[email protected]8e3e0662010-08-23 18:46:304109 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
[email protected]6b8cf1a2010-05-06 16:13:584110 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104111 if (params) {
[email protected]ed9f9cd2013-02-27 21:12:354112 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:454113 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
[email protected]0d6bfdc2011-11-02 01:32:204114 if (framebuffer) {
[email protected]4e8a5b122010-05-08 22:00:104115 GLuint client_id = 0;
4116 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:204117 framebuffer->service_id(), &client_id);
[email protected]8e3e0662010-08-23 18:46:304118 *params = client_id;
4119 } else {
4120 *params = 0;
4121 }
4122 }
4123 return true;
[email protected]ebfb73c2012-08-15 02:37:454124 case GL_READ_FRAMEBUFFER_BINDING_EXT:
[email protected]8e3e0662010-08-23 18:46:304125 *num_written = 1;
4126 if (params) {
[email protected]ed9f9cd2013-02-27 21:12:354127 Framebuffer* framebuffer =
[email protected]ebfb73c2012-08-15 02:37:454128 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
[email protected]0d6bfdc2011-11-02 01:32:204129 if (framebuffer) {
[email protected]8e3e0662010-08-23 18:46:304130 GLuint client_id = 0;
4131 framebuffer_manager()->GetClientId(
[email protected]0d6bfdc2011-11-02 01:32:204132 framebuffer->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:104133 *params = client_id;
4134 } else {
4135 *params = 0;
4136 }
[email protected]6b8cf1a2010-05-06 16:13:584137 }
4138 return true;
4139 case GL_RENDERBUFFER_BINDING:
4140 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104141 if (params) {
[email protected]ed9f9cd2013-02-27 21:12:354142 Renderbuffer* renderbuffer =
[email protected]0d6bfdc2011-11-02 01:32:204143 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4144 if (renderbuffer) {
[email protected]62e65f02013-05-29 22:28:104145 *params = renderbuffer->client_id();
[email protected]4e8a5b122010-05-08 22:00:104146 } else {
4147 *params = 0;
4148 }
[email protected]6b8cf1a2010-05-06 16:13:584149 }
4150 return true;
4151 case GL_CURRENT_PROGRAM:
4152 *num_written = 1;
[email protected]4e8a5b122010-05-08 22:00:104153 if (params) {
[email protected]7cd76fd2013-06-02 21:11:114154 if (state_.current_program.get()) {
[email protected]4e8a5b122010-05-08 22:00:104155 GLuint client_id = 0;
4156 program_manager()->GetClientId(
[email protected]e259eb412012-10-13 05:47:244157 state_.current_program->service_id(), &client_id);
[email protected]4e8a5b122010-05-08 22:00:104158 *params = client_id;
4159 } else {
4160 *params = 0;
4161 }
[email protected]6b8cf1a2010-05-06 16:13:584162 }
4163 return true;
[email protected]bf835842012-11-19 15:21:514164 case GL_VERTEX_ARRAY_BINDING_OES:
4165 *num_written = 1;
4166 if (params) {
[email protected]7cd76fd2013-06-02 21:11:114167 if (state_.vertex_attrib_manager.get() !=
4168 default_vertex_attrib_manager_.get()) {
[email protected]bf835842012-11-19 15:21:514169 GLuint client_id = 0;
4170 vertex_array_manager_->GetClientId(
4171 state_.vertex_attrib_manager->service_id(), &client_id);
4172 *params = client_id;
4173 } else {
4174 *params = 0;
4175 }
4176 }
4177 return true;
[email protected]4e8a5b122010-05-08 22:00:104178 case GL_TEXTURE_BINDING_2D:
4179 *num_written = 1;
4180 if (params) {
[email protected]e259eb412012-10-13 05:47:244181 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]7cd76fd2013-06-02 21:11:114182 if (unit.bound_texture_2d.get()) {
[email protected]62e65f02013-05-29 22:28:104183 *params = unit.bound_texture_2d->client_id();
[email protected]6b8cf1a2010-05-06 16:13:584184 } else {
4185 *params = 0;
4186 }
[email protected]6b8cf1a2010-05-06 16:13:584187 }
[email protected]4e8a5b122010-05-08 22:00:104188 return true;
4189 case GL_TEXTURE_BINDING_CUBE_MAP:
4190 *num_written = 1;
4191 if (params) {
[email protected]e259eb412012-10-13 05:47:244192 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]7cd76fd2013-06-02 21:11:114193 if (unit.bound_texture_cube_map.get()) {
[email protected]62e65f02013-05-29 22:28:104194 *params = unit.bound_texture_cube_map->client_id();
[email protected]6b8cf1a2010-05-06 16:13:584195 } else {
4196 *params = 0;
4197 }
[email protected]6b8cf1a2010-05-06 16:13:584198 }
[email protected]4e8a5b122010-05-08 22:00:104199 return true;
[email protected]61eeb33f2011-07-26 15:30:314200 case GL_TEXTURE_BINDING_EXTERNAL_OES:
4201 *num_written = 1;
4202 if (params) {
[email protected]e259eb412012-10-13 05:47:244203 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]7cd76fd2013-06-02 21:11:114204 if (unit.bound_texture_external_oes.get()) {
[email protected]62e65f02013-05-29 22:28:104205 *params = unit.bound_texture_external_oes->client_id();
[email protected]61eeb33f2011-07-26 15:30:314206 } else {
4207 *params = 0;
4208 }
4209 }
4210 return true;
[email protected]e51bdf32011-11-23 22:21:464211 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
4212 *num_written = 1;
4213 if (params) {
[email protected]e259eb412012-10-13 05:47:244214 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
[email protected]7cd76fd2013-06-02 21:11:114215 if (unit.bound_texture_rectangle_arb.get()) {
[email protected]62e65f02013-05-29 22:28:104216 *params = unit.bound_texture_rectangle_arb->client_id();
[email protected]e51bdf32011-11-23 22:21:464217 } else {
4218 *params = 0;
4219 }
4220 }
4221 return true;
[email protected]6c75c712012-06-19 15:43:174222 case GL_UNPACK_FLIP_Y_CHROMIUM:
4223 *num_written = 1;
4224 if (params) {
4225 params[0] = unpack_flip_y_;
4226 }
4227 return true;
4228 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
4229 *num_written = 1;
4230 if (params) {
4231 params[0] = unpack_premultiply_alpha_;
4232 }
4233 return true;
4234 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
4235 *num_written = 1;
4236 if (params) {
4237 params[0] = unpack_unpremultiply_alpha_;
4238 }
4239 return true;
[email protected]b273e432010-04-12 17:23:584240 default:
[email protected]2f143d482013-03-14 18:04:494241 if (pname >= GL_DRAW_BUFFER0_ARB &&
4242 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
4243 *num_written = 1;
4244 if (params) {
4245 Framebuffer* framebuffer =
4246 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4247 if (framebuffer) {
4248 params[0] = framebuffer->GetDrawBuffer(pname);
4249 } else { // backbuffer
4250 if (pname == GL_DRAW_BUFFER0_ARB)
4251 params[0] = group_->draw_buffer();
4252 else
4253 params[0] = GL_NONE;
4254 }
4255 }
4256 return true;
4257 }
[email protected]4e8a5b122010-05-08 22:00:104258 *num_written = util_.GLGetNumValuesReturned(pname);
[email protected]c5d798342010-09-24 20:42:534259 return false;
[email protected]b273e432010-04-12 17:23:584260 }
4261}
4262
[email protected]4e8a5b122010-05-08 22:00:104263bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
4264 GLenum pname, GLsizei* num_values) {
[email protected]d058bca2012-11-26 10:27:264265 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
[email protected]f63b1232012-10-31 07:03:534266 return true;
4267 }
[email protected]4e8a5b122010-05-08 22:00:104268 return GetHelper(pname, NULL, num_values);
4269}
4270
[email protected]7d3c36e2013-07-12 14:13:164271GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
4272 if (GL_MAX_SAMPLES == pname &&
4273 features().use_img_for_multisampled_render_to_texture) {
4274 return GL_MAX_SAMPLES_IMG;
4275 }
4276 return pname;
4277}
4278
[email protected]b273e432010-04-12 17:23:584279void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
4280 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:104281 GLsizei num_written = 0;
[email protected]f63b1232012-10-31 07:03:534282 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
[email protected]40d90a22013-04-09 03:39:554283 scoped_ptr<GLint[]> values(new GLint[num_written]);
[email protected]d058bca2012-11-26 10:27:264284 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
[email protected]f63b1232012-10-31 07:03:534285 GetHelper(pname, values.get(), &num_written);
4286 }
[email protected]b273e432010-04-12 17:23:584287 for (GLsizei ii = 0; ii < num_written; ++ii) {
4288 params[ii] = static_cast<GLboolean>(values[ii]);
4289 }
4290 } else {
[email protected]7d3c36e2013-07-12 14:13:164291 pname = AdjustGetPname(pname);
[email protected]b273e432010-04-12 17:23:584292 glGetBooleanv(pname, params);
4293 }
4294}
4295
4296void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
4297 DCHECK(params);
[email protected]4e8a5b122010-05-08 22:00:104298 GLsizei num_written = 0;
[email protected]d058bca2012-11-26 10:27:264299 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
[email protected]f63b1232012-10-31 07:03:534300 if (GetHelper(pname, NULL, &num_written)) {
[email protected]40d90a22013-04-09 03:39:554301 scoped_ptr<GLint[]> values(new GLint[num_written]);
[email protected]f63b1232012-10-31 07:03:534302 GetHelper(pname, values.get(), &num_written);
4303 for (GLsizei ii = 0; ii < num_written; ++ii) {
4304 params[ii] = static_cast<GLfloat>(values[ii]);
4305 }
4306 } else {
[email protected]7d3c36e2013-07-12 14:13:164307 pname = AdjustGetPname(pname);
[email protected]f63b1232012-10-31 07:03:534308 glGetFloatv(pname, params);
[email protected]b273e432010-04-12 17:23:584309 }
[email protected]b273e432010-04-12 17:23:584310 }
4311}
4312
4313void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
4314 DCHECK(params);
4315 GLsizei num_written;
[email protected]d058bca2012-11-26 10:27:264316 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
[email protected]f63b1232012-10-31 07:03:534317 !GetHelper(pname, params, &num_written)) {
[email protected]7d3c36e2013-07-12 14:13:164318 pname = AdjustGetPname(pname);
[email protected]b273e432010-04-12 17:23:584319 glGetIntegerv(pname, params);
4320 }
4321}
4322
[email protected]a0c3e972010-04-21 00:49:134323void GLES2DecoderImpl::DoGetProgramiv(
4324 GLuint program_id, GLenum pname, GLint* params) {
[email protected]df37b9932013-03-08 05:21:424325 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
4326 if (!program) {
[email protected]a0c3e972010-04-21 00:49:134327 return;
4328 }
[email protected]df37b9932013-03-08 05:21:424329 program->GetProgramiv(pname, params);
[email protected]a0c3e972010-04-21 00:49:134330}
4331
[email protected]17cfbe0e2013-03-07 01:26:084332void GLES2DecoderImpl::DoGetBufferParameteriv(
4333 GLenum target, GLenum pname, GLint* params) {
[email protected]0fbba3732013-07-17 15:40:134334 // Just delegate it. Some validation is actually done before this.
4335 buffer_manager()->ValidateAndDoGetBufferParameteriv(
4336 &state_, target, pname, params);
[email protected]17cfbe0e2013-03-07 01:26:084337}
4338
[email protected]258a3313f2011-10-18 20:13:574339void GLES2DecoderImpl::DoBindAttribLocation(
[email protected]df37b9932013-03-08 05:21:424340 GLuint program_id, GLuint index, const char* name) {
[email protected]258a3313f2011-10-18 20:13:574341 if (!StringIsValidForGLES(name)) {
[email protected]ab09b612013-03-11 22:11:514342 LOCAL_SET_GL_ERROR(
4343 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:574344 return;
4345 }
[email protected]68dcb1f2012-04-07 00:14:564346 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
[email protected]ab09b612013-03-11 22:11:514347 LOCAL_SET_GL_ERROR(
4348 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
[email protected]68dcb1f2012-04-07 00:14:564349 return;
4350 }
4351 if (index >= group_->max_vertex_attribs()) {
[email protected]ab09b612013-03-11 22:11:514352 LOCAL_SET_GL_ERROR(
4353 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
[email protected]68dcb1f2012-04-07 00:14:564354 return;
4355 }
[email protected]df37b9932013-03-08 05:21:424356 Program* program = GetProgramInfoNotShader(
4357 program_id, "glBindAttribLocation");
4358 if (!program) {
[email protected]258a3313f2011-10-18 20:13:574359 return;
[email protected]558847a2010-03-24 07:02:544360 }
[email protected]df37b9932013-03-08 05:21:424361 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
4362 glBindAttribLocation(program->service_id(), index, name);
[email protected]258a3313f2011-10-18 20:13:574363}
4364
4365error::Error GLES2DecoderImpl::HandleBindAttribLocation(
[email protected]ed9f9cd2013-02-27 21:12:354366 uint32 immediate_data_size, const cmds::BindAttribLocation& c) {
[email protected]258a3313f2011-10-18 20:13:574367 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:544368 GLuint index = static_cast<GLuint>(c.index);
4369 uint32 name_size = c.data_size;
4370 const char* name = GetSharedMemoryAs<const char*>(
4371 c.name_shm_id, c.name_shm_offset, name_size);
4372 if (name == NULL) {
4373 return error::kOutOfBounds;
4374 }
4375 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:574376 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:544377 return error::kNoError;
4378}
4379
4380error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
[email protected]ed9f9cd2013-02-27 21:12:354381 uint32 immediate_data_size, const cmds::BindAttribLocationImmediate& c) {
[email protected]6b8cf1a2010-05-06 16:13:584382 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:544383 GLuint index = static_cast<GLuint>(c.index);
4384 uint32 name_size = c.data_size;
4385 const char* name = GetImmediateDataAs<const char*>(
4386 c, name_size, immediate_data_size);
4387 if (name == NULL) {
4388 return error::kOutOfBounds;
4389 }
4390 String name_str(name, name_size);
[email protected]258a3313f2011-10-18 20:13:574391 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:544392 return error::kNoError;
4393}
4394
4395error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
[email protected]ed9f9cd2013-02-27 21:12:354396 uint32 immediate_data_size, const cmds::BindAttribLocationBucket& c) {
[email protected]6b8cf1a2010-05-06 16:13:584397 GLuint program = static_cast<GLuint>(c.program);
[email protected]558847a2010-03-24 07:02:544398 GLuint index = static_cast<GLuint>(c.index);
4399 Bucket* bucket = GetBucket(c.name_bucket_id);
4400 if (!bucket || bucket->size() == 0) {
4401 return error::kInvalidArguments;
4402 }
4403 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:184404 if (!bucket->GetAsString(&name_str)) {
4405 return error::kInvalidArguments;
4406 }
[email protected]258a3313f2011-10-18 20:13:574407 DoBindAttribLocation(program, index, name_str.c_str());
[email protected]558847a2010-03-24 07:02:544408 return error::kNoError;
4409}
4410
[email protected]2be6abf32012-06-26 00:28:334411void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
[email protected]df37b9932013-03-08 05:21:424412 GLuint program_id, GLint location, const char* name) {
[email protected]2be6abf32012-06-26 00:28:334413 if (!StringIsValidForGLES(name)) {
[email protected]ab09b612013-03-11 22:11:514414 LOCAL_SET_GL_ERROR(
4415 GL_INVALID_VALUE,
4416 "glBindUniformLocationCHROMIUM", "Invalid character");
[email protected]2be6abf32012-06-26 00:28:334417 return;
4418 }
4419 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
[email protected]ab09b612013-03-11 22:11:514420 LOCAL_SET_GL_ERROR(
4421 GL_INVALID_OPERATION,
4422 "glBindUniformLocationCHROMIUM", "reserved prefix");
[email protected]2be6abf32012-06-26 00:28:334423 return;
4424 }
4425 if (location < 0 || static_cast<uint32>(location) >=
4426 (group_->max_fragment_uniform_vectors() +
4427 group_->max_vertex_uniform_vectors()) * 4) {
[email protected]ab09b612013-03-11 22:11:514428 LOCAL_SET_GL_ERROR(
4429 GL_INVALID_VALUE,
4430 "glBindUniformLocationCHROMIUM", "location out of range");
[email protected]2be6abf32012-06-26 00:28:334431 return;
4432 }
[email protected]df37b9932013-03-08 05:21:424433 Program* program = GetProgramInfoNotShader(
4434 program_id, "glBindUniformLocationCHROMIUM");
4435 if (!program) {
[email protected]2be6abf32012-06-26 00:28:334436 return;
4437 }
[email protected]df37b9932013-03-08 05:21:424438 if (!program->SetUniformLocationBinding(name, location)) {
[email protected]ab09b612013-03-11 22:11:514439 LOCAL_SET_GL_ERROR(
4440 GL_INVALID_VALUE,
4441 "glBindUniformLocationCHROMIUM", "location out of range");
[email protected]2be6abf32012-06-26 00:28:334442 }
4443}
4444
4445error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:354446 uint32 immediate_data_size, const cmds::BindUniformLocationCHROMIUM& c) {
[email protected]2be6abf32012-06-26 00:28:334447 GLuint program = static_cast<GLuint>(c.program);
4448 GLint location = static_cast<GLint>(c.location);
4449 uint32 name_size = c.data_size;
4450 const char* name = GetSharedMemoryAs<const char*>(
4451 c.name_shm_id, c.name_shm_offset, name_size);
4452 if (name == NULL) {
4453 return error::kOutOfBounds;
4454 }
4455 String name_str(name, name_size);
4456 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4457 return error::kNoError;
4458}
4459
4460error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMImmediate(
4461 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:354462 const cmds::BindUniformLocationCHROMIUMImmediate& c) {
[email protected]2be6abf32012-06-26 00:28:334463 GLuint program = static_cast<GLuint>(c.program);
4464 GLint location = static_cast<GLint>(c.location);
4465 uint32 name_size = c.data_size;
4466 const char* name = GetImmediateDataAs<const char*>(
4467 c, name_size, immediate_data_size);
4468 if (name == NULL) {
4469 return error::kOutOfBounds;
4470 }
4471 String name_str(name, name_size);
4472 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4473 return error::kNoError;
4474}
4475
4476error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
4477 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:354478 const cmds::BindUniformLocationCHROMIUMBucket& c) {
[email protected]2be6abf32012-06-26 00:28:334479 GLuint program = static_cast<GLuint>(c.program);
4480 GLint location = static_cast<GLint>(c.location);
4481 Bucket* bucket = GetBucket(c.name_bucket_id);
4482 if (!bucket || bucket->size() == 0) {
4483 return error::kInvalidArguments;
4484 }
4485 std::string name_str;
4486 if (!bucket->GetAsString(&name_str)) {
4487 return error::kInvalidArguments;
4488 }
4489 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
4490 return error::kNoError;
4491}
4492
[email protected]f7a64ee2010-02-01 22:24:144493error::Error GLES2DecoderImpl::HandleDeleteShader(
[email protected]ed9f9cd2013-02-27 21:12:354494 uint32 immediate_data_size, const cmds::DeleteShader& c) {
[email protected]ae51d192010-04-27 00:48:034495 GLuint client_id = c.shader;
4496 if (client_id) {
[email protected]df37b9932013-03-08 05:21:424497 Shader* shader = GetShader(client_id);
4498 if (shader) {
4499 if (!shader->IsDeleted()) {
4500 glDeleteShader(shader->service_id());
4501 shader_manager()->MarkAsDeleted(shader);
[email protected]ca488e12010-12-13 20:06:144502 }
[email protected]ae51d192010-04-27 00:48:034503 } else {
[email protected]ab09b612013-03-11 22:11:514504 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
[email protected]ae51d192010-04-27 00:48:034505 }
[email protected]96449d2c2009-11-25 00:01:324506 }
[email protected]f7a64ee2010-02-01 22:24:144507 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324508}
4509
[email protected]f7a64ee2010-02-01 22:24:144510error::Error GLES2DecoderImpl::HandleDeleteProgram(
[email protected]ed9f9cd2013-02-27 21:12:354511 uint32 immediate_data_size, const cmds::DeleteProgram& c) {
[email protected]ae51d192010-04-27 00:48:034512 GLuint client_id = c.program;
4513 if (client_id) {
[email protected]df37b9932013-03-08 05:21:424514 Program* program = GetProgram(client_id);
4515 if (program) {
4516 if (!program->IsDeleted()) {
4517 program_manager()->MarkAsDeleted(shader_manager(), program);
[email protected]ca488e12010-12-13 20:06:144518 }
[email protected]ae51d192010-04-27 00:48:034519 } else {
[email protected]ab09b612013-03-11 22:11:514520 LOCAL_SET_GL_ERROR(
4521 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
[email protected]ae51d192010-04-27 00:48:034522 }
[email protected]96449d2c2009-11-25 00:01:324523 }
[email protected]f7a64ee2010-02-01 22:24:144524 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:324525}
4526
[email protected]269200b12010-11-18 22:53:064527void GLES2DecoderImpl::DoDeleteSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104528 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574529 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104530 for (GLsizei ii = 0; ii < n; ++ii) {
4531 id_allocator->FreeID(ids[ii]);
4532 }
4533}
4534
[email protected]269200b12010-11-18 22:53:064535error::Error GLES2DecoderImpl::HandleDeleteSharedIdsCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:354536 uint32 immediate_data_size, const cmds::DeleteSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104537 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4538 GLsizei n = static_cast<GLsizei>(c.n);
4539 uint32 data_size;
4540 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4541 return error::kOutOfBounds;
4542 }
4543 const GLuint* ids = GetSharedMemoryAs<const GLuint*>(
4544 c.ids_shm_id, c.ids_shm_offset, data_size);
4545 if (n < 0) {
[email protected]ab09b612013-03-11 22:11:514546 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "DeleteSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104547 return error::kNoError;
4548 }
4549 if (ids == NULL) {
4550 return error::kOutOfBounds;
4551 }
[email protected]269200b12010-11-18 22:53:064552 DoDeleteSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:104553 return error::kNoError;
4554}
4555
[email protected]269200b12010-11-18 22:53:064556void GLES2DecoderImpl::DoGenSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104557 GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574558 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104559 if (id_offset == 0) {
4560 for (GLsizei ii = 0; ii < n; ++ii) {
4561 ids[ii] = id_allocator->AllocateID();
4562 }
4563 } else {
4564 for (GLsizei ii = 0; ii < n; ++ii) {
4565 ids[ii] = id_allocator->AllocateIDAtOrAbove(id_offset);
4566 id_offset = ids[ii] + 1;
4567 }
4568 }
4569}
4570
[email protected]269200b12010-11-18 22:53:064571error::Error GLES2DecoderImpl::HandleGenSharedIdsCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:354572 uint32 immediate_data_size, const cmds::GenSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104573 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4574 GLuint id_offset = static_cast<GLuint>(c.id_offset);
4575 GLsizei n = static_cast<GLsizei>(c.n);
4576 uint32 data_size;
4577 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4578 return error::kOutOfBounds;
4579 }
4580 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4581 c.ids_shm_id, c.ids_shm_offset, data_size);
4582 if (n < 0) {
[email protected]ab09b612013-03-11 22:11:514583 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "GenSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104584 return error::kNoError;
4585 }
4586 if (ids == NULL) {
4587 return error::kOutOfBounds;
4588 }
[email protected]269200b12010-11-18 22:53:064589 DoGenSharedIdsCHROMIUM(namespace_id, id_offset, n, ids);
[email protected]066849e32010-05-03 19:14:104590 return error::kNoError;
4591}
4592
[email protected]269200b12010-11-18 22:53:064593void GLES2DecoderImpl::DoRegisterSharedIdsCHROMIUM(
[email protected]066849e32010-05-03 19:14:104594 GLuint namespace_id, GLsizei n, const GLuint* ids) {
[email protected]3b1ecc262011-08-03 22:49:574595 IdAllocatorInterface* id_allocator = group_->GetIdAllocator(namespace_id);
[email protected]066849e32010-05-03 19:14:104596 for (GLsizei ii = 0; ii < n; ++ii) {
4597 if (!id_allocator->MarkAsUsed(ids[ii])) {
4598 for (GLsizei jj = 0; jj < ii; ++jj) {
4599 id_allocator->FreeID(ids[jj]);
4600 }
[email protected]ab09b612013-03-11 22:11:514601 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:434602 GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM",
4603 "attempt to register id that already exists");
[email protected]066849e32010-05-03 19:14:104604 return;
4605 }
4606 }
4607}
4608
[email protected]269200b12010-11-18 22:53:064609error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:354610 uint32 immediate_data_size, const cmds::RegisterSharedIdsCHROMIUM& c) {
[email protected]066849e32010-05-03 19:14:104611 GLuint namespace_id = static_cast<GLuint>(c.namespace_id);
4612 GLsizei n = static_cast<GLsizei>(c.n);
4613 uint32 data_size;
4614 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
4615 return error::kOutOfBounds;
4616 }
4617 GLuint* ids = GetSharedMemoryAs<GLuint*>(
4618 c.ids_shm_id, c.ids_shm_offset, data_size);
4619 if (n < 0) {
[email protected]ab09b612013-03-11 22:11:514620 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "RegisterSharedIdsCHROMIUM", "n < 0");
[email protected]066849e32010-05-03 19:14:104621 return error::kNoError;
4622 }
4623 if (ids == NULL) {
4624 return error::kOutOfBounds;
4625 }
[email protected]269200b12010-11-18 22:53:064626 DoRegisterSharedIdsCHROMIUM(namespace_id, n, ids);
[email protected]066849e32010-05-03 19:14:104627 return error::kNoError;
4628}
4629
[email protected]a7266a92012-06-28 02:11:084630error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
[email protected]09e17272012-11-30 10:30:444631 DCHECK(!ShouldDeferDraws());
[email protected]0d6bfdc2011-11-02 01:32:204632 if (CheckBoundFramebuffersValid("glClear")) {
[email protected]297ca1c2011-06-20 23:08:464633 ApplyDirtyState();
[email protected]3a03a8f2011-03-19 00:51:274634 glClear(mask);
4635 }
[email protected]a7266a92012-06-28 02:11:084636 return error::kNoError;
4637}
4638
[email protected]36cef8ce2010-03-16 07:34:454639void GLES2DecoderImpl::DoFramebufferRenderbuffer(
4640 GLenum target, GLenum attachment, GLenum renderbuffertarget,
[email protected]ae51d192010-04-27 00:48:034641 GLuint client_renderbuffer_id) {
[email protected]4d8f0dd2013-03-09 14:37:064642 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4643 if (!framebuffer) {
[email protected]ab09b612013-03-11 22:11:514644 LOCAL_SET_GL_ERROR(
4645 GL_INVALID_OPERATION,
4646 "glFramebufferRenderbuffer", "no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454647 return;
4648 }
[email protected]ae51d192010-04-27 00:48:034649 GLuint service_id = 0;
[email protected]ee2a79c32013-03-10 03:50:274650 Renderbuffer* renderbuffer = NULL;
[email protected]ae51d192010-04-27 00:48:034651 if (client_renderbuffer_id) {
[email protected]ee2a79c32013-03-10 03:50:274652 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
4653 if (!renderbuffer) {
[email protected]ab09b612013-03-11 22:11:514654 LOCAL_SET_GL_ERROR(
4655 GL_INVALID_OPERATION,
4656 "glFramebufferRenderbuffer", "unknown renderbuffer");
[email protected]ae51d192010-04-27 00:48:034657 return;
4658 }
[email protected]ee2a79c32013-03-10 03:50:274659 service_id = renderbuffer->service_id();
[email protected]ae51d192010-04-27 00:48:034660 }
[email protected]ab09b612013-03-11 22:11:514661 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
[email protected]ae51d192010-04-27 00:48:034662 glFramebufferRenderbufferEXT(
4663 target, attachment, renderbuffertarget, service_id);
[email protected]ab09b612013-03-11 22:11:514664 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
[email protected]9edc6b22010-12-23 02:00:264665 if (error == GL_NO_ERROR) {
[email protected]ee2a79c32013-03-10 03:50:274666 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
[email protected]3a2e7c7b2010-08-06 01:12:284667 }
[email protected]7cd76fd2013-06-02 21:11:114668 if (framebuffer == state_.bound_draw_framebuffer.get()) {
[email protected]c986af502013-08-14 01:04:444669 framebuffer_state_.clear_state_dirty = true;
[email protected]297ca1c2011-06-20 23:08:464670 }
[email protected]81fc9d02013-03-14 23:53:324671 OnFboChanged();
[email protected]3a2e7c7b2010-08-06 01:12:284672}
4673
[email protected]3a2e7c7b2010-08-06 01:12:284674void GLES2DecoderImpl::DoDisable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464675 if (SetCapabilityState(cap, false)) {
4676 glDisable(cap);
4677 }
[email protected]3a2e7c7b2010-08-06 01:12:284678}
4679
4680void GLES2DecoderImpl::DoEnable(GLenum cap) {
[email protected]297ca1c2011-06-20 23:08:464681 if (SetCapabilityState(cap, true)) {
4682 glEnable(cap);
4683 }
[email protected]3a2e7c7b2010-08-06 01:12:284684}
4685
[email protected]88a61bf2012-10-27 13:00:424686void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
4687 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
4688 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
4689 glDepthRange(znear, zfar);
[email protected]3a2e7c7b2010-08-06 01:12:284690}
4691
[email protected]b04e24c2013-01-08 18:35:254692void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
[email protected]88a61bf2012-10-27 13:00:424693 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
4694 state_.sample_coverage_invert = (invert != 0);
4695 glSampleCoverage(state_.sample_coverage_value, invert);
[email protected]3a2e7c7b2010-08-06 01:12:284696}
4697
[email protected]0d6bfdc2011-11-02 01:32:204698// Assumes framebuffer is complete.
4699void GLES2DecoderImpl::ClearUnclearedAttachments(
[email protected]4d8f0dd2013-03-09 14:37:064700 GLenum target, Framebuffer* framebuffer) {
[email protected]8e3e0662010-08-23 18:46:304701 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]0d6bfdc2011-11-02 01:32:204702 // bind this to the DRAW point, clear then bind back to READ
4703 // TODO(gman): I don't think there is any guarantee that an FBO that
4704 // is complete on the READ attachment will be complete as a DRAW
4705 // attachment.
4706 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
[email protected]4d8f0dd2013-03-09 14:37:064707 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
[email protected]8e3e0662010-08-23 18:46:304708 }
[email protected]3a2e7c7b2010-08-06 01:12:284709 GLbitfield clear_bits = 0;
[email protected]4d8f0dd2013-03-09 14:37:064710 if (framebuffer->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
[email protected]297ca1c2011-06-20 23:08:464711 glClearColor(
[email protected]0d6bfdc2011-11-02 01:32:204712 0.0f, 0.0f, 0.0f,
[email protected]297ca1c2011-06-20 23:08:464713 (GLES2Util::GetChannelsForFormat(
[email protected]4d8f0dd2013-03-09 14:37:064714 framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
4715 1.0f);
[email protected]3a2e7c7b2010-08-06 01:12:284716 glColorMask(true, true, true, true);
4717 clear_bits |= GL_COLOR_BUFFER_BIT;
4718 }
4719
[email protected]4d8f0dd2013-03-09 14:37:064720 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
4721 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
[email protected]3a2e7c7b2010-08-06 01:12:284722 glClearStencil(0);
4723 glStencilMask(-1);
4724 clear_bits |= GL_STENCIL_BUFFER_BIT;
4725 }
4726
[email protected]4d8f0dd2013-03-09 14:37:064727 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
4728 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
[email protected]3a2e7c7b2010-08-06 01:12:284729 glClearDepth(1.0f);
4730 glDepthMask(true);
4731 clear_bits |= GL_DEPTH_BUFFER_BIT;
4732 }
4733
4734 glDisable(GL_SCISSOR_TEST);
4735 glClear(clear_bits);
4736
[email protected]968351b2011-12-20 08:26:514737 framebuffer_manager()->MarkAttachmentsAsCleared(
[email protected]4d8f0dd2013-03-09 14:37:064738 framebuffer, renderbuffer_manager(), texture_manager());
[email protected]3a2e7c7b2010-08-06 01:12:284739
[email protected]c007aa02010-09-02 22:22:404740 RestoreClearState();
4741
4742 if (target == GL_READ_FRAMEBUFFER_EXT) {
[email protected]4d8f0dd2013-03-09 14:37:064743 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
4744 Framebuffer* draw_framebuffer =
[email protected]87d1a3fe2011-12-01 04:25:484745 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
[email protected]4d8f0dd2013-03-09 14:37:064746 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
4747 GetBackbufferServiceId();
[email protected]87d1a3fe2011-12-01 04:25:484748 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
[email protected]c007aa02010-09-02 22:22:404749 }
4750}
4751
4752void GLES2DecoderImpl::RestoreClearState() {
[email protected]c986af502013-08-14 01:04:444753 framebuffer_state_.clear_state_dirty = true;
[email protected]e259eb412012-10-13 05:47:244754 glClearColor(
4755 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
4756 state_.color_clear_alpha);
4757 glClearStencil(state_.stencil_clear);
4758 glClearDepth(state_.depth_clear);
[email protected]f731b9462012-10-30 00:35:224759 if (state_.enable_flags.scissor_test) {
[email protected]3a2e7c7b2010-08-06 01:12:284760 glEnable(GL_SCISSOR_TEST);
4761 }
[email protected]36cef8ce2010-03-16 07:34:454762}
4763
4764GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
[email protected]ed9f9cd2013-02-27 21:12:354765 Framebuffer* framebuffer =
[email protected]8e3e0662010-08-23 18:46:304766 GetFramebufferInfoForTarget(target);
[email protected]0d6bfdc2011-11-02 01:32:204767 if (!framebuffer) {
[email protected]36cef8ce2010-03-16 07:34:454768 return GL_FRAMEBUFFER_COMPLETE;
4769 }
[email protected]0d6bfdc2011-11-02 01:32:204770 GLenum completeness = framebuffer->IsPossiblyComplete();
4771 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
4772 return completeness;
4773 }
[email protected]73276522012-11-09 05:50:204774 return framebuffer->GetStatus(texture_manager(), target);
[email protected]36cef8ce2010-03-16 07:34:454775}
4776
4777void GLES2DecoderImpl::DoFramebufferTexture2D(
[email protected]ae51d192010-04-27 00:48:034778 GLenum target, GLenum attachment, GLenum textarget,
4779 GLuint client_texture_id, GLint level) {
[email protected]7d3c36e2013-07-12 14:13:164780 DoFramebufferTexture2DCommon(
4781 "glFramebufferTexture2D", target, attachment,
4782 textarget, client_texture_id, level, 0);
4783}
4784
4785void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
4786 GLenum target, GLenum attachment, GLenum textarget,
4787 GLuint client_texture_id, GLint level, GLsizei samples) {
4788 if (!features().multisampled_render_to_texture) {
4789 LOCAL_SET_GL_ERROR(
4790 GL_INVALID_OPERATION,
4791 "glFramebufferTexture2DMultisample", "function not available");
4792 return;
4793 }
4794 DoFramebufferTexture2DCommon(
4795 "glFramebufferTexture2DMultisample", target, attachment,
4796 textarget, client_texture_id, level, samples);
4797}
4798
4799void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
4800 const char* name, GLenum target, GLenum attachment, GLenum textarget,
4801 GLuint client_texture_id, GLint level, GLsizei samples) {
4802 if (samples > renderbuffer_manager()->max_samples()) {
4803 LOCAL_SET_GL_ERROR(
4804 GL_INVALID_VALUE,
4805 "glFramebufferTexture2DMultisample", "samples too large");
4806 return;
4807 }
[email protected]4d8f0dd2013-03-09 14:37:064808 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4809 if (!framebuffer) {
[email protected]ab09b612013-03-11 22:11:514810 LOCAL_SET_GL_ERROR(
4811 GL_INVALID_OPERATION,
[email protected]7d3c36e2013-07-12 14:13:164812 name, "no framebuffer bound.");
[email protected]36cef8ce2010-03-16 07:34:454813 return;
4814 }
[email protected]ae51d192010-04-27 00:48:034815 GLuint service_id = 0;
[email protected]370eaf12013-05-18 09:19:494816 TextureRef* texture_ref = NULL;
[email protected]ae51d192010-04-27 00:48:034817 if (client_texture_id) {
[email protected]370eaf12013-05-18 09:19:494818 texture_ref = GetTexture(client_texture_id);
4819 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:514820 LOCAL_SET_GL_ERROR(
4821 GL_INVALID_OPERATION,
[email protected]7d3c36e2013-07-12 14:13:164822 name, "unknown texture_ref");
[email protected]ae51d192010-04-27 00:48:034823 return;
4824 }
[email protected]370eaf12013-05-18 09:19:494825 service_id = texture_ref->service_id();
[email protected]ae51d192010-04-27 00:48:034826 }
[email protected]0d6bfdc2011-11-02 01:32:204827
[email protected]80eb6b52012-01-19 00:14:414828 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
[email protected]ab09b612013-03-11 22:11:514829 LOCAL_SET_GL_ERROR(
4830 GL_INVALID_VALUE,
[email protected]7d3c36e2013-07-12 14:13:164831 name, "level out of range");
[email protected]0d6bfdc2011-11-02 01:32:204832 return;
4833 }
4834
[email protected]7d3c36e2013-07-12 14:13:164835 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
4836 if (0 == samples) {
4837 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
4838 } else {
4839 if (features().use_img_for_multisampled_render_to_texture) {
4840 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
4841 service_id, level, samples);
4842 } else {
4843 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
4844 service_id, level, samples);
4845 }
4846 }
4847 GLenum error = LOCAL_PEEK_GL_ERROR(name);
[email protected]9edc6b22010-12-23 02:00:264848 if (error == GL_NO_ERROR) {
[email protected]7d3c36e2013-07-12 14:13:164849 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
4850 samples);
[email protected]3a2e7c7b2010-08-06 01:12:284851 }
[email protected]7cd76fd2013-06-02 21:11:114852 if (framebuffer == state_.bound_draw_framebuffer.get()) {
[email protected]c986af502013-08-14 01:04:444853 framebuffer_state_.clear_state_dirty = true;
[email protected]297ca1c2011-06-20 23:08:464854 }
[email protected]81fc9d02013-03-14 23:53:324855 OnFboChanged();
[email protected]36cef8ce2010-03-16 07:34:454856}
4857
4858void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
4859 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
[email protected]4d8f0dd2013-03-09 14:37:064860 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
4861 if (!framebuffer) {
[email protected]ab09b612013-03-11 22:11:514862 LOCAL_SET_GL_ERROR(
4863 GL_INVALID_OPERATION,
4864 "glFramebufferAttachmentParameteriv", "no framebuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454865 return;
4866 }
[email protected]74c1ec42010-08-12 01:55:574867 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
[email protected]62e65f02013-05-29 22:28:104868 const Framebuffer::Attachment* attachment_object =
4869 framebuffer->GetAttachment(attachment);
4870 *params = attachment_object ? attachment_object->object_name() : 0;
4871 } else {
[email protected]7d3c36e2013-07-12 14:13:164872 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
4873 features().use_img_for_multisampled_render_to_texture) {
4874 pname = GL_TEXTURE_SAMPLES_IMG;
4875 }
[email protected]62e65f02013-05-29 22:28:104876 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
[email protected]74c1ec42010-08-12 01:55:574877 }
[email protected]36cef8ce2010-03-16 07:34:454878}
4879
4880void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
4881 GLenum target, GLenum pname, GLint* params) {
[email protected]ed9f9cd2013-02-27 21:12:354882 Renderbuffer* renderbuffer =
[email protected]0d6bfdc2011-11-02 01:32:204883 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4884 if (!renderbuffer) {
[email protected]ab09b612013-03-11 22:11:514885 LOCAL_SET_GL_ERROR(
4886 GL_INVALID_OPERATION,
4887 "glGetRenderbufferParameteriv", "no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:454888 return;
4889 }
[email protected]3a03a8f2011-03-19 00:51:274890 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:434891 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4892 *params = renderbuffer->internal_format();
4893 break;
4894 case GL_RENDERBUFFER_WIDTH:
4895 *params = renderbuffer->width();
4896 break;
4897 case GL_RENDERBUFFER_HEIGHT:
4898 *params = renderbuffer->height();
4899 break;
[email protected]7d3c36e2013-07-12 14:13:164900 case GL_RENDERBUFFER_SAMPLES_EXT:
4901 if (features().use_img_for_multisampled_render_to_texture) {
4902 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
4903 params);
4904 } else {
4905 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
4906 params);
4907 }
[email protected]ad84a3a2012-06-08 21:42:434908 default:
4909 glGetRenderbufferParameterivEXT(target, pname, params);
4910 break;
[email protected]b71f52c2010-06-18 22:20:204911 }
[email protected]36cef8ce2010-03-16 07:34:454912}
4913
[email protected]8e3e0662010-08-23 18:46:304914void GLES2DecoderImpl::DoBlitFramebufferEXT(
4915 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
4916 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
4917 GLbitfield mask, GLenum filter) {
[email protected]09e17272012-11-30 10:30:444918 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
[email protected]62e155e2012-10-23 22:43:154919 if (!features().chromium_framebuffer_multisample) {
[email protected]ab09b612013-03-11 22:11:514920 LOCAL_SET_GL_ERROR(
4921 GL_INVALID_OPERATION,
4922 "glBlitFramebufferEXT", "function not available");
[email protected]8e3e0662010-08-23 18:46:304923 }
[email protected]0c16343f2013-03-08 20:40:164924
4925 if (!CheckBoundFramebuffersValid("glBlitFramebufferEXT")) {
4926 return;
4927 }
4928
[email protected]d058bca2012-11-26 10:27:264929 glDisable(GL_SCISSOR_TEST);
[email protected]5094b0f2010-11-09 19:45:244930 if (IsAngle()) {
4931 glBlitFramebufferANGLE(
4932 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4933 } else {
4934 glBlitFramebufferEXT(
4935 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
4936 }
[email protected]d058bca2012-11-26 10:27:264937 EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
[email protected]8e3e0662010-08-23 18:46:304938}
4939
4940void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
4941 GLenum target, GLsizei samples, GLenum internalformat,
4942 GLsizei width, GLsizei height) {
[email protected]7d3c36e2013-07-12 14:13:164943 if (!features().chromium_framebuffer_multisample &&
4944 !features().multisampled_render_to_texture) {
[email protected]ab09b612013-03-11 22:11:514945 LOCAL_SET_GL_ERROR(
4946 GL_INVALID_OPERATION,
4947 "glRenderbufferStorageMultisample", "function not available");
[email protected]8e3e0662010-08-23 18:46:304948 return;
4949 }
[email protected]8e3e0662010-08-23 18:46:304950
[email protected]ed9f9cd2013-02-27 21:12:354951 Renderbuffer* renderbuffer =
[email protected]0d6bfdc2011-11-02 01:32:204952 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
4953 if (!renderbuffer) {
[email protected]ab09b612013-03-11 22:11:514954 LOCAL_SET_GL_ERROR(
4955 GL_INVALID_OPERATION,
4956 "glRenderbufferStorageMultisample", "no renderbuffer bound");
[email protected]0d6bfdc2011-11-02 01:32:204957 return;
4958 }
4959
[email protected]84afefa2011-10-19 21:45:534960 if (samples > renderbuffer_manager()->max_samples()) {
[email protected]ab09b612013-03-11 22:11:514961 LOCAL_SET_GL_ERROR(
4962 GL_INVALID_VALUE,
4963 "glRenderbufferStorageMultisample", "samples too large");
[email protected]84afefa2011-10-19 21:45:534964 return;
4965 }
4966
4967 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
4968 height > renderbuffer_manager()->max_renderbuffer_size()) {
[email protected]ab09b612013-03-11 22:11:514969 LOCAL_SET_GL_ERROR(
4970 GL_INVALID_VALUE,
4971 "glRenderbufferStorageMultisample", "dimensions too large");
[email protected]84afefa2011-10-19 21:45:534972 return;
4973 }
4974
[email protected]7989c9e2013-01-23 06:39:264975 uint32 estimated_size = 0;
4976 if (!RenderbufferManager::ComputeEstimatedRenderbufferSize(
4977 width, height, samples, internalformat, &estimated_size)) {
[email protected]ab09b612013-03-11 22:11:514978 LOCAL_SET_GL_ERROR(
4979 GL_OUT_OF_MEMORY,
4980 "glRenderbufferStorageMultsample", "dimensions too large");
[email protected]7989c9e2013-01-23 06:39:264981 return;
[email protected]8e3e0662010-08-23 18:46:304982 }
4983
[email protected]7989c9e2013-01-23 06:39:264984 if (!EnsureGPUMemoryAvailable(estimated_size)) {
[email protected]ab09b612013-03-11 22:11:514985 LOCAL_SET_GL_ERROR(
4986 GL_OUT_OF_MEMORY,
4987 "glRenderbufferStorageMultsample", "out of memory");
[email protected]7989c9e2013-01-23 06:39:264988 return;
4989 }
4990
4991 GLenum impl_format = RenderbufferManager::
4992 InternalRenderbufferFormatToImplFormat(internalformat);
[email protected]ab09b612013-03-11 22:11:514993 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisample");
[email protected]866b91c52011-03-23 14:38:084994 if (IsAngle()) {
4995 glRenderbufferStorageMultisampleANGLE(
4996 target, samples, impl_format, width, height);
[email protected]7d3c36e2013-07-12 14:13:164997 } else if (features().use_img_for_multisampled_render_to_texture) {
4998 glRenderbufferStorageMultisampleIMG(
4999 target, samples, impl_format, width, height);
[email protected]866b91c52011-03-23 14:38:085000 } else {
5001 glRenderbufferStorageMultisampleEXT(
5002 target, samples, impl_format, width, height);
5003 }
[email protected]ab09b612013-03-11 22:11:515004 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisample");
[email protected]9edc6b22010-12-23 02:00:265005 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:515006 // TODO(gman): If renderbuffers tracked which framebuffers they were
5007 // attached to we could just mark those framebuffers as not complete.
5008 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:205009 renderbuffer_manager()->SetInfo(
5010 renderbuffer, samples, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:265011 }
[email protected]8e3e0662010-08-23 18:46:305012}
5013
[email protected]36cef8ce2010-03-16 07:34:455014void GLES2DecoderImpl::DoRenderbufferStorage(
5015 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
[email protected]ed9f9cd2013-02-27 21:12:355016 Renderbuffer* renderbuffer =
[email protected]0d6bfdc2011-11-02 01:32:205017 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5018 if (!renderbuffer) {
[email protected]ab09b612013-03-11 22:11:515019 LOCAL_SET_GL_ERROR(
5020 GL_INVALID_OPERATION,
5021 "glRenderbufferStorage", "no renderbuffer bound");
[email protected]36cef8ce2010-03-16 07:34:455022 return;
5023 }
[email protected]876f6fee2010-08-02 23:10:325024
[email protected]84afefa2011-10-19 21:45:535025 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
5026 height > renderbuffer_manager()->max_renderbuffer_size()) {
[email protected]ab09b612013-03-11 22:11:515027 LOCAL_SET_GL_ERROR(
5028 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
[email protected]84afefa2011-10-19 21:45:535029 return;
5030 }
5031
[email protected]7989c9e2013-01-23 06:39:265032 uint32 estimated_size = 0;
5033 if (!RenderbufferManager::ComputeEstimatedRenderbufferSize(
5034 width, height, 1, internalformat, &estimated_size)) {
[email protected]ab09b612013-03-11 22:11:515035 LOCAL_SET_GL_ERROR(
5036 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
[email protected]7989c9e2013-01-23 06:39:265037 return;
5038 }
5039
5040 if (!EnsureGPUMemoryAvailable(estimated_size)) {
[email protected]ab09b612013-03-11 22:11:515041 LOCAL_SET_GL_ERROR(
5042 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
[email protected]7989c9e2013-01-23 06:39:265043 return;
[email protected]b71f52c2010-06-18 22:20:205044 }
[email protected]876f6fee2010-08-02 23:10:325045
[email protected]ab09b612013-03-11 22:11:515046 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
[email protected]7989c9e2013-01-23 06:39:265047 glRenderbufferStorageEXT(
5048 target, RenderbufferManager::
5049 InternalRenderbufferFormatToImplFormat(internalformat),
5050 width, height);
[email protected]ab09b612013-03-11 22:11:515051 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
[email protected]9edc6b22010-12-23 02:00:265052 if (error == GL_NO_ERROR) {
[email protected]968351b2011-12-20 08:26:515053 // TODO(gman): If tetxures tracked which framebuffers they were attached to
5054 // we could just mark those framebuffers as not complete.
5055 framebuffer_manager()->IncFramebufferStateChangeCount();
[email protected]0d6bfdc2011-11-02 01:32:205056 renderbuffer_manager()->SetInfo(
[email protected]7989c9e2013-01-23 06:39:265057 renderbuffer, 1, internalformat, width, height);
[email protected]9edc6b22010-12-23 02:00:265058 }
[email protected]36cef8ce2010-03-16 07:34:455059}
5060
[email protected]df37b9932013-03-08 05:21:425061void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
[email protected]43ed3a72012-05-30 22:55:385062 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
[email protected]df37b9932013-03-08 05:21:425063 Program* program = GetProgramInfoNotShader(
5064 program_id, "glLinkProgram");
5065 if (!program) {
[email protected]a93bb842010-02-16 23:03:475066 return;
5067 }
[email protected]05afda12011-01-20 00:17:345068
[email protected]df37b9932013-03-08 05:21:425069 LogClientServiceForInfo(program, program_id, "glLinkProgram");
[email protected]65dfc602012-07-23 20:39:395070 ShaderTranslator* vertex_translator = NULL;
5071 ShaderTranslator* fragment_translator = NULL;
5072 if (use_shader_translator_) {
[email protected]7cd76fd2013-06-02 21:11:115073 vertex_translator = vertex_translator_.get();
5074 fragment_translator = fragment_translator_.get();
[email protected]65dfc602012-07-23 20:39:395075 }
[email protected]df37b9932013-03-08 05:21:425076 if (program->Link(shader_manager(),
[email protected]7cd76fd2013-06-02 21:11:115077 vertex_translator,
5078 fragment_translator,
5079 feature_info_.get(),
5080 shader_cache_callback_)) {
[email protected]df37b9932013-03-08 05:21:425081 if (program == state_.current_program.get()) {
[email protected]62e155e2012-10-23 22:43:155082 if (workarounds().use_current_program_after_successful_link) {
[email protected]df37b9932013-03-08 05:21:425083 glUseProgram(program->service_id());
[email protected]c2a3caf12012-10-23 19:32:005084 }
[email protected]df37b9932013-03-08 05:21:425085 program_manager()->ClearUniforms(program);
[email protected]2df73892012-04-28 01:09:545086 }
5087 }
[email protected]07f54fcc2009-12-22 02:46:305088};
5089
[email protected]3916c97e2010-02-25 03:20:505090void GLES2DecoderImpl::DoTexParameterf(
5091 GLenum target, GLenum pname, GLfloat param) {
[email protected]c986af502013-08-14 01:04:445092 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5093 &state_, target);
[email protected]02965c22013-03-09 02:40:075094 if (!texture) {
[email protected]ab09b612013-03-11 22:11:515095 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:245096 return;
[email protected]07f54fcc2009-12-22 02:46:305097 }
[email protected]cbb22e42011-05-12 23:36:245098
[email protected]02965c22013-03-09 02:40:075099 texture_manager()->SetParameter(
[email protected]d3eba342013-04-18 21:11:505100 "glTexParameterf", GetErrorState(), texture, pname,
5101 static_cast<GLint>(param));
[email protected]07f54fcc2009-12-22 02:46:305102}
5103
[email protected]3916c97e2010-02-25 03:20:505104void GLES2DecoderImpl::DoTexParameteri(
5105 GLenum target, GLenum pname, GLint param) {
[email protected]c986af502013-08-14 01:04:445106 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5107 &state_, target);
[email protected]02965c22013-03-09 02:40:075108 if (!texture) {
[email protected]ab09b612013-03-11 22:11:515109 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:245110 return;
[email protected]3916c97e2010-02-25 03:20:505111 }
[email protected]cbb22e42011-05-12 23:36:245112
[email protected]02965c22013-03-09 02:40:075113 texture_manager()->SetParameter(
[email protected]d3eba342013-04-18 21:11:505114 "glTexParameteri", GetErrorState(), texture, pname, param);
[email protected]3916c97e2010-02-25 03:20:505115}
5116
5117void GLES2DecoderImpl::DoTexParameterfv(
5118 GLenum target, GLenum pname, const GLfloat* params) {
[email protected]c986af502013-08-14 01:04:445119 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5120 &state_, target);
[email protected]02965c22013-03-09 02:40:075121 if (!texture) {
[email protected]ab09b612013-03-11 22:11:515122 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:245123 return;
[email protected]3916c97e2010-02-25 03:20:505124 }
[email protected]cbb22e42011-05-12 23:36:245125
[email protected]02965c22013-03-09 02:40:075126 texture_manager()->SetParameter(
[email protected]d3eba342013-04-18 21:11:505127 "glTexParameterfv", GetErrorState(), texture, pname,
5128 static_cast<GLint>(params[0]));
[email protected]3916c97e2010-02-25 03:20:505129}
5130
5131void GLES2DecoderImpl::DoTexParameteriv(
5132 GLenum target, GLenum pname, const GLint* params) {
[email protected]c986af502013-08-14 01:04:445133 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
5134 &state_, target);
[email protected]02965c22013-03-09 02:40:075135 if (!texture) {
[email protected]ab09b612013-03-11 22:11:515136 LOCAL_SET_GL_ERROR(
5137 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
[email protected]cbb22e42011-05-12 23:36:245138 return;
[email protected]3916c97e2010-02-25 03:20:505139 }
[email protected]cbb22e42011-05-12 23:36:245140
[email protected]02965c22013-03-09 02:40:075141 texture_manager()->SetParameter(
[email protected]d3eba342013-04-18 21:11:505142 "glTexParameteriv", GetErrorState(), texture, pname, *params);
[email protected]3916c97e2010-02-25 03:20:505143}
5144
[email protected]939e7362010-05-13 20:49:105145bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
[email protected]7cd76fd2013-06-02 21:11:115146 if (!state_.current_program.get()) {
[email protected]ad84a3a2012-06-08 21:42:435147 // The program does not exist.
[email protected]ab09b612013-03-11 22:11:515148 LOCAL_SET_GL_ERROR(
5149 GL_INVALID_OPERATION, function_name, "no program in use");
[email protected]ad84a3a2012-06-08 21:42:435150 return false;
[email protected]939e7362010-05-13 20:49:105151 }
[email protected]e259eb412012-10-13 05:47:245152 if (!state_.current_program->InUse()) {
[email protected]ab09b612013-03-11 22:11:515153 LOCAL_SET_GL_ERROR(
5154 GL_INVALID_OPERATION, function_name, "program not linked");
[email protected]939e7362010-05-13 20:49:105155 return false;
5156 }
5157 return true;
5158}
5159
5160bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
5161 GLint location, const char* function_name) {
5162 if (!CheckCurrentProgram(function_name)) {
5163 return false;
5164 }
5165 return location != -1;
5166}
5167
[email protected]476ccb72012-12-06 15:52:525168namespace {
5169
5170static const GLenum valid_int_vec1_types_list[] = {
5171 GL_INT,
5172 GL_BOOL,
5173 GL_SAMPLER_2D,
5174 GL_SAMPLER_2D_RECT_ARB,
5175 GL_SAMPLER_CUBE,
5176 GL_SAMPLER_EXTERNAL_OES,
5177};
5178
5179static const GLenum valid_int_vec2_types_list[] = {
5180 GL_INT_VEC2,
5181 GL_BOOL_VEC2,
5182};
5183
5184static const GLenum valid_int_vec3_types_list[] = {
5185 GL_INT_VEC3,
5186 GL_BOOL_VEC3,
5187};
5188
5189static const GLenum valid_int_vec4_types_list[] = {
5190 GL_INT_VEC4,
5191 GL_BOOL_VEC4,
5192};
5193
5194static const GLenum valid_float_vec1_types_list[] = {
5195 GL_FLOAT,
5196 GL_BOOL,
5197};
5198
5199static const GLenum valid_float_vec2_types_list[] = {
5200 GL_FLOAT_VEC2,
5201 GL_BOOL_VEC2,
5202};
5203
5204static const GLenum valid_float_vec3_types_list[] = {
5205 GL_FLOAT_VEC3,
5206 GL_BOOL_VEC3,
5207};
5208
5209static const GLenum valid_float_vec4_types_list[] = {
5210 GL_FLOAT_VEC4,
5211 GL_BOOL_VEC4,
5212};
5213
5214static const GLenum valid_float_mat2_types_list[] = {
5215 GL_FLOAT_MAT2,
5216};
5217
5218static const GLenum valid_float_mat3_types_list[] = {
5219 GL_FLOAT_MAT3,
5220};
5221
5222static const GLenum valid_float_mat4_types_list[] = {
5223 GL_FLOAT_MAT4,
5224};
5225
5226static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec1_base_info = {
5227 valid_int_vec1_types_list,
5228 arraysize(valid_int_vec1_types_list),
5229};
5230
5231static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec2_base_info = {
5232 valid_int_vec2_types_list,
5233 arraysize(valid_int_vec2_types_list),
5234};
5235
5236static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec3_base_info = {
5237 valid_int_vec3_types_list,
5238 arraysize(valid_int_vec3_types_list),
5239};
5240
5241static const GLES2DecoderImpl::BaseUniformInfo valid_int_vec4_base_info = {
5242 valid_int_vec4_types_list,
5243 arraysize(valid_int_vec4_types_list),
5244};
5245
5246static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec1_base_info = {
5247 valid_float_vec1_types_list,
5248 arraysize(valid_float_vec1_types_list),
5249};
5250
5251static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec2_base_info = {
5252 valid_float_vec2_types_list,
5253 arraysize(valid_float_vec2_types_list),
5254};
5255
5256static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec3_base_info = {
5257 valid_float_vec3_types_list,
5258 arraysize(valid_float_vec3_types_list),
5259};
5260
5261static const GLES2DecoderImpl::BaseUniformInfo valid_float_vec4_base_info = {
5262 valid_float_vec4_types_list,
5263 arraysize(valid_float_vec4_types_list),
5264};
5265
5266static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat2_base_info = {
5267 valid_float_mat2_types_list,
5268 arraysize(valid_float_mat2_types_list),
5269};
5270
5271static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat3_base_info = {
5272 valid_float_mat3_types_list,
5273 arraysize(valid_float_mat3_types_list),
5274};
5275
5276static const GLES2DecoderImpl::BaseUniformInfo valid_float_mat4_base_info = {
5277 valid_float_mat4_types_list,
5278 arraysize(valid_float_mat4_types_list),
5279};
5280
5281} // anonymous namespace.
5282
[email protected]43c2f1f2011-03-25 18:35:365283bool GLES2DecoderImpl::PrepForSetUniformByLocation(
[email protected]1b0a6752012-02-22 03:44:125284 GLint fake_location, const char* function_name,
[email protected]476ccb72012-12-06 15:52:525285 const GLES2DecoderImpl::BaseUniformInfo& base_info,
[email protected]1b0a6752012-02-22 03:44:125286 GLint* real_location, GLenum* type, GLsizei* count) {
[email protected]43c2f1f2011-03-25 18:35:365287 DCHECK(type);
5288 DCHECK(count);
[email protected]1b0a6752012-02-22 03:44:125289 DCHECK(real_location);
[email protected]476ccb72012-12-06 15:52:525290
[email protected]1b0a6752012-02-22 03:44:125291 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
[email protected]939e7362010-05-13 20:49:105292 return false;
5293 }
[email protected]43c2f1f2011-03-25 18:35:365294 GLint array_index = -1;
[email protected]ed9f9cd2013-02-27 21:12:355295 const Program::UniformInfo* info =
[email protected]e259eb412012-10-13 05:47:245296 state_.current_program->GetUniformInfoByFakeLocation(
[email protected]1b0a6752012-02-22 03:44:125297 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:365298 if (!info) {
[email protected]ab09b612013-03-11 22:11:515299 LOCAL_SET_GL_ERROR(
5300 GL_INVALID_OPERATION, function_name, "unknown location");
[email protected]939e7362010-05-13 20:49:105301 return false;
5302 }
[email protected]476ccb72012-12-06 15:52:525303 bool okay = false;
5304 for (size_t ii = 0; ii < base_info.num_valid_types; ++ii) {
5305 if (base_info.valid_types[ii] == info->type) {
5306 okay = true;
5307 break;
5308 }
5309 }
5310 if (!okay) {
[email protected]ab09b612013-03-11 22:11:515311 LOCAL_SET_GL_ERROR(
5312 GL_INVALID_OPERATION, function_name,
5313 "wrong uniform function for type");
[email protected]476ccb72012-12-06 15:52:525314 return false;
5315 }
[email protected]43c2f1f2011-03-25 18:35:365316 if (*count > 1 && !info->is_array) {
[email protected]ab09b612013-03-11 22:11:515317 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:435318 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
[email protected]43c2f1f2011-03-25 18:35:365319 return false;
5320 }
5321 *count = std::min(info->size - array_index, *count);
5322 if (*count <= 0) {
5323 return false;
5324 }
5325 *type = info->type;
[email protected]939e7362010-05-13 20:49:105326 return true;
5327}
5328
[email protected]1b0a6752012-02-22 03:44:125329void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
5330 GLenum type = 0;
5331 GLsizei count = 1;
5332 GLint real_location = -1;
5333 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525334 fake_location, "glUniform1iv", valid_int_vec1_base_info,
5335 &real_location, &type, &count)) {
[email protected]3916c97e2010-02-25 03:20:505336 return;
5337 }
[email protected]e259eb412012-10-13 05:47:245338 if (!state_.current_program->SetSamplers(
[email protected]1868a342012-11-07 15:56:025339 state_.texture_units.size(), fake_location, 1, &v0)) {
[email protected]ab09b612013-03-11 22:11:515340 LOCAL_SET_GL_ERROR(
5341 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
[email protected]d20a6512012-05-02 20:17:465342 return;
5343 }
[email protected]1b0a6752012-02-22 03:44:125344 glUniform1i(real_location, v0);
[email protected]3916c97e2010-02-25 03:20:505345}
5346
5347void GLES2DecoderImpl::DoUniform1iv(
[email protected]1b0a6752012-02-22 03:44:125348 GLint fake_location, GLsizei count, const GLint *value) {
[email protected]43c2f1f2011-03-25 18:35:365349 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125350 GLint real_location = -1;
5351 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525352 fake_location, "glUniform1iv", valid_int_vec1_base_info,
5353 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365354 return;
5355 }
[email protected]74727112012-06-13 21:18:085356 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
5357 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
[email protected]e259eb412012-10-13 05:47:245358 if (!state_.current_program->SetSamplers(
[email protected]1868a342012-11-07 15:56:025359 state_.texture_units.size(), fake_location, count, value)) {
[email protected]ab09b612013-03-11 22:11:515360 LOCAL_SET_GL_ERROR(
5361 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
[email protected]d20a6512012-05-02 20:17:465362 return;
5363 }
[email protected]43c2f1f2011-03-25 18:35:365364 }
[email protected]1b0a6752012-02-22 03:44:125365 glUniform1iv(real_location, count, value);
[email protected]3916c97e2010-02-25 03:20:505366}
5367
[email protected]939e7362010-05-13 20:49:105368void GLES2DecoderImpl::DoUniform1fv(
[email protected]1b0a6752012-02-22 03:44:125369 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365370 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125371 GLint real_location = -1;
5372 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525373 fake_location, "glUniform1fv", valid_float_vec1_base_info,
5374 &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:105375 return;
5376 }
5377 if (type == GL_BOOL) {
[email protected]40d90a22013-04-09 03:39:555378 scoped_ptr<GLint[]> temp(new GLint[count]);
[email protected]939e7362010-05-13 20:49:105379 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]136a63e2010-11-12 22:01:535380 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:105381 }
[email protected]1b0a6752012-02-22 03:44:125382 DoUniform1iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:105383 } else {
[email protected]1b0a6752012-02-22 03:44:125384 glUniform1fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:105385 }
5386}
5387
5388void GLES2DecoderImpl::DoUniform2fv(
[email protected]1b0a6752012-02-22 03:44:125389 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365390 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125391 GLint real_location = -1;
5392 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525393 fake_location, "glUniform2fv", valid_float_vec2_base_info,
5394 &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:105395 return;
5396 }
5397 if (type == GL_BOOL_VEC2) {
5398 GLsizei num_values = count * 2;
[email protected]40d90a22013-04-09 03:39:555399 scoped_ptr<GLint[]> temp(new GLint[num_values]);
[email protected]939e7362010-05-13 20:49:105400 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:535401 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:105402 }
[email protected]1b0a6752012-02-22 03:44:125403 glUniform2iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:105404 } else {
[email protected]1b0a6752012-02-22 03:44:125405 glUniform2fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:105406 }
5407}
5408
5409void GLES2DecoderImpl::DoUniform3fv(
[email protected]1b0a6752012-02-22 03:44:125410 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365411 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125412 GLint real_location = -1;
5413 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525414 fake_location, "glUniform3fv", valid_float_vec3_base_info,
5415 &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:105416 return;
5417 }
5418 if (type == GL_BOOL_VEC3) {
5419 GLsizei num_values = count * 3;
[email protected]40d90a22013-04-09 03:39:555420 scoped_ptr<GLint[]> temp(new GLint[num_values]);
[email protected]939e7362010-05-13 20:49:105421 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:535422 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:105423 }
[email protected]1b0a6752012-02-22 03:44:125424 glUniform3iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:105425 } else {
[email protected]1b0a6752012-02-22 03:44:125426 glUniform3fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:105427 }
5428}
5429
5430void GLES2DecoderImpl::DoUniform4fv(
[email protected]1b0a6752012-02-22 03:44:125431 GLint fake_location, GLsizei count, const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365432 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125433 GLint real_location = -1;
5434 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525435 fake_location, "glUniform4fv", valid_float_vec4_base_info,
5436 &real_location, &type, &count)) {
[email protected]939e7362010-05-13 20:49:105437 return;
5438 }
5439 if (type == GL_BOOL_VEC4) {
5440 GLsizei num_values = count * 4;
[email protected]40d90a22013-04-09 03:39:555441 scoped_ptr<GLint[]> temp(new GLint[num_values]);
[email protected]939e7362010-05-13 20:49:105442 for (GLsizei ii = 0; ii < num_values; ++ii) {
[email protected]136a63e2010-11-12 22:01:535443 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
[email protected]939e7362010-05-13 20:49:105444 }
[email protected]1b0a6752012-02-22 03:44:125445 glUniform4iv(real_location, count, temp.get());
[email protected]939e7362010-05-13 20:49:105446 } else {
[email protected]1b0a6752012-02-22 03:44:125447 glUniform4fv(real_location, count, value);
[email protected]939e7362010-05-13 20:49:105448 }
5449}
5450
[email protected]43c2f1f2011-03-25 18:35:365451void GLES2DecoderImpl::DoUniform2iv(
[email protected]1b0a6752012-02-22 03:44:125452 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:365453 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125454 GLint real_location = -1;
5455 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525456 fake_location, "glUniform2iv", valid_int_vec2_base_info,
5457 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365458 return;
5459 }
[email protected]1b0a6752012-02-22 03:44:125460 glUniform2iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:365461}
5462
5463void GLES2DecoderImpl::DoUniform3iv(
[email protected]1b0a6752012-02-22 03:44:125464 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:365465 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125466 GLint real_location = -1;
5467 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525468 fake_location, "glUniform3iv", valid_int_vec3_base_info,
5469 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365470 return;
5471 }
[email protected]1b0a6752012-02-22 03:44:125472 glUniform3iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:365473}
5474
5475void GLES2DecoderImpl::DoUniform4iv(
[email protected]1b0a6752012-02-22 03:44:125476 GLint fake_location, GLsizei count, const GLint* value) {
[email protected]43c2f1f2011-03-25 18:35:365477 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125478 GLint real_location = -1;
5479 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525480 fake_location, "glUniform4iv", valid_int_vec4_base_info,
5481 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365482 return;
5483 }
[email protected]1b0a6752012-02-22 03:44:125484 glUniform4iv(real_location, count, value);
[email protected]43c2f1f2011-03-25 18:35:365485}
5486
5487void GLES2DecoderImpl::DoUniformMatrix2fv(
[email protected]1b0a6752012-02-22 03:44:125488 GLint fake_location, GLsizei count, GLboolean transpose,
5489 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365490 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125491 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:365492 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525493 fake_location, "glUniformMatrix2fv", valid_float_mat2_base_info,
5494 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365495 return;
5496 }
[email protected]1b0a6752012-02-22 03:44:125497 glUniformMatrix2fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:365498}
5499
5500void GLES2DecoderImpl::DoUniformMatrix3fv(
[email protected]1b0a6752012-02-22 03:44:125501 GLint fake_location, GLsizei count, GLboolean transpose,
5502 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365503 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125504 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:365505 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525506 fake_location, "glUniformMatrix3fv", valid_float_mat3_base_info,
5507 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365508 return;
5509 }
[email protected]1b0a6752012-02-22 03:44:125510 glUniformMatrix3fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:365511}
5512
5513void GLES2DecoderImpl::DoUniformMatrix4fv(
[email protected]1b0a6752012-02-22 03:44:125514 GLint fake_location, GLsizei count, GLboolean transpose,
5515 const GLfloat* value) {
[email protected]43c2f1f2011-03-25 18:35:365516 GLenum type = 0;
[email protected]1b0a6752012-02-22 03:44:125517 GLint real_location = -1;
[email protected]43c2f1f2011-03-25 18:35:365518 if (!PrepForSetUniformByLocation(
[email protected]476ccb72012-12-06 15:52:525519 fake_location, "glUniformMatrix4fv", valid_float_mat4_base_info,
5520 &real_location, &type, &count)) {
[email protected]43c2f1f2011-03-25 18:35:365521 return;
5522 }
[email protected]1b0a6752012-02-22 03:44:125523 glUniformMatrix4fv(real_location, count, transpose, value);
[email protected]43c2f1f2011-03-25 18:35:365524}
5525
[email protected]df37b9932013-03-08 05:21:425526void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
[email protected]ae51d192010-04-27 00:48:035527 GLuint service_id = 0;
[email protected]df37b9932013-03-08 05:21:425528 Program* program = NULL;
5529 if (program_id) {
5530 program = GetProgramInfoNotShader(program_id, "glUseProgram");
5531 if (!program) {
[email protected]ae51d192010-04-27 00:48:035532 return;
5533 }
[email protected]df37b9932013-03-08 05:21:425534 if (!program->IsValid()) {
[email protected]3916c97e2010-02-25 03:20:505535 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]ab09b612013-03-11 22:11:515536 LOCAL_SET_GL_ERROR(
5537 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
[email protected]3916c97e2010-02-25 03:20:505538 return;
5539 }
[email protected]df37b9932013-03-08 05:21:425540 service_id = program->service_id();
[email protected]3916c97e2010-02-25 03:20:505541 }
[email protected]7cd76fd2013-06-02 21:11:115542 if (state_.current_program.get()) {
5543 program_manager()->UnuseProgram(shader_manager(),
5544 state_.current_program.get());
[email protected]ca488e12010-12-13 20:06:145545 }
[email protected]df37b9932013-03-08 05:21:425546 state_.current_program = program;
5547 LogClientServiceMapping("glUseProgram", program_id, service_id);
[email protected]2df73892012-04-28 01:09:545548 glUseProgram(service_id);
[email protected]7cd76fd2013-06-02 21:11:115549 if (state_.current_program.get()) {
5550 program_manager()->UseProgram(state_.current_program.get());
[email protected]ca488e12010-12-13 20:06:145551 }
[email protected]3916c97e2010-02-25 03:20:505552}
5553
[email protected]ab09b612013-03-11 22:11:515554void GLES2DecoderImpl::RenderWarning(
5555 const char* filename, int line, const std::string& msg) {
[email protected]1d82e822013-04-10 21:32:325556 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
[email protected]0f8afe82012-05-14 23:43:015557}
5558
[email protected]ab09b612013-03-11 22:11:515559void GLES2DecoderImpl::PerformanceWarning(
5560 const char* filename, int line, const std::string& msg) {
[email protected]d3eba342013-04-18 21:11:505561 logger_.LogMessage(filename, line,
5562 std::string("PERFORMANCE WARNING: ") + msg);
[email protected]0f8afe82012-05-14 23:43:015563}
5564
[email protected]e56131d22013-07-28 16:14:115565void GLES2DecoderImpl::UpdateStreamTextureIfNeeded(Texture* texture) {
5566 if (texture && texture->IsStreamTexture()) {
5567 DCHECK(stream_texture_manager());
5568 StreamTexture* stream_tex =
5569 stream_texture_manager()->LookupStreamTexture(texture->service_id());
5570 if (stream_tex)
5571 stream_tex->Update();
5572 }
5573}
5574
5575bool GLES2DecoderImpl::PrepareTexturesForRender() {
[email protected]7cd76fd2013-06-02 21:11:115576 DCHECK(state_.current_program.get());
[email protected]e56131d22013-07-28 16:14:115577 bool have_unrenderable_textures =
5578 texture_manager()->HaveUnrenderableTextures();
5579 if (!have_unrenderable_textures && !features().oes_egl_image_external) {
5580 return true;
[email protected]ef526492010-06-02 23:12:255581 }
[email protected]e2367b42013-05-31 03:37:215582
[email protected]ef526492010-06-02 23:12:255583 bool textures_set = false;
[email protected]ed9f9cd2013-02-27 21:12:355584 const Program::SamplerIndices& sampler_indices =
[email protected]e259eb412012-10-13 05:47:245585 state_.current_program->sampler_indices();
[email protected]3916c97e2010-02-25 03:20:505586 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:355587 const Program::UniformInfo* uniform_info =
[email protected]e259eb412012-10-13 05:47:245588 state_.current_program->GetUniformInfo(sampler_indices[ii]);
[email protected]3916c97e2010-02-25 03:20:505589 DCHECK(uniform_info);
5590 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5591 GLuint texture_unit_index = uniform_info->texture_units[jj];
[email protected]1868a342012-11-07 15:56:025592 if (texture_unit_index < state_.texture_units.size()) {
[email protected]e259eb412012-10-13 05:47:245593 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
[email protected]370eaf12013-05-18 09:19:495594 TextureRef* texture =
[email protected]cadac622013-06-11 16:46:365595 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
[email protected]79dc5b32013-07-30 20:08:295596 if (texture)
5597 UpdateStreamTextureIfNeeded(texture->texture());
[email protected]e56131d22013-07-28 16:14:115598 if (have_unrenderable_textures &&
5599 (!texture || !texture_manager()->CanRender(texture))) {
[email protected]ef526492010-06-02 23:12:255600 textures_set = true;
[email protected]3916c97e2010-02-25 03:20:505601 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
5602 glBindTexture(
[email protected]61eeb33f2011-07-26 15:30:315603 GetBindTargetForSamplerType(uniform_info->type),
[email protected]00f893d2010-08-24 18:55:495604 texture_manager()->black_texture_id(uniform_info->type));
[email protected]ab09b612013-03-11 22:11:515605 LOCAL_RENDER_WARNING(
[email protected]0f8afe82012-05-14 23:43:015606 std::string("texture bound to texture unit ") +
5607 base::IntToString(texture_unit_index) +
[email protected]ad9b7f8b2013-06-17 07:36:295608 " is not renderable. It maybe non-power-of-2 and have"
5609 " incompatible texture filtering or is not"
5610 " 'texture complete'");
[email protected]3916c97e2010-02-25 03:20:505611 }
5612 }
5613 // else: should this be an error?
5614 }
5615 }
[email protected]e56131d22013-07-28 16:14:115616 return !textures_set;
[email protected]3916c97e2010-02-25 03:20:505617}
5618
5619void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
[email protected]7cd76fd2013-06-02 21:11:115620 DCHECK(state_.current_program.get());
[email protected]ed9f9cd2013-02-27 21:12:355621 const Program::SamplerIndices& sampler_indices =
[email protected]7cd76fd2013-06-02 21:11:115622 state_.current_program->sampler_indices();
[email protected]3916c97e2010-02-25 03:20:505623 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:355624 const Program::UniformInfo* uniform_info =
[email protected]e259eb412012-10-13 05:47:245625 state_.current_program->GetUniformInfo(sampler_indices[ii]);
[email protected]3916c97e2010-02-25 03:20:505626 DCHECK(uniform_info);
5627 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5628 GLuint texture_unit_index = uniform_info->texture_units[jj];
[email protected]1868a342012-11-07 15:56:025629 if (texture_unit_index < state_.texture_units.size()) {
[email protected]e259eb412012-10-13 05:47:245630 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
[email protected]7cd76fd2013-06-02 21:11:115631 TextureRef* texture_ref =
5632 uniform_info->type == GL_SAMPLER_2D
5633 ? texture_unit.bound_texture_2d.get()
5634 : texture_unit.bound_texture_cube_map.get();
[email protected]370eaf12013-05-18 09:19:495635 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
[email protected]3916c97e2010-02-25 03:20:505636 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
[email protected]370eaf12013-05-18 09:19:495637 // Get the texture_ref info that was previously bound here.
[email protected]7cd76fd2013-06-02 21:11:115638 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
5639 ? texture_unit.bound_texture_2d.get()
5640 : texture_unit.bound_texture_cube_map.get();
[email protected]3916c97e2010-02-25 03:20:505641 glBindTexture(texture_unit.bind_target,
[email protected]370eaf12013-05-18 09:19:495642 texture_ref ? texture_ref->service_id() : 0);
[email protected]3916c97e2010-02-25 03:20:505643 }
5644 }
5645 }
5646 }
5647 // Set the active texture back to whatever the user had it as.
[email protected]e259eb412012-10-13 05:47:245648 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
[email protected]07f54fcc2009-12-22 02:46:305649}
5650
[email protected]0d6bfdc2011-11-02 01:32:205651bool GLES2DecoderImpl::ClearUnclearedTextures() {
5652 // Only check if there are some uncleared textures.
5653 if (!texture_manager()->HaveUnsafeTextures()) {
5654 return true;
5655 }
5656
5657 // 1: Check all textures we are about to render with.
[email protected]7cd76fd2013-06-02 21:11:115658 if (state_.current_program.get()) {
[email protected]ed9f9cd2013-02-27 21:12:355659 const Program::SamplerIndices& sampler_indices =
[email protected]7cd76fd2013-06-02 21:11:115660 state_.current_program->sampler_indices();
[email protected]0d6bfdc2011-11-02 01:32:205661 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
[email protected]ed9f9cd2013-02-27 21:12:355662 const Program::UniformInfo* uniform_info =
[email protected]e259eb412012-10-13 05:47:245663 state_.current_program->GetUniformInfo(sampler_indices[ii]);
[email protected]0d6bfdc2011-11-02 01:32:205664 DCHECK(uniform_info);
5665 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
5666 GLuint texture_unit_index = uniform_info->texture_units[jj];
[email protected]1868a342012-11-07 15:56:025667 if (texture_unit_index < state_.texture_units.size()) {
[email protected]e259eb412012-10-13 05:47:245668 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
[email protected]370eaf12013-05-18 09:19:495669 TextureRef* texture_ref =
[email protected]cadac622013-06-11 16:46:365670 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
[email protected]370eaf12013-05-18 09:19:495671 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
5672 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
[email protected]0d6bfdc2011-11-02 01:32:205673 return false;
5674 }
5675 }
5676 }
5677 }
5678 }
5679 }
5680 return true;
5681}
5682
[email protected]c6aef902012-02-14 03:31:425683bool GLES2DecoderImpl::IsDrawValid(
[email protected]ad84a3a2012-06-08 21:42:435684 const char* function_name, GLuint max_vertex_accessed, GLsizei primcount) {
[email protected]689fa1c52010-06-09 18:35:035685 // NOTE: We specifically do not check current_program->IsValid() because
5686 // it could never be invalid since glUseProgram would have failed. While
5687 // glLinkProgram could later mark the program as invalid the previous
5688 // valid program will still function if it is still the current program.
[email protected]7cd76fd2013-06-02 21:11:115689 if (!state_.current_program.get()) {
[email protected]3916c97e2010-02-25 03:20:505690 // The program does not exist.
5691 // But GL says no ERROR.
[email protected]ab09b612013-03-11 22:11:515692 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
[email protected]3916c97e2010-02-25 03:20:505693 return false;
5694 }
[email protected]c6aef902012-02-14 03:31:425695
[email protected]7cd76fd2013-06-02 21:11:115696 return state_.vertex_attrib_manager
5697 ->ValidateBindings(function_name,
5698 this,
5699 feature_info_.get(),
5700 state_.current_program.get(),
5701 max_vertex_accessed,
5702 primcount);
[email protected]b1122982010-05-17 23:04:245703}
5704
[email protected]c13e1da62011-09-09 21:48:305705bool GLES2DecoderImpl::SimulateAttrib0(
[email protected]ad84a3a2012-06-08 21:42:435706 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
[email protected]c13e1da62011-09-09 21:48:305707 DCHECK(simulated);
5708 *simulated = false;
5709
[email protected]876f6fee2010-08-02 23:10:325710 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
[email protected]c13e1da62011-09-09 21:48:305711 return true;
[email protected]876f6fee2010-08-02 23:10:325712
[email protected]ac77603c72013-03-08 13:52:065713 const VertexAttrib* attrib =
[email protected]ed9f9cd2013-02-27 21:12:355714 state_.vertex_attrib_manager->GetVertexAttrib(0);
[email protected]b1122982010-05-17 23:04:245715 // If it's enabled or it's not used then we don't need to do anything.
[email protected]e259eb412012-10-13 05:47:245716 bool attrib_0_used =
5717 state_.current_program->GetAttribInfoByLocation(0) != NULL;
[email protected]ac77603c72013-03-08 13:52:065718 if (attrib->enabled() && attrib_0_used) {
[email protected]c13e1da62011-09-09 21:48:305719 return true;
[email protected]b1122982010-05-17 23:04:245720 }
5721
[email protected]b1122982010-05-17 23:04:245722 // Make a buffer with a single repeated vec4 value enough to
5723 // simulate the constant value that is supposed to be here.
5724 // This is required to emulate GLES2 on GL.
[email protected]c13e1da62011-09-09 21:48:305725 GLuint num_vertices = max_vertex_accessed + 1;
[email protected]3aad1a32012-09-07 20:54:475726 uint32 size_needed = 0;
[email protected]c13e1da62011-09-09 21:48:305727
5728 if (num_vertices == 0 ||
[email protected]3aad1a32012-09-07 20:54:475729 !SafeMultiplyUint32(num_vertices, sizeof(Vec4), &size_needed) ||
[email protected]c13e1da62011-09-09 21:48:305730 size_needed > 0x7FFFFFFFU) {
[email protected]ab09b612013-03-11 22:11:515731 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c13e1da62011-09-09 21:48:305732 return false;
5733 }
5734
[email protected]ab09b612013-03-11 22:11:515735 LOCAL_PERFORMANCE_WARNING(
[email protected]0f8afe82012-05-14 23:43:015736 "Attribute 0 is disabled. This has signficant performance penalty");
5737
[email protected]ab09b612013-03-11 22:11:515738 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
[email protected]c13e1da62011-09-09 21:48:305739 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
5740
[email protected]8f0b86c2f2012-04-10 05:48:285741 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
5742 if (new_buffer) {
[email protected]fc753442011-02-04 19:49:495743 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305744 GLenum error = glGetError();
5745 if (error != GL_NO_ERROR) {
[email protected]ab09b612013-03-11 22:11:515746 LOCAL_SET_GL_ERROR(
5747 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c13e1da62011-09-09 21:48:305748 return false;
5749 }
[email protected]fc753442011-02-04 19:49:495750 }
[email protected]af6380962012-11-29 23:24:135751
5752 const Vec4& value = state_.attrib_values[0];
[email protected]8f0b86c2f2012-04-10 05:48:285753 if (new_buffer ||
5754 (attrib_0_used &&
5755 (!attrib_0_buffer_matches_value_ ||
[email protected]af6380962012-11-29 23:24:135756 (value.v[0] != attrib_0_value_.v[0] ||
5757 value.v[1] != attrib_0_value_.v[1] ||
5758 value.v[2] != attrib_0_value_.v[2] ||
5759 value.v[3] != attrib_0_value_.v[3])))) {
5760 std::vector<Vec4> temp(num_vertices, value);
[email protected]fc753442011-02-04 19:49:495761 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
5762 attrib_0_buffer_matches_value_ = true;
[email protected]af6380962012-11-29 23:24:135763 attrib_0_value_ = value;
[email protected]b1122982010-05-17 23:04:245764 attrib_0_size_ = size_needed;
5765 }
5766
5767 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5768
[email protected]ac77603c72013-03-08 13:52:065769 if (attrib->divisor())
[email protected]c6aef902012-02-14 03:31:425770 glVertexAttribDivisorANGLE(0, 0);
5771
[email protected]c13e1da62011-09-09 21:48:305772 *simulated = true;
[email protected]b1122982010-05-17 23:04:245773 return true;
[email protected]b1122982010-05-17 23:04:245774}
5775
[email protected]ac77603c72013-03-08 13:52:065776void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib_index) {
5777 const VertexAttrib* attrib =
5778 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
5779 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
5780 Buffer* buffer = attrib->buffer();
[email protected]b10492f2013-03-08 05:24:075781 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
[email protected]b1122982010-05-17 23:04:245782 glVertexAttribPointer(
[email protected]ac77603c72013-03-08 13:52:065783 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
5784 attrib->gl_stride(), ptr);
5785 if (attrib->divisor())
5786 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
[email protected]e259eb412012-10-13 05:47:245787 glBindBuffer(
5788 GL_ARRAY_BUFFER,
[email protected]7cd76fd2013-06-02 21:11:115789 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
5790 : 0);
[email protected]43410e92012-04-20 17:06:285791
[email protected]265f8992012-07-20 01:03:145792 // Never touch vertex attribute 0's state (in particular, never
5793 // disable it) when running on desktop GL because it will never be
5794 // re-enabled.
[email protected]ac77603c72013-03-08 13:52:065795 if (attrib_index != 0 ||
[email protected]265f8992012-07-20 01:03:145796 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
[email protected]ac77603c72013-03-08 13:52:065797 if (attrib->enabled()) {
5798 glEnableVertexAttribArray(attrib_index);
[email protected]265f8992012-07-20 01:03:145799 } else {
[email protected]ac77603c72013-03-08 13:52:065800 glDisableVertexAttribArray(attrib_index);
[email protected]265f8992012-07-20 01:03:145801 }
[email protected]43410e92012-04-20 17:06:285802 }
[email protected]b1122982010-05-17 23:04:245803}
[email protected]07f54fcc2009-12-22 02:46:305804
[email protected]8fbedc02010-11-18 18:43:405805bool GLES2DecoderImpl::SimulateFixedAttribs(
[email protected]ad84a3a2012-06-08 21:42:435806 const char* function_name,
[email protected]c6aef902012-02-14 03:31:425807 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
[email protected]8fbedc02010-11-18 18:43:405808 DCHECK(simulated);
5809 *simulated = false;
5810 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
5811 return true;
5812
[email protected]e259eb412012-10-13 05:47:245813 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
[email protected]8fbedc02010-11-18 18:43:405814 return true;
5815 }
5816
[email protected]ab09b612013-03-11 22:11:515817 LOCAL_PERFORMANCE_WARNING(
[email protected]0f8afe82012-05-14 23:43:015818 "GL_FIXED attributes have a signficant performance penalty");
5819
[email protected]8fbedc02010-11-18 18:43:405820 // NOTE: we could be smart and try to check if a buffer is used
5821 // twice in 2 different attribs, find the overlapping parts and therefore
5822 // duplicate the minimum amount of data but this whole code path is not meant
5823 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
5824 // tests so we just add to the buffer attrib used.
5825
[email protected]c13e1da62011-09-09 21:48:305826 GLuint elements_needed = 0;
[email protected]ac77603c72013-03-08 13:52:065827 const VertexAttribManager::VertexAttribList& enabled_attribs =
5828 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
5829 for (VertexAttribManager::VertexAttribList::const_iterator it =
5830 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
5831 const VertexAttrib* attrib = *it;
[email protected]ed9f9cd2013-02-27 21:12:355832 const Program::VertexAttrib* attrib_info =
[email protected]ac77603c72013-03-08 13:52:065833 state_.current_program->GetAttribInfoByLocation(attrib->index());
5834 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
5835 max_vertex_accessed);
[email protected]c6aef902012-02-14 03:31:425836 GLuint num_vertices = max_accessed + 1;
5837 if (num_vertices == 0) {
[email protected]ab09b612013-03-11 22:11:515838 LOCAL_SET_GL_ERROR(
5839 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c6aef902012-02-14 03:31:425840 return false;
5841 }
[email protected]8fbedc02010-11-18 18:43:405842 if (attrib_info &&
[email protected]ac77603c72013-03-08 13:52:065843 attrib->CanAccess(max_accessed) &&
5844 attrib->type() == GL_FIXED) {
[email protected]3aad1a32012-09-07 20:54:475845 uint32 elements_used = 0;
[email protected]ac77603c72013-03-08 13:52:065846 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
[email protected]3aad1a32012-09-07 20:54:475847 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
[email protected]ab09b612013-03-11 22:11:515848 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:435849 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]8fbedc02010-11-18 18:43:405850 return false;
5851 }
5852 }
5853 }
5854
[email protected]3aad1a32012-09-07 20:54:475855 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
5856 uint32 size_needed = 0;
5857 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
[email protected]c13e1da62011-09-09 21:48:305858 size_needed > 0x7FFFFFFFU) {
[email protected]ab09b612013-03-11 22:11:515859 LOCAL_SET_GL_ERROR(
5860 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]8fbedc02010-11-18 18:43:405861 return false;
5862 }
5863
[email protected]ab09b612013-03-11 22:11:515864 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
[email protected]8fbedc02010-11-18 18:43:405865
5866 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
[email protected]c13e1da62011-09-09 21:48:305867 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
[email protected]8fbedc02010-11-18 18:43:405868 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
[email protected]c13e1da62011-09-09 21:48:305869 GLenum error = glGetError();
5870 if (error != GL_NO_ERROR) {
[email protected]ab09b612013-03-11 22:11:515871 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:435872 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
[email protected]c13e1da62011-09-09 21:48:305873 return false;
5874 }
[email protected]8fbedc02010-11-18 18:43:405875 }
5876
5877 // Copy the elements and convert to float
5878 GLintptr offset = 0;
[email protected]ac77603c72013-03-08 13:52:065879 for (VertexAttribManager::VertexAttribList::const_iterator it =
5880 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
5881 const VertexAttrib* attrib = *it;
[email protected]ed9f9cd2013-02-27 21:12:355882 const Program::VertexAttrib* attrib_info =
[email protected]ac77603c72013-03-08 13:52:065883 state_.current_program->GetAttribInfoByLocation(attrib->index());
5884 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
[email protected]c6aef902012-02-14 03:31:425885 max_vertex_accessed);
5886 GLuint num_vertices = max_accessed + 1;
5887 if (num_vertices == 0) {
[email protected]ab09b612013-03-11 22:11:515888 LOCAL_SET_GL_ERROR(
5889 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
[email protected]c6aef902012-02-14 03:31:425890 return false;
5891 }
[email protected]8fbedc02010-11-18 18:43:405892 if (attrib_info &&
[email protected]ac77603c72013-03-08 13:52:065893 attrib->CanAccess(max_accessed) &&
5894 attrib->type() == GL_FIXED) {
5895 int num_elements = attrib->size() * kSizeOfFloat;
[email protected]8fbedc02010-11-18 18:43:405896 int size = num_elements * num_vertices;
[email protected]40d90a22013-04-09 03:39:555897 scoped_ptr<float[]> data(new float[size]);
[email protected]8fbedc02010-11-18 18:43:405898 const int32* src = reinterpret_cast<const int32 *>(
[email protected]ac77603c72013-03-08 13:52:065899 attrib->buffer()->GetRange(attrib->offset(), size));
[email protected]8fbedc02010-11-18 18:43:405900 const int32* end = src + num_elements;
5901 float* dst = data.get();
5902 while (src != end) {
5903 *dst++ = static_cast<float>(*src++) / 65536.0f;
5904 }
5905 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
5906 glVertexAttribPointer(
[email protected]ac77603c72013-03-08 13:52:065907 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
[email protected]8fbedc02010-11-18 18:43:405908 reinterpret_cast<GLvoid*>(offset));
5909 offset += size;
5910 }
5911 }
5912 *simulated = true;
5913 return true;
5914}
5915
5916void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
5917 // There's no need to call glVertexAttribPointer because we shadow all the
5918 // settings and passing GL_FIXED to it will not work.
[email protected]e259eb412012-10-13 05:47:245919 glBindBuffer(
5920 GL_ARRAY_BUFFER,
[email protected]7cd76fd2013-06-02 21:11:115921 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
5922 : 0);
[email protected]8fbedc02010-11-18 18:43:405923}
5924
[email protected]ad84a3a2012-06-08 21:42:435925error::Error GLES2DecoderImpl::DoDrawArrays(
5926 const char* function_name,
5927 bool instanced,
5928 GLenum mode,
5929 GLint first,
5930 GLsizei count,
5931 GLsizei primcount) {
[email protected]a7266a92012-06-28 02:11:085932 if (ShouldDeferDraws())
5933 return error::kDeferCommandUntilLater;
[email protected]38d139d2011-07-14 00:38:435934 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]ab09b612013-03-11 22:11:515935 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
[email protected]38d139d2011-07-14 00:38:435936 return error::kNoError;
5937 }
5938 if (count < 0) {
[email protected]ab09b612013-03-11 22:11:515939 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
[email protected]38d139d2011-07-14 00:38:435940 return error::kNoError;
5941 }
[email protected]c6aef902012-02-14 03:31:425942 if (primcount < 0) {
[email protected]ab09b612013-03-11 22:11:515943 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
[email protected]c6aef902012-02-14 03:31:425944 return error::kNoError;
5945 }
[email protected]ad84a3a2012-06-08 21:42:435946 if (!CheckBoundFramebuffersValid(function_name)) {
[email protected]38d139d2011-07-14 00:38:435947 return error::kNoError;
5948 }
5949 // We have to check this here because the prototype for glDrawArrays
5950 // is GLint not GLsizei.
5951 if (first < 0) {
[email protected]ab09b612013-03-11 22:11:515952 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
[email protected]38d139d2011-07-14 00:38:435953 return error::kNoError;
5954 }
5955
[email protected]c6aef902012-02-14 03:31:425956 if (count == 0 || (instanced && primcount == 0)) {
[email protected]ab09b612013-03-11 22:11:515957 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
[email protected]38d139d2011-07-14 00:38:435958 return error::kNoError;
5959 }
5960
5961 GLuint max_vertex_accessed = first + count - 1;
[email protected]ad84a3a2012-06-08 21:42:435962 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:205963 if (!ClearUnclearedTextures()) {
[email protected]ab09b612013-03-11 22:11:515964 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
[email protected]0d6bfdc2011-11-02 01:32:205965 return error::kNoError;
5966 }
[email protected]c13e1da62011-09-09 21:48:305967 bool simulated_attrib_0 = false;
[email protected]ad84a3a2012-06-08 21:42:435968 if (!SimulateAttrib0(
5969 function_name, max_vertex_accessed, &simulated_attrib_0)) {
[email protected]c13e1da62011-09-09 21:48:305970 return error::kNoError;
5971 }
[email protected]38d139d2011-07-14 00:38:435972 bool simulated_fixed_attribs = false;
[email protected]ad84a3a2012-06-08 21:42:435973 if (SimulateFixedAttribs(
5974 function_name, max_vertex_accessed, &simulated_fixed_attribs,
5975 primcount)) {
[email protected]e56131d22013-07-28 16:14:115976 bool textures_set = !PrepareTexturesForRender();
[email protected]38d139d2011-07-14 00:38:435977 ApplyDirtyState();
[email protected]c6aef902012-02-14 03:31:425978 if (!instanced) {
5979 glDrawArrays(mode, first, count);
5980 } else {
5981 glDrawArraysInstancedANGLE(mode, first, count, primcount);
5982 }
[email protected]22e3f552012-03-13 01:54:195983 ProcessPendingQueries();
[email protected]38d139d2011-07-14 00:38:435984 if (textures_set) {
5985 RestoreStateForNonRenderableTextures();
5986 }
5987 if (simulated_fixed_attribs) {
5988 RestoreStateForSimulatedFixedAttribs();
5989 }
5990 }
5991 if (simulated_attrib_0) {
[email protected]43410e92012-04-20 17:06:285992 RestoreStateForAttrib(0);
[email protected]38d139d2011-07-14 00:38:435993 }
[email protected]38d139d2011-07-14 00:38:435994 }
5995 return error::kNoError;
5996}
5997
[email protected]c6aef902012-02-14 03:31:425998error::Error GLES2DecoderImpl::HandleDrawArrays(
[email protected]ed9f9cd2013-02-27 21:12:355999 uint32 immediate_data_size, const cmds::DrawArrays& c) {
[email protected]ad84a3a2012-06-08 21:42:436000 return DoDrawArrays("glDrawArrays",
6001 false,
[email protected]c6aef902012-02-14 03:31:426002 static_cast<GLenum>(c.mode),
6003 static_cast<GLint>(c.first),
6004 static_cast<GLsizei>(c.count),
6005 0);
6006}
6007
6008error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
[email protected]ed9f9cd2013-02-27 21:12:356009 uint32 immediate_data_size, const cmds::DrawArraysInstancedANGLE& c) {
[email protected]62e155e2012-10-23 22:43:156010 if (!features().angle_instanced_arrays) {
[email protected]ab09b612013-03-11 22:11:516011 LOCAL_SET_GL_ERROR(
6012 GL_INVALID_OPERATION,
6013 "glDrawArraysInstancedANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:426014 return error::kNoError;
6015 }
[email protected]ad84a3a2012-06-08 21:42:436016 return DoDrawArrays("glDrawArraysIntancedANGLE",
6017 true,
[email protected]c6aef902012-02-14 03:31:426018 static_cast<GLenum>(c.mode),
6019 static_cast<GLint>(c.first),
6020 static_cast<GLsizei>(c.count),
6021 static_cast<GLsizei>(c.primcount));
6022}
6023
[email protected]ad84a3a2012-06-08 21:42:436024error::Error GLES2DecoderImpl::DoDrawElements(
6025 const char* function_name,
6026 bool instanced,
6027 GLenum mode,
6028 GLsizei count,
6029 GLenum type,
6030 int32 offset,
6031 GLsizei primcount) {
[email protected]a7266a92012-06-28 02:11:086032 if (ShouldDeferDraws())
6033 return error::kDeferCommandUntilLater;
[email protected]e259eb412012-10-13 05:47:246034 if (!state_.vertex_attrib_manager->element_array_buffer()) {
[email protected]ab09b612013-03-11 22:11:516035 LOCAL_SET_GL_ERROR(
6036 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
[email protected]8eee29c2010-04-29 03:38:296037 return error::kNoError;
6038 }
6039
[email protected]8eee29c2010-04-29 03:38:296040 if (count < 0) {
[email protected]ab09b612013-03-11 22:11:516041 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
[email protected]8eee29c2010-04-29 03:38:296042 return error::kNoError;
6043 }
6044 if (offset < 0) {
[email protected]ab09b612013-03-11 22:11:516045 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
[email protected]8eee29c2010-04-29 03:38:296046 return error::kNoError;
6047 }
[email protected]9438b012010-06-15 22:55:056048 if (!validators_->draw_mode.IsValid(mode)) {
[email protected]ab09b612013-03-11 22:11:516049 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
[email protected]8eee29c2010-04-29 03:38:296050 return error::kNoError;
6051 }
[email protected]9438b012010-06-15 22:55:056052 if (!validators_->index_type.IsValid(type)) {
[email protected]ab09b612013-03-11 22:11:516053 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
[email protected]8eee29c2010-04-29 03:38:296054 return error::kNoError;
6055 }
[email protected]c6aef902012-02-14 03:31:426056 if (primcount < 0) {
[email protected]ab09b612013-03-11 22:11:516057 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
[email protected]c6aef902012-02-14 03:31:426058 return error::kNoError;
6059 }
[email protected]8eee29c2010-04-29 03:38:296060
[email protected]ad84a3a2012-06-08 21:42:436061 if (!CheckBoundFramebuffersValid(function_name)) {
[email protected]3a03a8f2011-03-19 00:51:276062 return error::kNoError;
6063 }
6064
[email protected]c6aef902012-02-14 03:31:426065 if (count == 0 || (instanced && primcount == 0)) {
[email protected]6c788fb72010-08-26 02:16:316066 return error::kNoError;
6067 }
6068
[email protected]8eee29c2010-04-29 03:38:296069 GLuint max_vertex_accessed;
[email protected]17cfbe0e2013-03-07 01:26:086070 Buffer* element_array_buffer =
6071 state_.vertex_attrib_manager->element_array_buffer();
6072
6073 if (!element_array_buffer->GetMaxValueForRange(
6074 offset, count, type, &max_vertex_accessed)) {
[email protected]ab09b612013-03-11 22:11:516075 LOCAL_SET_GL_ERROR(
6076 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
[email protected]8eee29c2010-04-29 03:38:296077 return error::kNoError;
6078 }
6079
[email protected]ad84a3a2012-06-08 21:42:436080 if (IsDrawValid(function_name, max_vertex_accessed, primcount)) {
[email protected]0d6bfdc2011-11-02 01:32:206081 if (!ClearUnclearedTextures()) {
[email protected]ab09b612013-03-11 22:11:516082 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
[email protected]0d6bfdc2011-11-02 01:32:206083 return error::kNoError;
6084 }
[email protected]c13e1da62011-09-09 21:48:306085 bool simulated_attrib_0 = false;
[email protected]ad84a3a2012-06-08 21:42:436086 if (!SimulateAttrib0(
6087 function_name, max_vertex_accessed, &simulated_attrib_0)) {
[email protected]c13e1da62011-09-09 21:48:306088 return error::kNoError;
6089 }
[email protected]8fbedc02010-11-18 18:43:406090 bool simulated_fixed_attribs = false;
[email protected]ad84a3a2012-06-08 21:42:436091 if (SimulateFixedAttribs(
6092 function_name, max_vertex_accessed, &simulated_fixed_attribs,
6093 primcount)) {
[email protected]e56131d22013-07-28 16:14:116094 bool textures_set = !PrepareTexturesForRender();
[email protected]297ca1c2011-06-20 23:08:466095 ApplyDirtyState();
[email protected]17cfbe0e2013-03-07 01:26:086096 // TODO(gman): Refactor to hide these details in BufferManager or
6097 // VertexAttribManager.
[email protected]8fbedc02010-11-18 18:43:406098 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
[email protected]17cfbe0e2013-03-07 01:26:086099 bool used_client_side_array = false;
6100 if (element_array_buffer->IsClientSideArray()) {
6101 used_client_side_array = true;
6102 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6103 indices = element_array_buffer->GetRange(offset, 0);
6104 }
6105
[email protected]c6aef902012-02-14 03:31:426106 if (!instanced) {
6107 glDrawElements(mode, count, type, indices);
6108 } else {
6109 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
6110 }
[email protected]17cfbe0e2013-03-07 01:26:086111
6112 if (used_client_side_array) {
6113 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
6114 element_array_buffer->service_id());
6115 }
6116
[email protected]22e3f552012-03-13 01:54:196117 ProcessPendingQueries();
[email protected]8fbedc02010-11-18 18:43:406118 if (textures_set) {
6119 RestoreStateForNonRenderableTextures();
6120 }
6121 if (simulated_fixed_attribs) {
6122 RestoreStateForSimulatedFixedAttribs();
6123 }
[email protected]ba3176a2009-12-16 18:19:466124 }
[email protected]b1122982010-05-17 23:04:246125 if (simulated_attrib_0) {
[email protected]43410e92012-04-20 17:06:286126 RestoreStateForAttrib(0);
[email protected]b1122982010-05-17 23:04:246127 }
[email protected]96449d2c2009-11-25 00:01:326128 }
[email protected]f7a64ee2010-02-01 22:24:146129 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326130}
6131
[email protected]c6aef902012-02-14 03:31:426132error::Error GLES2DecoderImpl::HandleDrawElements(
[email protected]ed9f9cd2013-02-27 21:12:356133 uint32 immediate_data_size, const cmds::DrawElements& c) {
[email protected]ad84a3a2012-06-08 21:42:436134 return DoDrawElements("glDrawElements",
6135 false,
[email protected]c6aef902012-02-14 03:31:426136 static_cast<GLenum>(c.mode),
6137 static_cast<GLsizei>(c.count),
6138 static_cast<GLenum>(c.type),
6139 static_cast<int32>(c.index_offset),
6140 0);
6141}
6142
6143error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
[email protected]ed9f9cd2013-02-27 21:12:356144 uint32 immediate_data_size, const cmds::DrawElementsInstancedANGLE& c) {
[email protected]62e155e2012-10-23 22:43:156145 if (!features().angle_instanced_arrays) {
[email protected]ab09b612013-03-11 22:11:516146 LOCAL_SET_GL_ERROR(
6147 GL_INVALID_OPERATION,
6148 "glDrawElementsInstancedANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:426149 return error::kNoError;
6150 }
[email protected]ad84a3a2012-06-08 21:42:436151 return DoDrawElements("glDrawElementsInstancedANGLE",
6152 true,
[email protected]c6aef902012-02-14 03:31:426153 static_cast<GLenum>(c.mode),
6154 static_cast<GLsizei>(c.count),
6155 static_cast<GLenum>(c.type),
6156 static_cast<int32>(c.index_offset),
6157 static_cast<GLsizei>(c.primcount));
6158}
6159
[email protected]269200b12010-11-18 22:53:066160GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
[email protected]29a9eb52010-04-13 09:04:236161 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
6162 GLuint max_vertex_accessed = 0;
[email protected]b10492f2013-03-08 05:24:076163 Buffer* buffer = GetBuffer(buffer_id);
6164 if (!buffer) {
[email protected]ae51d192010-04-27 00:48:036165 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]ab09b612013-03-11 22:11:516166 LOCAL_SET_GL_ERROR(
6167 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
[email protected]29a9eb52010-04-13 09:04:236168 } else {
[email protected]b10492f2013-03-08 05:24:076169 if (!buffer->GetMaxValueForRange(
6170 offset, count, type, &max_vertex_accessed)) {
[email protected]ae51d192010-04-27 00:48:036171 // TODO(gman): Should this be a GL error or a command buffer error?
[email protected]ab09b612013-03-11 22:11:516172 LOCAL_SET_GL_ERROR(
[email protected]269200b12010-11-18 22:53:066173 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:436174 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
[email protected]29a9eb52010-04-13 09:04:236175 }
6176 }
6177 return max_vertex_accessed;
6178}
6179
[email protected]96449d2c2009-11-25 00:01:326180// Calls glShaderSource for the various versions of the ShaderSource command.
6181// Assumes that data / data_size points to a piece of memory that is in range
6182// of whatever context it came from (shared memory, immediate memory, bucket
6183// memory.)
[email protected]45bf5152010-02-12 00:11:316184error::Error GLES2DecoderImpl::ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:036185 GLuint client_id, const char* data, uint32 data_size) {
[email protected]258a3313f2011-10-18 20:13:576186 std::string str(data, data + data_size);
[email protected]df37b9932013-03-08 05:21:426187 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
6188 if (!shader) {
[email protected]45bf5152010-02-12 00:11:316189 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326190 }
[email protected]45bf5152010-02-12 00:11:316191 // Note: We don't actually call glShaderSource here. We wait until
6192 // the call to glCompileShader.
[email protected]df37b9932013-03-08 05:21:426193 shader->UpdateSource(str.c_str());
[email protected]f7a64ee2010-02-01 22:24:146194 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326195}
6196
[email protected]f7a64ee2010-02-01 22:24:146197error::Error GLES2DecoderImpl::HandleShaderSource(
[email protected]ed9f9cd2013-02-27 21:12:356198 uint32 immediate_data_size, const cmds::ShaderSource& c) {
[email protected]96449d2c2009-11-25 00:01:326199 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:316200 const char* data = GetSharedMemoryAs<const char*>(
[email protected]96449d2c2009-11-25 00:01:326201 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]ba3176a2009-12-16 18:19:466202 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146203 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:326204 }
[email protected]ae51d192010-04-27 00:48:036205 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]96449d2c2009-11-25 00:01:326206}
6207
[email protected]f7a64ee2010-02-01 22:24:146208error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
[email protected]ed9f9cd2013-02-27 21:12:356209 uint32 immediate_data_size, const cmds::ShaderSourceImmediate& c) {
[email protected]96449d2c2009-11-25 00:01:326210 uint32 data_size = c.data_size;
[email protected]45bf5152010-02-12 00:11:316211 const char* data = GetImmediateDataAs<const char*>(
[email protected]07f54fcc2009-12-22 02:46:306212 c, data_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:466213 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:146214 return error::kOutOfBounds;
[email protected]96449d2c2009-11-25 00:01:326215 }
[email protected]ae51d192010-04-27 00:48:036216 return ShaderSourceHelper(c.shader, data, data_size);
[email protected]45bf5152010-02-12 00:11:316217}
6218
[email protected]558847a2010-03-24 07:02:546219error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
[email protected]ed9f9cd2013-02-27 21:12:356220 uint32 immediate_data_size, const cmds::ShaderSourceBucket& c) {
[email protected]558847a2010-03-24 07:02:546221 Bucket* bucket = GetBucket(c.data_bucket_id);
6222 if (!bucket || bucket->size() == 0) {
6223 return error::kInvalidArguments;
6224 }
6225 return ShaderSourceHelper(
[email protected]ae51d192010-04-27 00:48:036226 c.shader, bucket->GetDataAs<const char*>(0, bucket->size() - 1),
[email protected]558847a2010-03-24 07:02:546227 bucket->size() - 1);
6228}
6229
[email protected]ae51d192010-04-27 00:48:036230void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
[email protected]43ed3a72012-05-30 22:55:386231 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
[email protected]df37b9932013-03-08 05:21:426232 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
6233 if (!shader) {
[email protected]45bf5152010-02-12 00:11:316234 return;
6235 }
[email protected]f57bb282010-11-12 00:51:346236 ShaderTranslator* translator = NULL;
[email protected]b1d2dcb2010-05-17 19:24:186237 if (use_shader_translator_) {
[email protected]df37b9932013-03-08 05:21:426238 translator = shader->shader_type() == GL_VERTEX_SHADER ?
[email protected]a550584e2010-09-17 18:01:456239 vertex_translator_.get() : fragment_translator_.get();
[email protected]de17df392010-04-23 21:09:416240 }
[email protected]de17df392010-04-23 21:09:416241
[email protected]7cd76fd2013-06-02 21:11:116242 program_manager()->DoCompileShader(shader, translator, feature_info_.get());
[email protected]45bf5152010-02-12 00:11:316243};
6244
[email protected]ddd968b82010-03-02 00:44:296245void GLES2DecoderImpl::DoGetShaderiv(
[email protected]df37b9932013-03-08 05:21:426246 GLuint shader_id, GLenum pname, GLint* params) {
6247 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
6248 if (!shader) {
[email protected]ddd968b82010-03-02 00:44:296249 return;
6250 }
[email protected]8f1ccdac2010-05-19 21:01:486251 switch (pname) {
6252 case GL_SHADER_SOURCE_LENGTH:
[email protected]df37b9932013-03-08 05:21:426253 *params = shader->source() ? shader->source()->size() + 1 : 0;
[email protected]8f1ccdac2010-05-19 21:01:486254 return;
6255 case GL_COMPILE_STATUS:
[email protected]df37b9932013-03-08 05:21:426256 *params = compile_shader_always_succeeds_ ? true : shader->IsValid();
[email protected]e5186162010-06-14 18:54:416257 return;
[email protected]8f1ccdac2010-05-19 21:01:486258 case GL_INFO_LOG_LENGTH:
[email protected]df37b9932013-03-08 05:21:426259 *params = shader->log_info() ? shader->log_info()->size() + 1 : 0;
[email protected]e5186162010-06-14 18:54:416260 return;
[email protected]d6a53e42011-10-05 00:09:366261 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
[email protected]df37b9932013-03-08 05:21:426262 *params = shader->translated_source() ?
6263 shader->translated_source()->size() + 1 : 0;
[email protected]d6a53e42011-10-05 00:09:366264 return;
[email protected]8f1ccdac2010-05-19 21:01:486265 default:
6266 break;
[email protected]ddd968b82010-03-02 00:44:296267 }
[email protected]df37b9932013-03-08 05:21:426268 glGetShaderiv(shader->service_id(), pname, params);
[email protected]ddd968b82010-03-02 00:44:296269}
6270
[email protected]ae51d192010-04-27 00:48:036271error::Error GLES2DecoderImpl::HandleGetShaderSource(
[email protected]ed9f9cd2013-02-27 21:12:356272 uint32 immediate_data_size, const cmds::GetShaderSource& c) {
[email protected]df37b9932013-03-08 05:21:426273 GLuint shader_id = c.shader;
[email protected]ae51d192010-04-27 00:48:036274 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6275 Bucket* bucket = CreateBucket(bucket_id);
[email protected]df37b9932013-03-08 05:21:426276 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
6277 if (!shader || !shader->source()) {
[email protected]8eee29c2010-04-29 03:38:296278 bucket->SetSize(0);
[email protected]8eee29c2010-04-29 03:38:296279 return error::kNoError;
6280 }
[email protected]df37b9932013-03-08 05:21:426281 bucket->SetFromString(shader->source()->c_str());
[email protected]ae51d192010-04-27 00:48:036282 return error::kNoError;
6283}
6284
[email protected]d6a53e42011-10-05 00:09:366285error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
6286 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:356287 const cmds::GetTranslatedShaderSourceANGLE& c) {
[email protected]df37b9932013-03-08 05:21:426288 GLuint shader_id = c.shader;
[email protected]d6a53e42011-10-05 00:09:366289 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6290 Bucket* bucket = CreateBucket(bucket_id);
[email protected]df37b9932013-03-08 05:21:426291 Shader* shader = GetShaderInfoNotProgram(
6292 shader_id, "glTranslatedGetShaderSourceANGLE");
6293 if (!shader) {
[email protected]d6a53e42011-10-05 00:09:366294 bucket->SetSize(0);
6295 return error::kNoError;
6296 }
[email protected]d6a53e42011-10-05 00:09:366297
[email protected]df37b9932013-03-08 05:21:426298 bucket->SetFromString(shader->translated_source() ?
6299 shader->translated_source()->c_str() : NULL);
[email protected]d6a53e42011-10-05 00:09:366300 return error::kNoError;
6301}
6302
[email protected]ae51d192010-04-27 00:48:036303error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
[email protected]ed9f9cd2013-02-27 21:12:356304 uint32 immediate_data_size, const cmds::GetProgramInfoLog& c) {
[email protected]df37b9932013-03-08 05:21:426305 GLuint program_id = c.program;
[email protected]6b8cf1a2010-05-06 16:13:586306 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6307 Bucket* bucket = CreateBucket(bucket_id);
[email protected]df37b9932013-03-08 05:21:426308 Program* program = GetProgramInfoNotShader(
6309 program_id, "glGetProgramInfoLog");
6310 if (!program || !program->log_info()) {
[email protected]9a14ae612011-08-08 17:51:466311 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:036312 return error::kNoError;
[email protected]45bf5152010-02-12 00:11:316313 }
[email protected]df37b9932013-03-08 05:21:426314 bucket->SetFromString(program->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:036315 return error::kNoError;
6316}
6317
6318error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
[email protected]ed9f9cd2013-02-27 21:12:356319 uint32 immediate_data_size, const cmds::GetShaderInfoLog& c) {
[email protected]df37b9932013-03-08 05:21:426320 GLuint shader_id = c.shader;
[email protected]6b8cf1a2010-05-06 16:13:586321 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
6322 Bucket* bucket = CreateBucket(bucket_id);
[email protected]df37b9932013-03-08 05:21:426323 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
6324 if (!shader || !shader->log_info()) {
[email protected]9a14ae612011-08-08 17:51:466325 bucket->SetFromString("");
[email protected]ae51d192010-04-27 00:48:036326 return error::kNoError;
6327 }
[email protected]df37b9932013-03-08 05:21:426328 bucket->SetFromString(shader->log_info()->c_str());
[email protected]ae51d192010-04-27 00:48:036329 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326330}
6331
[email protected]d058bca2012-11-26 10:27:266332bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
6333 return state_.GetEnabled(cap);
6334}
6335
[email protected]1958e0e2010-04-22 05:17:156336bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
[email protected]16ccec12013-02-28 03:40:216337 const Buffer* buffer = GetBuffer(client_id);
[email protected]a0b78dc2011-11-11 10:43:106338 return buffer && buffer->IsValid() && !buffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156339}
6340
6341bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
[email protected]ed9f9cd2013-02-27 21:12:356342 const Framebuffer* framebuffer =
6343 GetFramebuffer(client_id);
[email protected]a0b78dc2011-11-11 10:43:106344 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156345}
6346
6347bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:366348 // IsProgram is true for programs as soon as they are created, until they are
6349 // deleted and no longer in use.
[email protected]ed9f9cd2013-02-27 21:12:356350 const Program* program = GetProgram(client_id);
[email protected]a0b78dc2011-11-11 10:43:106351 return program != NULL && !program->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156352}
6353
6354bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
[email protected]ed9f9cd2013-02-27 21:12:356355 const Renderbuffer* renderbuffer =
6356 GetRenderbuffer(client_id);
[email protected]a0b78dc2011-11-11 10:43:106357 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156358}
6359
6360bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
[email protected]06c8b082011-01-05 18:00:366361 // IsShader is true for shaders as soon as they are created, until they
6362 // are deleted and not attached to any programs.
[email protected]ed9f9cd2013-02-27 21:12:356363 const Shader* shader = GetShader(client_id);
[email protected]a0b78dc2011-11-11 10:43:106364 return shader != NULL && !shader->IsDeleted();
[email protected]1958e0e2010-04-22 05:17:156365}
6366
6367bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
[email protected]370eaf12013-05-18 09:19:496368 const TextureRef* texture_ref = GetTexture(client_id);
6369 return texture_ref && texture_ref->texture()->IsValid();
[email protected]ae51d192010-04-27 00:48:036370}
6371
6372void GLES2DecoderImpl::DoAttachShader(
6373 GLuint program_client_id, GLint shader_client_id) {
[email protected]df37b9932013-03-08 05:21:426374 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:586375 program_client_id, "glAttachShader");
[email protected]df37b9932013-03-08 05:21:426376 if (!program) {
[email protected]ae51d192010-04-27 00:48:036377 return;
[email protected]1958e0e2010-04-22 05:17:156378 }
[email protected]df37b9932013-03-08 05:21:426379 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
6380 if (!shader) {
[email protected]ae51d192010-04-27 00:48:036381 return;
6382 }
[email protected]df37b9932013-03-08 05:21:426383 if (!program->AttachShader(shader_manager(), shader)) {
[email protected]ab09b612013-03-11 22:11:516384 LOCAL_SET_GL_ERROR(
6385 GL_INVALID_OPERATION,
6386 "glAttachShader",
6387 "can not attach more than one shader of the same type.");
[email protected]fb96c8e2010-08-12 04:10:316388 return;
6389 }
[email protected]df37b9932013-03-08 05:21:426390 glAttachShader(program->service_id(), shader->service_id());
[email protected]ae51d192010-04-27 00:48:036391}
6392
6393void GLES2DecoderImpl::DoDetachShader(
6394 GLuint program_client_id, GLint shader_client_id) {
[email protected]df37b9932013-03-08 05:21:426395 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:586396 program_client_id, "glDetachShader");
[email protected]df37b9932013-03-08 05:21:426397 if (!program) {
[email protected]ae51d192010-04-27 00:48:036398 return;
6399 }
[email protected]df37b9932013-03-08 05:21:426400 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
6401 if (!shader) {
[email protected]ae51d192010-04-27 00:48:036402 return;
6403 }
[email protected]df37b9932013-03-08 05:21:426404 if (!program->DetachShader(shader_manager(), shader)) {
[email protected]ab09b612013-03-11 22:11:516405 LOCAL_SET_GL_ERROR(
6406 GL_INVALID_OPERATION,
6407 "glDetachShader", "shader not attached to program");
[email protected]9a0ccd42011-03-16 23:58:226408 return;
6409 }
[email protected]df37b9932013-03-08 05:21:426410 glDetachShader(program->service_id(), shader->service_id());
[email protected]ae51d192010-04-27 00:48:036411}
6412
6413void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
[email protected]df37b9932013-03-08 05:21:426414 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:586415 program_client_id, "glValidateProgram");
[email protected]df37b9932013-03-08 05:21:426416 if (!program) {
[email protected]ae51d192010-04-27 00:48:036417 return;
6418 }
[email protected]df37b9932013-03-08 05:21:426419 program->Validate();
[email protected]1958e0e2010-04-22 05:17:156420}
6421
[email protected]ac77603c72013-03-08 13:52:066422void GLES2DecoderImpl::GetVertexAttribHelper(
6423 const VertexAttrib* attrib, GLenum pname, GLint* params) {
[email protected]b1122982010-05-17 23:04:246424 switch (pname) {
6425 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
[email protected]ac77603c72013-03-08 13:52:066426 Buffer* buffer = attrib->buffer();
[email protected]b1122982010-05-17 23:04:246427 if (buffer && !buffer->IsDeleted()) {
6428 GLuint client_id;
6429 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
6430 *params = client_id;
6431 }
6432 break;
6433 }
6434 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
[email protected]ac77603c72013-03-08 13:52:066435 *params = attrib->enabled();
[email protected]b1122982010-05-17 23:04:246436 break;
6437 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
[email protected]ac77603c72013-03-08 13:52:066438 *params = attrib->size();
[email protected]b1122982010-05-17 23:04:246439 break;
6440 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
[email protected]ac77603c72013-03-08 13:52:066441 *params = attrib->gl_stride();
[email protected]b1122982010-05-17 23:04:246442 break;
6443 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
[email protected]ac77603c72013-03-08 13:52:066444 *params = attrib->type();
[email protected]b1122982010-05-17 23:04:246445 break;
6446 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
[email protected]ac77603c72013-03-08 13:52:066447 *params = attrib->normalized();
[email protected]b1122982010-05-17 23:04:246448 break;
[email protected]c6aef902012-02-14 03:31:426449 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
[email protected]ac77603c72013-03-08 13:52:066450 *params = attrib->divisor();
[email protected]c6aef902012-02-14 03:31:426451 break;
[email protected]ac77603c72013-03-08 13:52:066452 default:
6453 NOTREACHED();
6454 break;
6455 }
6456}
6457
6458void GLES2DecoderImpl::DoGetVertexAttribfv(
6459 GLuint index, GLenum pname, GLfloat* params) {
6460 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6461 if (!attrib) {
[email protected]ab09b612013-03-11 22:11:516462 LOCAL_SET_GL_ERROR(
6463 GL_INVALID_VALUE, "glGetVertexAttribfv", "index out of range");
[email protected]ac77603c72013-03-08 13:52:066464 return;
6465 }
6466 switch (pname) {
6467 case GL_CURRENT_VERTEX_ATTRIB: {
6468 const Vec4& value = state_.attrib_values[index];
6469 params[0] = value.v[0];
6470 params[1] = value.v[1];
6471 params[2] = value.v[2];
6472 params[3] = value.v[3];
6473 break;
6474 }
6475 default: {
6476 GLint value = 0;
6477 GetVertexAttribHelper(attrib, pname, &value);
6478 *params = static_cast<GLfloat>(value);
6479 break;
6480 }
6481 }
6482}
6483
6484void GLES2DecoderImpl::DoGetVertexAttribiv(
6485 GLuint index, GLenum pname, GLint* params) {
6486 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
6487 if (!attrib) {
[email protected]ab09b612013-03-11 22:11:516488 LOCAL_SET_GL_ERROR(
6489 GL_INVALID_VALUE, "glGetVertexAttribiv", "index out of range");
[email protected]ac77603c72013-03-08 13:52:066490 return;
6491 }
6492 switch (pname) {
[email protected]af6380962012-11-29 23:24:136493 case GL_CURRENT_VERTEX_ATTRIB: {
6494 const Vec4& value = state_.attrib_values[index];
6495 params[0] = static_cast<GLint>(value.v[0]);
6496 params[1] = static_cast<GLint>(value.v[1]);
6497 params[2] = static_cast<GLint>(value.v[2]);
6498 params[3] = static_cast<GLint>(value.v[3]);
[email protected]b1122982010-05-17 23:04:246499 break;
[email protected]af6380962012-11-29 23:24:136500 }
[email protected]b1122982010-05-17 23:04:246501 default:
[email protected]ac77603c72013-03-08 13:52:066502 GetVertexAttribHelper(attrib, pname, params);
[email protected]b1122982010-05-17 23:04:246503 break;
6504 }
6505}
6506
[email protected]af6380962012-11-29 23:24:136507bool GLES2DecoderImpl::SetVertexAttribValue(
6508 const char* function_name, GLuint index, const GLfloat* value) {
6509 if (index >= state_.attrib_values.size()) {
[email protected]ab09b612013-03-11 22:11:516510 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
[email protected]af6380962012-11-29 23:24:136511 return false;
[email protected]b1122982010-05-17 23:04:246512 }
[email protected]af6380962012-11-29 23:24:136513 Vec4& v = state_.attrib_values[index];
6514 v.v[0] = value[0];
6515 v.v[1] = value[1];
6516 v.v[2] = value[2];
6517 v.v[3] = value[3];
6518 return true;
6519}
6520
6521void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
6522 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
6523 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
6524 glVertexAttrib1f(index, v0);
6525 }
[email protected]b1122982010-05-17 23:04:246526}
6527
6528void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
[email protected]af6380962012-11-29 23:24:136529 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
6530 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
6531 glVertexAttrib2f(index, v0, v1);
[email protected]b1122982010-05-17 23:04:246532 }
[email protected]b1122982010-05-17 23:04:246533}
6534
6535void GLES2DecoderImpl::DoVertexAttrib3f(
6536 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
[email protected]af6380962012-11-29 23:24:136537 GLfloat v[4] = { v0, v1, v2, 1.0f, };
6538 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
6539 glVertexAttrib3f(index, v0, v1, v2);
[email protected]b1122982010-05-17 23:04:246540 }
[email protected]b1122982010-05-17 23:04:246541}
6542
6543void GLES2DecoderImpl::DoVertexAttrib4f(
6544 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
[email protected]af6380962012-11-29 23:24:136545 GLfloat v[4] = { v0, v1, v2, v3, };
6546 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
6547 glVertexAttrib4f(index, v0, v1, v2, v3);
[email protected]b1122982010-05-17 23:04:246548 }
[email protected]b1122982010-05-17 23:04:246549}
6550
6551void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136552 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
6553 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
6554 glVertexAttrib1fv(index, v);
[email protected]b1122982010-05-17 23:04:246555 }
[email protected]b1122982010-05-17 23:04:246556}
6557
6558void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136559 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
6560 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
6561 glVertexAttrib2fv(index, v);
[email protected]b1122982010-05-17 23:04:246562 }
[email protected]b1122982010-05-17 23:04:246563}
6564
6565void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136566 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
6567 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
6568 glVertexAttrib3fv(index, v);
[email protected]b1122982010-05-17 23:04:246569 }
[email protected]b1122982010-05-17 23:04:246570}
6571
6572void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
[email protected]af6380962012-11-29 23:24:136573 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
6574 glVertexAttrib4fv(index, v);
[email protected]b1122982010-05-17 23:04:246575 }
[email protected]b1122982010-05-17 23:04:246576}
6577
[email protected]f7a64ee2010-02-01 22:24:146578error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
[email protected]ed9f9cd2013-02-27 21:12:356579 uint32 immediate_data_size, const cmds::VertexAttribPointer& c) {
[email protected]944b62f32012-09-27 02:20:466580
[email protected]7cd76fd2013-06-02 21:11:116581 if (!state_.bound_array_buffer.get() ||
6582 state_.bound_array_buffer->IsDeleted()) {
6583 if (state_.vertex_attrib_manager.get() ==
6584 default_vertex_attrib_manager_.get()) {
[email protected]ab09b612013-03-11 22:11:516585 LOCAL_SET_GL_ERROR(
6586 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
[email protected]944b62f32012-09-27 02:20:466587 return error::kNoError;
6588 } else if (c.offset != 0) {
[email protected]ab09b612013-03-11 22:11:516589 LOCAL_SET_GL_ERROR(
6590 GL_INVALID_VALUE,
6591 "glVertexAttribPointer", "client side arrays are not allowed");
[email protected]944b62f32012-09-27 02:20:466592 return error::kNoError;
6593 }
[email protected]96449d2c2009-11-25 00:01:326594 }
[email protected]8eee29c2010-04-29 03:38:296595
6596 GLuint indx = c.indx;
6597 GLint size = c.size;
6598 GLenum type = c.type;
6599 GLboolean normalized = c.normalized;
6600 GLsizei stride = c.stride;
6601 GLsizei offset = c.offset;
6602 const void* ptr = reinterpret_cast<const void*>(offset);
[email protected]9438b012010-06-15 22:55:056603 if (!validators_->vertex_attrib_type.IsValid(type)) {
[email protected]ab09b612013-03-11 22:11:516604 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
[email protected]8eee29c2010-04-29 03:38:296605 return error::kNoError;
6606 }
[email protected]9438b012010-06-15 22:55:056607 if (!validators_->vertex_attrib_size.IsValid(size)) {
[email protected]ab09b612013-03-11 22:11:516608 LOCAL_SET_GL_ERROR(
6609 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
[email protected]8eee29c2010-04-29 03:38:296610 return error::kNoError;
6611 }
6612 if (indx >= group_->max_vertex_attribs()) {
[email protected]ab09b612013-03-11 22:11:516613 LOCAL_SET_GL_ERROR(
6614 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
[email protected]8eee29c2010-04-29 03:38:296615 return error::kNoError;
6616 }
6617 if (stride < 0) {
[email protected]ab09b612013-03-11 22:11:516618 LOCAL_SET_GL_ERROR(
6619 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
[email protected]8eee29c2010-04-29 03:38:296620 return error::kNoError;
6621 }
6622 if (stride > 255) {
[email protected]ab09b612013-03-11 22:11:516623 LOCAL_SET_GL_ERROR(
6624 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
[email protected]8eee29c2010-04-29 03:38:296625 return error::kNoError;
6626 }
6627 if (offset < 0) {
[email protected]ab09b612013-03-11 22:11:516628 LOCAL_SET_GL_ERROR(
6629 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
[email protected]8eee29c2010-04-29 03:38:296630 return error::kNoError;
6631 }
6632 GLsizei component_size =
[email protected]ff81c192011-01-07 23:04:316633 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
[email protected]8eee29c2010-04-29 03:38:296634 if (offset % component_size > 0) {
[email protected]ab09b612013-03-11 22:11:516635 LOCAL_SET_GL_ERROR(
6636 GL_INVALID_OPERATION,
6637 "glVertexAttribPointer", "offset not valid for type");
[email protected]ff81c192011-01-07 23:04:316638 return error::kNoError;
6639 }
6640 if (stride % component_size > 0) {
[email protected]ab09b612013-03-11 22:11:516641 LOCAL_SET_GL_ERROR(
6642 GL_INVALID_OPERATION,
6643 "glVertexAttribPointer", "stride not valid for type");
[email protected]8eee29c2010-04-29 03:38:296644 return error::kNoError;
6645 }
[email protected]7cd76fd2013-06-02 21:11:116646 state_.vertex_attrib_manager
6647 ->SetAttribInfo(indx,
6648 state_.bound_array_buffer.get(),
6649 size,
6650 type,
6651 normalized,
6652 stride,
6653 stride != 0 ? stride : component_size * size,
6654 offset);
[email protected]8fbedc02010-11-18 18:43:406655 if (type != GL_FIXED) {
6656 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
6657 }
[email protected]f7a64ee2010-02-01 22:24:146658 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326659}
6660
[email protected]43410e92012-04-20 17:06:286661void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
6662 GLsizei height) {
[email protected]e259eb412012-10-13 05:47:246663 state_.viewport_x = x;
6664 state_.viewport_y = y;
[email protected]1868a342012-11-07 15:56:026665 state_.viewport_width = std::min(width, viewport_max_width_);
6666 state_.viewport_height = std::min(height, viewport_max_height_);
[email protected]43410e92012-04-20 17:06:286667 glViewport(x, y, width, height);
6668}
6669
[email protected]c6aef902012-02-14 03:31:426670error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
[email protected]ed9f9cd2013-02-27 21:12:356671 uint32 immediate_data_size, const cmds::VertexAttribDivisorANGLE& c) {
[email protected]62e155e2012-10-23 22:43:156672 if (!features().angle_instanced_arrays) {
[email protected]ab09b612013-03-11 22:11:516673 LOCAL_SET_GL_ERROR(
6674 GL_INVALID_OPERATION,
6675 "glVertexAttribDivisorANGLE", "function not available");
[email protected]c6aef902012-02-14 03:31:426676 }
6677 GLuint index = c.index;
6678 GLuint divisor = c.divisor;
6679 if (index >= group_->max_vertex_attribs()) {
[email protected]ab09b612013-03-11 22:11:516680 LOCAL_SET_GL_ERROR(
6681 GL_INVALID_VALUE,
6682 "glVertexAttribDivisorANGLE", "index out of range");
[email protected]c6aef902012-02-14 03:31:426683 return error::kNoError;
6684 }
6685
[email protected]e259eb412012-10-13 05:47:246686 state_.vertex_attrib_manager->SetDivisor(
[email protected]c6aef902012-02-14 03:31:426687 index,
6688 divisor);
6689 glVertexAttribDivisorANGLE(index, divisor);
6690 return error::kNoError;
6691}
6692
[email protected]5a36dc132013-07-23 23:17:556693void GLES2DecoderImpl::FinishReadPixels(
6694 const cmds::ReadPixels& c,
6695 GLuint buffer) {
6696 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
6697 GLsizei width = c.width;
6698 GLsizei height = c.height;
6699 GLenum format = c.format;
6700 GLenum type = c.type;
6701 typedef cmds::ReadPixels::Result Result;
6702 uint32 pixels_size;
6703 Result* result = NULL;
6704 if (c.result_shm_id != 0) {
6705 result = GetSharedMemoryAs<Result*>(
6706 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6707 if (!result) {
6708 if (buffer != 0) {
6709 glDeleteBuffersARB(1, &buffer);
6710 }
6711 return;
6712 }
6713 }
6714 GLES2Util::ComputeImageDataSizes(
6715 width, height, format, type, state_.pack_alignment, &pixels_size,
6716 NULL, NULL);
6717 void* pixels = GetSharedMemoryAs<void*>(
6718 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
6719 if (!pixels) {
6720 if (buffer != 0) {
6721 glDeleteBuffersARB(1, &buffer);
6722 }
6723 return;
6724 }
6725
6726 if (buffer != 0) {
6727 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
[email protected]e585f9e22013-08-27 02:50:336728 void* data;
6729 if (features().map_buffer_range) {
6730 data = glMapBufferRange(
6731 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
6732 } else {
6733 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
6734 }
[email protected]5a36dc132013-07-23 23:17:556735 memcpy(pixels, data, pixels_size);
6736 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
6737 // have to restore the state.
6738 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
6739 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
6740 glDeleteBuffersARB(1, &buffer);
6741 }
6742
6743 if (result != NULL) {
6744 *result = true;
6745 }
6746
6747 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
6748 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
6749 if ((channels_exist & 0x0008) == 0 &&
6750 workarounds().clear_alpha_in_readpixels) {
6751 // Set the alpha to 255 because some drivers are buggy in this regard.
6752 uint32 temp_size;
6753
6754 uint32 unpadded_row_size;
6755 uint32 padded_row_size;
6756 if (!GLES2Util::ComputeImageDataSizes(
6757 width, 2, format, type, state_.pack_alignment, &temp_size,
6758 &unpadded_row_size, &padded_row_size)) {
6759 return;
6760 }
6761 // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
6762 // of this implementation.
6763 if (type != GL_UNSIGNED_BYTE) {
6764 return;
6765 }
6766 switch (format) {
6767 case GL_RGBA:
6768 case GL_BGRA_EXT:
6769 case GL_ALPHA: {
6770 int offset = (format == GL_ALPHA) ? 0 : 3;
6771 int step = (format == GL_ALPHA) ? 1 : 4;
6772 uint8* dst = static_cast<uint8*>(pixels) + offset;
6773 for (GLint yy = 0; yy < height; ++yy) {
6774 uint8* end = dst + unpadded_row_size;
6775 for (uint8* d = dst; d < end; d += step) {
6776 *d = 255;
6777 }
6778 dst += padded_row_size;
6779 }
6780 break;
6781 }
6782 default:
6783 break;
6784 }
6785 }
6786}
6787
6788
[email protected]f7a64ee2010-02-01 22:24:146789error::Error GLES2DecoderImpl::HandleReadPixels(
[email protected]ed9f9cd2013-02-27 21:12:356790 uint32 immediate_data_size, const cmds::ReadPixels& c) {
[email protected]09e17272012-11-30 10:30:446791 if (ShouldDeferReads())
6792 return error::kDeferCommandUntilLater;
[email protected]612d2f82009-12-08 20:49:316793 GLint x = c.x;
6794 GLint y = c.y;
6795 GLsizei width = c.width;
6796 GLsizei height = c.height;
6797 GLenum format = c.format;
6798 GLenum type = c.type;
[email protected]5a36dc132013-07-23 23:17:556799 GLboolean async = c.async;
[email protected]57f223832010-03-19 01:57:566800 if (width < 0 || height < 0) {
[email protected]ab09b612013-03-11 22:11:516801 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
[email protected]57f223832010-03-19 01:57:566802 return error::kNoError;
6803 }
[email protected]ed9f9cd2013-02-27 21:12:356804 typedef cmds::ReadPixels::Result Result;
[email protected]a76b0052010-03-05 00:33:186805 uint32 pixels_size;
[email protected]3458a64a2012-04-10 17:39:346806 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:246807 width, height, format, type, state_.pack_alignment, &pixels_size,
6808 NULL, NULL)) {
[email protected]a76b0052010-03-05 00:33:186809 return error::kOutOfBounds;
6810 }
[email protected]612d2f82009-12-08 20:49:316811 void* pixels = GetSharedMemoryAs<void*>(
6812 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
[email protected]de43f082013-04-02 01:16:106813 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:146814 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:466815 }
[email protected]de43f082013-04-02 01:16:106816 Result* result = NULL;
6817 if (c.result_shm_id != 0) {
6818 result = GetSharedMemoryAs<Result*>(
6819 c.result_shm_id, c.result_shm_offset, sizeof(*result));
6820 if (!result) {
6821 return error::kOutOfBounds;
6822 }
6823 }
[email protected]a51788e2010-02-24 21:54:256824
[email protected]9438b012010-06-15 22:55:056825 if (!validators_->read_pixel_format.IsValid(format)) {
[email protected]ab09b612013-03-11 22:11:516826 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
[email protected]8eee29c2010-04-29 03:38:296827 return error::kNoError;
6828 }
[email protected]9438b012010-06-15 22:55:056829 if (!validators_->pixel_type.IsValid(type)) {
[email protected]ab09b612013-03-11 22:11:516830 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
[email protected]d2cf0a2d2010-02-25 21:36:126831 return error::kNoError;
6832 }
[email protected]57f223832010-03-19 01:57:566833 if (width == 0 || height == 0) {
6834 return error::kNoError;
6835 }
6836
[email protected]57f223832010-03-19 01:57:566837 // Get the size of the current fbo or backbuffer.
[email protected]8e3e0662010-08-23 18:46:306838 gfx::Size max_size = GetBoundReadFrameBufferSize();
[email protected]57f223832010-03-19 01:57:566839
[email protected]3aad1a32012-09-07 20:54:476840 int32 max_x;
6841 int32 max_y;
6842 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
[email protected]ab09b612013-03-11 22:11:516843 LOCAL_SET_GL_ERROR(
6844 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]f7a64ee2010-02-01 22:24:146845 return error::kNoError;
[email protected]612d2f82009-12-08 20:49:316846 }
[email protected]57f223832010-03-19 01:57:566847
[email protected]0d6bfdc2011-11-02 01:32:206848 if (!CheckBoundFramebuffersValid("glReadPixels")) {
6849 return error::kNoError;
6850 }
6851
[email protected]ab09b612013-03-11 22:11:516852 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixel");
[email protected]a0b78dc2011-11-11 10:43:106853
6854 ScopedResolvedFrameBufferBinder binder(this, false, true);
6855
[email protected]d37231fa2010-04-09 21:16:026856 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
[email protected]57f223832010-03-19 01:57:566857 // The user requested an out of range area. Get the results 1 line
6858 // at a time.
6859 uint32 temp_size;
[email protected]3458a64a2012-04-10 17:39:346860 uint32 unpadded_row_size;
6861 uint32 padded_row_size;
6862 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:246863 width, 2, format, type, state_.pack_alignment, &temp_size,
[email protected]3458a64a2012-04-10 17:39:346864 &unpadded_row_size, &padded_row_size)) {
[email protected]ab09b612013-03-11 22:11:516865 LOCAL_SET_GL_ERROR(
6866 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]57f223832010-03-19 01:57:566867 return error::kNoError;
6868 }
6869
6870 GLint dest_x_offset = std::max(-x, 0);
6871 uint32 dest_row_offset;
[email protected]3458a64a2012-04-10 17:39:346872 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:246873 dest_x_offset, 1, format, type, state_.pack_alignment, &dest_row_offset,
6874 NULL, NULL)) {
[email protected]ab09b612013-03-11 22:11:516875 LOCAL_SET_GL_ERROR(
6876 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
[email protected]57f223832010-03-19 01:57:566877 return error::kNoError;
6878 }
6879
6880 // Copy each row into the larger dest rect.
6881 int8* dst = static_cast<int8*>(pixels);
6882 GLint read_x = std::max(0, x);
[email protected]d37231fa2010-04-09 21:16:026883 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
[email protected]57f223832010-03-19 01:57:566884 GLint read_width = read_end_x - read_x;
6885 for (GLint yy = 0; yy < height; ++yy) {
6886 GLint ry = y + yy;
6887
6888 // Clear the row.
6889 memset(dst, 0, unpadded_row_size);
6890
6891 // If the row is in range, copy it.
[email protected]d37231fa2010-04-09 21:16:026892 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
[email protected]57f223832010-03-19 01:57:566893 glReadPixels(
6894 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
6895 }
6896 dst += padded_row_size;
6897 }
6898 } else {
[email protected]5a36dc132013-07-23 23:17:556899 if (async && features().use_async_readpixels) {
6900 GLuint buffer;
6901 glGenBuffersARB(1, &buffer);
6902 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
6903 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
6904 GLenum error = glGetError();
6905 if (error == GL_NO_ERROR) {
6906 glReadPixels(x, y, width, height, format, type, 0);
6907 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
6908 new FenceCallback()));
6909 WaitForReadPixels(base::Bind(
6910 &GLES2DecoderImpl::FinishReadPixels,
6911 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
6912 <GLES2DecoderImpl>(this),
6913 c, buffer));
6914 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
6915 return error::kNoError;
6916 }
6917 }
[email protected]57f223832010-03-19 01:57:566918 glReadPixels(x, y, width, height, format, type, pixels);
6919 }
[email protected]ab09b612013-03-11 22:11:516920 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
[email protected]a51788e2010-02-24 21:54:256921 if (error == GL_NO_ERROR) {
[email protected]de43f082013-04-02 01:16:106922 if (result != NULL) {
6923 *result = true;
6924 }
[email protected]5a36dc132013-07-23 23:17:556925 FinishReadPixels(c, 0);
[email protected]a51788e2010-02-24 21:54:256926 }
[email protected]4848b9f82011-03-10 18:37:566927
[email protected]f7a64ee2010-02-01 22:24:146928 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:326929}
6930
[email protected]f7a64ee2010-02-01 22:24:146931error::Error GLES2DecoderImpl::HandlePixelStorei(
[email protected]ed9f9cd2013-02-27 21:12:356932 uint32 immediate_data_size, const cmds::PixelStorei& c) {
[email protected]b9849abf2009-11-25 19:13:196933 GLenum pname = c.pname;
6934 GLenum param = c.param;
[email protected]9438b012010-06-15 22:55:056935 if (!validators_->pixel_store.IsValid(pname)) {
[email protected]ab09b612013-03-11 22:11:516936 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
[email protected]d2cf0a2d2010-02-25 21:36:126937 return error::kNoError;
6938 }
[email protected]222471d2011-11-30 18:06:396939 switch (pname) {
6940 case GL_PACK_ALIGNMENT:
6941 case GL_UNPACK_ALIGNMENT:
6942 if (!validators_->pixel_store_alignment.IsValid(param)) {
[email protected]ab09b612013-03-11 22:11:516943 LOCAL_SET_GL_ERROR(
6944 GL_INVALID_VALUE, "glPixelStore", "param GL_INVALID_VALUE");
[email protected]222471d2011-11-30 18:06:396945 return error::kNoError;
6946 }
[email protected]164d6d52012-05-05 00:55:036947 break;
[email protected]0a1e9ad2012-05-04 21:13:036948 case GL_UNPACK_FLIP_Y_CHROMIUM:
6949 unpack_flip_y_ = (param != 0);
6950 return error::kNoError;
6951 case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM:
6952 unpack_premultiply_alpha_ = (param != 0);
6953 return error::kNoError;
[email protected]6c75c712012-06-19 15:43:176954 case GL_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM:
6955 unpack_unpremultiply_alpha_ = (param != 0);
6956 return error::kNoError;
[email protected]222471d2011-11-30 18:06:396957 default:
6958 break;
[email protected]b9849abf2009-11-25 19:13:196959 }
6960 glPixelStorei(pname, param);
6961 switch (pname) {
[email protected]ad84a3a2012-06-08 21:42:436962 case GL_PACK_ALIGNMENT:
[email protected]e259eb412012-10-13 05:47:246963 state_.pack_alignment = param;
[email protected]ad84a3a2012-06-08 21:42:436964 break;
6965 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
[email protected]88a61bf2012-10-27 13:00:426966 state_.pack_reverse_row_order = (param != 0);
[email protected]ad84a3a2012-06-08 21:42:436967 break;
6968 case GL_UNPACK_ALIGNMENT:
[email protected]e259eb412012-10-13 05:47:246969 state_.unpack_alignment = param;
[email protected]ad84a3a2012-06-08 21:42:436970 break;
6971 default:
6972 // Validation should have prevented us from getting here.
6973 NOTREACHED();
6974 break;
[email protected]b9849abf2009-11-25 19:13:196975 }
[email protected]f7a64ee2010-02-01 22:24:146976 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:196977}
6978
[email protected]1c75a3702011-11-11 14:15:286979error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:356980 uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
[email protected]43ed3a72012-05-30 22:55:386981 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
[email protected]6f5fac9d12012-06-26 21:02:456982 if (!surface_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
[email protected]ab09b612013-03-11 22:11:516983 LOCAL_SET_GL_ERROR(
6984 GL_INVALID_OPERATION,
6985 "glPostSubBufferCHROMIUM", "command not supported by surface");
[email protected]1c75a3702011-11-11 14:15:286986 return error::kNoError;
6987 }
[email protected]7794d512012-04-17 20:36:496988 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height)) {
[email protected]1c75a3702011-11-11 14:15:286989 return error::kNoError;
[email protected]7794d512012-04-17 20:36:496990 } else {
6991 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
[email protected]1c75a3702011-11-11 14:15:286992 return error::kLostContext;
[email protected]7794d512012-04-17 20:36:496993 }
[email protected]1c75a3702011-11-11 14:15:286994}
6995
[email protected]558847a2010-03-24 07:02:546996error::Error GLES2DecoderImpl::GetAttribLocationHelper(
6997 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
6998 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:576999 if (!StringIsValidForGLES(name_str.c_str())) {
[email protected]ab09b612013-03-11 22:11:517000 LOCAL_SET_GL_ERROR(
7001 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:577002 return error::kNoError;
7003 }
[email protected]df37b9932013-03-08 05:21:427004 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:587005 client_id, "glGetAttribLocation");
[email protected]df37b9932013-03-08 05:21:427006 if (!program) {
[email protected]f7a64ee2010-02-01 22:24:147007 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197008 }
[email protected]df37b9932013-03-08 05:21:427009 if (!program->IsValid()) {
[email protected]ab09b612013-03-11 22:11:517010 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437011 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
[email protected]0bfd9882010-02-05 23:02:257012 return error::kNoError;
7013 }
[email protected]b9849abf2009-11-25 19:13:197014 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:547015 location_shm_id, location_shm_offset, sizeof(GLint));
7016 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:147017 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197018 }
[email protected]558847a2010-03-24 07:02:547019 // Require the client to init this incase the context is lost and we are no
7020 // longer executing commands.
7021 if (*location != -1) {
7022 return error::kGenericError;
7023 }
[email protected]df37b9932013-03-08 05:21:427024 *location = program->GetAttribLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:147025 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197026}
7027
[email protected]558847a2010-03-24 07:02:547028error::Error GLES2DecoderImpl::HandleGetAttribLocation(
[email protected]ed9f9cd2013-02-27 21:12:357029 uint32 immediate_data_size, const cmds::GetAttribLocation& c) {
[email protected]558847a2010-03-24 07:02:547030 uint32 name_size = c.data_size;
7031 const char* name = GetSharedMemoryAs<const char*>(
7032 c.name_shm_id, c.name_shm_offset, name_size);
7033 if (!name) {
7034 return error::kOutOfBounds;
7035 }
7036 String name_str(name, name_size);
7037 return GetAttribLocationHelper(
7038 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7039}
7040
[email protected]f7a64ee2010-02-01 22:24:147041error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
[email protected]ed9f9cd2013-02-27 21:12:357042 uint32 immediate_data_size, const cmds::GetAttribLocationImmediate& c) {
[email protected]558847a2010-03-24 07:02:547043 uint32 name_size = c.data_size;
7044 const char* name = GetImmediateDataAs<const char*>(
7045 c, name_size, immediate_data_size);
7046 if (!name) {
7047 return error::kOutOfBounds;
7048 }
7049 String name_str(name, name_size);
7050 return GetAttribLocationHelper(
7051 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7052}
7053
7054error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
[email protected]ed9f9cd2013-02-27 21:12:357055 uint32 immediate_data_size, const cmds::GetAttribLocationBucket& c) {
[email protected]558847a2010-03-24 07:02:547056 Bucket* bucket = GetBucket(c.name_bucket_id);
7057 if (!bucket) {
7058 return error::kInvalidArguments;
7059 }
7060 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:187061 if (!bucket->GetAsString(&name_str)) {
7062 return error::kInvalidArguments;
7063 }
[email protected]558847a2010-03-24 07:02:547064 return GetAttribLocationHelper(
7065 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7066}
7067
7068error::Error GLES2DecoderImpl::GetUniformLocationHelper(
7069 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
7070 const std::string& name_str) {
[email protected]258a3313f2011-10-18 20:13:577071 if (!StringIsValidForGLES(name_str.c_str())) {
[email protected]ab09b612013-03-11 22:11:517072 LOCAL_SET_GL_ERROR(
7073 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
[email protected]258a3313f2011-10-18 20:13:577074 return error::kNoError;
7075 }
[email protected]df37b9932013-03-08 05:21:427076 Program* program = GetProgramInfoNotShader(
[email protected]6b8cf1a2010-05-06 16:13:587077 client_id, "glUniformLocation");
[email protected]df37b9932013-03-08 05:21:427078 if (!program) {
[email protected]f7a64ee2010-02-01 22:24:147079 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197080 }
[email protected]df37b9932013-03-08 05:21:427081 if (!program->IsValid()) {
[email protected]ab09b612013-03-11 22:11:517082 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437083 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
[email protected]0bfd9882010-02-05 23:02:257084 return error::kNoError;
7085 }
[email protected]b9849abf2009-11-25 19:13:197086 GLint* location = GetSharedMemoryAs<GLint*>(
[email protected]558847a2010-03-24 07:02:547087 location_shm_id, location_shm_offset, sizeof(GLint));
7088 if (!location) {
[email protected]f7a64ee2010-02-01 22:24:147089 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197090 }
[email protected]558847a2010-03-24 07:02:547091 // Require the client to init this incase the context is lost an we are no
7092 // longer executing commands.
7093 if (*location != -1) {
7094 return error::kGenericError;
7095 }
[email protected]df37b9932013-03-08 05:21:427096 *location = program->GetUniformFakeLocation(name_str);
[email protected]f7a64ee2010-02-01 22:24:147097 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197098}
7099
[email protected]f7a64ee2010-02-01 22:24:147100error::Error GLES2DecoderImpl::HandleGetUniformLocation(
[email protected]ed9f9cd2013-02-27 21:12:357101 uint32 immediate_data_size, const cmds::GetUniformLocation& c) {
[email protected]b9849abf2009-11-25 19:13:197102 uint32 name_size = c.data_size;
7103 const char* name = GetSharedMemoryAs<const char*>(
7104 c.name_shm_id, c.name_shm_offset, name_size);
[email protected]558847a2010-03-24 07:02:547105 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:147106 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197107 }
7108 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:547109 return GetUniformLocationHelper(
7110 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:197111}
7112
[email protected]f7a64ee2010-02-01 22:24:147113error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
[email protected]ed9f9cd2013-02-27 21:12:357114 uint32 immediate_data_size, const cmds::GetUniformLocationImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:197115 uint32 name_size = c.data_size;
[email protected]07f54fcc2009-12-22 02:46:307116 const char* name = GetImmediateDataAs<const char*>(
7117 c, name_size, immediate_data_size);
[email protected]558847a2010-03-24 07:02:547118 if (!name) {
[email protected]f7a64ee2010-02-01 22:24:147119 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197120 }
7121 String name_str(name, name_size);
[email protected]558847a2010-03-24 07:02:547122 return GetUniformLocationHelper(
7123 c.program, c.location_shm_id, c.location_shm_offset, name_str);
7124}
7125
7126error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
[email protected]ed9f9cd2013-02-27 21:12:357127 uint32 immediate_data_size, const cmds::GetUniformLocationBucket& c) {
[email protected]558847a2010-03-24 07:02:547128 Bucket* bucket = GetBucket(c.name_bucket_id);
7129 if (!bucket) {
7130 return error::kInvalidArguments;
7131 }
7132 std::string name_str;
[email protected]b1d2dcb2010-05-17 19:24:187133 if (!bucket->GetAsString(&name_str)) {
7134 return error::kInvalidArguments;
7135 }
[email protected]558847a2010-03-24 07:02:547136 return GetUniformLocationHelper(
7137 c.program, c.location_shm_id, c.location_shm_offset, name_str);
[email protected]b9849abf2009-11-25 19:13:197138}
7139
[email protected]ddd968b82010-03-02 00:44:297140error::Error GLES2DecoderImpl::HandleGetString(
[email protected]ed9f9cd2013-02-27 21:12:357141 uint32 immediate_data_size, const cmds::GetString& c) {
[email protected]ddd968b82010-03-02 00:44:297142 GLenum name = static_cast<GLenum>(c.name);
[email protected]9438b012010-06-15 22:55:057143 if (!validators_->string_type.IsValid(name)) {
[email protected]ab09b612013-03-11 22:11:517144 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
[email protected]ddd968b82010-03-02 00:44:297145 return error::kNoError;
7146 }
[email protected]1958e0e2010-04-22 05:17:157147 const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
7148 const char* str = NULL;
[email protected]f0d74742011-10-03 16:31:047149 std::string extensions;
[email protected]1958e0e2010-04-22 05:17:157150 switch (name) {
7151 case GL_VERSION:
7152 str = "OpenGL ES 2.0 Chromium";
7153 break;
7154 case GL_SHADING_LANGUAGE_VERSION:
7155 str = "OpenGL ES GLSL ES 1.0 Chromium";
7156 break;
[email protected]32939602012-05-09 06:25:167157 case GL_RENDERER:
7158 str = "Chromium";
7159 break;
7160 case GL_VENDOR:
7161 str = "Chromium";
7162 break;
[email protected]1958e0e2010-04-22 05:17:157163 case GL_EXTENSIONS:
[email protected]f0d74742011-10-03 16:31:047164 {
[email protected]70dc60932013-06-04 03:33:497165 // For WebGL contexts, strip out the OES derivatives and
7166 // EXT frag depth extensions if they have not been enabled.
7167 if (force_webgl_glsl_validation_) {
[email protected]f0d74742011-10-03 16:31:047168 extensions = feature_info_->extensions();
[email protected]70dc60932013-06-04 03:33:497169 if (!derivatives_explicitly_enabled_) {
7170 size_t offset = extensions.find(kOESDerivativeExtension);
7171 if (std::string::npos != offset) {
[email protected]f16cc9f2013-06-14 01:04:097172 extensions.replace(offset, arraysize(kOESDerivativeExtension),
[email protected]70dc60932013-06-04 03:33:497173 std::string());
7174 }
7175 }
7176 if (!frag_depth_explicitly_enabled_) {
7177 size_t offset = extensions.find(kEXTFragDepthExtension);
7178 if (std::string::npos != offset) {
[email protected]f16cc9f2013-06-14 01:04:097179 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
[email protected]70dc60932013-06-04 03:33:497180 std::string());
7181 }
[email protected]f0d74742011-10-03 16:31:047182 }
[email protected]aff39ac82013-06-08 04:53:137183 if (!draw_buffers_explicitly_enabled_) {
7184 size_t offset = extensions.find(kEXTDrawBuffersExtension);
7185 if (std::string::npos != offset) {
[email protected]f16cc9f2013-06-14 01:04:097186 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
[email protected]aff39ac82013-06-08 04:53:137187 std::string());
7188 }
7189 }
[email protected]f0d74742011-10-03 16:31:047190 } else {
[email protected]6f5fac9d12012-06-26 21:02:457191 extensions = feature_info_->extensions().c_str();
[email protected]f0d74742011-10-03 16:31:047192 }
[email protected]6f5fac9d12012-06-26 21:02:457193 std::string surface_extensions = surface_->GetExtensions();
7194 if (!surface_extensions.empty())
7195 extensions += " " + surface_extensions;
7196 str = extensions.c_str();
[email protected]f0d74742011-10-03 16:31:047197 }
[email protected]1958e0e2010-04-22 05:17:157198 break;
7199 default:
7200 str = gl_str;
7201 break;
7202 }
[email protected]ddd968b82010-03-02 00:44:297203 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]1958e0e2010-04-22 05:17:157204 bucket->SetFromString(str);
[email protected]ddd968b82010-03-02 00:44:297205 return error::kNoError;
7206}
7207
[email protected]0c86dbf2010-03-05 08:14:117208error::Error GLES2DecoderImpl::HandleBufferData(
[email protected]ed9f9cd2013-02-27 21:12:357209 uint32 immediate_data_size, const cmds::BufferData& c) {
[email protected]0c86dbf2010-03-05 08:14:117210 GLenum target = static_cast<GLenum>(c.target);
7211 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
7212 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7213 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7214 GLenum usage = static_cast<GLenum>(c.usage);
7215 const void* data = NULL;
7216 if (data_shm_id != 0 || data_shm_offset != 0) {
7217 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
7218 if (!data) {
7219 return error::kOutOfBounds;
7220 }
7221 }
[email protected]0fbba3732013-07-17 15:40:137222 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
[email protected]f7a64ee2010-02-01 22:24:147223 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197224}
7225
[email protected]f7a64ee2010-02-01 22:24:147226error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
[email protected]ed9f9cd2013-02-27 21:12:357227 uint32 immediate_data_size, const cmds::BufferDataImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:197228 GLenum target = static_cast<GLenum>(c.target);
7229 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
[email protected]07f54fcc2009-12-22 02:46:307230 const void* data = GetImmediateDataAs<const void*>(
7231 c, size, immediate_data_size);
7232 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:147233 return error::kOutOfBounds;
[email protected]07f54fcc2009-12-22 02:46:307234 }
[email protected]b9849abf2009-11-25 19:13:197235 GLenum usage = static_cast<GLenum>(c.usage);
[email protected]0fbba3732013-07-17 15:40:137236 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
[email protected]0c86dbf2010-03-05 08:14:117237 return error::kNoError;
7238}
7239
7240void GLES2DecoderImpl::DoBufferSubData(
7241 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
[email protected]0fbba3732013-07-17 15:40:137242 // Just delegate it. Some validation is actually done before this.
7243 buffer_manager()->ValidateAndDoBufferSubData(
7244 &state_, target, offset, size, data);
[email protected]b9849abf2009-11-25 19:13:197245}
7246
[email protected]0d6bfdc2011-11-02 01:32:207247bool GLES2DecoderImpl::ClearLevel(
7248 unsigned service_id,
7249 unsigned bind_target,
7250 unsigned target,
7251 int level,
7252 unsigned format,
7253 unsigned type,
7254 int width,
[email protected]4502e6492011-12-14 19:39:157255 int height,
7256 bool is_texture_immutable) {
[email protected]81375742012-06-08 00:04:007257 uint32 channels = GLES2Util::GetChannelsForFormat(format);
7258 if (IsAngle() && (channels & GLES2Util::kDepth) != 0) {
7259 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
7260 // on depth formats.
7261 GLuint fb = 0;
7262 glGenFramebuffersEXT(1, &fb);
7263 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
7264
7265 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
7266 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
7267 GL_DEPTH_ATTACHMENT;
7268
7269 glFramebufferTexture2DEXT(
7270 GL_DRAW_FRAMEBUFFER_EXT, attachment, target, service_id, level);
7271 // ANGLE promises a depth only attachment ok.
7272 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
7273 GL_FRAMEBUFFER_COMPLETE) {
7274 return false;
7275 }
7276 glClearStencil(0);
7277 glStencilMask(-1);
7278 glClearDepth(1.0f);
7279 glDepthMask(true);
7280 glDisable(GL_SCISSOR_TEST);
7281 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
7282
7283 RestoreClearState();
7284
7285 glDeleteFramebuffersEXT(1, &fb);
[email protected]ed9f9cd2013-02-27 21:12:357286 Framebuffer* framebuffer =
[email protected]81375742012-06-08 00:04:007287 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
7288 GLuint fb_service_id =
7289 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
7290 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
7291 return true;
7292 }
7293
[email protected]45d15a62012-04-18 14:33:177294 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
7295
7296 uint32 size;
7297 uint32 padded_row_size;
[email protected]3458a64a2012-04-10 17:39:347298 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247299 width, height, format, type, state_.unpack_alignment, &size,
[email protected]45d15a62012-04-18 14:33:177300 NULL, &padded_row_size)) {
[email protected]0d6bfdc2011-11-02 01:32:207301 return false;
7302 }
[email protected]45d15a62012-04-18 14:33:177303
[email protected]a5d3dad2012-05-26 04:34:447304 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
7305
[email protected]45d15a62012-04-18 14:33:177306 int tile_height;
7307
7308 if (size > kMaxZeroSize) {
7309 if (kMaxZeroSize < padded_row_size) {
7310 // That'd be an awfully large texture.
7311 return false;
7312 }
7313 // We should never have a large total size with a zero row size.
7314 DCHECK_GT(padded_row_size, 0U);
7315 tile_height = kMaxZeroSize / padded_row_size;
7316 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247317 width, tile_height, format, type, state_.unpack_alignment, &size,
7318 NULL, NULL)) {
[email protected]45d15a62012-04-18 14:33:177319 return false;
7320 }
[email protected]4502e6492011-12-14 19:39:157321 } else {
[email protected]45d15a62012-04-18 14:33:177322 tile_height = height;
7323 }
7324
7325 // Assumes the size has already been checked.
[email protected]40d90a22013-04-09 03:39:557326 scoped_ptr<char[]> zero(new char[size]);
[email protected]45d15a62012-04-18 14:33:177327 memset(zero.get(), 0, size);
7328 glBindTexture(bind_target, service_id);
7329
7330 GLint y = 0;
7331 while (y < height) {
7332 GLint h = y + tile_height > height ? height - y : tile_height;
7333 if (is_texture_immutable || h != height) {
7334 glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get());
7335 } else {
[email protected]8f1d2aa2013-05-10 23:45:387336 glTexImage2D(
[email protected]45d15a62012-04-18 14:33:177337 target, level, format, width, h, 0, format, type, zero.get());
7338 }
7339 y += tile_height;
[email protected]4502e6492011-12-14 19:39:157340 }
[email protected]c986af502013-08-14 01:04:447341 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
7342 &state_, bind_target);
[email protected]02965c22013-03-09 02:40:077343 glBindTexture(bind_target, texture ? texture->service_id() : 0);
[email protected]0d6bfdc2011-11-02 01:32:207344 return true;
7345}
7346
[email protected]ad84a3a2012-06-08 21:42:437347namespace {
7348
7349const int kS3TCBlockWidth = 4;
7350const int kS3TCBlockHeight = 4;
7351const int kS3TCDXT1BlockSize = 8;
7352const int kS3TCDXT3AndDXT5BlockSize = 16;
[email protected]2d3765b2012-10-03 00:31:077353const int kETC1BlockWidth = 4;
7354const int kETC1BlockHeight = 4;
7355const int kETC1BlockSize = 8;
[email protected]ad84a3a2012-06-08 21:42:437356
7357bool IsValidDXTSize(GLint level, GLsizei size) {
[email protected]10b56de2012-07-14 02:09:517358 return (size == 1) ||
7359 (size == 2) || !(size % kS3TCBlockWidth);
[email protected]ad84a3a2012-06-08 21:42:437360}
7361
7362} // anonymous namespace.
7363
7364bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
7365 const char* function_name,
7366 GLsizei width, GLsizei height, GLenum format, size_t size) {
7367 unsigned int bytes_required = 0;
7368
7369 switch (format) {
7370 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7371 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: {
7372 int num_blocks_across =
7373 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7374 int num_blocks_down =
7375 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7376 int num_blocks = num_blocks_across * num_blocks_down;
7377 bytes_required = num_blocks * kS3TCDXT1BlockSize;
7378 break;
7379 }
7380 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7381 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7382 int num_blocks_across =
7383 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
7384 int num_blocks_down =
7385 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
7386 int num_blocks = num_blocks_across * num_blocks_down;
7387 bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
7388 break;
7389 }
[email protected]2d3765b2012-10-03 00:31:077390 case GL_ETC1_RGB8_OES: {
7391 int num_blocks_across =
7392 (width + kETC1BlockWidth - 1) / kETC1BlockWidth;
7393 int num_blocks_down =
7394 (height + kETC1BlockHeight - 1) / kETC1BlockHeight;
7395 int num_blocks = num_blocks_across * num_blocks_down;
7396 bytes_required = num_blocks * kETC1BlockSize;
7397 break;
7398 }
[email protected]ad84a3a2012-06-08 21:42:437399 default:
[email protected]ab09b612013-03-11 22:11:517400 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
[email protected]ad84a3a2012-06-08 21:42:437401 return false;
7402 }
7403
7404 if (size != bytes_required) {
[email protected]ab09b612013-03-11 22:11:517405 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437406 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
7407 return false;
7408 }
7409
7410 return true;
7411}
7412
7413bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
7414 const char* function_name,
7415 GLint level, GLsizei width, GLsizei height, GLenum format) {
7416 switch (format) {
7417 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7418 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7419 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7420 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7421 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
[email protected]ab09b612013-03-11 22:11:517422 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437423 GL_INVALID_OPERATION, function_name,
7424 "width or height invalid for level");
7425 return false;
7426 }
7427 return true;
7428 }
[email protected]2d3765b2012-10-03 00:31:077429 case GL_ETC1_RGB8_OES:
7430 if (width <= 0 || height <= 0) {
[email protected]ab09b612013-03-11 22:11:517431 LOCAL_SET_GL_ERROR(
[email protected]2d3765b2012-10-03 00:31:077432 GL_INVALID_OPERATION, function_name,
7433 "width or height invalid for level");
7434 return false;
7435 }
7436 return true;
[email protected]ad84a3a2012-06-08 21:42:437437 default:
7438 return false;
7439 }
7440}
7441
7442bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
7443 const char* function_name,
7444 GLenum target, GLint level, GLint xoffset, GLint yoffset,
7445 GLsizei width, GLsizei height, GLenum format,
[email protected]ed9f9cd2013-02-27 21:12:357446 Texture* texture) {
[email protected]ad84a3a2012-06-08 21:42:437447 if (xoffset < 0 || yoffset < 0) {
[email protected]ab09b612013-03-11 22:11:517448 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437449 GL_INVALID_VALUE, function_name, "xoffset or yoffset < 0");
7450 return false;
7451 }
7452
7453 switch (format) {
7454 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
7455 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
7456 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
7457 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
7458 const int kBlockWidth = 4;
7459 const int kBlockHeight = 4;
7460 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
[email protected]ab09b612013-03-11 22:11:517461 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437462 GL_INVALID_OPERATION, function_name,
7463 "xoffset or yoffset not multiple of 4");
7464 return false;
7465 }
7466 GLsizei tex_width = 0;
7467 GLsizei tex_height = 0;
7468 if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
7469 width - xoffset > tex_width ||
7470 height - yoffset > tex_height) {
[email protected]ab09b612013-03-11 22:11:517471 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437472 GL_INVALID_OPERATION, function_name, "dimensions out of range");
7473 return false;
7474 }
7475 return ValidateCompressedTexDimensions(
7476 function_name, level, width, height, format);
7477 }
[email protected]2d3765b2012-10-03 00:31:077478 case GL_ETC1_RGB8_OES: {
[email protected]ab09b612013-03-11 22:11:517479 LOCAL_SET_GL_ERROR(
[email protected]2d3765b2012-10-03 00:31:077480 GL_INVALID_OPERATION, function_name,
7481 "TexsubImage2d not supported for ECT1_RGB8_OES textures");
7482 return false;
7483 }
[email protected]ad84a3a2012-06-08 21:42:437484 default:
7485 return false;
7486 }
7487}
7488
[email protected]a93bb842010-02-16 23:03:477489error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
7490 GLenum target,
7491 GLint level,
7492 GLenum internal_format,
7493 GLsizei width,
7494 GLsizei height,
7495 GLint border,
7496 GLsizei image_size,
7497 const void* data) {
[email protected]a93bb842010-02-16 23:03:477498 // TODO(gman): Validate image_size is correct for width, height and format.
[email protected]9438b012010-06-15 22:55:057499 if (!validators_->texture_target.IsValid(target)) {
[email protected]ab09b612013-03-11 22:11:517500 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7501 "glCompressedTexImage2D", target, "target");
[email protected]8eee29c2010-04-29 03:38:297502 return error::kNoError;
7503 }
[email protected]9438b012010-06-15 22:55:057504 if (!validators_->compressed_texture_format.IsValid(
7505 internal_format)) {
[email protected]ab09b612013-03-11 22:11:517506 LOCAL_SET_GL_ERROR_INVALID_ENUM(
[email protected]f80e6e12012-08-31 00:43:537507 "glCompressedTexImage2D", internal_format, "internal_format");
[email protected]a93bb842010-02-16 23:03:477508 return error::kNoError;
7509 }
[email protected]80eb6b52012-01-19 00:14:417510 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]a93bb842010-02-16 23:03:477511 border != 0) {
[email protected]ab09b612013-03-11 22:11:517512 LOCAL_SET_GL_ERROR(
7513 GL_INVALID_VALUE,
7514 "glCompressedTexImage2D", "dimensions out of range");
[email protected]a93bb842010-02-16 23:03:477515 return error::kNoError;
7516 }
[email protected]c986af502013-08-14 01:04:447517 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7518 &state_, target);
[email protected]370eaf12013-05-18 09:19:497519 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:517520 LOCAL_SET_GL_ERROR(
7521 GL_INVALID_VALUE,
7522 "glCompressedTexImage2D", "unknown texture target");
[email protected]a93bb842010-02-16 23:03:477523 return error::kNoError;
7524 }
[email protected]370eaf12013-05-18 09:19:497525 Texture* texture = texture_ref->texture();
[email protected]02965c22013-03-09 02:40:077526 if (texture->IsImmutable()) {
[email protected]ab09b612013-03-11 22:11:517527 LOCAL_SET_GL_ERROR(
7528 GL_INVALID_OPERATION,
7529 "glCompressedTexImage2D", "texture is immutable");
[email protected]ad84a3a2012-06-08 21:42:437530 return error::kNoError;
7531 }
7532
7533 if (!ValidateCompressedTexDimensions(
7534 "glCompressedTexImage2D", level, width, height, internal_format) ||
7535 !ValidateCompressedTexFuncData(
7536 "glCompressedTexImage2D", width, height, internal_format, image_size)) {
[email protected]97dc7cbe2011-12-06 17:26:177537 return error::kNoError;
7538 }
[email protected]968351b2011-12-20 08:26:517539
[email protected]7989c9e2013-01-23 06:39:267540 if (!EnsureGPUMemoryAvailable(image_size)) {
[email protected]ab09b612013-03-11 22:11:517541 LOCAL_SET_GL_ERROR(
7542 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
[email protected]7989c9e2013-01-23 06:39:267543 return error::kNoError;
7544 }
7545
[email protected]02965c22013-03-09 02:40:077546 if (texture->IsAttachedToFramebuffer()) {
[email protected]c986af502013-08-14 01:04:447547 framebuffer_state_.clear_state_dirty = true;
[email protected]968351b2011-12-20 08:26:517548 }
7549
[email protected]40d90a22013-04-09 03:39:557550 scoped_ptr<int8[]> zero;
[email protected]a93bb842010-02-16 23:03:477551 if (!data) {
7552 zero.reset(new int8[image_size]);
7553 memset(zero.get(), 0, image_size);
7554 data = zero.get();
7555 }
[email protected]ab09b612013-03-11 22:11:517556 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
[email protected]a93bb842010-02-16 23:03:477557 glCompressedTexImage2D(
7558 target, level, internal_format, width, height, border, image_size, data);
[email protected]ab09b612013-03-11 22:11:517559 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
[email protected]cadde4a2010-07-31 17:10:437560 if (error == GL_NO_ERROR) {
7561 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:497562 texture_ref, target, level, internal_format,
7563 width, height, 1, border, 0, 0, true);
[email protected]cadde4a2010-07-31 17:10:437564 }
[email protected]a93bb842010-02-16 23:03:477565 return error::kNoError;
7566}
7567
[email protected]f7a64ee2010-02-01 22:24:147568error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
[email protected]ed9f9cd2013-02-27 21:12:357569 uint32 immediate_data_size, const cmds::CompressedTexImage2D& c) {
[email protected]b9849abf2009-11-25 19:13:197570 GLenum target = static_cast<GLenum>(c.target);
7571 GLint level = static_cast<GLint>(c.level);
7572 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7573 GLsizei width = static_cast<GLsizei>(c.width);
7574 GLsizei height = static_cast<GLsizei>(c.height);
7575 GLint border = static_cast<GLint>(c.border);
7576 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
7577 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
7578 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
7579 const void* data = NULL;
7580 if (data_shm_id != 0 || data_shm_offset != 0) {
7581 data = GetSharedMemoryAs<const void*>(
7582 data_shm_id, data_shm_offset, image_size);
[email protected]ba3176a2009-12-16 18:19:467583 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:147584 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197585 }
7586 }
[email protected]a93bb842010-02-16 23:03:477587 return DoCompressedTexImage2D(
[email protected]b9849abf2009-11-25 19:13:197588 target, level, internal_format, width, height, border, image_size, data);
[email protected]b9849abf2009-11-25 19:13:197589}
7590
[email protected]f7a64ee2010-02-01 22:24:147591error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
[email protected]ed9f9cd2013-02-27 21:12:357592 uint32 immediate_data_size, const cmds::CompressedTexImage2DImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:197593 GLenum target = static_cast<GLenum>(c.target);
7594 GLint level = static_cast<GLint>(c.level);
7595 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7596 GLsizei width = static_cast<GLsizei>(c.width);
7597 GLsizei height = static_cast<GLsizei>(c.height);
7598 GLint border = static_cast<GLint>(c.border);
7599 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
[email protected]07f54fcc2009-12-22 02:46:307600 const void* data = GetImmediateDataAs<const void*>(
7601 c, image_size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:467602 if (!data) {
[email protected]f7a64ee2010-02-01 22:24:147603 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:467604 }
[email protected]a93bb842010-02-16 23:03:477605 return DoCompressedTexImage2D(
7606 target, level, internal_format, width, height, border, image_size, data);
7607}
7608
[email protected]b6140d02010-05-17 14:47:167609error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
[email protected]ed9f9cd2013-02-27 21:12:357610 uint32 immediate_data_size, const cmds::CompressedTexImage2DBucket& c) {
[email protected]b6140d02010-05-17 14:47:167611 GLenum target = static_cast<GLenum>(c.target);
7612 GLint level = static_cast<GLint>(c.level);
7613 GLenum internal_format = static_cast<GLenum>(c.internalformat);
7614 GLsizei width = static_cast<GLsizei>(c.width);
7615 GLsizei height = static_cast<GLsizei>(c.height);
7616 GLint border = static_cast<GLint>(c.border);
7617 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287618 if (!bucket) {
7619 return error::kInvalidArguments;
7620 }
7621 uint32 data_size = bucket->size();
7622 GLsizei imageSize = data_size;
7623 const void* data = bucket->GetData(0, data_size);
7624 if (!data) {
7625 return error::kInvalidArguments;
7626 }
[email protected]b6140d02010-05-17 14:47:167627 return DoCompressedTexImage2D(
7628 target, level, internal_format, width, height, border,
[email protected]12f93d82011-10-17 21:16:287629 imageSize, data);
[email protected]b6140d02010-05-17 14:47:167630}
7631
7632error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
7633 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:357634 const cmds::CompressedTexSubImage2DBucket& c) {
[email protected]b6140d02010-05-17 14:47:167635 GLenum target = static_cast<GLenum>(c.target);
7636 GLint level = static_cast<GLint>(c.level);
7637 GLint xoffset = static_cast<GLint>(c.xoffset);
7638 GLint yoffset = static_cast<GLint>(c.yoffset);
7639 GLsizei width = static_cast<GLsizei>(c.width);
7640 GLsizei height = static_cast<GLsizei>(c.height);
7641 GLenum format = static_cast<GLenum>(c.format);
7642 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:287643 if (!bucket) {
7644 return error::kInvalidArguments;
7645 }
[email protected]b6140d02010-05-17 14:47:167646 uint32 data_size = bucket->size();
7647 GLsizei imageSize = data_size;
7648 const void* data = bucket->GetData(0, data_size);
[email protected]12f93d82011-10-17 21:16:287649 if (!data) {
7650 return error::kInvalidArguments;
7651 }
[email protected]9438b012010-06-15 22:55:057652 if (!validators_->texture_target.IsValid(target)) {
[email protected]ab09b612013-03-11 22:11:517653 LOCAL_SET_GL_ERROR(
[email protected]f80e6e12012-08-31 00:43:537654 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
[email protected]b6140d02010-05-17 14:47:167655 return error::kNoError;
7656 }
[email protected]9438b012010-06-15 22:55:057657 if (!validators_->compressed_texture_format.IsValid(format)) {
[email protected]ab09b612013-03-11 22:11:517658 LOCAL_SET_GL_ERROR_INVALID_ENUM(
7659 "glCompressedTexSubImage2D", format, "format");
[email protected]9438b012010-06-15 22:55:057660 return error::kNoError;
7661 }
[email protected]b6140d02010-05-17 14:47:167662 if (width < 0) {
[email protected]ab09b612013-03-11 22:11:517663 LOCAL_SET_GL_ERROR(
7664 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
[email protected]b6140d02010-05-17 14:47:167665 return error::kNoError;
7666 }
7667 if (height < 0) {
[email protected]ab09b612013-03-11 22:11:517668 LOCAL_SET_GL_ERROR(
7669 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
[email protected]b6140d02010-05-17 14:47:167670 return error::kNoError;
7671 }
7672 if (imageSize < 0) {
[email protected]ab09b612013-03-11 22:11:517673 LOCAL_SET_GL_ERROR(
7674 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
[email protected]b6140d02010-05-17 14:47:167675 return error::kNoError;
7676 }
[email protected]cadde4a2010-07-31 17:10:437677 DoCompressedTexSubImage2D(
[email protected]b6140d02010-05-17 14:47:167678 target, level, xoffset, yoffset, width, height, format, imageSize, data);
7679 return error::kNoError;
7680}
7681
[email protected]f7a64ee2010-02-01 22:24:147682error::Error GLES2DecoderImpl::HandleTexImage2D(
[email protected]ed9f9cd2013-02-27 21:12:357683 uint32 immediate_data_size, const cmds::TexImage2D& c) {
[email protected]43ed3a72012-05-30 22:55:387684 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
[email protected]c986af502013-08-14 01:04:447685 // Set as failed for now, but if it successed, this will be set to not failed.
7686 texture_state_.tex_image_2d_failed = true;
[email protected]b9849abf2009-11-25 19:13:197687 GLenum target = static_cast<GLenum>(c.target);
7688 GLint level = static_cast<GLint>(c.level);
[email protected]c986af502013-08-14 01:04:447689 // TODO(kloveless): Change TexImage2D command to use unsigned integer
7690 // for internalformat.
7691 GLenum internal_format = static_cast<GLenum>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:197692 GLsizei width = static_cast<GLsizei>(c.width);
7693 GLsizei height = static_cast<GLsizei>(c.height);
7694 GLint border = static_cast<GLint>(c.border);
7695 GLenum format = static_cast<GLenum>(c.format);
7696 GLenum type = static_cast<GLenum>(c.type);
7697 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
7698 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
[email protected]a76b0052010-03-05 00:33:187699 uint32 pixels_size;
[email protected]3458a64a2012-04-10 17:39:347700 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247701 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
[email protected]3458a64a2012-04-10 17:39:347702 NULL)) {
[email protected]a76b0052010-03-05 00:33:187703 return error::kOutOfBounds;
7704 }
[email protected]b9849abf2009-11-25 19:13:197705 const void* pixels = NULL;
7706 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
7707 pixels = GetSharedMemoryAs<const void*>(
7708 pixels_shm_id, pixels_shm_offset, pixels_size);
[email protected]ba3176a2009-12-16 18:19:467709 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:147710 return error::kOutOfBounds;
[email protected]b9849abf2009-11-25 19:13:197711 }
7712 }
[email protected]f598f422012-12-07 08:30:037713
[email protected]c986af502013-08-14 01:04:447714 TextureManager::DoTextImage2DArguments args = {
7715 target, level, internal_format, width, height, border, format, type,
7716 pixels, pixels_size};
7717 texture_manager()->ValidateAndDoTexImage2D(
7718 &texture_state_, &state_, &framebuffer_state_, args);
[email protected]f598f422012-12-07 08:30:037719 return error::kNoError;
[email protected]b9849abf2009-11-25 19:13:197720}
7721
[email protected]f7a64ee2010-02-01 22:24:147722error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
[email protected]ed9f9cd2013-02-27 21:12:357723 uint32 immediate_data_size, const cmds::TexImage2DImmediate& c) {
[email protected]b9849abf2009-11-25 19:13:197724 GLenum target = static_cast<GLenum>(c.target);
7725 GLint level = static_cast<GLint>(c.level);
[email protected]c986af502013-08-14 01:04:447726 // TODO(kloveless): Change TexImage2DImmediate command to use unsigned
7727 // integer for internalformat.
7728 GLenum internal_format = static_cast<GLenum>(c.internalformat);
[email protected]b9849abf2009-11-25 19:13:197729 GLsizei width = static_cast<GLsizei>(c.width);
7730 GLsizei height = static_cast<GLsizei>(c.height);
7731 GLint border = static_cast<GLint>(c.border);
7732 GLenum format = static_cast<GLenum>(c.format);
7733 GLenum type = static_cast<GLenum>(c.type);
[email protected]a76b0052010-03-05 00:33:187734 uint32 size;
[email protected]3458a64a2012-04-10 17:39:347735 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:247736 width, height, format, type, state_.unpack_alignment, &size,
7737 NULL, NULL)) {
[email protected]a76b0052010-03-05 00:33:187738 return error::kOutOfBounds;
7739 }
[email protected]07f54fcc2009-12-22 02:46:307740 const void* pixels = GetImmediateDataAs<const void*>(
7741 c, size, immediate_data_size);
[email protected]ba3176a2009-12-16 18:19:467742 if (!pixels) {
[email protected]f7a64ee2010-02-01 22:24:147743 return error::kOutOfBounds;
[email protected]ba3176a2009-12-16 18:19:467744 }
[email protected]c986af502013-08-14 01:04:447745
7746 TextureManager::DoTextImage2DArguments args = {
7747 target, level, internal_format, width, height, border, format, type,
7748 pixels, size};
7749 texture_manager()->ValidateAndDoTexImage2D(
7750 &texture_state_, &state_, &framebuffer_state_, args);
[email protected]f7a64ee2010-02-01 22:24:147751 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:327752}
7753
[email protected]cadde4a2010-07-31 17:10:437754void GLES2DecoderImpl::DoCompressedTexSubImage2D(
7755 GLenum target,
7756 GLint level,
7757 GLint xoffset,
7758 GLint yoffset,
7759 GLsizei width,
7760 GLsizei height,
7761 GLenum format,
7762 GLsizei image_size,
7763 const void * data) {
[email protected]c986af502013-08-14 01:04:447764 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7765 &state_, target);
[email protected]370eaf12013-05-18 09:19:497766 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:517767 LOCAL_SET_GL_ERROR(
7768 GL_INVALID_OPERATION,
7769 "glCompressedTexSubImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:437770 return;
7771 }
[email protected]370eaf12013-05-18 09:19:497772 Texture* texture = texture_ref->texture();
[email protected]cadde4a2010-07-31 17:10:437773 GLenum type = 0;
[email protected]df6cf1ad2011-01-29 01:20:527774 GLenum internal_format = 0;
[email protected]02965c22013-03-09 02:40:077775 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
[email protected]ab09b612013-03-11 22:11:517776 LOCAL_SET_GL_ERROR(
[email protected]df6cf1ad2011-01-29 01:20:527777 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437778 "glCompressedTexSubImage2D", "level does not exist.");
[email protected]df6cf1ad2011-01-29 01:20:527779 return;
7780 }
7781 if (internal_format != format) {
[email protected]ab09b612013-03-11 22:11:517782 LOCAL_SET_GL_ERROR(
[email protected]df6cf1ad2011-01-29 01:20:527783 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437784 "glCompressedTexSubImage2D", "format does not match internal format.");
[email protected]df6cf1ad2011-01-29 01:20:527785 return;
7786 }
[email protected]02965c22013-03-09 02:40:077787 if (!texture->ValidForTexture(
[email protected]df6cf1ad2011-01-29 01:20:527788 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]ab09b612013-03-11 22:11:517789 LOCAL_SET_GL_ERROR(
7790 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:437791 return;
7792 }
[email protected]ad84a3a2012-06-08 21:42:437793
7794 if (!ValidateCompressedTexFuncData(
7795 "glCompressedTexSubImage2D", width, height, format, image_size) ||
7796 !ValidateCompressedTexSubDimensions(
7797 "glCompressedTexSubImage2D",
[email protected]02965c22013-03-09 02:40:077798 target, level, xoffset, yoffset, width, height, format, texture)) {
[email protected]ad84a3a2012-06-08 21:42:437799 return;
7800 }
7801
7802
[email protected]0d6bfdc2011-11-02 01:32:207803 // Note: There is no need to deal with texture cleared tracking here
7804 // because the validation above means you can only get here if the level
7805 // is already a matching compressed format and in that case
7806 // CompressedTexImage2D already cleared the texture.
[email protected]cadde4a2010-07-31 17:10:437807 glCompressedTexSubImage2D(
7808 target, level, xoffset, yoffset, width, height, format, image_size, data);
7809}
7810
[email protected]6e288612010-12-21 20:45:037811static void Clip(
7812 GLint start, GLint range, GLint sourceRange,
7813 GLint* out_start, GLint* out_range) {
7814 DCHECK(out_start);
7815 DCHECK(out_range);
7816 if (start < 0) {
7817 range += start;
7818 start = 0;
7819 }
7820 GLint end = start + range;
7821 if (end > sourceRange) {
7822 range -= end - sourceRange;
7823 }
7824 *out_start = start;
7825 *out_range = range;
7826}
7827
[email protected]cadde4a2010-07-31 17:10:437828void GLES2DecoderImpl::DoCopyTexImage2D(
[email protected]a5d3dad2012-05-26 04:34:447829 GLenum target,
7830 GLint level,
7831 GLenum internal_format,
7832 GLint x,
7833 GLint y,
7834 GLsizei width,
7835 GLsizei height,
7836 GLint border) {
[email protected]09e17272012-11-30 10:30:447837 DCHECK(!ShouldDeferReads());
[email protected]c986af502013-08-14 01:04:447838 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7839 &state_, target);
[email protected]370eaf12013-05-18 09:19:497840 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:517841 LOCAL_SET_GL_ERROR(
7842 GL_INVALID_OPERATION,
7843 "glCopyTexImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:437844 return;
7845 }
[email protected]370eaf12013-05-18 09:19:497846 Texture* texture = texture_ref->texture();
[email protected]02965c22013-03-09 02:40:077847 if (texture->IsImmutable()) {
[email protected]ab09b612013-03-11 22:11:517848 LOCAL_SET_GL_ERROR(
7849 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
[email protected]97dc7cbe2011-12-06 17:26:177850 }
[email protected]80eb6b52012-01-19 00:14:417851 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
[email protected]f5719fb2010-08-04 18:27:187852 border != 0) {
[email protected]ab09b612013-03-11 22:11:517853 LOCAL_SET_GL_ERROR(
7854 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
[email protected]f5719fb2010-08-04 18:27:187855 return;
7856 }
[email protected]c986af502013-08-14 01:04:447857 if (!texture_manager()->ValidateTextureParameters(
7858 state_.GetErrorState(), "glCopyTexImage2D", target, internal_format,
7859 GL_UNSIGNED_BYTE, level)) {
[email protected]81375742012-06-08 00:04:007860 return;
7861 }
[email protected]f5719fb2010-08-04 18:27:187862
[email protected]9edc6b22010-12-23 02:00:267863 // Check we have compatible formats.
7864 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7865 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7866 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
7867
7868 if ((channels_needed & channels_exist) != channels_needed) {
[email protected]ab09b612013-03-11 22:11:517869 LOCAL_SET_GL_ERROR(
7870 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
[email protected]9edc6b22010-12-23 02:00:267871 return;
7872 }
7873
[email protected]81375742012-06-08 00:04:007874 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
[email protected]ab09b612013-03-11 22:11:517875 LOCAL_SET_GL_ERROR(
[email protected]81375742012-06-08 00:04:007876 GL_INVALID_OPERATION,
[email protected]7989c9e2013-01-23 06:39:267877 "glCopyTexImage2D", "can not be used with depth or stencil textures");
7878 return;
7879 }
7880
7881 uint32 estimated_size = 0;
7882 if (!GLES2Util::ComputeImageDataSizes(
7883 width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment,
7884 &estimated_size, NULL, NULL)) {
[email protected]ab09b612013-03-11 22:11:517885 LOCAL_SET_GL_ERROR(
7886 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
[email protected]7989c9e2013-01-23 06:39:267887 return;
7888 }
7889
7890 if (!EnsureGPUMemoryAvailable(estimated_size)) {
[email protected]ab09b612013-03-11 22:11:517891 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
[email protected]81375742012-06-08 00:04:007892 return;
7893 }
7894
[email protected]a0b78dc2011-11-11 10:43:107895 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
7896 return;
7897 }
7898
[email protected]ab09b612013-03-11 22:11:517899 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
[email protected]de26b3c2011-08-03 21:54:277900 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:037901 gfx::Size size = GetBoundReadFrameBufferSize();
[email protected]9edc6b22010-12-23 02:00:267902
[email protected]02965c22013-03-09 02:40:077903 if (texture->IsAttachedToFramebuffer()) {
[email protected]c986af502013-08-14 01:04:447904 framebuffer_state_.clear_state_dirty = true;
[email protected]297ca1c2011-06-20 23:08:467905 }
7906
[email protected]9edc6b22010-12-23 02:00:267907 // Clip to size to source dimensions
[email protected]6e288612010-12-21 20:45:037908 GLint copyX = 0;
7909 GLint copyY = 0;
7910 GLint copyWidth = 0;
7911 GLint copyHeight = 0;
7912 Clip(x, width, size.width(), &copyX, &copyWidth);
7913 Clip(y, height, size.height(), &copyY, &copyHeight);
7914
7915 if (copyX != x ||
7916 copyY != y ||
7917 copyWidth != width ||
7918 copyHeight != height) {
7919 // some part was clipped so clear the texture.
[email protected]0d6bfdc2011-11-02 01:32:207920 if (!ClearLevel(
[email protected]02965c22013-03-09 02:40:077921 texture->service_id(), texture->target(),
[email protected]4502e6492011-12-14 19:39:157922 target, level, internal_format, GL_UNSIGNED_BYTE, width, height,
[email protected]02965c22013-03-09 02:40:077923 texture->IsImmutable())) {
[email protected]ab09b612013-03-11 22:11:517924 LOCAL_SET_GL_ERROR(
7925 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
[email protected]6e288612010-12-21 20:45:037926 return;
7927 }
[email protected]6e288612010-12-21 20:45:037928 if (copyHeight > 0 && copyWidth > 0) {
7929 GLint dx = copyX - x;
7930 GLint dy = copyY - y;
7931 GLint destX = dx;
7932 GLint destY = dy;
7933 glCopyTexSubImage2D(target, level,
7934 destX, destY, copyX, copyY,
7935 copyWidth, copyHeight);
7936 }
7937 } else {
7938 glCopyTexImage2D(target, level, internal_format,
7939 copyX, copyY, copyWidth, copyHeight, border);
7940 }
[email protected]ab09b612013-03-11 22:11:517941 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
[email protected]cadde4a2010-07-31 17:10:437942 if (error == GL_NO_ERROR) {
7943 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:497944 texture_ref, target, level, internal_format, width, height, 1,
[email protected]0d6bfdc2011-11-02 01:32:207945 border, internal_format, GL_UNSIGNED_BYTE, true);
[email protected]cadde4a2010-07-31 17:10:437946 }
7947}
7948
7949void GLES2DecoderImpl::DoCopyTexSubImage2D(
[email protected]a5d3dad2012-05-26 04:34:447950 GLenum target,
7951 GLint level,
7952 GLint xoffset,
7953 GLint yoffset,
7954 GLint x,
7955 GLint y,
7956 GLsizei width,
7957 GLsizei height) {
[email protected]09e17272012-11-30 10:30:447958 DCHECK(!ShouldDeferReads());
[email protected]c986af502013-08-14 01:04:447959 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7960 &state_, target);
[email protected]370eaf12013-05-18 09:19:497961 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:517962 LOCAL_SET_GL_ERROR(
7963 GL_INVALID_OPERATION,
7964 "glCopyTexSubImage2D", "unknown texture for target");
[email protected]cadde4a2010-07-31 17:10:437965 return;
7966 }
[email protected]370eaf12013-05-18 09:19:497967 Texture* texture = texture_ref->texture();
[email protected]cadde4a2010-07-31 17:10:437968 GLenum type = 0;
7969 GLenum format = 0;
[email protected]02965c22013-03-09 02:40:077970 if (!texture->GetLevelType(target, level, &type, &format) ||
7971 !texture->ValidForTexture(
[email protected]cadde4a2010-07-31 17:10:437972 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]ab09b612013-03-11 22:11:517973 LOCAL_SET_GL_ERROR(
7974 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
[email protected]cadde4a2010-07-31 17:10:437975 return;
7976 }
[email protected]85a4ac22013-05-31 01:58:477977 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
[email protected]ab09b612013-03-11 22:11:517978 LOCAL_SET_GL_ERROR(
7979 GL_INVALID_OPERATION,
7980 "glCopyTexSubImage2D", "async upload pending for texture");
[email protected]32145a92012-12-17 09:01:597981 return;
7982 }
[email protected]9edc6b22010-12-23 02:00:267983
7984 // Check we have compatible formats.
7985 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
7986 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
7987 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
7988
[email protected]2d3765b2012-10-03 00:31:077989 if (!channels_needed ||
7990 (channels_needed & channels_exist) != channels_needed) {
[email protected]ab09b612013-03-11 22:11:517991 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:437992 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
[email protected]9edc6b22010-12-23 02:00:267993 return;
7994 }
7995
[email protected]81375742012-06-08 00:04:007996 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
[email protected]ab09b612013-03-11 22:11:517997 LOCAL_SET_GL_ERROR(
[email protected]81375742012-06-08 00:04:007998 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:437999 "glCopySubImage2D", "can not be used with depth or stencil textures");
[email protected]81375742012-06-08 00:04:008000 return;
8001 }
8002
[email protected]a0b78dc2011-11-11 10:43:108003 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
8004 return;
8005 }
8006
[email protected]de26b3c2011-08-03 21:54:278007 ScopedResolvedFrameBufferBinder binder(this, false, true);
[email protected]6e288612010-12-21 20:45:038008 gfx::Size size = GetBoundReadFrameBufferSize();
8009 GLint copyX = 0;
8010 GLint copyY = 0;
8011 GLint copyWidth = 0;
8012 GLint copyHeight = 0;
8013 Clip(x, width, size.width(), &copyX, &copyWidth);
8014 Clip(y, height, size.height(), &copyY, &copyHeight);
[email protected]0d6bfdc2011-11-02 01:32:208015
[email protected]370eaf12013-05-18 09:19:498016 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, level)) {
[email protected]ab09b612013-03-11 22:11:518017 LOCAL_SET_GL_ERROR(
8018 GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", "dimensions too big");
[email protected]0d6bfdc2011-11-02 01:32:208019 return;
8020 }
8021
[email protected]6e288612010-12-21 20:45:038022 if (copyX != x ||
8023 copyY != y ||
8024 copyWidth != width ||
8025 copyHeight != height) {
[email protected]0d6bfdc2011-11-02 01:32:208026 // some part was clipped so clear the sub rect.
[email protected]6e288612010-12-21 20:45:038027 uint32 pixels_size = 0;
[email protected]3458a64a2012-04-10 17:39:348028 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:248029 width, height, format, type, state_.unpack_alignment, &pixels_size,
8030 NULL, NULL)) {
[email protected]ab09b612013-03-11 22:11:518031 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:438032 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
[email protected]6e288612010-12-21 20:45:038033 return;
8034 }
[email protected]40d90a22013-04-09 03:39:558035 scoped_ptr<char[]> zero(new char[pixels_size]);
[email protected]6e288612010-12-21 20:45:038036 memset(zero.get(), 0, pixels_size);
8037 glTexSubImage2D(
8038 target, level, xoffset, yoffset, width, height,
8039 format, type, zero.get());
8040 }
[email protected]0d6bfdc2011-11-02 01:32:208041
[email protected]6e288612010-12-21 20:45:038042 if (copyHeight > 0 && copyWidth > 0) {
8043 GLint dx = copyX - x;
8044 GLint dy = copyY - y;
8045 GLint destX = xoffset + dx;
8046 GLint destY = yoffset + dy;
8047 glCopyTexSubImage2D(target, level,
8048 destX, destY, copyX, copyY,
8049 copyWidth, copyHeight);
8050 }
[email protected]cadde4a2010-07-31 17:10:438051}
8052
[email protected]f598f422012-12-07 08:30:038053bool GLES2DecoderImpl::ValidateTexSubImage2D(
8054 error::Error* error,
8055 const char* function_name,
8056 GLenum target,
8057 GLint level,
8058 GLint xoffset,
8059 GLint yoffset,
8060 GLsizei width,
8061 GLsizei height,
8062 GLenum format,
8063 GLenum type,
8064 const void * data) {
8065 (*error) = error::kNoError;
8066 if (!validators_->texture_target.IsValid(target)) {
[email protected]ab09b612013-03-11 22:11:518067 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
[email protected]f598f422012-12-07 08:30:038068 return false;
8069 }
8070 if (width < 0) {
[email protected]ab09b612013-03-11 22:11:518071 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
[email protected]f598f422012-12-07 08:30:038072 return false;
8073 }
8074 if (height < 0) {
[email protected]ab09b612013-03-11 22:11:518075 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
[email protected]f598f422012-12-07 08:30:038076 return false;
8077 }
8078 if (!validators_->texture_format.IsValid(format)) {
[email protected]ab09b612013-03-11 22:11:518079 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
[email protected]f598f422012-12-07 08:30:038080 return false;
8081 }
8082 if (!validators_->pixel_type.IsValid(type)) {
[email protected]ab09b612013-03-11 22:11:518083 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
[email protected]f598f422012-12-07 08:30:038084 return false;
8085 }
[email protected]c986af502013-08-14 01:04:448086 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8087 &state_, target);
[email protected]370eaf12013-05-18 09:19:498088 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:518089 LOCAL_SET_GL_ERROR(
8090 GL_INVALID_OPERATION,
8091 function_name, "unknown texture for target");
[email protected]f598f422012-12-07 08:30:038092 return false;
[email protected]cadde4a2010-07-31 17:10:438093 }
[email protected]370eaf12013-05-18 09:19:498094 Texture* texture = texture_ref->texture();
[email protected]df6cf1ad2011-01-29 01:20:528095 GLenum current_type = 0;
8096 GLenum internal_format = 0;
[email protected]02965c22013-03-09 02:40:078097 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
[email protected]ab09b612013-03-11 22:11:518098 LOCAL_SET_GL_ERROR(
[email protected]f598f422012-12-07 08:30:038099 GL_INVALID_OPERATION, function_name, "level does not exist.");
8100 return false;
[email protected]df6cf1ad2011-01-29 01:20:528101 }
8102 if (format != internal_format) {
[email protected]ab09b612013-03-11 22:11:518103 LOCAL_SET_GL_ERROR(
8104 GL_INVALID_OPERATION,
8105 function_name, "format does not match internal format.");
[email protected]f598f422012-12-07 08:30:038106 return false;
[email protected]df6cf1ad2011-01-29 01:20:528107 }
8108 if (type != current_type) {
[email protected]ab09b612013-03-11 22:11:518109 LOCAL_SET_GL_ERROR(
8110 GL_INVALID_OPERATION,
8111 function_name, "type does not match type of texture.");
[email protected]f598f422012-12-07 08:30:038112 return false;
[email protected]df6cf1ad2011-01-29 01:20:528113 }
[email protected]85a4ac22013-05-31 01:58:478114 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
[email protected]ab09b612013-03-11 22:11:518115 LOCAL_SET_GL_ERROR(
8116 GL_INVALID_OPERATION,
8117 function_name, "async upload pending for texture");
[email protected]32145a92012-12-17 09:01:598118 return false;
8119 }
[email protected]02965c22013-03-09 02:40:078120 if (!texture->ValidForTexture(
[email protected]cadde4a2010-07-31 17:10:438121 target, level, xoffset, yoffset, width, height, format, type)) {
[email protected]ab09b612013-03-11 22:11:518122 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
[email protected]f598f422012-12-07 08:30:038123 return false;
[email protected]cadde4a2010-07-31 17:10:438124 }
[email protected]81375742012-06-08 00:04:008125 if ((GLES2Util::GetChannelsForFormat(format) &
8126 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
[email protected]ab09b612013-03-11 22:11:518127 LOCAL_SET_GL_ERROR(
[email protected]81375742012-06-08 00:04:008128 GL_INVALID_OPERATION,
[email protected]f598f422012-12-07 08:30:038129 function_name, "can not supply data for depth or stencil textures");
8130 return false;
[email protected]81375742012-06-08 00:04:008131 }
[email protected]f598f422012-12-07 08:30:038132 if (data == NULL) {
8133 (*error) = error::kOutOfBounds;
8134 return false;
8135 }
8136 return true;
8137}
[email protected]81375742012-06-08 00:04:008138
[email protected]f598f422012-12-07 08:30:038139error::Error GLES2DecoderImpl::DoTexSubImage2D(
8140 GLenum target,
8141 GLint level,
8142 GLint xoffset,
8143 GLint yoffset,
8144 GLsizei width,
8145 GLsizei height,
8146 GLenum format,
8147 GLenum type,
8148 const void * data) {
8149 error::Error error = error::kNoError;
8150 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
8151 xoffset, yoffset, width, height, format, type, data)) {
8152 return error;
8153 }
[email protected]c986af502013-08-14 01:04:448154 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
8155 &state_, target);
[email protected]370eaf12013-05-18 09:19:498156 Texture* texture = texture_ref->texture();
[email protected]4502e6492011-12-14 19:39:158157 GLsizei tex_width = 0;
8158 GLsizei tex_height = 0;
[email protected]02965c22013-03-09 02:40:078159 bool ok = texture->GetLevelSize(target, level, &tex_width, &tex_height);
[email protected]4502e6492011-12-14 19:39:158160 DCHECK(ok);
8161 if (xoffset != 0 || yoffset != 0 ||
8162 width != tex_width || height != tex_height) {
[email protected]370eaf12013-05-18 09:19:498163 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
8164 target, level)) {
[email protected]ab09b612013-03-11 22:11:518165 LOCAL_SET_GL_ERROR(
8166 GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
[email protected]f598f422012-12-07 08:30:038167 return error::kNoError;
[email protected]473c01ccb2011-06-07 01:33:308168 }
[email protected]c986af502013-08-14 01:04:448169 ScopedTextureUploadTimer timer(&texture_state_);
[email protected]4502e6492011-12-14 19:39:158170 glTexSubImage2D(
8171 target, level, xoffset, yoffset, width, height, format, type, data);
[email protected]f598f422012-12-07 08:30:038172 return error::kNoError;
[email protected]0d6bfdc2011-11-02 01:32:208173 }
[email protected]4502e6492011-12-14 19:39:158174
[email protected]c986af502013-08-14 01:04:448175 if (texture_state_.teximage2d_faster_than_texsubimage2d &&
8176 !texture->IsImmutable()) {
8177 ScopedTextureUploadTimer timer(&texture_state_);
[email protected]4502e6492011-12-14 19:39:158178 // NOTE: In OpenGL ES 2.0 border is always zero and format is always the
8179 // same as internal_foramt. If that changes we'll need to look them up.
[email protected]8f1d2aa2013-05-10 23:45:388180 glTexImage2D(
[email protected]4502e6492011-12-14 19:39:158181 target, level, format, width, height, 0, format, type, data);
8182 } else {
[email protected]c986af502013-08-14 01:04:448183 ScopedTextureUploadTimer timer(&texture_state_);
[email protected]4502e6492011-12-14 19:39:158184 glTexSubImage2D(
8185 target, level, xoffset, yoffset, width, height, format, type, data);
8186 }
[email protected]370eaf12013-05-18 09:19:498187 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
[email protected]f598f422012-12-07 08:30:038188 return error::kNoError;
[email protected]cadde4a2010-07-31 17:10:438189}
8190
[email protected]b493ee622011-04-13 23:52:008191error::Error GLES2DecoderImpl::HandleTexSubImage2D(
[email protected]ed9f9cd2013-02-27 21:12:358192 uint32 immediate_data_size, const cmds::TexSubImage2D& c) {
[email protected]43ed3a72012-05-30 22:55:388193 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
[email protected]b493ee622011-04-13 23:52:008194 GLboolean internal = static_cast<GLboolean>(c.internal);
[email protected]c986af502013-08-14 01:04:448195 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
[email protected]b493ee622011-04-13 23:52:008196 return error::kNoError;
8197
8198 GLenum target = static_cast<GLenum>(c.target);
8199 GLint level = static_cast<GLint>(c.level);
8200 GLint xoffset = static_cast<GLint>(c.xoffset);
8201 GLint yoffset = static_cast<GLint>(c.yoffset);
8202 GLsizei width = static_cast<GLsizei>(c.width);
8203 GLsizei height = static_cast<GLsizei>(c.height);
8204 GLenum format = static_cast<GLenum>(c.format);
8205 GLenum type = static_cast<GLenum>(c.type);
8206 uint32 data_size;
[email protected]3458a64a2012-04-10 17:39:348207 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:248208 width, height, format, type, state_.unpack_alignment, &data_size,
8209 NULL, NULL)) {
[email protected]b493ee622011-04-13 23:52:008210 return error::kOutOfBounds;
8211 }
8212 const void* pixels = GetSharedMemoryAs<const void*>(
8213 c.pixels_shm_id, c.pixels_shm_offset, data_size);
[email protected]f598f422012-12-07 08:30:038214 return DoTexSubImage2D(
[email protected]b493ee622011-04-13 23:52:008215 target, level, xoffset, yoffset, width, height, format, type, pixels);
[email protected]b493ee622011-04-13 23:52:008216}
8217
8218error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
[email protected]ed9f9cd2013-02-27 21:12:358219 uint32 immediate_data_size, const cmds::TexSubImage2DImmediate& c) {
[email protected]b493ee622011-04-13 23:52:008220 GLboolean internal = static_cast<GLboolean>(c.internal);
[email protected]c986af502013-08-14 01:04:448221 if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
[email protected]b493ee622011-04-13 23:52:008222 return error::kNoError;
8223
8224 GLenum target = static_cast<GLenum>(c.target);
8225 GLint level = static_cast<GLint>(c.level);
8226 GLint xoffset = static_cast<GLint>(c.xoffset);
8227 GLint yoffset = static_cast<GLint>(c.yoffset);
8228 GLsizei width = static_cast<GLsizei>(c.width);
8229 GLsizei height = static_cast<GLsizei>(c.height);
8230 GLenum format = static_cast<GLenum>(c.format);
8231 GLenum type = static_cast<GLenum>(c.type);
8232 uint32 data_size;
[email protected]3458a64a2012-04-10 17:39:348233 if (!GLES2Util::ComputeImageDataSizes(
[email protected]e259eb412012-10-13 05:47:248234 width, height, format, type, state_.unpack_alignment, &data_size,
8235 NULL, NULL)) {
[email protected]b493ee622011-04-13 23:52:008236 return error::kOutOfBounds;
8237 }
8238 const void* pixels = GetImmediateDataAs<const void*>(
8239 c, data_size, immediate_data_size);
[email protected]f598f422012-12-07 08:30:038240 return DoTexSubImage2D(
[email protected]b493ee622011-04-13 23:52:008241 target, level, xoffset, yoffset, width, height, format, type, pixels);
[email protected]b493ee622011-04-13 23:52:008242}
8243
[email protected]f7a64ee2010-02-01 22:24:148244error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
[email protected]ed9f9cd2013-02-27 21:12:358245 uint32 immediate_data_size, const cmds::GetVertexAttribPointerv& c) {
[email protected]8bf5a3e2010-01-29 04:21:368246 GLuint index = static_cast<GLuint>(c.index);
8247 GLenum pname = static_cast<GLenum>(c.pname);
[email protected]ed9f9cd2013-02-27 21:12:358248 typedef cmds::GetVertexAttribPointerv::Result Result;
[email protected]0bfd9882010-02-05 23:02:258249 Result* result = GetSharedMemoryAs<Result*>(
8250 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
[email protected]8bf5a3e2010-01-29 04:21:368251 if (!result) {
[email protected]f7a64ee2010-02-01 22:24:148252 return error::kOutOfBounds;
[email protected]8bf5a3e2010-01-29 04:21:368253 }
[email protected]07d0cc82010-02-17 04:51:408254 // Check that the client initialized the result.
8255 if (result->size != 0) {
8256 return error::kInvalidArguments;
8257 }
[email protected]9438b012010-06-15 22:55:058258 if (!validators_->vertex_pointer.IsValid(pname)) {
[email protected]ab09b612013-03-11 22:11:518259 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8260 "glGetVertexAttribPointerv", pname, "pname");
[email protected]f7a64ee2010-02-01 22:24:148261 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:368262 }
[email protected]3916c97e2010-02-25 03:20:508263 if (index >= group_->max_vertex_attribs()) {
[email protected]ab09b612013-03-11 22:11:518264 LOCAL_SET_GL_ERROR(
8265 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
[email protected]f7a64ee2010-02-01 22:24:148266 return error::kNoError;
[email protected]8bf5a3e2010-01-29 04:21:368267 }
[email protected]0bfd9882010-02-05 23:02:258268 result->SetNumResults(1);
[email protected]f39f4b3f2010-05-12 17:04:088269 *result->GetData() =
[email protected]ed9f9cd2013-02-27 21:12:358270 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
[email protected]f7a64ee2010-02-01 22:24:148271 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328272}
8273
[email protected]f7b85372010-02-03 01:11:378274bool GLES2DecoderImpl::GetUniformSetup(
[email protected]df37b9932013-03-08 05:21:428275 GLuint program_id, GLint fake_location,
[email protected]f7b85372010-02-03 01:11:378276 uint32 shm_id, uint32 shm_offset,
[email protected]1b0a6752012-02-22 03:44:128277 error::Error* error, GLint* real_location,
8278 GLuint* service_id, void** result_pointer, GLenum* result_type) {
[email protected]939e7362010-05-13 20:49:108279 DCHECK(error);
8280 DCHECK(service_id);
8281 DCHECK(result_pointer);
8282 DCHECK(result_type);
[email protected]1b0a6752012-02-22 03:44:128283 DCHECK(real_location);
[email protected]f7b85372010-02-03 01:11:378284 *error = error::kNoError;
8285 // Make sure we have enough room for the result on failure.
[email protected]0bfd9882010-02-05 23:02:258286 SizedResult<GLint>* result;
8287 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8288 shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0));
8289 if (!result) {
[email protected]f7b85372010-02-03 01:11:378290 *error = error::kOutOfBounds;
8291 return false;
8292 }
[email protected]0bfd9882010-02-05 23:02:258293 *result_pointer = result;
[email protected]f7b85372010-02-03 01:11:378294 // Set the result size to 0 so the client does not have to check for success.
[email protected]0bfd9882010-02-05 23:02:258295 result->SetNumResults(0);
[email protected]df37b9932013-03-08 05:21:428296 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
8297 if (!program) {
[email protected]ae51d192010-04-27 00:48:038298 return false;
8299 }
[email protected]df37b9932013-03-08 05:21:428300 if (!program->IsValid()) {
[email protected]f7b85372010-02-03 01:11:378301 // Program was not linked successfully. (ie, glLinkProgram)
[email protected]ab09b612013-03-11 22:11:518302 LOCAL_SET_GL_ERROR(
8303 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
[email protected]f7b85372010-02-03 01:11:378304 return false;
8305 }
[email protected]df37b9932013-03-08 05:21:428306 *service_id = program->service_id();
[email protected]43c2f1f2011-03-25 18:35:368307 GLint array_index = -1;
[email protected]ed9f9cd2013-02-27 21:12:358308 const Program::UniformInfo* uniform_info =
[email protected]df37b9932013-03-08 05:21:428309 program->GetUniformInfoByFakeLocation(
[email protected]1b0a6752012-02-22 03:44:128310 fake_location, real_location, &array_index);
[email protected]43c2f1f2011-03-25 18:35:368311 if (!uniform_info) {
[email protected]f7b85372010-02-03 01:11:378312 // No such location.
[email protected]ab09b612013-03-11 22:11:518313 LOCAL_SET_GL_ERROR(
8314 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
[email protected]f7b85372010-02-03 01:11:378315 return false;
8316 }
[email protected]43c2f1f2011-03-25 18:35:368317 GLenum type = uniform_info->type;
[email protected]3916c97e2010-02-25 03:20:508318 GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
[email protected]f7b85372010-02-03 01:11:378319 if (size == 0) {
[email protected]ab09b612013-03-11 22:11:518320 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
[email protected]f7b85372010-02-03 01:11:378321 return false;
8322 }
[email protected]0bfd9882010-02-05 23:02:258323 result = GetSharedMemoryAs<SizedResult<GLint>*>(
8324 shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size));
8325 if (!result) {
[email protected]f7b85372010-02-03 01:11:378326 *error = error::kOutOfBounds;
8327 return false;
8328 }
[email protected]0bfd9882010-02-05 23:02:258329 result->size = size;
[email protected]939e7362010-05-13 20:49:108330 *result_type = type;
[email protected]f7b85372010-02-03 01:11:378331 return true;
8332}
8333
[email protected]f7a64ee2010-02-01 22:24:148334error::Error GLES2DecoderImpl::HandleGetUniformiv(
[email protected]ed9f9cd2013-02-27 21:12:358335 uint32 immediate_data_size, const cmds::GetUniformiv& c) {
[email protected]f7b85372010-02-03 01:11:378336 GLuint program = c.program;
[email protected]2be6abf32012-06-26 00:28:338337 GLint fake_location = c.location;
[email protected]f7b85372010-02-03 01:11:378338 GLuint service_id;
[email protected]939e7362010-05-13 20:49:108339 GLenum result_type;
[email protected]1b0a6752012-02-22 03:44:128340 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:378341 Error error;
[email protected]0bfd9882010-02-05 23:02:258342 void* result;
[email protected]f7b85372010-02-03 01:11:378343 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:128344 program, fake_location, c.params_shm_id, c.params_shm_offset,
8345 &error, &real_location, &service_id, &result, &result_type)) {
[email protected]0bfd9882010-02-05 23:02:258346 glGetUniformiv(
[email protected]1b0a6752012-02-22 03:44:128347 service_id, real_location,
[email protected]ed9f9cd2013-02-27 21:12:358348 static_cast<cmds::GetUniformiv::Result*>(result)->GetData());
[email protected]f7b85372010-02-03 01:11:378349 }
8350 return error;
[email protected]96449d2c2009-11-25 00:01:328351}
8352
[email protected]f7a64ee2010-02-01 22:24:148353error::Error GLES2DecoderImpl::HandleGetUniformfv(
[email protected]ed9f9cd2013-02-27 21:12:358354 uint32 immediate_data_size, const cmds::GetUniformfv& c) {
[email protected]f7b85372010-02-03 01:11:378355 GLuint program = c.program;
[email protected]2be6abf32012-06-26 00:28:338356 GLint fake_location = c.location;
[email protected]f7b85372010-02-03 01:11:378357 GLuint service_id;
[email protected]1b0a6752012-02-22 03:44:128358 GLint real_location = -1;
[email protected]f7b85372010-02-03 01:11:378359 Error error;
[email protected]ed9f9cd2013-02-27 21:12:358360 typedef cmds::GetUniformfv::Result Result;
[email protected]939e7362010-05-13 20:49:108361 Result* result;
8362 GLenum result_type;
[email protected]f7b85372010-02-03 01:11:378363 if (GetUniformSetup(
[email protected]1b0a6752012-02-22 03:44:128364 program, fake_location, c.params_shm_id, c.params_shm_offset,
8365 &error, &real_location, &service_id,
8366 reinterpret_cast<void**>(&result), &result_type)) {
[email protected]939e7362010-05-13 20:49:108367 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
8368 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
8369 GLsizei num_values = result->GetNumResults();
[email protected]40d90a22013-04-09 03:39:558370 scoped_ptr<GLint[]> temp(new GLint[num_values]);
[email protected]1b0a6752012-02-22 03:44:128371 glGetUniformiv(service_id, real_location, temp.get());
[email protected]939e7362010-05-13 20:49:108372 GLfloat* dst = result->GetData();
8373 for (GLsizei ii = 0; ii < num_values; ++ii) {
8374 dst[ii] = (temp[ii] != 0);
8375 }
8376 } else {
[email protected]1b0a6752012-02-22 03:44:128377 glGetUniformfv(service_id, real_location, result->GetData());
[email protected]939e7362010-05-13 20:49:108378 }
[email protected]f7b85372010-02-03 01:11:378379 }
8380 return error;
[email protected]96449d2c2009-11-25 00:01:328381}
8382
[email protected]f7a64ee2010-02-01 22:24:148383error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
[email protected]ed9f9cd2013-02-27 21:12:358384 uint32 immediate_data_size, const cmds::GetShaderPrecisionFormat& c) {
[email protected]0bfd9882010-02-05 23:02:258385 GLenum shader_type = static_cast<GLenum>(c.shadertype);
8386 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
[email protected]ed9f9cd2013-02-27 21:12:358387 typedef cmds::GetShaderPrecisionFormat::Result Result;
[email protected]0bfd9882010-02-05 23:02:258388 Result* result = GetSharedMemoryAs<Result*>(
8389 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8390 if (!result) {
8391 return error::kOutOfBounds;
8392 }
[email protected]07d0cc82010-02-17 04:51:408393 // Check that the client initialized the result.
8394 if (result->success != 0) {
8395 return error::kInvalidArguments;
8396 }
[email protected]9438b012010-06-15 22:55:058397 if (!validators_->shader_type.IsValid(shader_type)) {
[email protected]ab09b612013-03-11 22:11:518398 LOCAL_SET_GL_ERROR_INVALID_ENUM(
[email protected]f80e6e12012-08-31 00:43:538399 "glGetShaderPrecisionFormat", shader_type, "shader_type");
[email protected]8eee29c2010-04-29 03:38:298400 return error::kNoError;
8401 }
[email protected]9438b012010-06-15 22:55:058402 if (!validators_->shader_precision.IsValid(precision_type)) {
[email protected]ab09b612013-03-11 22:11:518403 LOCAL_SET_GL_ERROR_INVALID_ENUM(
[email protected]f80e6e12012-08-31 00:43:538404 "glGetShaderPrecisionFormat", precision_type, "precision_type");
[email protected]8eee29c2010-04-29 03:38:298405 return error::kNoError;
8406 }
8407
8408 result->success = 1; // true
[email protected]d8bc3ec2013-03-07 06:28:408409
[email protected]46c86752013-05-21 05:08:398410 GLint range[2] = { 0, 0 };
[email protected]d8bc3ec2013-03-07 06:28:408411 GLint precision = 0;
[email protected]8dc1bf92013-03-12 03:58:218412 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
[email protected]d8bc3ec2013-03-07 06:28:408413
8414 result->min_range = range[0];
8415 result->max_range = range[1];
8416 result->precision = precision;
8417
[email protected]f7a64ee2010-02-01 22:24:148418 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328419}
8420
[email protected]f7a64ee2010-02-01 22:24:148421error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
[email protected]ed9f9cd2013-02-27 21:12:358422 uint32 immediate_data_size, const cmds::GetAttachedShaders& c) {
[email protected]0bfd9882010-02-05 23:02:258423 uint32 result_size = c.result_size;
[email protected]df37b9932013-03-08 05:21:428424 GLuint program_id = static_cast<GLuint>(c.program);
8425 Program* program = GetProgramInfoNotShader(
8426 program_id, "glGetAttachedShaders");
8427 if (!program) {
[email protected]0bfd9882010-02-05 23:02:258428 return error::kNoError;
8429 }
[email protected]ed9f9cd2013-02-27 21:12:358430 typedef cmds::GetAttachedShaders::Result Result;
[email protected]0bfd9882010-02-05 23:02:258431 uint32 max_count = Result::ComputeMaxResults(result_size);
8432 Result* result = GetSharedMemoryAs<Result*>(
8433 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
8434 if (!result) {
8435 return error::kOutOfBounds;
8436 }
[email protected]07d0cc82010-02-17 04:51:408437 // Check that the client initialized the result.
8438 if (result->size != 0) {
8439 return error::kInvalidArguments;
8440 }
[email protected]0bfd9882010-02-05 23:02:258441 GLsizei count = 0;
[email protected]ae51d192010-04-27 00:48:038442 glGetAttachedShaders(
[email protected]df37b9932013-03-08 05:21:428443 program->service_id(), max_count, &count, result->GetData());
[email protected]0bfd9882010-02-05 23:02:258444 for (GLsizei ii = 0; ii < count; ++ii) {
[email protected]ae51d192010-04-27 00:48:038445 if (!shader_manager()->GetClientId(result->GetData()[ii],
8446 &result->GetData()[ii])) {
[email protected]0bfd9882010-02-05 23:02:258447 NOTREACHED();
8448 return error::kGenericError;
8449 }
8450 }
8451 result->SetNumResults(count);
[email protected]f7a64ee2010-02-01 22:24:148452 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328453}
8454
[email protected]f7a64ee2010-02-01 22:24:148455error::Error GLES2DecoderImpl::HandleGetActiveUniform(
[email protected]ed9f9cd2013-02-27 21:12:358456 uint32 immediate_data_size, const cmds::GetActiveUniform& c) {
[email protected]df37b9932013-03-08 05:21:428457 GLuint program_id = c.program;
[email protected]0bfd9882010-02-05 23:02:258458 GLuint index = c.index;
8459 uint32 name_bucket_id = c.name_bucket_id;
[email protected]ed9f9cd2013-02-27 21:12:358460 typedef cmds::GetActiveUniform::Result Result;
[email protected]0bfd9882010-02-05 23:02:258461 Result* result = GetSharedMemoryAs<Result*>(
8462 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8463 if (!result) {
8464 return error::kOutOfBounds;
8465 }
[email protected]07d0cc82010-02-17 04:51:408466 // Check that the client initialized the result.
8467 if (result->success != 0) {
8468 return error::kInvalidArguments;
8469 }
[email protected]df37b9932013-03-08 05:21:428470 Program* program = GetProgramInfoNotShader(
8471 program_id, "glGetActiveUniform");
8472 if (!program) {
[email protected]0bfd9882010-02-05 23:02:258473 return error::kNoError;
8474 }
[email protected]ed9f9cd2013-02-27 21:12:358475 const Program::UniformInfo* uniform_info =
[email protected]df37b9932013-03-08 05:21:428476 program->GetUniformInfo(index);
[email protected]0bfd9882010-02-05 23:02:258477 if (!uniform_info) {
[email protected]ab09b612013-03-11 22:11:518478 LOCAL_SET_GL_ERROR(
8479 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
[email protected]0bfd9882010-02-05 23:02:258480 return error::kNoError;
8481 }
8482 result->success = 1; // true.
8483 result->size = uniform_info->size;
8484 result->type = uniform_info->type;
8485 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:298486 bucket->SetFromString(uniform_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:148487 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328488}
8489
[email protected]f7a64ee2010-02-01 22:24:148490error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
[email protected]ed9f9cd2013-02-27 21:12:358491 uint32 immediate_data_size, const cmds::GetActiveAttrib& c) {
[email protected]df37b9932013-03-08 05:21:428492 GLuint program_id = c.program;
[email protected]0bfd9882010-02-05 23:02:258493 GLuint index = c.index;
8494 uint32 name_bucket_id = c.name_bucket_id;
[email protected]ed9f9cd2013-02-27 21:12:358495 typedef cmds::GetActiveAttrib::Result Result;
[email protected]0bfd9882010-02-05 23:02:258496 Result* result = GetSharedMemoryAs<Result*>(
8497 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8498 if (!result) {
8499 return error::kOutOfBounds;
8500 }
[email protected]07d0cc82010-02-17 04:51:408501 // Check that the client initialized the result.
8502 if (result->success != 0) {
8503 return error::kInvalidArguments;
8504 }
[email protected]df37b9932013-03-08 05:21:428505 Program* program = GetProgramInfoNotShader(
8506 program_id, "glGetActiveAttrib");
8507 if (!program) {
[email protected]0bfd9882010-02-05 23:02:258508 return error::kNoError;
8509 }
[email protected]ed9f9cd2013-02-27 21:12:358510 const Program::VertexAttrib* attrib_info =
[email protected]df37b9932013-03-08 05:21:428511 program->GetAttribInfo(index);
[email protected]0bfd9882010-02-05 23:02:258512 if (!attrib_info) {
[email protected]ab09b612013-03-11 22:11:518513 LOCAL_SET_GL_ERROR(
8514 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
[email protected]0bfd9882010-02-05 23:02:258515 return error::kNoError;
8516 }
8517 result->success = 1; // true.
8518 result->size = attrib_info->size;
8519 result->type = attrib_info->type;
8520 Bucket* bucket = CreateBucket(name_bucket_id);
[email protected]262d7aa2010-12-03 22:07:298521 bucket->SetFromString(attrib_info->name.c_str());
[email protected]f7a64ee2010-02-01 22:24:148522 return error::kNoError;
[email protected]96449d2c2009-11-25 00:01:328523}
8524
[email protected]b273e432010-04-12 17:23:588525error::Error GLES2DecoderImpl::HandleShaderBinary(
[email protected]ed9f9cd2013-02-27 21:12:358526 uint32 immediate_data_size, const cmds::ShaderBinary& c) {
[email protected]b273e432010-04-12 17:23:588527#if 1 // No binary shader support.
[email protected]ab09b612013-03-11 22:11:518528 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
[email protected]b273e432010-04-12 17:23:588529 return error::kNoError;
8530#else
8531 GLsizei n = static_cast<GLsizei>(c.n);
8532 if (n < 0) {
[email protected]ab09b612013-03-11 22:11:518533 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
[email protected]b273e432010-04-12 17:23:588534 return error::kNoError;
8535 }
8536 GLsizei length = static_cast<GLsizei>(c.length);
8537 if (length < 0) {
[email protected]ab09b612013-03-11 22:11:518538 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
[email protected]b273e432010-04-12 17:23:588539 return error::kNoError;
8540 }
8541 uint32 data_size;
8542 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
8543 return error::kOutOfBounds;
8544 }
8545 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
8546 c.shaders_shm_id, c.shaders_shm_offset, data_size);
8547 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
8548 const void* binary = GetSharedMemoryAs<const void*>(
8549 c.binary_shm_id, c.binary_shm_offset, length);
8550 if (shaders == NULL || binary == NULL) {
8551 return error::kOutOfBounds;
8552 }
8553 scoped_array<GLuint> service_ids(new GLuint[n]);
8554 for (GLsizei ii = 0; ii < n; ++ii) {
[email protected]df37b9932013-03-08 05:21:428555 Shader* shader = GetShader(shaders[ii]);
8556 if (!shader) {
[email protected]ab09b612013-03-11 22:11:518557 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
[email protected]b273e432010-04-12 17:23:588558 return error::kNoError;
8559 }
[email protected]df37b9932013-03-08 05:21:428560 service_ids[ii] = shader->service_id();
[email protected]b273e432010-04-12 17:23:588561 }
8562 // TODO(gman): call glShaderBinary
8563 return error::kNoError;
8564#endif
8565}
8566
[email protected]6d792ee12013-05-15 00:40:568567void GLES2DecoderImpl::DoSwapBuffers() {
[email protected]64ace852011-05-19 21:49:498568 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
[email protected]a7266a92012-06-28 02:11:088569
[email protected]64ace852011-05-19 21:49:498570 int this_frame_number = frame_number_++;
[email protected]2ac620e52012-07-23 20:31:428571 // TRACE_EVENT for gpu tests:
8572 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
[email protected]c76faea2013-03-26 07:42:428573 TRACE_EVENT_SCOPE_THREAD,
[email protected]2ac620e52012-07-23 20:31:428574 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
8575 "width", (is_offscreen ? offscreen_size_.width() :
8576 surface_->GetSize().width()));
[email protected]6d792ee12013-05-15 00:40:568577 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
[email protected]64ace852011-05-19 21:49:498578 "offscreen", is_offscreen,
8579 "frame", this_frame_number);
[email protected]6217d392010-03-25 22:08:358580 // If offscreen then don't actually SwapBuffers to the display. Just copy
8581 // the rendered frame to another frame buffer.
[email protected]64ace852011-05-19 21:49:498582 if (is_offscreen) {
[email protected]111975c62012-09-06 01:37:318583 TRACE_EVENT2("gpu", "Offscreen",
8584 "width", offscreen_size_.width(), "height", offscreen_size_.height());
[email protected]1fb8c482011-08-31 01:01:538585 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
8586 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
8587 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
8588 // fix this.
[email protected]62e155e2012-10-23 22:43:158589 if (workarounds().needs_offscreen_buffer_workaround) {
[email protected]1fb8c482011-08-31 01:01:538590 offscreen_saved_frame_buffer_->Create();
8591 glFinish();
8592 }
8593
8594 // Allocate the offscreen saved color texture.
8595 DCHECK(offscreen_saved_color_format_);
8596 offscreen_saved_color_texture_->AllocateStorage(
[email protected]678a73f2012-12-19 19:22:098597 offscreen_size_, offscreen_saved_color_format_, false);
[email protected]1fb8c482011-08-31 01:01:538598
8599 offscreen_saved_frame_buffer_->AttachRenderTexture(
8600 offscreen_saved_color_texture_.get());
[email protected]f0cfe752013-01-14 01:09:058601 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
8602 if (offscreen_saved_frame_buffer_->CheckStatus() !=
8603 GL_FRAMEBUFFER_COMPLETE) {
8604 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
8605 << "because offscreen saved FBO was incomplete.";
[email protected]6d792ee12013-05-15 00:40:568606 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
8607 return;
[email protected]f0cfe752013-01-14 01:09:058608 }
[email protected]1fb8c482011-08-31 01:01:538609
[email protected]f0cfe752013-01-14 01:09:058610 // Clear the offscreen color texture.
8611 // TODO(piman): Is this still necessary?
8612 {
8613 ScopedFrameBufferBinder binder(this,
8614 offscreen_saved_frame_buffer_->id());
8615 glClearColor(0, 0, 0, 0);
8616 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
8617 glDisable(GL_SCISSOR_TEST);
8618 glClear(GL_COLOR_BUFFER_BIT);
8619 RestoreClearState();
8620 }
[email protected]1fb8c482011-08-31 01:01:538621 }
8622
8623 UpdateParentTextureInfo();
8624 }
8625
[email protected]f0cfe752013-01-14 01:09:058626 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
[email protected]6d792ee12013-05-15 00:40:568627 return;
[email protected]ab09b612013-03-11 22:11:518628 ScopedGLErrorSuppressor suppressor(
[email protected]6d792ee12013-05-15 00:40:568629 "GLES2DecoderImpl::DoSwapBuffers", this);
[email protected]6217d392010-03-25 22:08:358630
[email protected]34ff8b0c2010-10-01 20:06:028631 if (IsOffscreenBufferMultisampled()) {
[email protected]51411e32012-01-19 20:21:138632 // For multisampled buffers, resolve the frame buffer.
[email protected]de26b3c2011-08-03 21:54:278633 ScopedResolvedFrameBufferBinder binder(this, true, false);
[email protected]b86b14982010-10-11 18:45:488634 } else {
[email protected]069944672012-04-25 20:52:238635 ScopedFrameBufferBinder binder(this,
8636 offscreen_target_frame_buffer_->id());
[email protected]51411e32012-01-19 20:21:138637
[email protected]069944672012-04-25 20:52:238638 if (offscreen_target_buffer_preserved_) {
8639 // Copy the target frame buffer to the saved offscreen texture.
8640 offscreen_saved_color_texture_->Copy(
8641 offscreen_saved_color_texture_->size(),
8642 offscreen_saved_color_format_);
8643 } else {
8644 // Flip the textures in the parent context via the texture manager.
8645 if (!!offscreen_saved_color_texture_info_.get())
[email protected]370eaf12013-05-18 09:19:498646 offscreen_saved_color_texture_info_->texture()->
[email protected]069944672012-04-25 20:52:238647 SetServiceId(offscreen_target_color_texture_->id());
[email protected]8a61d872012-01-20 12:43:568648
[email protected]069944672012-04-25 20:52:238649 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
8650 offscreen_target_frame_buffer_->AttachRenderTexture(
8651 offscreen_target_color_texture_.get());
[email protected]b86b14982010-10-11 18:45:488652 }
[email protected]069944672012-04-25 20:52:238653
8654 // Ensure the side effects of the copy are visible to the parent
8655 // context. There is no need to do this for ANGLE because it uses a
8656 // single D3D device for all contexts.
8657 if (!IsAngle())
8658 glFlush();
[email protected]0c8c9d22010-06-25 17:36:398659 }
[email protected]6217d392010-03-25 22:08:358660 } else {
[email protected]111975c62012-09-06 01:37:318661 TRACE_EVENT2("gpu", "Onscreen",
8662 "width", surface_->GetSize().width(),
8663 "height", surface_->GetSize().height());
[email protected]f62a5ab2011-05-23 20:34:158664 if (!surface_->SwapBuffers()) {
[email protected]d0498742010-09-20 20:27:018665 LOG(ERROR) << "Context lost because SwapBuffers failed.";
[email protected]6d792ee12013-05-15 00:40:568666 LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB);
[email protected]d0498742010-09-20 20:27:018667 }
[email protected]6217d392010-03-25 22:08:358668 }
[email protected]6217d392010-03-25 22:08:358669}
8670
[email protected]d4239852011-08-12 04:51:228671error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:358672 uint32 immediate_data_size, const cmds::EnableFeatureCHROMIUM& c) {
[email protected]b1d2dcb2010-05-17 19:24:188673 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:288674 if (!bucket || bucket->size() == 0) {
8675 return error::kInvalidArguments;
8676 }
[email protected]ed9f9cd2013-02-27 21:12:358677 typedef cmds::EnableFeatureCHROMIUM::Result Result;
[email protected]b1d2dcb2010-05-17 19:24:188678 Result* result = GetSharedMemoryAs<Result*>(
8679 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8680 if (!result) {
8681 return error::kOutOfBounds;
[email protected]4e8a5b122010-05-08 22:00:108682 }
[email protected]b1d2dcb2010-05-17 19:24:188683 // Check that the client initialized the result.
8684 if (*result != 0) {
8685 return error::kInvalidArguments;
8686 }
8687 std::string feature_str;
8688 if (!bucket->GetAsString(&feature_str)) {
8689 return error::kInvalidArguments;
8690 }
8691
8692 // TODO(gman): make this some kind of table to function pointer thingy.
[email protected]d4239852011-08-12 04:51:228693 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
[email protected]b1d2dcb2010-05-17 19:24:188694 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
[email protected]d4239852011-08-12 04:51:228695 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
[email protected]8fbedc02010-11-18 18:43:408696 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
8697 // TODO(gman): decide how to remove the need for this const_cast.
8698 // I could make validators_ non const but that seems bad as this is the only
8699 // place it is needed. I could make some special friend class of validators
8700 // just to allow this to set them. That seems silly. I could refactor this
8701 // code to use the extension mechanism or the initialization attributes to
8702 // turn this feature on. Given that the only real point of this is to make
8703 // the conformance tests pass and given that there is lots of real work that
8704 // needs to be done it seems like refactoring for one to one of those
8705 // methods is a very low priority.
8706 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
[email protected]f0d74742011-10-03 16:31:048707 } else if (feature_str.compare("webgl_enable_glsl_webgl_validation") == 0) {
8708 force_webgl_glsl_validation_ = true;
8709 InitializeShaderTranslator();
[email protected]b1d2dcb2010-05-17 19:24:188710 } else {
8711 return error::kNoError;
8712 }
8713
8714 *result = 1; // true.
8715 return error::kNoError;
[email protected]4e8a5b122010-05-08 22:00:108716}
8717
[email protected]c2f8c8402010-12-06 18:07:248718error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
8719 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:358720 const cmds::GetRequestableExtensionsCHROMIUM& c) {
[email protected]c2f8c8402010-12-06 18:07:248721 Bucket* bucket = CreateBucket(c.bucket_id);
[email protected]ed9f9cd2013-02-27 21:12:358722 scoped_refptr<FeatureInfo> info(new FeatureInfo());
[email protected]e82fb792011-09-22 00:33:298723 info->Initialize(disallowed_features_, NULL);
[email protected]c2f8c8402010-12-06 18:07:248724 bucket->SetFromString(info->extensions().c_str());
8725 return error::kNoError;
8726}
8727
8728error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:358729 uint32 immediate_data_size, const cmds::RequestExtensionCHROMIUM& c) {
[email protected]c2f8c8402010-12-06 18:07:248730 Bucket* bucket = GetBucket(c.bucket_id);
[email protected]12f93d82011-10-17 21:16:288731 if (!bucket || bucket->size() == 0) {
8732 return error::kInvalidArguments;
8733 }
[email protected]c2f8c8402010-12-06 18:07:248734 std::string feature_str;
8735 if (!bucket->GetAsString(&feature_str)) {
8736 return error::kInvalidArguments;
8737 }
8738
[email protected]4b7eba92013-01-08 02:23:568739 bool desire_webgl_glsl_validation =
8740 feature_str.find("GL_CHROMIUM_webglsl") != std::string::npos;
8741 bool desire_standard_derivatives = false;
[email protected]70dc60932013-06-04 03:33:498742 bool desire_frag_depth = false;
[email protected]aff39ac82013-06-08 04:53:138743 bool desire_draw_buffers = false;
[email protected]4b7eba92013-01-08 02:23:568744 if (force_webgl_glsl_validation_) {
8745 desire_standard_derivatives =
8746 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
[email protected]70dc60932013-06-04 03:33:498747 desire_frag_depth =
8748 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
[email protected]aff39ac82013-06-08 04:53:138749 desire_draw_buffers =
8750 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
[email protected]f0d74742011-10-03 16:31:048751 }
8752
[email protected]4b7eba92013-01-08 02:23:568753 if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
[email protected]70dc60932013-06-04 03:33:498754 desire_standard_derivatives != derivatives_explicitly_enabled_ ||
[email protected]aff39ac82013-06-08 04:53:138755 desire_frag_depth != frag_depth_explicitly_enabled_ ||
8756 desire_draw_buffers != draw_buffers_explicitly_enabled_) {
[email protected]70dc60932013-06-04 03:33:498757 force_webgl_glsl_validation_ |= desire_webgl_glsl_validation;
8758 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
8759 frag_depth_explicitly_enabled_ |= desire_frag_depth;
[email protected]aff39ac82013-06-08 04:53:138760 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
[email protected]c2f8c8402010-12-06 18:07:248761 InitializeShaderTranslator();
8762 }
8763
[email protected]302ce6d2011-07-07 23:28:118764 UpdateCapabilities();
8765
[email protected]c2f8c8402010-12-06 18:07:248766 return error::kNoError;
8767}
8768
[email protected]372e0412011-06-28 16:08:568769error::Error GLES2DecoderImpl::HandleGetMultipleIntegervCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:358770 uint32 immediate_data_size, const cmds::GetMultipleIntegervCHROMIUM& c) {
[email protected]372e0412011-06-28 16:08:568771 GLuint count = c.count;
8772 uint32 pnames_size;
8773 if (!SafeMultiplyUint32(count, sizeof(GLenum), &pnames_size)) {
8774 return error::kOutOfBounds;
8775 }
8776 const GLenum* pnames = GetSharedMemoryAs<const GLenum*>(
8777 c.pnames_shm_id, c.pnames_shm_offset, pnames_size);
8778 if (pnames == NULL) {
8779 return error::kOutOfBounds;
8780 }
8781
8782 // We have to copy them since we use them twice so the client
8783 // can't change them between the time we validate them and the time we use
8784 // them.
[email protected]40d90a22013-04-09 03:39:558785 scoped_ptr<GLenum[]> enums(new GLenum[count]);
[email protected]372e0412011-06-28 16:08:568786 memcpy(enums.get(), pnames, pnames_size);
8787
8788 // Count up the space needed for the result.
8789 uint32 num_results = 0;
8790 for (GLuint ii = 0; ii < count; ++ii) {
8791 uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
8792 if (num == 0) {
[email protected]ab09b612013-03-11 22:11:518793 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8794 "glGetMulitpleCHROMIUM", enums[ii], "pname");
[email protected]372e0412011-06-28 16:08:568795 return error::kNoError;
8796 }
8797 // Num will never be more than 4.
8798 DCHECK_LE(num, 4u);
[email protected]3aad1a32012-09-07 20:54:478799 if (!SafeAddUint32(num_results, num, &num_results)) {
[email protected]372e0412011-06-28 16:08:568800 return error::kOutOfBounds;
8801 }
8802 }
8803
8804 uint32 result_size = 0;
8805 if (!SafeMultiplyUint32(num_results, sizeof(GLint), &result_size)) {
8806 return error::kOutOfBounds;
8807 }
8808
8809 if (result_size != static_cast<uint32>(c.size)) {
[email protected]ab09b612013-03-11 22:11:518810 LOCAL_SET_GL_ERROR(
8811 GL_INVALID_VALUE,
8812 "glGetMulitpleCHROMIUM", "bad size GL_INVALID_VALUE");
[email protected]372e0412011-06-28 16:08:568813 return error::kNoError;
8814 }
8815
8816 GLint* results = GetSharedMemoryAs<GLint*>(
8817 c.results_shm_id, c.results_shm_offset, result_size);
8818 if (results == NULL) {
8819 return error::kOutOfBounds;
8820 }
8821
8822 // Check the results have been cleared in case the context was lost.
8823 for (uint32 ii = 0; ii < num_results; ++ii) {
8824 if (results[ii]) {
8825 return error::kInvalidArguments;
8826 }
8827 }
8828
8829 // Get each result.
8830 GLint* start = results;
8831 for (GLuint ii = 0; ii < count; ++ii) {
8832 GLsizei num_written = 0;
[email protected]d058bca2012-11-26 10:27:268833 if (!state_.GetStateAsGLint(enums[ii], results, &num_written) &&
[email protected]f63b1232012-10-31 07:03:538834 !GetHelper(enums[ii], results, &num_written)) {
[email protected]b0ce0982013-05-13 18:51:488835 DoGetIntegerv(enums[ii], results);
[email protected]372e0412011-06-28 16:08:568836 }
8837 results += num_written;
8838 }
8839
8840 // Just to verify. Should this be a DCHECK?
8841 if (static_cast<uint32>(results - start) != num_results) {
8842 return error::kOutOfBounds;
8843 }
8844
8845 return error::kNoError;
8846}
8847
[email protected]2318d342011-07-11 22:27:428848error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:358849 uint32 immediate_data_size, const cmds::GetProgramInfoCHROMIUM& c) {
[email protected]df37b9932013-03-08 05:21:428850 GLuint program_id = static_cast<GLuint>(c.program);
[email protected]2318d342011-07-11 22:27:428851 uint32 bucket_id = c.bucket_id;
8852 Bucket* bucket = CreateBucket(bucket_id);
8853 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
[email protected]df37b9932013-03-08 05:21:428854 Program* program = NULL;
8855 program = GetProgram(program_id);
8856 if (!program || !program->IsValid()) {
[email protected]9a14ae612011-08-08 17:51:468857 return error::kNoError;
[email protected]2318d342011-07-11 22:27:428858 }
[email protected]df37b9932013-03-08 05:21:428859 program->GetProgramInfo(program_manager(), bucket);
[email protected]2318d342011-07-11 22:27:428860 return error::kNoError;
8861}
8862
[email protected]38d139d2011-07-14 00:38:438863error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
8864 switch (reset_status_) {
[email protected]ad84a3a2012-06-08 21:42:438865 case GL_NO_ERROR:
8866 // TODO(kbr): improve the precision of the error code in this case.
8867 // Consider delegating to context for error code if MakeCurrent fails.
8868 return error::kUnknown;
8869 case GL_GUILTY_CONTEXT_RESET_ARB:
8870 return error::kGuilty;
8871 case GL_INNOCENT_CONTEXT_RESET_ARB:
8872 return error::kInnocent;
8873 case GL_UNKNOWN_CONTEXT_RESET_ARB:
8874 return error::kUnknown;
[email protected]38d139d2011-07-14 00:38:438875 }
8876
8877 NOTREACHED();
8878 return error::kUnknown;
8879}
8880
8881bool GLES2DecoderImpl::WasContextLost() {
[email protected]c4485aad62012-12-17 10:19:098882 if (reset_status_ != GL_NO_ERROR) {
8883 return true;
8884 }
[email protected]706b69f2012-07-27 04:59:308885 if (context_->WasAllocatedUsingRobustnessExtension()) {
8886 GLenum status = GL_NO_ERROR;
8887 if (has_robustness_extension_)
8888 status = glGetGraphicsResetStatusARB();
[email protected]38d139d2011-07-14 00:38:438889 if (status != GL_NO_ERROR) {
8890 // The graphics card was reset. Signal a lost context to the application.
8891 reset_status_ = status;
[email protected]93a7d98f2013-07-11 00:04:228892 reset_by_robustness_extension_ = true;
[email protected]38d139d2011-07-14 00:38:438893 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
[email protected]c4485aad62012-12-17 10:19:098894 << " context lost via ARB/EXT_robustness. Reset status = "
8895 << GLES2Util::GetStringEnum(status);
[email protected]38d139d2011-07-14 00:38:438896 return true;
8897 }
8898 }
8899 return false;
8900}
8901
[email protected]93a7d98f2013-07-11 00:04:228902bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() {
8903 return WasContextLost() && reset_by_robustness_extension_;
8904}
8905
[email protected]c4485aad62012-12-17 10:19:098906void GLES2DecoderImpl::LoseContext(uint32 reset_status) {
8907 // Only loses the context once.
8908 if (reset_status_ != GL_NO_ERROR) {
8909 return;
8910 }
8911
8912 // Marks this context as lost.
8913 reset_status_ = reset_status;
8914 current_decoder_error_ = error::kLostContext;
[email protected]c4485aad62012-12-17 10:19:098915}
8916
8917error::Error GLES2DecoderImpl::HandleLoseContextCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:358918 uint32 immediate_data_size, const cmds::LoseContextCHROMIUM& c) {
[email protected]c4485aad62012-12-17 10:19:098919 GLenum current = static_cast<GLenum>(c.current);
8920 GLenum other = static_cast<GLenum>(c.other);
8921 if (!validators_->reset_status.IsValid(current)) {
[email protected]ab09b612013-03-11 22:11:518922 LOCAL_SET_GL_ERROR_INVALID_ENUM(
8923 "glLoseContextCHROMIUM", current, "current");
[email protected]c4485aad62012-12-17 10:19:098924 }
8925 if (!validators_->reset_status.IsValid(other)) {
[email protected]ab09b612013-03-11 22:11:518926 LOCAL_SET_GL_ERROR_INVALID_ENUM("glLoseContextCHROMIUM", other, "other");
[email protected]c4485aad62012-12-17 10:19:098927 }
8928 group_->LoseContexts(other);
8929 reset_status_ = current;
8930 current_decoder_error_ = error::kLostContext;
8931 return error::kLostContext;
8932}
8933
[email protected]b096d032013-03-08 03:08:018934error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
8935 uint32 immediate_data_size, const cmds::InsertSyncPointCHROMIUM& c) {
8936 return error::kUnknownCommand;
8937}
8938
[email protected]840a7e462013-02-27 01:29:518939error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:358940 uint32 immediate_data_size, const cmds::WaitSyncPointCHROMIUM& c) {
[email protected]840a7e462013-02-27 01:29:518941 if (wait_sync_point_callback_.is_null())
8942 return error::kNoError;
8943
8944 return wait_sync_point_callback_.Run(c.sync_point) ?
8945 error::kNoError : error::kDeferCommandUntilLater;
8946}
8947
[email protected]882ba1e22012-03-08 19:02:538948bool GLES2DecoderImpl::GenQueriesEXTHelper(
8949 GLsizei n, const GLuint* client_ids) {
8950 for (GLsizei ii = 0; ii < n; ++ii) {
8951 if (query_manager_->GetQuery(client_ids[ii])) {
8952 return false;
8953 }
8954 }
[email protected]c45f1972012-03-14 07:27:368955 // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
[email protected]882ba1e22012-03-08 19:02:538956 return true;
8957}
8958
8959void GLES2DecoderImpl::DeleteQueriesEXTHelper(
8960 GLsizei n, const GLuint* client_ids) {
8961 for (GLsizei ii = 0; ii < n; ++ii) {
8962 QueryManager::Query* query = query_manager_->GetQuery(client_ids[ii]);
8963 if (query && !query->IsDeleted()) {
[email protected]7cd76fd2013-06-02 21:11:118964 if (query == state_.current_query.get()) {
[email protected]e259eb412012-10-13 05:47:248965 state_.current_query = NULL;
[email protected]882ba1e22012-03-08 19:02:538966 }
[email protected]c45f1972012-03-14 07:27:368967 query->Destroy(true);
[email protected]882ba1e22012-03-08 19:02:538968 query_manager_->RemoveQuery(client_ids[ii]);
8969 }
8970 }
8971}
8972
[email protected]22e3f552012-03-13 01:54:198973bool GLES2DecoderImpl::ProcessPendingQueries() {
8974 if (query_manager_.get() == NULL) {
8975 return false;
8976 }
[email protected]c45f1972012-03-14 07:27:368977 if (!query_manager_->ProcessPendingQueries()) {
[email protected]22e3f552012-03-13 01:54:198978 current_decoder_error_ = error::kOutOfBounds;
8979 }
8980 return query_manager_->HavePendingQueries();
8981}
8982
[email protected]5a36dc132013-07-23 23:17:558983// Note that if there are no pending readpixels right now,
8984// this function will call the callback immediately.
8985void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
8986 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
8987 pending_readpixel_fences_.back()->callbacks.push_back(callback);
8988 } else {
8989 callback.Run();
8990 }
8991}
8992
8993void GLES2DecoderImpl::ProcessPendingReadPixels() {
8994 while (!pending_readpixel_fences_.empty() &&
8995 pending_readpixel_fences_.front()->fence->HasCompleted()) {
8996 std::vector<base::Closure> callbacks =
8997 pending_readpixel_fences_.front()->callbacks;
8998 pending_readpixel_fences_.pop();
8999 for (size_t i = 0; i < callbacks.size(); i++) {
9000 callbacks[i].Run();
9001 }
9002 }
9003}
9004
[email protected]2b1767cf2013-03-16 09:25:059005bool GLES2DecoderImpl::HasMoreIdleWork() {
[email protected]5a36dc132013-07-23 23:17:559006 return !pending_readpixel_fences_.empty() ||
9007 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
[email protected]2b1767cf2013-03-16 09:25:059008}
9009
9010void GLES2DecoderImpl::PerformIdleWork() {
[email protected]5a36dc132013-07-23 23:17:559011 ProcessPendingReadPixels();
[email protected]b68b100752013-06-05 08:34:489012 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
[email protected]2b1767cf2013-03-16 09:25:059013 return;
[email protected]b68b100752013-06-05 08:34:489014 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
[email protected]2b1767cf2013-03-16 09:25:059015 ProcessFinishedAsyncTransfers();
9016}
9017
[email protected]882ba1e22012-03-08 19:02:539018error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
[email protected]ed9f9cd2013-02-27 21:12:359019 uint32 immediate_data_size, const cmds::BeginQueryEXT& c) {
[email protected]882ba1e22012-03-08 19:02:539020 GLenum target = static_cast<GLenum>(c.target);
9021 GLuint client_id = static_cast<GLuint>(c.id);
9022 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
9023 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
9024
[email protected]c45f1972012-03-14 07:27:369025 switch (target) {
9026 case GL_COMMANDS_ISSUED_CHROMIUM:
[email protected]fb4bf5822012-10-23 21:25:559027 case GL_LATENCY_QUERY_CHROMIUM:
[email protected]5537605d2013-08-27 05:22:319028 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
9029 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
[email protected]620b0db02013-03-20 15:47:009030 case GL_GET_ERROR_QUERY_CHROMIUM:
[email protected]c45f1972012-03-14 07:27:369031 break;
9032 default:
[email protected]62e155e2012-10-23 22:43:159033 if (!features().occlusion_query_boolean) {
[email protected]ab09b612013-03-11 22:11:519034 LOCAL_SET_GL_ERROR(
[email protected]620b0db02013-03-20 15:47:009035 GL_INVALID_OPERATION, "glBeginQueryEXT",
9036 "not enabled for occlusion queries");
[email protected]c45f1972012-03-14 07:27:369037 return error::kNoError;
9038 }
9039 break;
[email protected]882ba1e22012-03-08 19:02:539040 }
9041
[email protected]5a36dc132013-07-23 23:17:559042 // TODO(hubbe): Make it possible to have one query per type running at the
9043 // same time.
[email protected]7cd76fd2013-06-02 21:11:119044 if (state_.current_query.get()) {
[email protected]ab09b612013-03-11 22:11:519045 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439046 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
[email protected]882ba1e22012-03-08 19:02:539047 return error::kNoError;
9048 }
9049
9050 if (client_id == 0) {
[email protected]ab09b612013-03-11 22:11:519051 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
[email protected]882ba1e22012-03-08 19:02:539052 return error::kNoError;
9053 }
9054
9055 QueryManager::Query* query = query_manager_->GetQuery(client_id);
9056 if (!query) {
[email protected]c45f1972012-03-14 07:27:369057 // TODO(gman): Decide if we need this check.
9058 //
[email protected]882ba1e22012-03-08 19:02:539059 // Checks id was made by glGenQueries
[email protected]c45f1972012-03-14 07:27:369060 //
9061 // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
9062 // for all Query ids but from the POV of the command buffer service maybe
9063 // you don't.
9064 //
9065 // The client can enforce this. I don't think the service cares.
9066 //
9067 // IdAllocatorInterface* id_allocator =
9068 // group_->GetIdAllocator(id_namespaces::kQueries);
9069 // if (!id_allocator->InUse(client_id)) {
[email protected]ab09b612013-03-11 22:11:519070 // LOCAL_SET_GL_ERROR(
9071 // GL_INVALID_OPERATION,
9072 // "glBeginQueryEXT", "id not made by glGenQueriesEXT");
[email protected]c45f1972012-03-14 07:27:369073 // return error::kNoError;
9074 // }
9075 query = query_manager_->CreateQuery(
9076 target, client_id, sync_shm_id, sync_shm_offset);
[email protected]882ba1e22012-03-08 19:02:539077 }
9078
[email protected]c45f1972012-03-14 07:27:369079 if (query->target() != target) {
[email protected]ab09b612013-03-11 22:11:519080 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439081 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
[email protected]882ba1e22012-03-08 19:02:539082 return error::kNoError;
9083 } else if (query->shm_id() != sync_shm_id ||
9084 query->shm_offset() != sync_shm_offset) {
9085 DLOG(ERROR) << "Shared memory used by query not the same as before";
9086 return error::kInvalidArguments;
9087 }
9088
[email protected]c45f1972012-03-14 07:27:369089 if (!query_manager_->BeginQuery(query)) {
9090 return error::kOutOfBounds;
9091 }
[email protected]882ba1e22012-03-08 19:02:539092
[email protected]e259eb412012-10-13 05:47:249093 state_.current_query = query;
[email protected]882ba1e22012-03-08 19:02:539094 return error::kNoError;
9095}
9096
9097error::Error GLES2DecoderImpl::HandleEndQueryEXT(
[email protected]ed9f9cd2013-02-27 21:12:359098 uint32 immediate_data_size, const cmds::EndQueryEXT& c) {
[email protected]882ba1e22012-03-08 19:02:539099 GLenum target = static_cast<GLenum>(c.target);
9100 uint32 submit_count = static_cast<GLuint>(c.submit_count);
9101
[email protected]7cd76fd2013-06-02 21:11:119102 if (!state_.current_query.get()) {
[email protected]ab09b612013-03-11 22:11:519103 LOCAL_SET_GL_ERROR(
9104 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
[email protected]882ba1e22012-03-08 19:02:539105 return error::kNoError;
9106 }
[email protected]e259eb412012-10-13 05:47:249107 if (state_.current_query->target() != target) {
[email protected]ab09b612013-03-11 22:11:519108 LOCAL_SET_GL_ERROR(
9109 GL_INVALID_OPERATION,
9110 "glEndQueryEXT", "target does not match active query");
[email protected]882ba1e22012-03-08 19:02:539111 return error::kNoError;
9112 }
[email protected]882ba1e22012-03-08 19:02:539113
[email protected]7cd76fd2013-06-02 21:11:119114 if (!query_manager_->EndQuery(state_.current_query.get(), submit_count)) {
[email protected]c45f1972012-03-14 07:27:369115 return error::kOutOfBounds;
9116 }
9117
[email protected]fe8d73c2013-02-16 22:37:329118 query_manager_->ProcessPendingTransferQueries();
9119
[email protected]e259eb412012-10-13 05:47:249120 state_.current_query = NULL;
[email protected]882ba1e22012-03-08 19:02:539121 return error::kNoError;
9122}
9123
[email protected]944b62f32012-09-27 02:20:469124bool GLES2DecoderImpl::GenVertexArraysOESHelper(
9125 GLsizei n, const GLuint* client_ids) {
[email protected]944b62f32012-09-27 02:20:469126 for (GLsizei ii = 0; ii < n; ++ii) {
9127 if (GetVertexAttribManager(client_ids[ii])) {
9128 return false;
9129 }
9130 }
[email protected]ab4fd7282012-10-12 16:25:579131
[email protected]62e155e2012-10-23 22:43:159132 if (!features().native_vertex_array_object) {
[email protected]ab4fd7282012-10-12 16:25:579133 // Emulated VAO
9134 for (GLsizei ii = 0; ii < n; ++ii) {
9135 CreateVertexAttribManager(client_ids[ii], 0);
9136 }
9137 } else {
[email protected]40d90a22013-04-09 03:39:559138 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
[email protected]ab4fd7282012-10-12 16:25:579139
9140 glGenVertexArraysOES(n, service_ids.get());
9141 for (GLsizei ii = 0; ii < n; ++ii) {
9142 CreateVertexAttribManager(client_ids[ii], service_ids[ii]);
9143 }
[email protected]944b62f32012-09-27 02:20:469144 }
[email protected]ab4fd7282012-10-12 16:25:579145
[email protected]944b62f32012-09-27 02:20:469146 return true;
9147}
9148
9149void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
9150 GLsizei n, const GLuint* client_ids) {
[email protected]944b62f32012-09-27 02:20:469151 for (GLsizei ii = 0; ii < n; ++ii) {
9152 VertexAttribManager* vao =
9153 GetVertexAttribManager(client_ids[ii]);
9154 if (vao && !vao->IsDeleted()) {
[email protected]7cd76fd2013-06-02 21:11:119155 if (state_.vertex_attrib_manager.get() == vao) {
[email protected]e259eb412012-10-13 05:47:249156 state_.vertex_attrib_manager = default_vertex_attrib_manager_;
[email protected]944b62f32012-09-27 02:20:469157 }
9158 RemoveVertexAttribManager(client_ids[ii]);
9159 }
9160 }
9161}
9162
9163void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
[email protected]944b62f32012-09-27 02:20:469164 VertexAttribManager* vao = NULL;
9165 GLuint service_id = 0;
9166 if (client_id != 0) {
9167 vao = GetVertexAttribManager(client_id);
9168 if (!vao) {
9169 // Unlike most Bind* methods, the spec explicitly states that VertexArray
9170 // only allows names that have been previously generated. As such, we do
9171 // not generate new names here.
[email protected]ab09b612013-03-11 22:11:519172 LOCAL_SET_GL_ERROR(
9173 GL_INVALID_OPERATION,
9174 "glBindVertexArrayOES", "bad vertex array id.");
[email protected]944b62f32012-09-27 02:20:469175 current_decoder_error_ = error::kNoError;
9176 return;
9177 } else {
9178 service_id = vao->service_id();
9179 }
[email protected]944b62f32012-09-27 02:20:469180 } else {
[email protected]7cd76fd2013-06-02 21:11:119181 vao = default_vertex_attrib_manager_.get();
[email protected]944b62f32012-09-27 02:20:469182 }
9183
[email protected]ab4fd7282012-10-12 16:25:579184 // Only set the VAO state if it's changed
[email protected]7cd76fd2013-06-02 21:11:119185 if (state_.vertex_attrib_manager.get() != vao) {
[email protected]e259eb412012-10-13 05:47:249186 state_.vertex_attrib_manager = vao;
[email protected]62e155e2012-10-23 22:43:159187 if (!features().native_vertex_array_object) {
[email protected]ab4fd7282012-10-12 16:25:579188 EmulateVertexArrayState();
9189 } else {
9190 glBindVertexArrayOES(service_id);
9191 }
9192 }
9193}
9194
9195// Used when OES_vertex_array_object isn't natively supported
9196void GLES2DecoderImpl::EmulateVertexArrayState() {
9197 // Setup the Vertex attribute state
9198 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
9199 RestoreStateForAttrib(vv);
9200 }
9201
9202 // Setup the element buffer
[email protected]16ccec12013-02-28 03:40:219203 Buffer* element_array_buffer =
[email protected]e259eb412012-10-13 05:47:249204 state_.vertex_attrib_manager->element_array_buffer();
[email protected]ab4fd7282012-10-12 16:25:579205 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
9206 element_array_buffer ? element_array_buffer->service_id() : 0);
[email protected]944b62f32012-09-27 02:20:469207}
9208
9209bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
[email protected]944b62f32012-09-27 02:20:469210 const VertexAttribManager* vao =
9211 GetVertexAttribManager(client_id);
9212 return vao && vao->IsValid() && !vao->IsDeleted();
9213}
9214
[email protected]b0af4f52011-09-28 22:04:429215error::Error GLES2DecoderImpl::HandleCreateStreamTextureCHROMIUM(
9216 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:359217 const cmds::CreateStreamTextureCHROMIUM& c) {
[email protected]62e155e2012-10-23 22:43:159218 if (!features().chromium_stream_texture) {
[email protected]ab09b612013-03-11 22:11:519219 LOCAL_SET_GL_ERROR(
9220 GL_INVALID_OPERATION,
9221 "glOpenStreamTextureCHROMIUM", "not supported.");
[email protected]b0af4f52011-09-28 22:04:429222 return error::kNoError;
9223 }
9224
9225 uint32 client_id = c.client_id;
[email protected]ed9f9cd2013-02-27 21:12:359226 typedef cmds::CreateStreamTextureCHROMIUM::Result Result;
[email protected]b0af4f52011-09-28 22:04:429227 Result* result = GetSharedMemoryAs<Result*>(
9228 c.result_shm_id, c.result_shm_offset, sizeof(*result));
9229
[email protected]e5081262012-01-05 23:09:039230 if (!result)
9231 return error::kOutOfBounds;
[email protected]b0af4f52011-09-28 22:04:429232 *result = GL_ZERO;
[email protected]370eaf12013-05-18 09:19:499233 TextureRef* texture_ref = texture_manager()->GetTexture(client_id);
9234 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519235 LOCAL_SET_GL_ERROR(
9236 GL_INVALID_VALUE,
9237 "glCreateStreamTextureCHROMIUM", "bad texture id.");
[email protected]b0af4f52011-09-28 22:04:429238 return error::kNoError;
9239 }
9240
[email protected]370eaf12013-05-18 09:19:499241 Texture* texture = texture_ref->texture();
[email protected]02965c22013-03-09 02:40:079242 if (texture->IsStreamTexture()) {
[email protected]ab09b612013-03-11 22:11:519243 LOCAL_SET_GL_ERROR(
9244 GL_INVALID_OPERATION,
9245 "glCreateStreamTextureCHROMIUM", "is already a stream texture.");
[email protected]b0af4f52011-09-28 22:04:429246 return error::kNoError;
9247 }
9248
[email protected]02965c22013-03-09 02:40:079249 if (texture->target() && texture->target() != GL_TEXTURE_EXTERNAL_OES) {
[email protected]ab09b612013-03-11 22:11:519250 LOCAL_SET_GL_ERROR(
9251 GL_INVALID_OPERATION,
9252 "glCreateStreamTextureCHROMIUM",
9253 "is already bound to incompatible target.");
[email protected]b0af4f52011-09-28 22:04:429254 return error::kNoError;
9255 }
9256
[email protected]4f9958142013-07-02 03:58:079257 if (!stream_texture_manager())
[email protected]b0af4f52011-09-28 22:04:429258 return error::kInvalidArguments;
9259
[email protected]4f9958142013-07-02 03:58:079260 GLuint object_id = stream_texture_manager()->CreateStreamTexture(
[email protected]02965c22013-03-09 02:40:079261 texture->service_id(), client_id);
[email protected]b0af4f52011-09-28 22:04:429262
9263 if (object_id) {
[email protected]370eaf12013-05-18 09:19:499264 texture_manager()->SetStreamTexture(texture_ref, true);
[email protected]b0af4f52011-09-28 22:04:429265 } else {
[email protected]ab09b612013-03-11 22:11:519266 LOCAL_SET_GL_ERROR(
9267 GL_OUT_OF_MEMORY,
9268 "glCreateStreamTextureCHROMIUM", "failed to create platform texture.");
[email protected]b0af4f52011-09-28 22:04:429269 }
9270
9271 *result = object_id;
9272 return error::kNoError;
9273}
9274
9275error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM(
9276 uint32 immediate_data_size,
[email protected]ed9f9cd2013-02-27 21:12:359277 const cmds::DestroyStreamTextureCHROMIUM& c) {
[email protected]b0af4f52011-09-28 22:04:429278 GLuint client_id = c.texture;
[email protected]370eaf12013-05-18 09:19:499279 TextureRef* texture_ref = texture_manager()->GetTexture(client_id);
[email protected]4f9958142013-07-02 03:58:079280 if (texture_ref && texture_manager()->IsStreamTextureOwner(texture_ref)) {
9281 if (!stream_texture_manager())
[email protected]b0af4f52011-09-28 22:04:429282 return error::kInvalidArguments;
9283
[email protected]4f9958142013-07-02 03:58:079284 stream_texture_manager()->DestroyStreamTexture(texture_ref->service_id());
[email protected]370eaf12013-05-18 09:19:499285 texture_manager()->SetStreamTexture(texture_ref, false);
[email protected]b0af4f52011-09-28 22:04:429286 } else {
[email protected]ab09b612013-03-11 22:11:519287 LOCAL_SET_GL_ERROR(
9288 GL_INVALID_VALUE,
9289 "glDestroyStreamTextureCHROMIUM", "bad texture id.");
[email protected]b0af4f52011-09-28 22:04:429290 }
9291
9292 return error::kNoError;
9293}
9294
[email protected]e51bdf32011-11-23 22:21:469295#if defined(OS_MACOSX)
9296void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
9297 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
9298 texture_id);
9299 if (it != texture_to_io_surface_map_.end()) {
9300 // Found a previous IOSurface bound to this texture; release it.
9301 CFTypeRef surface = it->second;
9302 CFRelease(surface);
9303 texture_to_io_surface_map_.erase(it);
9304 }
9305}
9306#endif
9307
9308void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
9309 GLenum target, GLsizei width, GLsizei height,
9310 GLuint io_surface_id, GLuint plane) {
9311#if defined(OS_MACOSX)
9312 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
[email protected]ab09b612013-03-11 22:11:519313 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439314 GL_INVALID_OPERATION,
9315 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
[email protected]e51bdf32011-11-23 22:21:469316 return;
9317 }
9318
9319 IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize();
9320 if (!surface_support) {
[email protected]ab09b612013-03-11 22:11:519321 LOCAL_SET_GL_ERROR(
9322 GL_INVALID_OPERATION,
9323 "glTexImageIOSurface2DCHROMIUM", "only supported on 10.6.");
[email protected]e51bdf32011-11-23 22:21:469324 return;
9325 }
9326
9327 if (target != GL_TEXTURE_RECTANGLE_ARB) {
9328 // This might be supported in the future, and if we could require
9329 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
9330 // could delete a lot of code. For now, perform strict validation so we
9331 // know what's going on.
[email protected]ab09b612013-03-11 22:11:519332 LOCAL_SET_GL_ERROR(
[email protected]e51bdf32011-11-23 22:21:469333 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439334 "glTexImageIOSurface2DCHROMIUM",
9335 "requires TEXTURE_RECTANGLE_ARB target");
[email protected]e51bdf32011-11-23 22:21:469336 return;
9337 }
9338
[email protected]09d50362012-10-18 20:54:379339 // Default target might be conceptually valid, but disallow it to avoid
9340 // accidents.
[email protected]c986af502013-08-14 01:04:449341 TextureRef* texture_ref =
9342 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
[email protected]370eaf12013-05-18 09:19:499343 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519344 LOCAL_SET_GL_ERROR(
9345 GL_INVALID_OPERATION,
9346 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
[email protected]e51bdf32011-11-23 22:21:469347 return;
9348 }
[email protected]e51bdf32011-11-23 22:21:469349
9350 // Look up the new IOSurface. Note that because of asynchrony
9351 // between processes this might fail; during live resizing the
9352 // plugin process might allocate and release an IOSurface before
9353 // this process gets a chance to look it up. Hold on to any old
9354 // IOSurface in this case.
9355 CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id);
9356 if (!surface) {
[email protected]ab09b612013-03-11 22:11:519357 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439358 GL_INVALID_OPERATION,
9359 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
[email protected]e51bdf32011-11-23 22:21:469360 return;
9361 }
9362
9363 // Release any IOSurface previously bound to this texture.
[email protected]370eaf12013-05-18 09:19:499364 ReleaseIOSurfaceForTexture(texture_ref->service_id());
[email protected]e51bdf32011-11-23 22:21:469365
9366 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
9367 texture_to_io_surface_map_.insert(
[email protected]370eaf12013-05-18 09:19:499368 std::make_pair(texture_ref->service_id(), surface));
[email protected]e51bdf32011-11-23 22:21:469369
9370 CGLContextObj context =
9371 static_cast<CGLContextObj>(context_->GetHandle());
9372
9373 CGLError err = surface_support->CGLTexImageIOSurface2D(
9374 context,
9375 target,
9376 GL_RGBA,
9377 width,
9378 height,
9379 GL_BGRA,
9380 GL_UNSIGNED_INT_8_8_8_8_REV,
9381 surface,
9382 plane);
9383
9384 if (err != kCGLNoError) {
[email protected]ab09b612013-03-11 22:11:519385 LOCAL_SET_GL_ERROR(
[email protected]e51bdf32011-11-23 22:21:469386 GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439387 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
[email protected]e51bdf32011-11-23 22:21:469388 return;
9389 }
9390
9391 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:499392 texture_ref, target, 0, GL_RGBA, width, height, 1, 0,
[email protected]e51bdf32011-11-23 22:21:469393 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true);
9394
9395#else
[email protected]ab09b612013-03-11 22:11:519396 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
[email protected]ad84a3a2012-06-08 21:42:439397 "glTexImageIOSurface2DCHROMIUM", "not supported.");
[email protected]e51bdf32011-11-23 22:21:469398#endif
9399}
9400
[email protected]97dc7cbe2011-12-06 17:26:179401static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
9402 switch (internalformat) {
9403 case GL_RGB565:
9404 return GL_RGB;
9405 case GL_RGBA4:
9406 return GL_RGBA;
9407 case GL_RGB5_A1:
9408 return GL_RGBA;
9409 case GL_RGB8_OES:
9410 return GL_RGB;
9411 case GL_RGBA8_OES:
9412 return GL_RGBA;
9413 case GL_LUMINANCE8_ALPHA8_EXT:
9414 return GL_LUMINANCE_ALPHA;
9415 case GL_LUMINANCE8_EXT:
9416 return GL_LUMINANCE;
9417 case GL_ALPHA8_EXT:
9418 return GL_ALPHA;
9419 case GL_RGBA32F_EXT:
9420 return GL_RGBA;
9421 case GL_RGB32F_EXT:
9422 return GL_RGB;
9423 case GL_ALPHA32F_EXT:
9424 return GL_ALPHA;
9425 case GL_LUMINANCE32F_EXT:
9426 return GL_LUMINANCE;
9427 case GL_LUMINANCE_ALPHA32F_EXT:
9428 return GL_LUMINANCE_ALPHA;
9429 case GL_RGBA16F_EXT:
9430 return GL_RGBA;
9431 case GL_RGB16F_EXT:
9432 return GL_RGB;
9433 case GL_ALPHA16F_EXT:
9434 return GL_ALPHA;
9435 case GL_LUMINANCE16F_EXT:
9436 return GL_LUMINANCE;
9437 case GL_LUMINANCE_ALPHA16F_EXT:
9438 return GL_LUMINANCE_ALPHA;
9439 case GL_BGRA8_EXT:
9440 return GL_BGRA_EXT;
9441 default:
9442 return GL_NONE;
9443 }
9444}
9445
[email protected]43410e92012-04-20 17:06:289446void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
[email protected]0a1e9ad2012-05-04 21:13:039447 GLenum target, GLuint source_id, GLuint dest_id, GLint level,
[email protected]a4a6bdd12013-04-19 20:46:549448 GLenum internal_format, GLenum dest_type) {
[email protected]370eaf12013-05-18 09:19:499449 TextureRef* dest_texture_ref = GetTexture(dest_id);
9450 TextureRef* source_texture_ref = GetTexture(source_id);
[email protected]43410e92012-04-20 17:06:289451
[email protected]370eaf12013-05-18 09:19:499452 if (!source_texture_ref || !dest_texture_ref) {
[email protected]ab09b612013-03-11 22:11:519453 LOCAL_SET_GL_ERROR(
9454 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "unknown texture id");
[email protected]43410e92012-04-20 17:06:289455 return;
9456 }
9457
9458 if (GL_TEXTURE_2D != target) {
[email protected]ab09b612013-03-11 22:11:519459 LOCAL_SET_GL_ERROR(
9460 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "invalid texture target");
[email protected]43410e92012-04-20 17:06:289461 return;
9462 }
9463
[email protected]370eaf12013-05-18 09:19:499464 Texture* source_texture = source_texture_ref->texture();
9465 Texture* dest_texture = dest_texture_ref->texture();
[email protected]02965c22013-03-09 02:40:079466 if (dest_texture->target() != GL_TEXTURE_2D ||
[email protected]9bc9a2e82013-04-03 03:56:259467 (source_texture->target() != GL_TEXTURE_2D &&
9468 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
[email protected]ab09b612013-03-11 22:11:519469 LOCAL_SET_GL_ERROR(
9470 GL_INVALID_VALUE,
9471 "glCopyTextureCHROMIUM", "invalid texture target binding");
[email protected]0a1e9ad2012-05-04 21:13:039472 return;
9473 }
9474
[email protected]43410e92012-04-20 17:06:289475 int source_width, source_height, dest_width, dest_height;
[email protected]43410e92012-04-20 17:06:289476
[email protected]9bc9a2e82013-04-03 03:56:259477 if (source_texture->target() == GL_TEXTURE_2D) {
9478 if (!source_texture->GetLevelSize(GL_TEXTURE_2D, 0, &source_width,
9479 &source_height)) {
9480 LOCAL_SET_GL_ERROR(
9481 GL_INVALID_VALUE,
9482 "glCopyTextureChromium", "source texture has no level 0");
9483 return;
9484 }
9485
9486 // Check that this type of texture is allowed.
9487 if (!texture_manager()->ValidForTarget(GL_TEXTURE_2D, level, source_width,
9488 source_height, 1)) {
9489 LOCAL_SET_GL_ERROR(
9490 GL_INVALID_VALUE,
9491 "glCopyTextureCHROMIUM", "Bad dimensions");
9492 return;
9493 }
[email protected]43410e92012-04-20 17:06:289494 }
9495
[email protected]377976552013-05-14 23:32:569496 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
[email protected]4f9958142013-07-02 03:58:079497 DCHECK(stream_texture_manager());
[email protected]377976552013-05-14 23:32:569498 StreamTexture* stream_tex =
[email protected]4f9958142013-07-02 03:58:079499 stream_texture_manager()->LookupStreamTexture(
[email protected]377976552013-05-14 23:32:569500 source_texture->service_id());
9501 if (!stream_tex) {
9502 LOCAL_SET_GL_ERROR(
9503 GL_INVALID_VALUE,
9504 "glCopyTextureChromium", "Stream texture lookup failed");
9505 return;
9506 }
9507 gfx::Size size = stream_tex->GetSize();
9508 source_width = size.width();
9509 source_height = size.height();
9510 if (source_width <= 0 || source_height <= 0) {
9511 LOCAL_SET_GL_ERROR(
9512 GL_INVALID_VALUE,
9513 "glCopyTextureChromium", "invalid streamtexture size");
9514 return;
9515 }
9516 }
9517
[email protected]cf6b8f62012-05-25 21:43:379518 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
9519 // needed because it takes 10s of milliseconds to initialize.
9520 if (!copy_texture_CHROMIUM_.get()) {
[email protected]ab09b612013-03-11 22:11:519521 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
[email protected]cf6b8f62012-05-25 21:43:379522 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
[email protected]07a0cc32013-02-28 00:36:279523 copy_texture_CHROMIUM_->Initialize(this);
[email protected]cf6b8f62012-05-25 21:43:379524 RestoreCurrentFramebufferBindings();
[email protected]ab09b612013-03-11 22:11:519525 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
[email protected]cf6b8f62012-05-25 21:43:379526 return;
9527 }
9528
[email protected]a4a6bdd12013-04-19 20:46:549529 GLenum dest_type_previous;
[email protected]0a1e9ad2012-05-04 21:13:039530 GLenum dest_internal_format;
[email protected]02965c22013-03-09 02:40:079531 bool dest_level_defined = dest_texture->GetLevelSize(
9532 GL_TEXTURE_2D, level, &dest_width, &dest_height);
[email protected]43410e92012-04-20 17:06:289533
[email protected]0a1e9ad2012-05-04 21:13:039534 if (dest_level_defined) {
[email protected]a4a6bdd12013-04-19 20:46:549535 dest_texture->GetLevelType(GL_TEXTURE_2D, level, &dest_type_previous,
[email protected]02965c22013-03-09 02:40:079536 &dest_internal_format);
[email protected]0a1e9ad2012-05-04 21:13:039537 }
9538
9539 // Resize the destination texture to the dimensions of the source texture.
9540 if (!dest_level_defined || dest_width != source_width ||
9541 dest_height != source_height ||
[email protected]a4a6bdd12013-04-19 20:46:549542 dest_internal_format != internal_format ||
9543 dest_type_previous != dest_type) {
[email protected]43410e92012-04-20 17:06:289544 // Ensure that the glTexImage2D succeeds.
[email protected]ab09b612013-03-11 22:11:519545 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
[email protected]02965c22013-03-09 02:40:079546 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
[email protected]8f1d2aa2013-05-10 23:45:389547 glTexImage2D(
[email protected]43410e92012-04-20 17:06:289548 GL_TEXTURE_2D, level, internal_format, source_width, source_height,
[email protected]0a1e9ad2012-05-04 21:13:039549 0, internal_format, dest_type, NULL);
[email protected]ab09b612013-03-11 22:11:519550 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
[email protected]0a1e9ad2012-05-04 21:13:039551 if (error != GL_NO_ERROR) {
9552 RestoreCurrentTexture2DBindings();
[email protected]43410e92012-04-20 17:06:289553 return;
[email protected]0a1e9ad2012-05-04 21:13:039554 }
[email protected]43410e92012-04-20 17:06:289555
9556 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:499557 dest_texture_ref, GL_TEXTURE_2D, level, internal_format, source_width,
[email protected]0a1e9ad2012-05-04 21:13:039558 source_height, 1, 0, internal_format, dest_type, true);
[email protected]f7024712012-05-15 21:30:259559 } else {
[email protected]02965c22013-03-09 02:40:079560 texture_manager()->SetLevelCleared(
[email protected]370eaf12013-05-18 09:19:499561 dest_texture_ref, GL_TEXTURE_2D, level, true);
[email protected]43410e92012-04-20 17:06:289562 }
9563
[email protected]5394a4102013-04-18 05:41:379564 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
9565 // before presenting.
9566 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
9567 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
9568 // instead of using default matrix crbug.com/226218.
9569 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
9570 0.0f, 1.0f, 0.0f, 0.0f,
9571 0.0f, 0.0f, 1.0f, 0.0f,
9572 0.0f, 0.0f, 0.0f, 1.0f};
9573 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
9574 this,
9575 source_texture->target(),
9576 dest_texture->target(),
9577 source_texture->service_id(),
9578 dest_texture->service_id(), level,
9579 source_width, source_height,
9580 unpack_flip_y_,
9581 unpack_premultiply_alpha_,
9582 unpack_unpremultiply_alpha_,
9583 default_matrix);
9584 } else {
9585 copy_texture_CHROMIUM_->DoCopyTexture(
9586 this,
9587 source_texture->target(),
9588 dest_texture->target(),
9589 source_texture->service_id(),
9590 dest_texture->service_id(), level,
9591 source_width, source_height,
9592 unpack_flip_y_,
9593 unpack_premultiply_alpha_,
9594 unpack_unpremultiply_alpha_);
9595 }
[email protected]43410e92012-04-20 17:06:289596}
9597
[email protected]97dc7cbe2011-12-06 17:26:179598static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
9599 switch (internalformat) {
9600 case GL_RGB565:
9601 return GL_UNSIGNED_SHORT_5_6_5;
9602 case GL_RGBA4:
9603 return GL_UNSIGNED_SHORT_4_4_4_4;
9604 case GL_RGB5_A1:
9605 return GL_UNSIGNED_SHORT_5_5_5_1;
9606 case GL_RGB8_OES:
9607 return GL_UNSIGNED_BYTE;
9608 case GL_RGBA8_OES:
9609 return GL_UNSIGNED_BYTE;
9610 case GL_LUMINANCE8_ALPHA8_EXT:
9611 return GL_UNSIGNED_BYTE;
9612 case GL_LUMINANCE8_EXT:
9613 return GL_UNSIGNED_BYTE;
9614 case GL_ALPHA8_EXT:
9615 return GL_UNSIGNED_BYTE;
9616 case GL_RGBA32F_EXT:
9617 return GL_FLOAT;
9618 case GL_RGB32F_EXT:
9619 return GL_FLOAT;
9620 case GL_ALPHA32F_EXT:
9621 return GL_FLOAT;
9622 case GL_LUMINANCE32F_EXT:
9623 return GL_FLOAT;
9624 case GL_LUMINANCE_ALPHA32F_EXT:
9625 return GL_FLOAT;
9626 case GL_RGBA16F_EXT:
9627 return GL_HALF_FLOAT_OES;
9628 case GL_RGB16F_EXT:
9629 return GL_HALF_FLOAT_OES;
9630 case GL_ALPHA16F_EXT:
9631 return GL_HALF_FLOAT_OES;
9632 case GL_LUMINANCE16F_EXT:
9633 return GL_HALF_FLOAT_OES;
9634 case GL_LUMINANCE_ALPHA16F_EXT:
9635 return GL_HALF_FLOAT_OES;
9636 case GL_BGRA8_EXT:
9637 return GL_UNSIGNED_BYTE;
9638 default:
9639 return GL_NONE;
9640 }
9641}
9642
9643void GLES2DecoderImpl::DoTexStorage2DEXT(
[email protected]a5d3dad2012-05-26 04:34:449644 GLenum target,
9645 GLint levels,
9646 GLenum internal_format,
9647 GLsizei width,
9648 GLsizei height) {
[email protected]43ed3a72012-05-30 22:55:389649 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
[email protected]80eb6b52012-01-19 00:14:419650 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
[email protected]97dc7cbe2011-12-06 17:26:179651 TextureManager::ComputeMipMapCount(width, height, 1) < levels) {
[email protected]ab09b612013-03-11 22:11:519652 LOCAL_SET_GL_ERROR(
[email protected]ad84a3a2012-06-08 21:42:439653 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
[email protected]97dc7cbe2011-12-06 17:26:179654 return;
9655 }
[email protected]c986af502013-08-14 01:04:449656 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9657 &state_, target);
[email protected]370eaf12013-05-18 09:19:499658 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519659 LOCAL_SET_GL_ERROR(
9660 GL_INVALID_OPERATION,
9661 "glTexStorage2DEXT", "unknown texture for target");
[email protected]97dc7cbe2011-12-06 17:26:179662 return;
9663 }
[email protected]370eaf12013-05-18 09:19:499664 Texture* texture = texture_ref->texture();
[email protected]02965c22013-03-09 02:40:079665 if (texture->IsAttachedToFramebuffer()) {
[email protected]c986af502013-08-14 01:04:449666 framebuffer_state_.clear_state_dirty = true;
[email protected]97dc7cbe2011-12-06 17:26:179667 }
[email protected]02965c22013-03-09 02:40:079668 if (texture->IsImmutable()) {
[email protected]ab09b612013-03-11 22:11:519669 LOCAL_SET_GL_ERROR(
9670 GL_INVALID_OPERATION,
9671 "glTexStorage2DEXT", "texture is immutable");
[email protected]97dc7cbe2011-12-06 17:26:179672 return;
9673 }
[email protected]7989c9e2013-01-23 06:39:269674
9675 GLenum format = ExtractFormatFromStorageFormat(internal_format);
9676 GLenum type = ExtractTypeFromStorageFormat(internal_format);
9677
9678 {
9679 GLsizei level_width = width;
9680 GLsizei level_height = height;
9681 uint32 estimated_size = 0;
9682 for (int ii = 0; ii < levels; ++ii) {
9683 uint32 level_size = 0;
9684 if (!GLES2Util::ComputeImageDataSizes(
9685 level_width, level_height, format, type, state_.unpack_alignment,
9686 &estimated_size, NULL, NULL) ||
9687 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
[email protected]ab09b612013-03-11 22:11:519688 LOCAL_SET_GL_ERROR(
9689 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
[email protected]7989c9e2013-01-23 06:39:269690 return;
9691 }
9692 level_width = std::max(1, level_width >> 1);
9693 level_height = std::max(1, level_height >> 1);
9694 }
9695 if (!EnsureGPUMemoryAvailable(estimated_size)) {
[email protected]ab09b612013-03-11 22:11:519696 LOCAL_SET_GL_ERROR(
9697 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
[email protected]7989c9e2013-01-23 06:39:269698 return;
9699 }
9700 }
9701
[email protected]ab09b612013-03-11 22:11:519702 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
[email protected]8f1d2aa2013-05-10 23:45:389703 glTexStorage2DEXT(target, levels, internal_format, width, height);
[email protected]ab09b612013-03-11 22:11:519704 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
[email protected]97dc7cbe2011-12-06 17:26:179705 if (error == GL_NO_ERROR) {
[email protected]4502e6492011-12-14 19:39:159706 GLsizei level_width = width;
9707 GLsizei level_height = height;
9708 for (int ii = 0; ii < levels; ++ii) {
9709 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:499710 texture_ref, target, ii, format,
9711 level_width, level_height, 1, 0, format, type, false);
[email protected]4502e6492011-12-14 19:39:159712 level_width = std::max(1, level_width >> 1);
9713 level_height = std::max(1, level_height >> 1);
9714 }
[email protected]02965c22013-03-09 02:40:079715 texture->SetImmutable(true);
[email protected]97dc7cbe2011-12-06 17:26:179716 }
[email protected]97dc7cbe2011-12-06 17:26:179717}
[email protected]e51bdf32011-11-23 22:21:469718
[email protected]78b514b2012-05-01 21:50:599719error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:359720 uint32 immediate_data_size, const cmds::GenMailboxCHROMIUM& c) {
[email protected]78b514b2012-05-01 21:50:599721 MailboxName name;
9722 mailbox_manager()->GenerateMailboxName(&name);
9723 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
9724 Bucket* bucket = CreateBucket(bucket_id);
9725
9726 bucket->SetSize(GL_MAILBOX_SIZE_CHROMIUM);
9727 bucket->SetData(&name, 0, GL_MAILBOX_SIZE_CHROMIUM);
9728
9729 return error::kNoError;
9730}
9731
9732void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
9733 const GLbyte* mailbox) {
[email protected]987b9c02013-03-23 00:58:029734 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
[email protected]1d82e822013-04-10 21:32:329735 "context", logger_.GetLogPrefix(),
[email protected]987b9c02013-03-23 00:58:029736 "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
9737
[email protected]c986af502013-08-14 01:04:449738 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9739 &state_, target);
[email protected]370eaf12013-05-18 09:19:499740 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519741 LOCAL_SET_GL_ERROR(
9742 GL_INVALID_OPERATION,
9743 "glProduceTextureCHROMIUM", "unknown texture for target");
[email protected]78b514b2012-05-01 21:50:599744 return;
9745 }
9746
[email protected]62e65f02013-05-29 22:28:109747 Texture* produced = texture_manager()->Produce(texture_ref);
9748 if (!produced) {
[email protected]ab09b612013-03-11 22:11:519749 LOCAL_SET_GL_ERROR(
9750 GL_INVALID_OPERATION,
9751 "glProduceTextureCHROMIUM", "invalid texture");
[email protected]78b514b2012-05-01 21:50:599752 return;
9753 }
9754
9755 if (!group_->mailbox_manager()->ProduceTexture(
9756 target,
9757 *reinterpret_cast<const MailboxName*>(mailbox),
[email protected]62e65f02013-05-29 22:28:109758 produced)) {
[email protected]ab09b612013-03-11 22:11:519759 LOCAL_SET_GL_ERROR(
9760 GL_INVALID_OPERATION,
9761 "glProduceTextureCHROMIUM", "invalid mailbox name");
[email protected]78b514b2012-05-01 21:50:599762 return;
9763 }
[email protected]78b514b2012-05-01 21:50:599764}
9765
9766void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
9767 const GLbyte* mailbox) {
[email protected]987b9c02013-03-23 00:58:029768 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
[email protected]1d82e822013-04-10 21:32:329769 "context", logger_.GetLogPrefix(),
[email protected]987b9c02013-03-23 00:58:029770 "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
9771
[email protected]62e65f02013-05-29 22:28:109772 scoped_refptr<TextureRef> texture_ref =
[email protected]c986af502013-08-14 01:04:449773 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
[email protected]7cd76fd2013-06-02 21:11:119774 if (!texture_ref.get()) {
9775 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
9776 "glConsumeTextureCHROMIUM",
9777 "unknown texture for target");
[email protected]78b514b2012-05-01 21:50:599778 return;
9779 }
[email protected]62e65f02013-05-29 22:28:109780 GLuint client_id = texture_ref->client_id();
9781 if (!client_id) {
9782 LOCAL_SET_GL_ERROR(
9783 GL_INVALID_OPERATION,
9784 "glConsumeTextureCHROMIUM", "unknown texture for target");
9785 return;
9786 }
9787 Texture* texture =
[email protected]78b514b2012-05-01 21:50:599788 group_->mailbox_manager()->ConsumeTexture(
9789 target,
[email protected]62e65f02013-05-29 22:28:109790 *reinterpret_cast<const MailboxName*>(mailbox));
9791 if (!texture) {
[email protected]ab09b612013-03-11 22:11:519792 LOCAL_SET_GL_ERROR(
9793 GL_INVALID_OPERATION,
9794 "glConsumeTextureCHROMIUM", "invalid mailbox name");
[email protected]78b514b2012-05-01 21:50:599795 return;
9796 }
[email protected]62e65f02013-05-29 22:28:109797 if (texture->target() != target) {
[email protected]ab09b612013-03-11 22:11:519798 LOCAL_SET_GL_ERROR(
9799 GL_INVALID_OPERATION,
[email protected]62e65f02013-05-29 22:28:109800 "glConsumeTextureCHROMIUM", "invalid target");
[email protected]78b514b2012-05-01 21:50:599801 return;
9802 }
[email protected]62e65f02013-05-29 22:28:109803
9804 DeleteTexturesHelper(1, &client_id);
9805 texture_ref = texture_manager()->Consume(client_id, texture);
9806 glBindTexture(target, texture_ref->service_id());
9807
9808 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
9809 unit.bind_target = target;
9810 switch (target) {
9811 case GL_TEXTURE_2D:
9812 unit.bound_texture_2d = texture_ref;
9813 break;
9814 case GL_TEXTURE_CUBE_MAP:
9815 unit.bound_texture_cube_map = texture_ref;
9816 break;
9817 case GL_TEXTURE_EXTERNAL_OES:
9818 unit.bound_texture_external_oes = texture_ref;
9819 break;
9820 case GL_TEXTURE_RECTANGLE_ARB:
9821 unit.bound_texture_rectangle_arb = texture_ref;
9822 break;
9823 default:
9824 NOTREACHED(); // Validation should prevent us getting here.
9825 break;
9826 }
[email protected]78b514b2012-05-01 21:50:599827}
9828
[email protected]d2a0e1a2012-08-12 02:25:019829void GLES2DecoderImpl::DoInsertEventMarkerEXT(
9830 GLsizei length, const GLchar* marker) {
9831 if (!marker) {
9832 marker = "";
9833 }
9834 debug_marker_manager_.SetMarker(
9835 length ? std::string(marker, length) : std::string(marker));
9836}
9837
9838void GLES2DecoderImpl::DoPushGroupMarkerEXT(
9839 GLsizei length, const GLchar* marker) {
9840 if (!marker) {
9841 marker = "";
9842 }
9843 debug_marker_manager_.PushGroup(
9844 length ? std::string(marker, length) : std::string(marker));
9845}
9846
9847void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
9848 debug_marker_manager_.PopGroup();
9849}
9850
[email protected]09d50362012-10-18 20:54:379851void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
9852 GLenum target, GLint image_id) {
9853 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
9854 if (target != GL_TEXTURE_2D) {
9855 // This might be supported in the future.
[email protected]ab09b612013-03-11 22:11:519856 LOCAL_SET_GL_ERROR(
[email protected]09d50362012-10-18 20:54:379857 GL_INVALID_OPERATION,
9858 "glBindTexImage2DCHROMIUM", "requires TEXTURE_2D target");
9859 return;
9860 }
9861
9862 // Default target might be conceptually valid, but disallow it to avoid
9863 // accidents.
[email protected]c986af502013-08-14 01:04:449864 TextureRef* texture_ref =
9865 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
[email protected]370eaf12013-05-18 09:19:499866 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519867 LOCAL_SET_GL_ERROR(
9868 GL_INVALID_OPERATION,
9869 "glBindTexImage2DCHROMIUM", "no texture bound");
[email protected]09d50362012-10-18 20:54:379870 return;
9871 }
9872
9873 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
9874 if (!gl_image) {
[email protected]ab09b612013-03-11 22:11:519875 LOCAL_SET_GL_ERROR(
9876 GL_INVALID_OPERATION,
9877 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
[email protected]09d50362012-10-18 20:54:379878 return;
9879 }
9880
[email protected]b8160812013-04-09 00:41:049881 {
9882 ScopedGLErrorSuppressor suppressor(
9883 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", this);
9884 if (!gl_image->BindTexImage()) {
9885 LOCAL_SET_GL_ERROR(
9886 GL_INVALID_OPERATION,
9887 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
9888 return;
9889 }
[email protected]09d50362012-10-18 20:54:379890 }
9891
9892 gfx::Size size = gl_image->GetSize();
9893 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:499894 texture_ref, target, 0, GL_RGBA, size.width(), size.height(), 1, 0,
[email protected]09d50362012-10-18 20:54:379895 GL_RGBA, GL_UNSIGNED_BYTE, true);
[email protected]370eaf12013-05-18 09:19:499896 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
[email protected]09d50362012-10-18 20:54:379897}
9898
9899void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
9900 GLenum target, GLint image_id) {
9901 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
9902 if (target != GL_TEXTURE_2D) {
9903 // This might be supported in the future.
[email protected]ab09b612013-03-11 22:11:519904 LOCAL_SET_GL_ERROR(
[email protected]09d50362012-10-18 20:54:379905 GL_INVALID_OPERATION,
9906 "glReleaseTexImage2DCHROMIUM", "requires TEXTURE_2D target");
9907 return;
9908 }
9909
9910 // Default target might be conceptually valid, but disallow it to avoid
9911 // accidents.
[email protected]c986af502013-08-14 01:04:449912 TextureRef* texture_ref =
9913 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
[email protected]370eaf12013-05-18 09:19:499914 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:519915 LOCAL_SET_GL_ERROR(
9916 GL_INVALID_OPERATION,
9917 "glReleaseTexImage2DCHROMIUM", "no texture bound");
[email protected]09d50362012-10-18 20:54:379918 return;
9919 }
9920
9921 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
9922 if (!gl_image) {
[email protected]ab09b612013-03-11 22:11:519923 LOCAL_SET_GL_ERROR(
9924 GL_INVALID_OPERATION,
9925 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
[email protected]09d50362012-10-18 20:54:379926 return;
9927 }
9928
9929 // Do nothing when image is not currently bound.
[email protected]370eaf12013-05-18 09:19:499930 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
[email protected]09d50362012-10-18 20:54:379931 return;
9932
[email protected]b8160812013-04-09 00:41:049933 {
9934 ScopedGLErrorSuppressor suppressor(
9935 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", this);
9936 gl_image->ReleaseTexImage();
9937 }
[email protected]09d50362012-10-18 20:54:379938
9939 texture_manager()->SetLevelInfo(
[email protected]370eaf12013-05-18 09:19:499940 texture_ref, target, 0, GL_RGBA, 0, 0, 1, 0,
[email protected]09d50362012-10-18 20:54:379941 GL_RGBA, GL_UNSIGNED_BYTE, false);
9942}
[email protected]d2a0e1a2012-08-12 02:25:019943
[email protected]94307712012-11-16 23:26:119944error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:359945 uint32 immediate_data_size, const cmds::TraceBeginCHROMIUM& c) {
[email protected]94307712012-11-16 23:26:119946 Bucket* bucket = GetBucket(c.bucket_id);
9947 if (!bucket || bucket->size() == 0) {
9948 return error::kInvalidArguments;
9949 }
9950 std::string command_name;
9951 if (!bucket->GetAsString(&command_name)) {
9952 return error::kInvalidArguments;
9953 }
[email protected]fb97b662013-02-20 23:02:149954 TRACE_EVENT_COPY_ASYNC_BEGIN0("gpu", command_name.c_str(), this);
9955 if (!gpu_tracer_->Begin(command_name)) {
[email protected]ab09b612013-03-11 22:11:519956 LOCAL_SET_GL_ERROR(
9957 GL_INVALID_OPERATION,
9958 "glTraceBeginCHROMIUM", "unable to create begin trace");
[email protected]fb97b662013-02-20 23:02:149959 return error::kNoError;
9960 }
[email protected]94307712012-11-16 23:26:119961 return error::kNoError;
9962}
9963
9964void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
[email protected]fb97b662013-02-20 23:02:149965 if (gpu_tracer_->CurrentName().empty()) {
[email protected]ab09b612013-03-11 22:11:519966 LOCAL_SET_GL_ERROR(
9967 GL_INVALID_OPERATION,
9968 "glTraceEndCHROMIUM", "no trace begin found");
[email protected]94307712012-11-16 23:26:119969 return;
9970 }
[email protected]fb97b662013-02-20 23:02:149971 TRACE_EVENT_COPY_ASYNC_END0("gpu", gpu_tracer_->CurrentName().c_str(), this);
9972 gpu_tracer_->End();
[email protected]94307712012-11-16 23:26:119973}
9974
[email protected]2f143d482013-03-14 18:04:499975void GLES2DecoderImpl::DoDrawBuffersEXT(
9976 GLsizei count, const GLenum* bufs) {
9977 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
9978 LOCAL_SET_GL_ERROR(
9979 GL_INVALID_VALUE,
9980 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
9981 return;
9982 }
9983
9984 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
9985 if (framebuffer) {
9986 for (GLsizei i = 0; i < count; ++i) {
9987 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
9988 bufs[i] != GL_NONE) {
9989 LOCAL_SET_GL_ERROR(
9990 GL_INVALID_OPERATION,
9991 "glDrawBuffersEXT",
9992 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
9993 return;
9994 }
9995 }
9996 glDrawBuffersARB(count, bufs);
9997 framebuffer->SetDrawBuffers(count, bufs);
9998 } else { // backbuffer
9999 if (count > 1 ||
10000 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
10001 LOCAL_SET_GL_ERROR(
10002 GL_INVALID_OPERATION,
10003 "glDrawBuffersEXT",
10004 "more than one buffer or bufs not GL_NONE or GL_BACK");
10005 return;
10006 }
10007 GLenum mapped_buf = bufs[0];
10008 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
10009 bufs[0] == GL_BACK) {
10010 mapped_buf = GL_COLOR_ATTACHMENT0;
10011 }
10012 glDrawBuffersARB(count, &mapped_buf);
10013 group_->set_draw_buffer(bufs[0]);
10014 }
10015}
10016
[email protected]32145a92012-12-17 09:01:5910017bool GLES2DecoderImpl::ValidateAsyncTransfer(
10018 const char* function_name,
[email protected]85a4ac22013-05-31 01:58:4710019 TextureRef* texture_ref,
[email protected]32145a92012-12-17 09:01:5910020 GLenum target,
10021 GLint level,
10022 const void * data) {
10023 // We only support async uploads to 2D textures for now.
10024 if (GL_TEXTURE_2D != target) {
[email protected]ab09b612013-03-11 22:11:5110025 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
[email protected]32145a92012-12-17 09:01:5910026 return false;
10027 }
10028 // We only support uploads to level zero for now.
10029 if (level != 0) {
[email protected]ab09b612013-03-11 22:11:5110030 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
[email protected]32145a92012-12-17 09:01:5910031 return false;
10032 }
10033 // A transfer buffer must be bound, even for asyncTexImage2D.
10034 if (data == NULL) {
[email protected]ab09b612013-03-11 22:11:5110035 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
[email protected]32145a92012-12-17 09:01:5910036 return false;
10037 }
10038 // We only support one async transfer in progress.
[email protected]85a4ac22013-05-31 01:58:4710039 if (!texture_ref ||
10040 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
[email protected]ab09b612013-03-11 22:11:5110041 LOCAL_SET_GL_ERROR(
10042 GL_INVALID_OPERATION,
[email protected]32145a92012-12-17 09:01:5910043 function_name, "transfer already in progress");
10044 return false;
10045 }
10046 return true;
10047}
10048
[email protected]69023942012-11-30 19:57:1610049error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:3510050 uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) {
[email protected]69023942012-11-30 19:57:1610051 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
[email protected]69023942012-11-30 19:57:1610052 GLenum target = static_cast<GLenum>(c.target);
10053 GLint level = static_cast<GLint>(c.level);
[email protected]c986af502013-08-14 01:04:4410054 // TODO(kloveless): Change HandleAsyncTexImage2DCHROMIUM command to use
10055 // unsigned integer for internalformat.
10056 GLenum internal_format = static_cast<GLenum>(c.internalformat);
[email protected]69023942012-11-30 19:57:1610057 GLsizei width = static_cast<GLsizei>(c.width);
10058 GLsizei height = static_cast<GLsizei>(c.height);
10059 GLint border = static_cast<GLint>(c.border);
10060 GLenum format = static_cast<GLenum>(c.format);
10061 GLenum type = static_cast<GLenum>(c.type);
10062 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10063 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10064 uint32 pixels_size;
[email protected]32145a92012-12-17 09:01:5910065
10066 // TODO(epenner): Move this and copies of this memory validation
10067 // into ValidateTexImage2D step.
[email protected]69023942012-11-30 19:57:1610068 if (!GLES2Util::ComputeImageDataSizes(
10069 width, height, format, type, state_.unpack_alignment, &pixels_size, NULL,
10070 NULL)) {
10071 return error::kOutOfBounds;
10072 }
10073 const void* pixels = NULL;
10074 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10075 pixels = GetSharedMemoryAs<const void*>(
10076 pixels_shm_id, pixels_shm_offset, pixels_size);
10077 if (!pixels) {
10078 return error::kOutOfBounds;
10079 }
10080 }
10081
[email protected]c986af502013-08-14 01:04:4410082 TextureManager::DoTextImage2DArguments args = {
10083 target, level, internal_format, width, height, border, format, type,
10084 pixels, pixels_size};
10085 TextureRef* texture_ref;
[email protected]32145a92012-12-17 09:01:5910086 // All the normal glTexSubImage2D validation.
[email protected]c986af502013-08-14 01:04:4410087 if (!texture_manager()->ValidateTexImage2D(
10088 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
[email protected]32145a92012-12-17 09:01:5910089 return error::kNoError;
10090 }
10091
10092 // Extra async validation.
[email protected]370eaf12013-05-18 09:19:4910093 Texture* texture = texture_ref->texture();
[email protected]32145a92012-12-17 09:01:5910094 if (!ValidateAsyncTransfer(
[email protected]85a4ac22013-05-31 01:58:4710095 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
[email protected]32145a92012-12-17 09:01:5910096 return error::kNoError;
10097
10098 // Don't allow async redefinition of a textures.
[email protected]02965c22013-03-09 02:40:0710099 if (texture->IsDefined()) {
[email protected]ab09b612013-03-11 22:11:5110100 LOCAL_SET_GL_ERROR(
10101 GL_INVALID_OPERATION,
[email protected]32145a92012-12-17 09:01:5910102 "glAsyncTexImage2DCHROMIUM", "already defined");
10103 return error::kNoError;
10104 }
10105
[email protected]7989c9e2013-01-23 06:39:2610106 if (!EnsureGPUMemoryAvailable(pixels_size)) {
[email protected]ab09b612013-03-11 22:11:5110107 LOCAL_SET_GL_ERROR(
10108 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
[email protected]7989c9e2013-01-23 06:39:2610109 return error::kNoError;
10110 }
10111
[email protected]32145a92012-12-17 09:01:5910112 // We know the memory/size is safe, so get the real shared memory since
10113 // it might need to be duped to prevent use-after-free of the memory.
[email protected]16ccec12013-02-28 03:40:2110114 gpu::Buffer buffer = GetSharedMemoryBuffer(c.pixels_shm_id);
[email protected]32145a92012-12-17 09:01:5910115 base::SharedMemory* shared_memory = buffer.shared_memory;
10116 uint32 shm_size = buffer.size;
10117 uint32 shm_data_offset = c.pixels_shm_offset;
10118 uint32 shm_data_size = pixels_size;
10119
[email protected]5b3a8e02013-03-13 05:36:4410120 // Setup the parameters.
[email protected]8f1d2aa2013-05-10 23:45:3810121 AsyncTexImage2DParams tex_params = {
10122 target, level, static_cast<GLenum>(internal_format),
10123 width, height, border, format, type};
10124 AsyncMemoryParams mem_params = {
10125 shared_memory, shm_size, shm_data_offset, shm_data_size};
[email protected]32145a92012-12-17 09:01:5910126
[email protected]5b3a8e02013-03-13 05:36:4410127 // Set up the async state if needed, and make the texture
10128 // immutable so the async state stays valid. The level info
10129 // is set up lazily when the transfer completes.
[email protected]896425e2013-06-12 17:27:1810130 AsyncPixelTransferDelegate* delegate =
10131 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
10132 tex_params);
[email protected]5b3a8e02013-03-13 05:36:4410133 texture->SetImmutable(true);
[email protected]32145a92012-12-17 09:01:5910134
[email protected]896425e2013-06-12 17:27:1810135 delegate->AsyncTexImage2D(
[email protected]5b3a8e02013-03-13 05:36:4410136 tex_params,
10137 mem_params,
10138 base::Bind(&TextureManager::SetLevelInfoFromParams,
[email protected]370eaf12013-05-18 09:19:4910139 // The callback is only invoked if the transfer delegate still
10140 // exists, which implies through manager->texture_ref->state
[email protected]5b3a8e02013-03-13 05:36:4410141 // ownership that both of these pointers are valid.
10142 base::Unretained(texture_manager()),
[email protected]370eaf12013-05-18 09:19:4910143 base::Unretained(texture_ref),
[email protected]5b3a8e02013-03-13 05:36:4410144 tex_params));
[email protected]f598f422012-12-07 08:30:0310145 return error::kNoError;
[email protected]69023942012-11-30 19:57:1610146}
10147
10148error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
[email protected]ed9f9cd2013-02-27 21:12:3510149 uint32 immediate_data_size, const cmds::AsyncTexSubImage2DCHROMIUM& c) {
[email protected]69023942012-11-30 19:57:1610150 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
[email protected]69023942012-11-30 19:57:1610151 GLenum target = static_cast<GLenum>(c.target);
10152 GLint level = static_cast<GLint>(c.level);
10153 GLint xoffset = static_cast<GLint>(c.xoffset);
10154 GLint yoffset = static_cast<GLint>(c.yoffset);
10155 GLsizei width = static_cast<GLsizei>(c.width);
10156 GLsizei height = static_cast<GLsizei>(c.height);
10157 GLenum format = static_cast<GLenum>(c.format);
10158 GLenum type = static_cast<GLenum>(c.type);
[email protected]32145a92012-12-17 09:01:5910159
10160 // TODO(epenner): Move this and copies of this memory validation
10161 // into ValidateTexSubImage2D step.
[email protected]69023942012-11-30 19:57:1610162 uint32 data_size;
10163 if (!GLES2Util::ComputeImageDataSizes(
10164 width, height, format, type, state_.unpack_alignment, &data_size,
10165 NULL, NULL)) {
10166 return error::kOutOfBounds;
10167 }
10168 const void* pixels = GetSharedMemoryAs<const void*>(
10169 c.data_shm_id, c.data_shm_offset, data_size);
[email protected]32145a92012-12-17 09:01:5910170
10171 // All the normal glTexSubImage2D validation.
10172 error::Error error = error::kNoError;
10173 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
10174 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
10175 return error;
[email protected]69023942012-11-30 19:57:1610176 }
10177
[email protected]32145a92012-12-17 09:01:5910178 // Extra async validation.
[email protected]c986af502013-08-14 01:04:4410179 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10180 &state_, target);
[email protected]370eaf12013-05-18 09:19:4910181 Texture* texture = texture_ref->texture();
[email protected]32145a92012-12-17 09:01:5910182 if (!ValidateAsyncTransfer(
[email protected]85a4ac22013-05-31 01:58:4710183 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
[email protected]32145a92012-12-17 09:01:5910184 return error::kNoError;
10185
10186 // Guarantee async textures are always 'cleared' as follows:
10187 // - AsyncTexImage2D can not redefine an existing texture
10188 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
10189 // - AsyncTexSubImage2D clears synchronously if not already cleared.
10190 // - Textures become immutable after an async call.
10191 // This way we know in all cases that an async texture is always clear.
[email protected]02965c22013-03-09 02:40:0710192 if (!texture->SafeToRenderFrom()) {
[email protected]370eaf12013-05-18 09:19:4910193 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
10194 target, level)) {
[email protected]ab09b612013-03-11 22:11:5110195 LOCAL_SET_GL_ERROR(
10196 GL_OUT_OF_MEMORY,
[email protected]b04e24c2013-01-08 18:35:2510197 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
[email protected]32145a92012-12-17 09:01:5910198 return error::kNoError;
10199 }
10200 }
10201
10202 // We know the memory/size is safe, so get the real shared memory since
10203 // it might need to be duped to prevent use-after-free of the memory.
[email protected]16ccec12013-02-28 03:40:2110204 gpu::Buffer buffer = GetSharedMemoryBuffer(c.data_shm_id);
[email protected]32145a92012-12-17 09:01:5910205 base::SharedMemory* shared_memory = buffer.shared_memory;
10206 uint32 shm_size = buffer.size;
10207 uint32 shm_data_offset = c.data_shm_offset;
10208 uint32 shm_data_size = data_size;
10209
[email protected]5b3a8e02013-03-13 05:36:4410210 // Setup the parameters.
[email protected]2a7568a2013-05-09 23:12:0310211 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
[email protected]32145a92012-12-17 09:01:5910212 width, height, format, type};
[email protected]2a7568a2013-05-09 23:12:0310213 AsyncMemoryParams mem_params = {shared_memory, shm_size,
[email protected]32145a92012-12-17 09:01:5910214 shm_data_offset, shm_data_size};
[email protected]896425e2013-06-12 17:27:1810215 AsyncPixelTransferDelegate* delegate =
10216 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10217 if (!delegate) {
[email protected]5b3a8e02013-03-13 05:36:4410218 // TODO(epenner): We may want to enforce exclusive use
10219 // of async APIs in which case this should become an error,
10220 // (the texture should have been async defined).
[email protected]2a7568a2013-05-09 23:12:0310221 AsyncTexImage2DParams define_params = {target, level,
[email protected]5b3a8e02013-03-13 05:36:4410222 0, 0, 0, 0, 0, 0};
10223 texture->GetLevelSize(target, level, &define_params.width,
10224 &define_params.height);
10225 texture->GetLevelType(target, level, &define_params.type,
10226 &define_params.internal_format);
10227 // Set up the async state if needed, and make the texture
10228 // immutable so the async state stays valid.
[email protected]896425e2013-06-12 17:27:1810229 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
[email protected]85a4ac22013-05-31 01:58:4710230 texture_ref, define_params);
[email protected]5b3a8e02013-03-13 05:36:4410231 texture->SetImmutable(true);
10232 }
10233
[email protected]896425e2013-06-12 17:27:1810234 delegate->AsyncTexSubImage2D(tex_params, mem_params);
[email protected]32145a92012-12-17 09:01:5910235 return error::kNoError;
[email protected]69023942012-11-30 19:57:1610236}
10237
[email protected]a00c1f742013-03-05 17:02:1610238error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
10239 uint32 immediate_data_size, const cmds::WaitAsyncTexImage2DCHROMIUM& c) {
10240 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
10241 GLenum target = static_cast<GLenum>(c.target);
10242
10243 if (GL_TEXTURE_2D != target) {
[email protected]ab09b612013-03-11 22:11:5110244 LOCAL_SET_GL_ERROR(
10245 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
[email protected]a00c1f742013-03-05 17:02:1610246 return error::kNoError;
10247 }
[email protected]c986af502013-08-14 01:04:4410248 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10249 &state_, target);
[email protected]370eaf12013-05-18 09:19:4910250 if (!texture_ref) {
[email protected]ab09b612013-03-11 22:11:5110251 LOCAL_SET_GL_ERROR(
10252 GL_INVALID_OPERATION,
10253 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
[email protected]a00c1f742013-03-05 17:02:1610254 return error::kNoError;
10255 }
[email protected]896425e2013-06-12 17:27:1810256 AsyncPixelTransferDelegate* delegate =
10257 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
10258 if (!delegate) {
[email protected]370eaf12013-05-18 09:19:4910259 LOCAL_SET_GL_ERROR(
10260 GL_INVALID_OPERATION,
10261 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
10262 return error::kNoError;
10263 }
[email protected]896425e2013-06-12 17:27:1810264 delegate->WaitForTransferCompletion();
[email protected]69a8701e2013-03-07 21:31:0910265 ProcessFinishedAsyncTransfers();
[email protected]a00c1f742013-03-05 17:02:1610266 return error::kNoError;
10267}
10268
[email protected]96449d2c2009-11-25 00:01:3210269// Include the auto-generated part of this file. We split this because it means
10270// we can easily edit the non-auto generated parts right here in this file
10271// instead of having to edit some template or the code generator.
10272#include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
10273
10274} // namespace gles2
[email protected]a7a27ace2009-12-12 00:11:2510275} // namespace gpu