Have GPUTracer process traces during CommandBuffer Idle time.
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
blob3132b4d6eca6344ad39879d3eca4e19f5ed1435d
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
7 #include <stdio.h>
9 #include <algorithm>
10 #include <cmath>
11 #include <list>
12 #include <map>
13 #include <queue>
15 #include "base/callback.h"
16 #include "base/callback_helpers.h"
17 #include "base/command_line.h"
18 #include "base/logging.h"
19 #include "base/memory/linked_ptr.h"
20 #include "base/memory/scoped_ptr.h"
21 #include "base/metrics/histogram_macros.h"
22 #include "base/numerics/safe_math.h"
23 #include "base/strings/string_number_conversions.h"
24 #include "base/trace_event/trace_event.h"
25 #include "base/trace_event/trace_event_synthetic_delay.h"
26 #include "build/build_config.h"
27 #define GLES2_GPU_SERVICE 1
28 #include "gpu/command_buffer/common/debug_marker_manager.h"
29 #include "gpu/command_buffer/common/gles2_cmd_format.h"
30 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
31 #include "gpu/command_buffer/common/mailbox.h"
32 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
33 #include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
34 #include "gpu/command_buffer/service/buffer_manager.h"
35 #include "gpu/command_buffer/service/context_group.h"
36 #include "gpu/command_buffer/service/context_state.h"
37 #include "gpu/command_buffer/service/error_state.h"
38 #include "gpu/command_buffer/service/feature_info.h"
39 #include "gpu/command_buffer/service/framebuffer_manager.h"
40 #include "gpu/command_buffer/service/gl_utils.h"
41 #include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
42 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
43 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
44 #include "gpu/command_buffer/service/gpu_state_tracer.h"
45 #include "gpu/command_buffer/service/gpu_switches.h"
46 #include "gpu/command_buffer/service/gpu_tracer.h"
47 #include "gpu/command_buffer/service/image_manager.h"
48 #include "gpu/command_buffer/service/logger.h"
49 #include "gpu/command_buffer/service/mailbox_manager.h"
50 #include "gpu/command_buffer/service/memory_tracking.h"
51 #include "gpu/command_buffer/service/path_manager.h"
52 #include "gpu/command_buffer/service/program_manager.h"
53 #include "gpu/command_buffer/service/query_manager.h"
54 #include "gpu/command_buffer/service/renderbuffer_manager.h"
55 #include "gpu/command_buffer/service/shader_manager.h"
56 #include "gpu/command_buffer/service/shader_translator.h"
57 #include "gpu/command_buffer/service/texture_manager.h"
58 #include "gpu/command_buffer/service/valuebuffer_manager.h"
59 #include "gpu/command_buffer/service/vertex_array_manager.h"
60 #include "gpu/command_buffer/service/vertex_attrib_manager.h"
61 #include "third_party/smhasher/src/City.h"
62 #include "ui/gfx/geometry/point.h"
63 #include "ui/gfx/geometry/rect.h"
64 #include "ui/gfx/geometry/size.h"
65 #include "ui/gfx/overlay_transform.h"
66 #include "ui/gl/gl_bindings.h"
67 #include "ui/gl/gl_context.h"
68 #include "ui/gl/gl_fence.h"
69 #include "ui/gl/gl_image.h"
70 #include "ui/gl/gl_implementation.h"
71 #include "ui/gl/gl_surface.h"
72 #include "ui/gl/gl_version_info.h"
73 #include "ui/gl/gpu_timing.h"
75 #if defined(OS_MACOSX)
76 #include <IOSurface/IOSurface.h>
77 // Note that this must be included after gl_bindings.h to avoid conflicts.
78 #include <OpenGL/CGLIOSurface.h>
79 #endif
81 namespace gpu {
82 namespace gles2 {
84 namespace {
86 const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
87 const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
88 const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
89 const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
91 const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
92 0.0f, 1.0f, 0.0f, 0.0f,
93 0.0f, 0.0f, 1.0f, 0.0f,
94 0.0f, 0.0f, 0.0f, 1.0f};
96 bool PrecisionMeetsSpecForHighpFloat(GLint rangeMin,
97 GLint rangeMax,
98 GLint precision) {
99 return (rangeMin >= 62) && (rangeMax >= 62) && (precision >= 16);
102 void GetShaderPrecisionFormatImpl(GLenum shader_type,
103 GLenum precision_type,
104 GLint* range, GLint* precision) {
105 switch (precision_type) {
106 case GL_LOW_INT:
107 case GL_MEDIUM_INT:
108 case GL_HIGH_INT:
109 // These values are for a 32-bit twos-complement integer format.
110 range[0] = 31;
111 range[1] = 30;
112 *precision = 0;
113 break;
114 case GL_LOW_FLOAT:
115 case GL_MEDIUM_FLOAT:
116 case GL_HIGH_FLOAT:
117 // These values are for an IEEE single-precision floating-point format.
118 range[0] = 127;
119 range[1] = 127;
120 *precision = 23;
121 break;
122 default:
123 NOTREACHED();
124 break;
127 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
128 gfx::g_driver_gl.fn.glGetShaderPrecisionFormatFn) {
129 // This function is sometimes defined even though it's really just
130 // a stub, so we need to set range and precision as if it weren't
131 // defined before calling it.
132 // On Mac OS with some GPUs, calling this generates a
133 // GL_INVALID_OPERATION error. Avoid calling it on non-GLES2
134 // platforms.
135 glGetShaderPrecisionFormat(shader_type, precision_type,
136 range, precision);
138 // TODO(brianderson): Make the following official workarounds.
140 // Some drivers have bugs where they report the ranges as a negative number.
141 // Taking the absolute value here shouldn't hurt because negative numbers
142 // aren't expected anyway.
143 range[0] = abs(range[0]);
144 range[1] = abs(range[1]);
146 // If the driver reports a precision for highp float that isn't actually
147 // highp, don't pretend like it's supported because shader compilation will
148 // fail anyway.
149 if (precision_type == GL_HIGH_FLOAT &&
150 !PrecisionMeetsSpecForHighpFloat(range[0], range[1], *precision)) {
151 range[0] = 0;
152 range[1] = 0;
153 *precision = 0;
158 gfx::OverlayTransform GetGFXOverlayTransform(GLenum plane_transform) {
159 switch (plane_transform) {
160 case GL_OVERLAY_TRANSFORM_NONE_CHROMIUM:
161 return gfx::OVERLAY_TRANSFORM_NONE;
162 case GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM:
163 return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
164 case GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM:
165 return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
166 case GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM:
167 return gfx::OVERLAY_TRANSFORM_ROTATE_90;
168 case GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM:
169 return gfx::OVERLAY_TRANSFORM_ROTATE_180;
170 case GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM:
171 return gfx::OVERLAY_TRANSFORM_ROTATE_270;
172 default:
173 return gfx::OVERLAY_TRANSFORM_INVALID;
177 template <typename MANAGER_TYPE, typename OBJECT_TYPE>
178 GLuint GetClientId(const MANAGER_TYPE* manager, const OBJECT_TYPE* object) {
179 DCHECK(manager);
180 GLuint client_id = 0;
181 if (object) {
182 manager->GetClientId(object->service_id(), &client_id);
184 return client_id;
187 struct Vec4f {
188 explicit Vec4f(const Vec4& data) {
189 data.GetValues(v);
192 GLfloat v[4];
195 // Returns the union of |rect1| and |rect2| if one of the rectangles is empty,
196 // contains the other rectangle or shares an edge with the other rectangle.
197 bool CombineAdjacentRects(const gfx::Rect& rect1,
198 const gfx::Rect& rect2,
199 gfx::Rect* result) {
200 // Return |rect2| if |rect1| is empty or |rect2| contains |rect1|.
201 if (rect1.IsEmpty() || rect2.Contains(rect1)) {
202 *result = rect2;
203 return true;
206 // Return |rect1| if |rect2| is empty or |rect1| contains |rect2|.
207 if (rect2.IsEmpty() || rect1.Contains(rect2)) {
208 *result = rect1;
209 return true;
212 // Return the union of |rect1| and |rect2| if they share an edge.
213 if (rect1.SharesEdgeWith(rect2)) {
214 *result = gfx::UnionRects(rect1, rect2);
215 return true;
218 // Return false if it's not possible to combine |rect1| and |rect2|.
219 return false;
222 } // namespace
224 class GLES2DecoderImpl;
226 // Local versions of the SET_GL_ERROR macros
227 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \
228 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg)
229 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \
230 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \
231 function_name, value, label)
232 #define LOCAL_SET_GL_ERROR_INVALID_PARAM(error, function_name, pname) \
233 ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(state_.GetErrorState(), error, \
234 function_name, pname)
235 #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \
236 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \
237 function_name)
238 #define LOCAL_PEEK_GL_ERROR(function_name) \
239 ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name)
240 #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \
241 ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name)
242 #define LOCAL_PERFORMANCE_WARNING(msg) \
243 PerformanceWarning(__FILE__, __LINE__, msg)
244 #define LOCAL_RENDER_WARNING(msg) \
245 RenderWarning(__FILE__, __LINE__, msg)
247 // Check that certain assumptions the code makes are true. There are places in
248 // the code where shared memory is passed direclty to GL. Example, glUniformiv,
249 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe
250 // a few others) are 32bits. If they are not 32bits the code will have to change
251 // to call those GL functions with service side memory and then copy the results
252 // to shared memory, converting the sizes.
253 static_assert(sizeof(GLint) == sizeof(uint32), // NOLINT
254 "GLint should be the same size as uint32");
255 static_assert(sizeof(GLsizei) == sizeof(uint32), // NOLINT
256 "GLsizei should be the same size as uint32");
257 static_assert(sizeof(GLfloat) == sizeof(float), // NOLINT
258 "GLfloat should be the same size as float");
260 // TODO(kbr): the use of this anonymous namespace core dumps the
261 // linker on Mac OS X 10.6 when the symbol ordering file is used
262 // namespace {
264 // Returns the address of the first byte after a struct.
265 template <typename T>
266 const void* AddressAfterStruct(const T& pod) {
267 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
270 // Returns the address of the frst byte after the struct or NULL if size >
271 // immediate_data_size.
272 template <typename RETURN_TYPE, typename COMMAND_TYPE>
273 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod,
274 uint32 size,
275 uint32 immediate_data_size) {
276 return (size <= immediate_data_size) ?
277 static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) :
278 NULL;
281 // Computes the data size for certain gl commands like glUniform.
282 bool ComputeDataSize(
283 GLuint count,
284 size_t size,
285 unsigned int elements_per_unit,
286 uint32* dst) {
287 uint32 value;
288 if (!SafeMultiplyUint32(count, size, &value)) {
289 return false;
291 if (!SafeMultiplyUint32(value, elements_per_unit, &value)) {
292 return false;
294 *dst = value;
295 return true;
298 // Return true if a character belongs to the ASCII subset as defined in
299 // GLSL ES 1.0 spec section 3.1.
300 static bool CharacterIsValidForGLES(unsigned char c) {
301 // Printing characters are valid except " $ ` @ \ ' DEL.
302 if (c >= 32 && c <= 126 &&
303 c != '"' &&
304 c != '$' &&
305 c != '`' &&
306 c != '@' &&
307 c != '\\' &&
308 c != '\'') {
309 return true;
311 // Horizontal tab, line feed, vertical tab, form feed, carriage return
312 // are also valid.
313 if (c >= 9 && c <= 13) {
314 return true;
317 return false;
320 static bool StringIsValidForGLES(const char* str) {
321 for (; *str; ++str) {
322 if (!CharacterIsValidForGLES(*str)) {
323 return false;
326 return true;
329 // This class prevents any GL errors that occur when it is in scope from
330 // being reported to the client.
331 class ScopedGLErrorSuppressor {
332 public:
333 explicit ScopedGLErrorSuppressor(
334 const char* function_name, ErrorState* error_state);
335 ~ScopedGLErrorSuppressor();
336 private:
337 const char* function_name_;
338 ErrorState* error_state_;
339 DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
342 // Temporarily changes a decoder's bound texture and restore it when this
343 // object goes out of scope. Also temporarily switches to using active texture
344 // unit zero in case the client has changed that to something invalid.
345 class ScopedTextureBinder {
346 public:
347 explicit ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
348 ~ScopedTextureBinder();
350 private:
351 ContextState* state_;
352 GLenum target_;
353 DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
356 // Temporarily changes a decoder's bound render buffer and restore it when this
357 // object goes out of scope.
358 class ScopedRenderBufferBinder {
359 public:
360 explicit ScopedRenderBufferBinder(ContextState* state, GLuint id);
361 ~ScopedRenderBufferBinder();
363 private:
364 ContextState* state_;
365 DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
368 // Temporarily changes a decoder's bound frame buffer and restore it when this
369 // object goes out of scope.
370 class ScopedFrameBufferBinder {
371 public:
372 explicit ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
373 ~ScopedFrameBufferBinder();
375 private:
376 GLES2DecoderImpl* decoder_;
377 DISALLOW_COPY_AND_ASSIGN(ScopedFrameBufferBinder);
380 // Temporarily changes a decoder's bound frame buffer to a resolved version of
381 // the multisampled offscreen render buffer if that buffer is multisampled, and,
382 // if it is bound or enforce_internal_framebuffer is true. If internal is
383 // true, the resolved framebuffer is not visible to the parent.
384 class ScopedResolvedFrameBufferBinder {
385 public:
386 explicit ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder,
387 bool enforce_internal_framebuffer,
388 bool internal);
389 ~ScopedResolvedFrameBufferBinder();
391 private:
392 GLES2DecoderImpl* decoder_;
393 bool resolve_and_bind_;
394 DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
397 class ScopedModifyPixels {
398 public:
399 explicit ScopedModifyPixels(TextureRef* ref);
400 ~ScopedModifyPixels();
402 private:
403 TextureRef* ref_;
406 ScopedModifyPixels::ScopedModifyPixels(TextureRef* ref) : ref_(ref) {
407 if (ref_)
408 ref_->texture()->OnWillModifyPixels();
411 ScopedModifyPixels::~ScopedModifyPixels() {
412 if (ref_)
413 ref_->texture()->OnDidModifyPixels();
416 class ScopedRenderTo {
417 public:
418 explicit ScopedRenderTo(Framebuffer* framebuffer);
419 ~ScopedRenderTo();
421 private:
422 const Framebuffer* framebuffer_;
425 ScopedRenderTo::ScopedRenderTo(Framebuffer* framebuffer)
426 : framebuffer_(framebuffer) {
427 if (framebuffer)
428 framebuffer_->OnWillRenderTo();
431 ScopedRenderTo::~ScopedRenderTo() {
432 if (framebuffer_)
433 framebuffer_->OnDidRenderTo();
436 // Encapsulates an OpenGL texture.
437 class BackTexture {
438 public:
439 explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
440 ~BackTexture();
442 // Create a new render texture.
443 void Create();
445 // Set the initial size and format of a render texture or resize it.
446 bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero);
448 // Copy the contents of the currently bound frame buffer.
449 void Copy(const gfx::Size& size, GLenum format);
451 // Destroy the render texture. This must be explicitly called before
452 // destroying this object.
453 void Destroy();
455 // Invalidate the texture. This can be used when a context is lost and it is
456 // not possible to make it current in order to free the resource.
457 void Invalidate();
459 GLuint id() const {
460 return id_;
463 gfx::Size size() const {
464 return size_;
467 private:
468 MemoryTypeTracker memory_tracker_;
469 ContextState* state_;
470 size_t bytes_allocated_;
471 GLuint id_;
472 gfx::Size size_;
473 DISALLOW_COPY_AND_ASSIGN(BackTexture);
476 // Encapsulates an OpenGL render buffer of any format.
477 class BackRenderbuffer {
478 public:
479 explicit BackRenderbuffer(
480 RenderbufferManager* renderbuffer_manager,
481 MemoryTracker* memory_tracker,
482 ContextState* state);
483 ~BackRenderbuffer();
485 // Create a new render buffer.
486 void Create();
488 // Set the initial size and format of a render buffer or resize it.
489 bool AllocateStorage(const FeatureInfo* feature_info,
490 const gfx::Size& size,
491 GLenum format,
492 GLsizei samples);
494 // Destroy the render buffer. This must be explicitly called before destroying
495 // this object.
496 void Destroy();
498 // Invalidate the render buffer. This can be used when a context is lost and
499 // it is not possible to make it current in order to free the resource.
500 void Invalidate();
502 GLuint id() const {
503 return id_;
506 private:
507 RenderbufferManager* renderbuffer_manager_;
508 MemoryTypeTracker memory_tracker_;
509 ContextState* state_;
510 size_t bytes_allocated_;
511 GLuint id_;
512 DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
515 // Encapsulates an OpenGL frame buffer.
516 class BackFramebuffer {
517 public:
518 explicit BackFramebuffer(GLES2DecoderImpl* decoder);
519 ~BackFramebuffer();
521 // Create a new frame buffer.
522 void Create();
524 // Attach a color render buffer to a frame buffer.
525 void AttachRenderTexture(BackTexture* texture);
527 // Attach a render buffer to a frame buffer. Note that this unbinds any
528 // currently bound frame buffer.
529 void AttachRenderBuffer(GLenum target, BackRenderbuffer* render_buffer);
531 // Destroy the frame buffer. This must be explicitly called before destroying
532 // this object.
533 void Destroy();
535 // Invalidate the frame buffer. This can be used when a context is lost and it
536 // is not possible to make it current in order to free the resource.
537 void Invalidate();
539 // See glCheckFramebufferStatusEXT.
540 GLenum CheckStatus();
542 GLuint id() const {
543 return id_;
546 private:
547 GLES2DecoderImpl* decoder_;
548 GLuint id_;
549 DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
552 struct FenceCallback {
553 FenceCallback()
554 : fence(gfx::GLFence::Create()) {
555 DCHECK(fence);
557 std::vector<base::Closure> callbacks;
558 scoped_ptr<gfx::GLFence> fence;
561 class AsyncUploadTokenCompletionObserver
562 : public AsyncPixelTransferCompletionObserver {
563 public:
564 explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token)
565 : async_upload_token_(async_upload_token) {
568 void DidComplete(const AsyncMemoryParams& mem_params) override {
569 DCHECK(mem_params.buffer().get());
570 void* data = mem_params.GetDataAddress();
571 AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data);
572 sync->SetAsyncUploadToken(async_upload_token_);
575 private:
576 ~AsyncUploadTokenCompletionObserver() override {}
578 uint32 async_upload_token_;
580 DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver);
583 // } // anonymous namespace.
585 // static
586 const unsigned int GLES2Decoder::kDefaultStencilMask =
587 static_cast<unsigned int>(-1);
589 bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
590 uint32* service_texture_id) {
591 return false;
594 GLES2Decoder::GLES2Decoder()
595 : initialized_(false),
596 debug_(false),
597 log_commands_(false),
598 unsafe_es3_apis_enabled_(false) {
601 GLES2Decoder::~GLES2Decoder() {
604 void GLES2Decoder::BeginDecoding() {}
606 void GLES2Decoder::EndDecoding() {}
608 // This class implements GLES2Decoder so we don't have to expose all the GLES2
609 // cmd stuff to outside this class.
610 class GLES2DecoderImpl : public GLES2Decoder,
611 public FramebufferManager::TextureDetachObserver,
612 public ErrorStateClient {
613 public:
614 explicit GLES2DecoderImpl(ContextGroup* group);
615 ~GLES2DecoderImpl() override;
617 // Overridden from AsyncAPIInterface.
618 Error DoCommand(unsigned int command,
619 unsigned int arg_count,
620 const void* args) override;
622 error::Error DoCommands(unsigned int num_commands,
623 const void* buffer,
624 int num_entries,
625 int* entries_processed) override;
627 template <bool DebugImpl>
628 error::Error DoCommandsImpl(unsigned int num_commands,
629 const void* buffer,
630 int num_entries,
631 int* entries_processed);
633 // Overridden from AsyncAPIInterface.
634 const char* GetCommandName(unsigned int command_id) const override;
636 // Overridden from GLES2Decoder.
637 bool Initialize(const scoped_refptr<gfx::GLSurface>& surface,
638 const scoped_refptr<gfx::GLContext>& context,
639 bool offscreen,
640 const gfx::Size& offscreen_size,
641 const DisallowedFeatures& disallowed_features,
642 const std::vector<int32>& attribs) override;
643 void Destroy(bool have_context) override;
644 void SetSurface(const scoped_refptr<gfx::GLSurface>& surface) override;
645 void ProduceFrontBuffer(const Mailbox& mailbox) override;
646 bool ResizeOffscreenFrameBuffer(const gfx::Size& size) override;
647 void UpdateParentTextureInfo();
648 bool MakeCurrent() override;
649 GLES2Util* GetGLES2Util() override { return &util_; }
650 gfx::GLContext* GetGLContext() override { return context_.get(); }
651 ContextGroup* GetContextGroup() override { return group_.get(); }
652 Capabilities GetCapabilities() override;
653 void RestoreState(const ContextState* prev_state) override;
655 void RestoreActiveTexture() const override { state_.RestoreActiveTexture(); }
656 void RestoreAllTextureUnitBindings(
657 const ContextState* prev_state) const override {
658 state_.RestoreAllTextureUnitBindings(prev_state);
660 void RestoreActiveTextureUnitBinding(unsigned int target) const override {
661 state_.RestoreActiveTextureUnitBinding(target);
663 void RestoreBufferBindings() const override {
664 state_.RestoreBufferBindings();
666 void RestoreGlobalState() const override { state_.RestoreGlobalState(NULL); }
667 void RestoreProgramBindings() const override {
668 state_.RestoreProgramBindings();
670 void RestoreTextureUnitBindings(unsigned unit) const override {
671 state_.RestoreTextureUnitBindings(unit, NULL);
673 void RestoreFramebufferBindings() const override;
674 void RestoreRenderbufferBindings() override;
675 void RestoreTextureState(unsigned service_id) const override;
677 void ClearAllAttributes() const override;
678 void RestoreAllAttributes() const override;
680 QueryManager* GetQueryManager() override { return query_manager_.get(); }
681 VertexArrayManager* GetVertexArrayManager() override {
682 return vertex_array_manager_.get();
684 ImageManager* GetImageManager() override { return image_manager_.get(); }
686 ValuebufferManager* GetValuebufferManager() override {
687 return valuebuffer_manager();
690 bool ProcessPendingQueries(bool did_finish) override;
692 bool HasMoreIdleWork() override;
693 void PerformIdleWork() override;
695 void WaitForReadPixels(base::Closure callback) override;
697 void SetResizeCallback(
698 const base::Callback<void(gfx::Size, float)>& callback) override;
700 Logger* GetLogger() override;
702 void BeginDecoding() override;
703 void EndDecoding() override;
705 ErrorState* GetErrorState() override;
706 const ContextState* GetContextState() override { return &state_; }
708 void SetShaderCacheCallback(const ShaderCacheCallback& callback) override;
709 void SetWaitSyncPointCallback(const WaitSyncPointCallback& callback) override;
711 AsyncPixelTransferManager* GetAsyncPixelTransferManager() override;
712 void ResetAsyncPixelTransferManagerForTest() override;
713 void SetAsyncPixelTransferManagerForTest(
714 AsyncPixelTransferManager* manager) override;
715 void SetIgnoreCachedStateForTest(bool ignore) override;
716 void ProcessFinishedAsyncTransfers();
718 bool GetServiceTextureId(uint32 client_texture_id,
719 uint32* service_texture_id) override;
721 uint32 GetTextureUploadCount() override;
722 base::TimeDelta GetTotalTextureUploadTime() override;
723 base::TimeDelta GetTotalProcessingCommandsTime() override;
724 void AddProcessingCommandsTime(base::TimeDelta) override;
726 // Restores the current state to the user's settings.
727 void RestoreCurrentFramebufferBindings();
729 // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
730 void ApplyDirtyState();
732 // These check the state of the currently bound framebuffer or the
733 // backbuffer if no framebuffer is bound.
734 // Check with all attached and enabled color attachments.
735 bool BoundFramebufferHasColorAttachmentWithAlpha();
736 bool BoundFramebufferHasDepthAttachment();
737 bool BoundFramebufferHasStencilAttachment();
739 error::ContextLostReason GetContextLostReason() override;
741 // Overridden from FramebufferManager::TextureDetachObserver:
742 void OnTextureRefDetachedFromFramebuffer(TextureRef* texture) override;
744 // Overriden from ErrorStateClient.
745 void OnContextLostError() override;
746 void OnOutOfMemoryError() override;
748 // Ensure Renderbuffer corresponding to last DoBindRenderbuffer() is bound.
749 void EnsureRenderbufferBound();
751 // Helpers to facilitate calling into compatible extensions.
752 static void RenderbufferStorageMultisampleHelper(
753 const FeatureInfo* feature_info,
754 GLenum target,
755 GLsizei samples,
756 GLenum internal_format,
757 GLsizei width,
758 GLsizei height);
760 void BlitFramebufferHelper(GLint srcX0,
761 GLint srcY0,
762 GLint srcX1,
763 GLint srcY1,
764 GLint dstX0,
765 GLint dstY0,
766 GLint dstX1,
767 GLint dstY1,
768 GLbitfield mask,
769 GLenum filter);
771 private:
772 friend class ScopedFrameBufferBinder;
773 friend class ScopedResolvedFrameBufferBinder;
774 friend class BackFramebuffer;
776 // Initialize or re-initialize the shader translator.
777 bool InitializeShaderTranslator();
779 void UpdateCapabilities();
781 // Helpers for the glGen and glDelete functions.
782 bool GenTexturesHelper(GLsizei n, const GLuint* client_ids);
783 void DeleteTexturesHelper(GLsizei n, const GLuint* client_ids);
784 bool GenBuffersHelper(GLsizei n, const GLuint* client_ids);
785 void DeleteBuffersHelper(GLsizei n, const GLuint* client_ids);
786 bool GenFramebuffersHelper(GLsizei n, const GLuint* client_ids);
787 void DeleteFramebuffersHelper(GLsizei n, const GLuint* client_ids);
788 bool GenRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
789 void DeleteRenderbuffersHelper(GLsizei n, const GLuint* client_ids);
790 bool GenValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
791 void DeleteValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* client_ids);
792 bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
793 void DeleteQueriesEXTHelper(GLsizei n, const GLuint* client_ids);
794 bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
795 void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
796 bool GenPathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
797 bool DeletePathsCHROMIUMHelper(GLuint first_client_id, GLsizei range);
799 // Helper for async upload token completion notification callback.
800 base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
801 uint32 sync_data_shm_id,
802 uint32 sync_data_shm_offset);
806 // Workarounds
807 void OnFboChanged() const;
808 void OnUseFramebuffer() const;
810 error::ContextLostReason GetContextLostReasonFromResetStatus(
811 GLenum reset_status) const;
813 // TODO(gman): Cache these pointers?
814 BufferManager* buffer_manager() {
815 return group_->buffer_manager();
818 RenderbufferManager* renderbuffer_manager() {
819 return group_->renderbuffer_manager();
822 FramebufferManager* framebuffer_manager() {
823 return group_->framebuffer_manager();
826 ValuebufferManager* valuebuffer_manager() {
827 return group_->valuebuffer_manager();
830 PathManager* path_manager() { return group_->path_manager(); }
832 ProgramManager* program_manager() {
833 return group_->program_manager();
836 ShaderManager* shader_manager() {
837 return group_->shader_manager();
840 ShaderTranslatorCache* shader_translator_cache() {
841 return group_->shader_translator_cache();
844 const TextureManager* texture_manager() const {
845 return group_->texture_manager();
848 TextureManager* texture_manager() {
849 return group_->texture_manager();
852 MailboxManager* mailbox_manager() {
853 return group_->mailbox_manager();
856 ImageManager* image_manager() { return image_manager_.get(); }
858 VertexArrayManager* vertex_array_manager() {
859 return vertex_array_manager_.get();
862 MemoryTracker* memory_tracker() {
863 return group_->memory_tracker();
866 bool EnsureGPUMemoryAvailable(size_t estimated_size) {
867 MemoryTracker* tracker = memory_tracker();
868 if (tracker) {
869 return tracker->EnsureGPUMemoryAvailable(estimated_size);
871 return true;
874 bool IsWebGLContext() const {
875 return webgl_version_ == 1 || webgl_version_ == 2;
878 bool IsOffscreenBufferMultisampled() const {
879 return offscreen_target_samples_ > 1;
882 // Creates a Texture for the given texture.
883 TextureRef* CreateTexture(
884 GLuint client_id, GLuint service_id) {
885 return texture_manager()->CreateTexture(client_id, service_id);
888 // Gets the texture info for the given texture. Returns NULL if none exists.
889 TextureRef* GetTexture(GLuint client_id) const {
890 return texture_manager()->GetTexture(client_id);
893 // Deletes the texture info for the given texture.
894 void RemoveTexture(GLuint client_id) {
895 texture_manager()->RemoveTexture(client_id);
898 // Get the size (in pixels) of the currently bound frame buffer (either FBO
899 // or regular back buffer).
900 gfx::Size GetBoundReadFrameBufferSize();
902 // Get the format/type of the currently bound frame buffer (either FBO or
903 // regular back buffer).
904 // If the color image is a renderbuffer, returns 0 for type.
905 GLenum GetBoundReadFrameBufferTextureType();
906 GLenum GetBoundReadFrameBufferInternalFormat();
908 // Wrapper for CompressedTexImage2D commands.
909 error::Error DoCompressedTexImage2D(
910 GLenum target,
911 GLint level,
912 GLenum internal_format,
913 GLsizei width,
914 GLsizei height,
915 GLint border,
916 GLsizei image_size,
917 const void* data);
919 // Wrapper for CompressedTexImage3D commands.
920 error::Error DoCompressedTexImage3D(
921 GLenum target,
922 GLint level,
923 GLenum internal_format,
924 GLsizei width,
925 GLsizei height,
926 GLsizei depth,
927 GLint border,
928 GLsizei image_size,
929 const void* data);
931 // Wrapper for CompressedTexSubImage2D.
932 void DoCompressedTexSubImage2D(
933 GLenum target,
934 GLint level,
935 GLint xoffset,
936 GLint yoffset,
937 GLsizei width,
938 GLsizei height,
939 GLenum format,
940 GLsizei imageSize,
941 const void * data);
943 // Wrapper for CompressedTexSubImage3D.
944 void DoCompressedTexSubImage3D(
945 GLenum target,
946 GLint level,
947 GLint xoffset,
948 GLint yoffset,
949 GLint zoffset,
950 GLsizei width,
951 GLsizei height,
952 GLsizei depth,
953 GLenum format,
954 GLsizei image_size,
955 const void* data);
957 // Wrapper for CopyTexImage2D.
958 void DoCopyTexImage2D(
959 GLenum target,
960 GLint level,
961 GLenum internal_format,
962 GLint x,
963 GLint y,
964 GLsizei width,
965 GLsizei height,
966 GLint border);
968 // Wrapper for SwapBuffers.
969 void DoSwapBuffers();
971 // Wrapper for SwapInterval.
972 void DoSwapInterval(int interval);
974 // Wrapper for CopyTexSubImage2D.
975 void DoCopyTexSubImage2D(
976 GLenum target,
977 GLint level,
978 GLint xoffset,
979 GLint yoffset,
980 GLint x,
981 GLint y,
982 GLsizei width,
983 GLsizei height);
985 // Validation for TexSubImage2D.
986 bool ValidateTexSubImage2D(
987 error::Error* error,
988 const char* function_name,
989 GLenum target,
990 GLint level,
991 GLint xoffset,
992 GLint yoffset,
993 GLsizei width,
994 GLsizei height,
995 GLenum format,
996 GLenum type,
997 const void * data);
999 // Wrapper for TexSubImage2D.
1000 error::Error DoTexSubImage2D(
1001 GLenum target,
1002 GLint level,
1003 GLint xoffset,
1004 GLint yoffset,
1005 GLsizei width,
1006 GLsizei height,
1007 GLenum format,
1008 GLenum type,
1009 const void * data);
1011 // Wrapper for TexSubImage3D.
1012 error::Error DoTexSubImage3D(
1013 GLenum target,
1014 GLint level,
1015 GLint xoffset,
1016 GLint yoffset,
1017 GLint zoffset,
1018 GLsizei width,
1019 GLsizei height,
1020 GLsizei depth,
1021 GLenum format,
1022 GLenum type,
1023 const void * data);
1025 // Extra validation for async tex(Sub)Image2D.
1026 bool ValidateAsyncTransfer(
1027 const char* function_name,
1028 TextureRef* texture_ref,
1029 GLenum target,
1030 GLint level,
1031 const void * data);
1033 // Wrapper for TexImageIOSurface2DCHROMIUM.
1034 void DoTexImageIOSurface2DCHROMIUM(
1035 GLenum target,
1036 GLsizei width,
1037 GLsizei height,
1038 GLuint io_surface_id,
1039 GLuint plane);
1041 void DoCopyTextureCHROMIUM(GLenum target,
1042 GLuint source_id,
1043 GLuint dest_id,
1044 GLenum internal_format,
1045 GLenum dest_type,
1046 GLboolean unpack_flip_y,
1047 GLboolean unpack_premultiply_alpha,
1048 GLboolean unpack_unmultiply_alpha);
1050 void DoCopySubTextureCHROMIUM(GLenum target,
1051 GLuint source_id,
1052 GLuint dest_id,
1053 GLint xoffset,
1054 GLint yoffset,
1055 GLint x,
1056 GLint y,
1057 GLsizei width,
1058 GLsizei height,
1059 GLboolean unpack_flip_y,
1060 GLboolean unpack_premultiply_alpha,
1061 GLboolean unpack_unmultiply_alpha);
1063 void DoCompressedCopyTextureCHROMIUM(GLenum target,
1064 GLuint source_id,
1065 GLuint dest_id);
1067 void DoCompressedCopySubTextureCHROMIUM(GLenum target,
1068 GLuint source_id,
1069 GLuint dest_id,
1070 GLint xoffset,
1071 GLint yoffset,
1072 GLint x,
1073 GLint y,
1074 GLsizei width,
1075 GLsizei height);
1077 // Wrapper for TexStorage2DEXT.
1078 void DoTexStorage2DEXT(
1079 GLenum target,
1080 GLint levels,
1081 GLenum internal_format,
1082 GLsizei width,
1083 GLsizei height);
1085 void DoProduceTextureCHROMIUM(GLenum target, const GLbyte* key);
1086 void DoProduceTextureDirectCHROMIUM(GLuint texture, GLenum target,
1087 const GLbyte* key);
1088 void ProduceTextureRef(std::string func_name, TextureRef* texture_ref,
1089 GLenum target, const GLbyte* data);
1091 void EnsureTextureForClientId(GLenum target, GLuint client_id);
1092 void DoConsumeTextureCHROMIUM(GLenum target, const GLbyte* key);
1093 void DoCreateAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* key,
1094 GLuint client_id);
1096 bool DoIsValuebufferCHROMIUM(GLuint client_id);
1097 void DoBindValueBufferCHROMIUM(GLenum target, GLuint valuebuffer);
1098 void DoSubscribeValueCHROMIUM(GLenum target, GLenum subscription);
1099 void DoPopulateSubscribedValuesCHROMIUM(GLenum target);
1100 void DoUniformValueBufferCHROMIUM(GLint location,
1101 GLenum target,
1102 GLenum subscription);
1104 void DoBindTexImage2DCHROMIUM(
1105 GLenum target,
1106 GLint image_id);
1107 void DoReleaseTexImage2DCHROMIUM(
1108 GLenum target,
1109 GLint image_id);
1111 void DoTraceEndCHROMIUM(void);
1113 void DoDrawBuffersEXT(GLsizei count, const GLenum* bufs);
1115 void DoLoseContextCHROMIUM(GLenum current, GLenum other);
1117 void DoFlushDriverCachesCHROMIUM(void);
1119 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, const GLfloat* matrix);
1120 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode);
1122 // Creates a Program for the given program.
1123 Program* CreateProgram(
1124 GLuint client_id, GLuint service_id) {
1125 return program_manager()->CreateProgram(client_id, service_id);
1128 // Gets the program info for the given program. Returns NULL if none exists.
1129 Program* GetProgram(GLuint client_id) {
1130 return program_manager()->GetProgram(client_id);
1133 #if defined(NDEBUG)
1134 void LogClientServiceMapping(
1135 const char* /* function_name */,
1136 GLuint /* client_id */,
1137 GLuint /* service_id */) {
1139 template<typename T>
1140 void LogClientServiceForInfo(
1141 T* /* info */, GLuint /* client_id */, const char* /* function_name */) {
1143 #else
1144 void LogClientServiceMapping(
1145 const char* function_name, GLuint client_id, GLuint service_id) {
1146 if (service_logging_) {
1147 VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
1148 << ": client_id = " << client_id
1149 << ", service_id = " << service_id;
1152 template<typename T>
1153 void LogClientServiceForInfo(
1154 T* info, GLuint client_id, const char* function_name) {
1155 if (info) {
1156 LogClientServiceMapping(function_name, client_id, info->service_id());
1159 #endif
1161 // Gets the program info for the given program. If it's not a program
1162 // generates a GL error. Returns NULL if not program.
1163 Program* GetProgramInfoNotShader(
1164 GLuint client_id, const char* function_name) {
1165 Program* program = GetProgram(client_id);
1166 if (!program) {
1167 if (GetShader(client_id)) {
1168 LOCAL_SET_GL_ERROR(
1169 GL_INVALID_OPERATION, function_name, "shader passed for program");
1170 } else {
1171 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown program");
1174 LogClientServiceForInfo(program, client_id, function_name);
1175 return program;
1179 // Creates a Shader for the given shader.
1180 Shader* CreateShader(
1181 GLuint client_id,
1182 GLuint service_id,
1183 GLenum shader_type) {
1184 return shader_manager()->CreateShader(
1185 client_id, service_id, shader_type);
1188 // Gets the shader info for the given shader. Returns NULL if none exists.
1189 Shader* GetShader(GLuint client_id) {
1190 return shader_manager()->GetShader(client_id);
1193 // Gets the shader info for the given shader. If it's not a shader generates a
1194 // GL error. Returns NULL if not shader.
1195 Shader* GetShaderInfoNotProgram(
1196 GLuint client_id, const char* function_name) {
1197 Shader* shader = GetShader(client_id);
1198 if (!shader) {
1199 if (GetProgram(client_id)) {
1200 LOCAL_SET_GL_ERROR(
1201 GL_INVALID_OPERATION, function_name, "program passed for shader");
1202 } else {
1203 LOCAL_SET_GL_ERROR(
1204 GL_INVALID_VALUE, function_name, "unknown shader");
1207 LogClientServiceForInfo(shader, client_id, function_name);
1208 return shader;
1211 // Creates a buffer info for the given buffer.
1212 void CreateBuffer(GLuint client_id, GLuint service_id) {
1213 return buffer_manager()->CreateBuffer(client_id, service_id);
1216 // Gets the buffer info for the given buffer.
1217 Buffer* GetBuffer(GLuint client_id) {
1218 Buffer* buffer = buffer_manager()->GetBuffer(client_id);
1219 return buffer;
1222 // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
1223 // on glDeleteBuffers so we can make sure the user does not try to render
1224 // with deleted buffers.
1225 void RemoveBuffer(GLuint client_id);
1227 // Creates a framebuffer info for the given framebuffer.
1228 void CreateFramebuffer(GLuint client_id, GLuint service_id) {
1229 return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
1232 // Gets the framebuffer info for the given framebuffer.
1233 Framebuffer* GetFramebuffer(GLuint client_id) {
1234 return framebuffer_manager()->GetFramebuffer(client_id);
1237 // Removes the framebuffer info for the given framebuffer.
1238 void RemoveFramebuffer(GLuint client_id) {
1239 framebuffer_manager()->RemoveFramebuffer(client_id);
1242 // Creates a renderbuffer info for the given renderbuffer.
1243 void CreateRenderbuffer(GLuint client_id, GLuint service_id) {
1244 return renderbuffer_manager()->CreateRenderbuffer(
1245 client_id, service_id);
1248 // Gets the renderbuffer info for the given renderbuffer.
1249 Renderbuffer* GetRenderbuffer(GLuint client_id) {
1250 return renderbuffer_manager()->GetRenderbuffer(client_id);
1253 // Removes the renderbuffer info for the given renderbuffer.
1254 void RemoveRenderbuffer(GLuint client_id) {
1255 renderbuffer_manager()->RemoveRenderbuffer(client_id);
1258 // Creates a valuebuffer info for the given valuebuffer.
1259 void CreateValuebuffer(GLuint client_id) {
1260 return valuebuffer_manager()->CreateValuebuffer(client_id);
1263 // Gets the valuebuffer info for a given valuebuffer.
1264 Valuebuffer* GetValuebuffer(GLuint client_id) {
1265 return valuebuffer_manager()->GetValuebuffer(client_id);
1268 // Removes the valuebuffer info for the given valuebuffer.
1269 void RemoveValuebuffer(GLuint client_id) {
1270 valuebuffer_manager()->RemoveValuebuffer(client_id);
1273 // Gets the vertex attrib manager for the given vertex array.
1274 VertexAttribManager* GetVertexAttribManager(GLuint client_id) {
1275 VertexAttribManager* info =
1276 vertex_array_manager()->GetVertexAttribManager(client_id);
1277 return info;
1280 // Removes the vertex attrib manager for the given vertex array.
1281 void RemoveVertexAttribManager(GLuint client_id) {
1282 vertex_array_manager()->RemoveVertexAttribManager(client_id);
1285 // Creates a vertex attrib manager for the given vertex array.
1286 scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
1287 GLuint client_id,
1288 GLuint service_id,
1289 bool client_visible) {
1290 return vertex_array_manager()->CreateVertexAttribManager(
1291 client_id, service_id, group_->max_vertex_attribs(), client_visible);
1294 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
1295 void DoBindUniformLocationCHROMIUM(
1296 GLuint client_id, GLint location, const char* name);
1298 error::Error GetAttribLocationHelper(
1299 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1300 const std::string& name_str);
1302 error::Error GetUniformLocationHelper(
1303 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1304 const std::string& name_str);
1306 error::Error GetFragDataLocationHelper(
1307 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
1308 const std::string& name_str);
1310 // Wrapper for glShaderSource.
1311 void DoShaderSource(
1312 GLuint client_id, GLsizei count, const char** data, const GLint* length);
1314 // Wrapper for glTransformFeedbackVaryings.
1315 void DoTransformFeedbackVaryings(
1316 GLuint client_program_id, GLsizei count, const char* const* varyings,
1317 GLenum buffer_mode);
1319 // Clear any textures used by the current program.
1320 bool ClearUnclearedTextures();
1322 // Clears any uncleared attachments attached to the given frame buffer.
1323 // Returns false if there was a generated GL error.
1324 void ClearUnclearedAttachments(GLenum target, Framebuffer* framebuffer);
1326 // overridden from GLES2Decoder
1327 bool ClearLevel(Texture* texture,
1328 unsigned target,
1329 int level,
1330 unsigned format,
1331 unsigned type,
1332 int xoffset,
1333 int yoffset,
1334 int width,
1335 int height) override;
1337 // Restore all GL state that affects clearing.
1338 void RestoreClearState();
1340 // Remembers the state of some capabilities.
1341 // Returns: true if glEnable/glDisable should actually be called.
1342 bool SetCapabilityState(GLenum cap, bool enabled);
1344 // Check that the currently bound framebuffers are valid.
1345 // Generates GL error if not.
1346 bool CheckBoundFramebuffersValid(const char* func_name);
1348 // Check that the currently bound read framebuffer has a color image
1349 // attached. Generates GL error if not.
1350 bool CheckBoundReadFramebufferColorAttachment(const char* func_name);
1352 // Check that the currently bound read framebuffer's color image
1353 // isn't the target texture of the glCopyTex{Sub}Image2D.
1354 bool FormsTextureCopyingFeedbackLoop(TextureRef* texture, GLint level);
1356 // Check if a framebuffer meets our requirements.
1357 bool CheckFramebufferValid(
1358 Framebuffer* framebuffer,
1359 GLenum target,
1360 const char* func_name);
1362 // Check if the current valuebuffer exists and is valid. If not generates
1363 // the appropriate GL error. Returns true if the current valuebuffer is in
1364 // a usable state.
1365 bool CheckCurrentValuebuffer(const char* function_name);
1367 // Check if the current valuebuffer exists and is valiud and that the
1368 // value buffer is actually subscribed to the given subscription
1369 bool CheckCurrentValuebufferForSubscription(GLenum subscription,
1370 const char* function_name);
1372 // Check if the location can be used for the given subscription target. If not
1373 // generates the appropriate GL error. Returns true if the location is usable
1374 bool CheckSubscriptionTarget(GLint location,
1375 GLenum subscription,
1376 const char* function_name);
1378 // Checks if the current program exists and is valid. If not generates the
1379 // appropriate GL error. Returns true if the current program is in a usable
1380 // state.
1381 bool CheckCurrentProgram(const char* function_name);
1383 // Checks if the current program exists and is valid and that location is not
1384 // -1. If the current program is not valid generates the appropriate GL
1385 // error. Returns true if the current program is in a usable state and
1386 // location is not -1.
1387 bool CheckCurrentProgramForUniform(GLint location, const char* function_name);
1389 // Checks if the current program samples a texture that is also the color
1390 // image of the current bound framebuffer, i.e., the source and destination
1391 // of the draw operation are the same.
1392 bool CheckDrawingFeedbackLoops();
1394 // Checks if |api_type| is valid for the given uniform
1395 // If the api type is not valid generates the appropriate GL
1396 // error. Returns true if |api_type| is valid for the uniform
1397 bool CheckUniformForApiType(const Program::UniformInfo* info,
1398 const char* function_name,
1399 Program::UniformApiType api_type);
1401 // Gets the type of a uniform for a location in the current program. Sets GL
1402 // errors if the current program is not valid. Returns true if the current
1403 // program is valid and the location exists. Adjusts count so it
1404 // does not overflow the uniform.
1405 bool PrepForSetUniformByLocation(GLint fake_location,
1406 const char* function_name,
1407 Program::UniformApiType api_type,
1408 GLint* real_location,
1409 GLenum* type,
1410 GLsizei* count);
1412 // Gets the service id for any simulated backbuffer fbo.
1413 GLuint GetBackbufferServiceId() const;
1415 // Helper for glGetBooleanv, glGetFloatv and glGetIntegerv
1416 bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written);
1418 // Helper for glGetVertexAttrib
1419 void GetVertexAttribHelper(
1420 const VertexAttrib* attrib, GLenum pname, GLint* param);
1422 // Wrapper for glActiveTexture
1423 void DoActiveTexture(GLenum texture_unit);
1425 // Wrapper for glAttachShader
1426 void DoAttachShader(GLuint client_program_id, GLint client_shader_id);
1428 // Wrapper for glBindBuffer since we need to track the current targets.
1429 void DoBindBuffer(GLenum target, GLuint buffer);
1431 // Wrapper for glBindFramebuffer since we need to track the current targets.
1432 void DoBindFramebuffer(GLenum target, GLuint framebuffer);
1434 // Wrapper for glBindRenderbuffer since we need to track the current targets.
1435 void DoBindRenderbuffer(GLenum target, GLuint renderbuffer);
1437 // Wrapper for glBindTexture since we need to track the current targets.
1438 void DoBindTexture(GLenum target, GLuint texture);
1440 // Wrapper for glBindVertexArrayOES
1441 void DoBindVertexArrayOES(GLuint array);
1442 void EmulateVertexArrayState();
1444 // Wrapper for glBlitFramebufferCHROMIUM.
1445 void DoBlitFramebufferCHROMIUM(
1446 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
1447 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
1448 GLbitfield mask, GLenum filter);
1450 // Wrapper for glBufferSubData.
1451 void DoBufferSubData(
1452 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
1454 // Wrapper for glCheckFramebufferStatus
1455 GLenum DoCheckFramebufferStatus(GLenum target);
1457 // Wrapper for glClear
1458 error::Error DoClear(GLbitfield mask);
1460 // Wrappers for various state.
1461 void DoDepthRangef(GLclampf znear, GLclampf zfar);
1462 void DoSampleCoverage(GLclampf value, GLboolean invert);
1464 // Wrapper for glCompileShader.
1465 void DoCompileShader(GLuint shader);
1467 // Wrapper for glDetachShader
1468 void DoDetachShader(GLuint client_program_id, GLint client_shader_id);
1470 // Wrapper for glDisable
1471 void DoDisable(GLenum cap);
1473 // Wrapper for glDisableVertexAttribArray.
1474 void DoDisableVertexAttribArray(GLuint index);
1476 // Wrapper for glDiscardFramebufferEXT, since we need to track undefined
1477 // attachments.
1478 void DoDiscardFramebufferEXT(GLenum target,
1479 GLsizei numAttachments,
1480 const GLenum* attachments);
1482 // Wrapper for glEnable
1483 void DoEnable(GLenum cap);
1485 // Wrapper for glEnableVertexAttribArray.
1486 void DoEnableVertexAttribArray(GLuint index);
1488 // Wrapper for glFinish.
1489 void DoFinish();
1491 // Wrapper for glFlush.
1492 void DoFlush();
1494 // Wrapper for glFramebufferRenderbufffer.
1495 void DoFramebufferRenderbuffer(
1496 GLenum target, GLenum attachment, GLenum renderbuffertarget,
1497 GLuint renderbuffer);
1499 // Wrapper for glFramebufferTexture2D.
1500 void DoFramebufferTexture2D(
1501 GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
1502 GLint level);
1504 // Wrapper for glFramebufferTexture2DMultisampleEXT.
1505 void DoFramebufferTexture2DMultisample(
1506 GLenum target, GLenum attachment, GLenum textarget,
1507 GLuint texture, GLint level, GLsizei samples);
1509 // Common implementation for both DoFramebufferTexture2D wrappers.
1510 void DoFramebufferTexture2DCommon(const char* name,
1511 GLenum target, GLenum attachment, GLenum textarget,
1512 GLuint texture, GLint level, GLsizei samples);
1514 // Wrapper for glFramebufferTextureLayer.
1515 void DoFramebufferTextureLayer(
1516 GLenum target, GLenum attachment, GLuint texture, GLint level,
1517 GLint layer);
1519 // Wrapper for glGenerateMipmap
1520 void DoGenerateMipmap(GLenum target);
1522 // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname
1523 // to account for different pname values defined in different extension
1524 // variants.
1525 GLenum AdjustGetPname(GLenum pname);
1527 // Wrapper for DoGetBooleanv.
1528 void DoGetBooleanv(GLenum pname, GLboolean* params);
1530 // Wrapper for DoGetFloatv.
1531 void DoGetFloatv(GLenum pname, GLfloat* params);
1533 // Wrapper for glGetFramebufferAttachmentParameteriv.
1534 void DoGetFramebufferAttachmentParameteriv(
1535 GLenum target, GLenum attachment, GLenum pname, GLint* params);
1537 // Wrapper for glGetInteger64v.
1538 void DoGetInteger64v(GLenum pname, GLint64* params);
1540 // Wrapper for glGetIntegerv.
1541 void DoGetIntegerv(GLenum pname, GLint* params);
1543 // Gets the max value in a range in a buffer.
1544 GLuint DoGetMaxValueInBufferCHROMIUM(
1545 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset);
1547 // Wrapper for glGetBufferParameteri64v.
1548 void DoGetBufferParameteri64v(
1549 GLenum target, GLenum pname, GLint64* params);
1551 // Wrapper for glGetBufferParameteriv.
1552 void DoGetBufferParameteriv(
1553 GLenum target, GLenum pname, GLint* params);
1555 // Wrapper for glGetProgramiv.
1556 void DoGetProgramiv(
1557 GLuint program_id, GLenum pname, GLint* params);
1559 // Wrapper for glRenderbufferParameteriv.
1560 void DoGetRenderbufferParameteriv(
1561 GLenum target, GLenum pname, GLint* params);
1563 // Wrapper for glGetShaderiv
1564 void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
1566 // Wrappers for glGetTexParameter.
1567 void DoGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
1568 void DoGetTexParameteriv(GLenum target, GLenum pname, GLint* params);
1569 void InitTextureMaxAnisotropyIfNeeded(GLenum target, GLenum pname);
1571 // Wrappers for glGetVertexAttrib.
1572 template <typename T>
1573 void DoGetVertexAttribImpl(GLuint index, GLenum pname, T* params);
1574 void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
1575 void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
1576 void DoGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params);
1577 void DoGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params);
1579 // Wrappers for glIsXXX functions.
1580 bool DoIsEnabled(GLenum cap);
1581 bool DoIsBuffer(GLuint client_id);
1582 bool DoIsFramebuffer(GLuint client_id);
1583 bool DoIsProgram(GLuint client_id);
1584 bool DoIsRenderbuffer(GLuint client_id);
1585 bool DoIsShader(GLuint client_id);
1586 bool DoIsTexture(GLuint client_id);
1587 bool DoIsVertexArrayOES(GLuint client_id);
1588 bool DoIsPathCHROMIUM(GLuint client_id);
1590 // Wrapper for glLinkProgram
1591 void DoLinkProgram(GLuint program);
1593 // Wrapper for glReadBuffer
1594 void DoReadBuffer(GLenum src);
1596 // Wrapper for glRenderbufferStorage.
1597 void DoRenderbufferStorage(
1598 GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
1600 // Handler for glRenderbufferStorageMultisampleCHROMIUM.
1601 void DoRenderbufferStorageMultisampleCHROMIUM(
1602 GLenum target, GLsizei samples, GLenum internalformat,
1603 GLsizei width, GLsizei height);
1605 // Handler for glRenderbufferStorageMultisampleEXT
1606 // (multisampled_render_to_texture).
1607 void DoRenderbufferStorageMultisampleEXT(
1608 GLenum target, GLsizei samples, GLenum internalformat,
1609 GLsizei width, GLsizei height);
1611 // Common validation for multisample extensions.
1612 bool ValidateRenderbufferStorageMultisample(GLsizei samples,
1613 GLenum internalformat,
1614 GLsizei width,
1615 GLsizei height);
1617 // Verifies that the currently bound multisample renderbuffer is valid
1618 // Very slow! Only done on platforms with driver bugs that return invalid
1619 // buffers under memory pressure
1620 bool VerifyMultisampleRenderbufferIntegrity(
1621 GLuint renderbuffer, GLenum format);
1623 // Wrapper for glReleaseShaderCompiler.
1624 void DoReleaseShaderCompiler() { }
1626 // Wrappers for glSamplerParameter*v functions.
1627 void DoSamplerParameterfv(
1628 GLuint sampler, GLenum pname, const GLfloat* params);
1629 void DoSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* params);
1631 // Wrappers for glTexParameter functions.
1632 void DoTexParameterf(GLenum target, GLenum pname, GLfloat param);
1633 void DoTexParameteri(GLenum target, GLenum pname, GLint param);
1634 void DoTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
1635 void DoTexParameteriv(GLenum target, GLenum pname, const GLint* params);
1637 // Wrappers for glUniform1i and glUniform1iv as according to the GLES2
1638 // spec only these 2 functions can be used to set sampler uniforms.
1639 void DoUniform1i(GLint fake_location, GLint v0);
1640 void DoUniform1iv(GLint fake_location, GLsizei count, const GLint* value);
1641 void DoUniform2iv(GLint fake_location, GLsizei count, const GLint* value);
1642 void DoUniform3iv(GLint fake_location, GLsizei count, const GLint* value);
1643 void DoUniform4iv(GLint fake_location, GLsizei count, const GLint* value);
1645 // Wrappers for glUniformfv because some drivers don't correctly accept
1646 // bool uniforms.
1647 void DoUniform1fv(GLint fake_location, GLsizei count, const GLfloat* value);
1648 void DoUniform2fv(GLint fake_location, GLsizei count, const GLfloat* value);
1649 void DoUniform3fv(GLint fake_location, GLsizei count, const GLfloat* value);
1650 void DoUniform4fv(GLint fake_location, GLsizei count, const GLfloat* value);
1652 void DoUniformMatrix2fv(
1653 GLint fake_location, GLsizei count, GLboolean transpose,
1654 const GLfloat* value);
1655 void DoUniformMatrix3fv(
1656 GLint fake_location, GLsizei count, GLboolean transpose,
1657 const GLfloat* value);
1658 void DoUniformMatrix4fv(
1659 GLint fake_location, GLsizei count, GLboolean transpose,
1660 const GLfloat* value);
1662 template <typename T>
1663 bool SetVertexAttribValue(
1664 const char* function_name, GLuint index, const T* value);
1666 // Wrappers for glVertexAttrib??
1667 void DoVertexAttrib1f(GLuint index, GLfloat v0);
1668 void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
1669 void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
1670 void DoVertexAttrib4f(
1671 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
1672 void DoVertexAttrib1fv(GLuint index, const GLfloat* v);
1673 void DoVertexAttrib2fv(GLuint index, const GLfloat* v);
1674 void DoVertexAttrib3fv(GLuint index, const GLfloat* v);
1675 void DoVertexAttrib4fv(GLuint index, const GLfloat* v);
1676 void DoVertexAttribI4i(GLuint index, GLint v0, GLint v1, GLint v2, GLint v3);
1677 void DoVertexAttribI4iv(GLuint index, const GLint* v);
1678 void DoVertexAttribI4ui(
1679 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
1680 void DoVertexAttribI4uiv(GLuint index, const GLuint* v);
1682 // Wrapper for glViewport
1683 void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height);
1685 // Wrapper for glUseProgram
1686 void DoUseProgram(GLuint program);
1688 // Wrapper for glValidateProgram.
1689 void DoValidateProgram(GLuint program_client_id);
1691 void DoInsertEventMarkerEXT(GLsizei length, const GLchar* marker);
1692 void DoPushGroupMarkerEXT(GLsizei length, const GLchar* group);
1693 void DoPopGroupMarkerEXT(void);
1695 // Gets the number of values that will be returned by glGetXXX. Returns
1696 // false if pname is unknown.
1697 bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values);
1699 // Checks if the current program and vertex attributes are valid for drawing.
1700 bool IsDrawValid(
1701 const char* function_name, GLuint max_vertex_accessed, bool instanced,
1702 GLsizei primcount);
1704 // Returns true if successful, simulated will be true if attrib0 was
1705 // simulated.
1706 bool SimulateAttrib0(
1707 const char* function_name, GLuint max_vertex_accessed, bool* simulated);
1708 void RestoreStateForAttrib(GLuint attrib, bool restore_array_binding);
1710 // If an image is bound to texture, this will call Will/DidUseTexImage
1711 // if needed.
1712 void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1713 void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
1715 // Returns false if textures were replaced.
1716 bool PrepareTexturesForRender();
1717 void RestoreStateForTextures();
1719 // Returns true if GL_FIXED attribs were simulated.
1720 bool SimulateFixedAttribs(
1721 const char* function_name,
1722 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount);
1723 void RestoreStateForSimulatedFixedAttribs();
1725 // Handle DrawArrays and DrawElements for both instanced and non-instanced
1726 // cases (primcount is always 1 for non-instanced).
1727 error::Error DoDrawArrays(
1728 const char* function_name,
1729 bool instanced, GLenum mode, GLint first, GLsizei count,
1730 GLsizei primcount);
1731 error::Error DoDrawElements(
1732 const char* function_name,
1733 bool instanced, GLenum mode, GLsizei count, GLenum type,
1734 int32 offset, GLsizei primcount);
1736 GLenum GetBindTargetForSamplerType(GLenum type) {
1737 DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
1738 type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
1739 switch (type) {
1740 case GL_SAMPLER_2D:
1741 return GL_TEXTURE_2D;
1742 case GL_SAMPLER_CUBE:
1743 return GL_TEXTURE_CUBE_MAP;
1744 case GL_SAMPLER_EXTERNAL_OES:
1745 return GL_TEXTURE_EXTERNAL_OES;
1746 case GL_SAMPLER_2D_RECT_ARB:
1747 return GL_TEXTURE_RECTANGLE_ARB;
1750 NOTREACHED();
1751 return 0;
1754 // Gets the framebuffer info for a particular target.
1755 Framebuffer* GetFramebufferInfoForTarget(GLenum target) {
1756 Framebuffer* framebuffer = NULL;
1757 switch (target) {
1758 case GL_FRAMEBUFFER:
1759 case GL_DRAW_FRAMEBUFFER_EXT:
1760 framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
1761 break;
1762 case GL_READ_FRAMEBUFFER_EXT:
1763 framebuffer = framebuffer_state_.bound_read_framebuffer.get();
1764 break;
1765 default:
1766 NOTREACHED();
1767 break;
1769 return framebuffer;
1772 Renderbuffer* GetRenderbufferInfoForTarget(
1773 GLenum target) {
1774 Renderbuffer* renderbuffer = NULL;
1775 switch (target) {
1776 case GL_RENDERBUFFER:
1777 renderbuffer = state_.bound_renderbuffer.get();
1778 break;
1779 default:
1780 NOTREACHED();
1781 break;
1783 return renderbuffer;
1786 // Validates the program and location for a glGetUniform call and returns
1787 // a SizeResult setup to receive the result. Returns true if glGetUniform
1788 // should be called.
1789 template <class T>
1790 bool GetUniformSetup(GLuint program,
1791 GLint fake_location,
1792 uint32 shm_id,
1793 uint32 shm_offset,
1794 error::Error* error,
1795 GLint* real_location,
1796 GLuint* service_id,
1797 SizedResult<T>** result,
1798 GLenum* result_type,
1799 GLsizei* result_size);
1801 bool WasContextLost() const override;
1802 bool WasContextLostByRobustnessExtension() const override;
1803 void MarkContextLost(error::ContextLostReason reason) override;
1804 bool CheckResetStatus();
1806 #if defined(OS_MACOSX)
1807 void ReleaseIOSurfaceForTexture(GLuint texture_id);
1808 #endif
1810 bool GetCompressedTexSizeInBytes(
1811 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
1812 GLenum format, GLsizei* size_in_bytes);
1814 bool ValidateCompressedTexDimensions(
1815 const char* function_name, GLenum target, GLint level,
1816 GLsizei width, GLsizei height, GLsizei depth, GLenum format);
1817 bool ValidateCompressedTexFuncData(
1818 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
1819 GLenum format, GLsizei size);
1820 bool ValidateCompressedTexSubDimensions(
1821 const char* function_name,
1822 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
1823 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
1824 Texture* texture);
1825 bool ValidateCopyTextureCHROMIUM(const char* function_name,
1826 GLenum target,
1827 TextureRef* source_texture_ref,
1828 TextureRef* dest_texture_ref,
1829 GLenum dest_internal_format);
1830 bool ValidateCompressedCopyTextureCHROMIUM(const char* function_name,
1831 GLenum target,
1832 TextureRef* source_texture_ref,
1833 TextureRef* dest_texture_ref);
1835 void RenderWarning(const char* filename, int line, const std::string& msg);
1836 void PerformanceWarning(
1837 const char* filename, int line, const std::string& msg);
1839 const FeatureInfo::FeatureFlags& features() const {
1840 return feature_info_->feature_flags();
1843 const FeatureInfo::Workarounds& workarounds() const {
1844 return feature_info_->workarounds();
1847 bool ShouldDeferDraws() {
1848 return !offscreen_target_frame_buffer_.get() &&
1849 framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
1850 surface_->DeferDraws();
1853 bool ShouldDeferReads() {
1854 return !offscreen_target_frame_buffer_.get() &&
1855 framebuffer_state_.bound_read_framebuffer.get() == NULL &&
1856 surface_->DeferDraws();
1859 bool IsRobustnessSupported() {
1860 return has_robustness_extension_ &&
1861 context_->WasAllocatedUsingRobustnessExtension();
1864 error::Error WillAccessBoundFramebufferForDraw() {
1865 if (ShouldDeferDraws())
1866 return error::kDeferCommandUntilLater;
1867 if (!offscreen_target_frame_buffer_.get() &&
1868 !framebuffer_state_.bound_draw_framebuffer.get() &&
1869 !surface_->SetBackbufferAllocation(true))
1870 return error::kLostContext;
1871 return error::kNoError;
1874 error::Error WillAccessBoundFramebufferForRead() {
1875 if (ShouldDeferReads())
1876 return error::kDeferCommandUntilLater;
1877 if (!offscreen_target_frame_buffer_.get() &&
1878 !framebuffer_state_.bound_read_framebuffer.get() &&
1879 !surface_->SetBackbufferAllocation(true))
1880 return error::kLostContext;
1881 return error::kNoError;
1884 bool BackBufferHasAlpha() const {
1885 if (back_buffer_draw_buffer_ == GL_NONE)
1886 return false;
1887 if (offscreen_target_frame_buffer_.get()) {
1888 return (offscreen_target_color_format_ == GL_RGBA ||
1889 offscreen_target_color_format_ == GL_RGBA8);
1891 return (back_buffer_color_format_ == GL_RGBA ||
1892 back_buffer_color_format_ == GL_RGBA8);
1895 // Set remaining commands to process to 0 to force DoCommands to return
1896 // and allow context preemption and GPU watchdog checks in GpuScheduler().
1897 void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
1899 void ProcessPendingReadPixels(bool did_finish);
1900 void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
1902 // Generate a member function prototype for each command in an automated and
1903 // typesafe way.
1904 #define GLES2_CMD_OP(name) \
1905 Error Handle##name(uint32 immediate_data_size, const void* data);
1907 GLES2_COMMAND_LIST(GLES2_CMD_OP)
1909 #undef GLES2_CMD_OP
1911 // The GL context this decoder renders to on behalf of the client.
1912 scoped_refptr<gfx::GLSurface> surface_;
1913 scoped_refptr<gfx::GLContext> context_;
1915 // The ContextGroup for this decoder uses to track resources.
1916 scoped_refptr<ContextGroup> group_;
1918 DebugMarkerManager debug_marker_manager_;
1919 Logger logger_;
1921 // All the state for this context.
1922 ContextState state_;
1924 // Current width and height of the offscreen frame buffer.
1925 gfx::Size offscreen_size_;
1927 // Util to help with GL.
1928 GLES2Util util_;
1930 // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
1931 GLuint attrib_0_buffer_id_;
1933 // The value currently in attrib_0.
1934 Vec4 attrib_0_value_;
1936 // Whether or not the attrib_0 buffer holds the attrib_0_value.
1937 bool attrib_0_buffer_matches_value_;
1939 // The size of attrib 0.
1940 GLsizei attrib_0_size_;
1942 // The buffer used to simulate GL_FIXED attribs.
1943 GLuint fixed_attrib_buffer_id_;
1945 // The size of fiixed attrib buffer.
1946 GLsizei fixed_attrib_buffer_size_;
1948 // The offscreen frame buffer that the client renders to. With EGL, the
1949 // depth and stencil buffers are separate. With regular GL there is a single
1950 // packed depth stencil buffer in offscreen_target_depth_render_buffer_.
1951 // offscreen_target_stencil_render_buffer_ is unused.
1952 scoped_ptr<BackFramebuffer> offscreen_target_frame_buffer_;
1953 scoped_ptr<BackTexture> offscreen_target_color_texture_;
1954 scoped_ptr<BackRenderbuffer> offscreen_target_color_render_buffer_;
1955 scoped_ptr<BackRenderbuffer> offscreen_target_depth_render_buffer_;
1956 scoped_ptr<BackRenderbuffer> offscreen_target_stencil_render_buffer_;
1957 GLenum offscreen_target_color_format_;
1958 GLenum offscreen_target_depth_format_;
1959 GLenum offscreen_target_stencil_format_;
1960 GLsizei offscreen_target_samples_;
1961 GLboolean offscreen_target_buffer_preserved_;
1963 // The copy that is saved when SwapBuffers is called.
1964 scoped_ptr<BackFramebuffer> offscreen_saved_frame_buffer_;
1965 scoped_ptr<BackTexture> offscreen_saved_color_texture_;
1966 scoped_refptr<TextureRef>
1967 offscreen_saved_color_texture_info_;
1969 // The copy that is used as the destination for multi-sample resolves.
1970 scoped_ptr<BackFramebuffer> offscreen_resolved_frame_buffer_;
1971 scoped_ptr<BackTexture> offscreen_resolved_color_texture_;
1972 GLenum offscreen_saved_color_format_;
1974 scoped_ptr<QueryManager> query_manager_;
1976 scoped_ptr<VertexArrayManager> vertex_array_manager_;
1978 scoped_ptr<ImageManager> image_manager_;
1980 base::Callback<void(gfx::Size, float)> resize_callback_;
1982 WaitSyncPointCallback wait_sync_point_callback_;
1984 ShaderCacheCallback shader_cache_callback_;
1986 scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
1988 // The format of the back buffer_
1989 GLenum back_buffer_color_format_;
1990 bool back_buffer_has_depth_;
1991 bool back_buffer_has_stencil_;
1993 // Tracks read buffer and draw buffer for backbuffer, whether it's onscreen
1994 // or offscreen.
1995 // TODO(zmo): when ES3 APIs are exposed to Nacl, make sure read_buffer_
1996 // setting is set correctly when SwapBuffers().
1997 GLenum back_buffer_read_buffer_;
1998 GLenum back_buffer_draw_buffer_;
2000 bool surfaceless_;
2002 // Backbuffer attachments that are currently undefined.
2003 uint32 backbuffer_needs_clear_bits_;
2005 // The current decoder error communicates the decoder error through command
2006 // processing functions that do not return the error value. Should be set only
2007 // if not returning an error.
2008 error::Error current_decoder_error_;
2010 bool use_shader_translator_;
2011 scoped_refptr<ShaderTranslatorInterface> vertex_translator_;
2012 scoped_refptr<ShaderTranslatorInterface> fragment_translator_;
2014 DisallowedFeatures disallowed_features_;
2016 // Cached from ContextGroup
2017 const Validators* validators_;
2018 scoped_refptr<FeatureInfo> feature_info_;
2020 int frame_number_;
2022 // Number of commands remaining to be processed in DoCommands().
2023 int commands_to_process_;
2025 bool has_robustness_extension_;
2026 error::ContextLostReason context_lost_reason_;
2027 bool context_was_lost_;
2028 bool reset_by_robustness_extension_;
2029 bool supports_post_sub_buffer_;
2031 // Indicates whether this is a context for WebGL1, WebGL2, or others.
2032 // 0: other types
2033 // 1: WebGL 1
2034 // 2: WebGL 2
2035 unsigned webgl_version_;
2037 // These flags are used to override the state of the shared feature_info_
2038 // member. Because the same FeatureInfo instance may be shared among many
2039 // contexts, the assumptions on the availablity of extensions in WebGL
2040 // contexts may be broken. These flags override the shared state to preserve
2041 // WebGL semantics.
2042 bool derivatives_explicitly_enabled_;
2043 bool frag_depth_explicitly_enabled_;
2044 bool draw_buffers_explicitly_enabled_;
2045 bool shader_texture_lod_explicitly_enabled_;
2047 bool compile_shader_always_succeeds_;
2049 // An optional behaviour to lose the context and group when OOM.
2050 bool lose_context_when_out_of_memory_;
2052 // Log extra info.
2053 bool service_logging_;
2055 #if defined(OS_MACOSX)
2056 typedef std::map<GLuint, IOSurfaceRef> TextureToIOSurfaceMap;
2057 TextureToIOSurfaceMap texture_to_io_surface_map_;
2058 #endif
2060 scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
2061 scoped_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_;
2063 // Cached values of the currently assigned viewport dimensions.
2064 GLsizei viewport_max_width_;
2065 GLsizei viewport_max_height_;
2067 // Command buffer stats.
2068 base::TimeDelta total_processing_commands_time_;
2070 // States related to each manager.
2071 DecoderTextureState texture_state_;
2072 DecoderFramebufferState framebuffer_state_;
2074 scoped_ptr<GPUTracer> gpu_tracer_;
2075 scoped_ptr<GPUStateTracer> gpu_state_tracer_;
2076 const unsigned char* cb_command_trace_category_;
2077 const unsigned char* gpu_decoder_category_;
2078 int gpu_trace_level_;
2079 bool gpu_trace_commands_;
2080 bool gpu_debug_commands_;
2082 std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
2084 // Used to validate multisample renderbuffers if needed
2085 GLuint validation_texture_;
2086 GLuint validation_fbo_multisample_;
2087 GLuint validation_fbo_;
2089 typedef gpu::gles2::GLES2Decoder::Error (GLES2DecoderImpl::*CmdHandler)(
2090 uint32 immediate_data_size,
2091 const void* data);
2093 // A struct to hold info about each command.
2094 struct CommandInfo {
2095 CmdHandler cmd_handler;
2096 uint8 arg_flags; // How to handle the arguments for this command
2097 uint8 cmd_flags; // How to handle this command
2098 uint16 arg_count; // How many arguments are expected for this command.
2101 // A table of CommandInfo for all the commands.
2102 static const CommandInfo command_info[kNumCommands - kStartPoint];
2104 DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
2107 const GLES2DecoderImpl::CommandInfo GLES2DecoderImpl::command_info[] = {
2108 #define GLES2_CMD_OP(name) \
2110 &GLES2DecoderImpl::Handle##name, cmds::name::kArgFlags, \
2111 cmds::name::cmd_flags, \
2112 sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \
2114 , /* NOLINT */
2115 GLES2_COMMAND_LIST(GLES2_CMD_OP)
2116 #undef GLES2_CMD_OP
2119 ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
2120 const char* function_name, ErrorState* error_state)
2121 : function_name_(function_name),
2122 error_state_(error_state) {
2123 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
2126 ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
2127 ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
2130 static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
2131 TextureUnit& info = state->texture_units[0];
2132 GLuint last_id;
2133 scoped_refptr<TextureRef> texture_ref;
2134 switch (target) {
2135 case GL_TEXTURE_2D:
2136 texture_ref = info.bound_texture_2d;
2137 break;
2138 case GL_TEXTURE_CUBE_MAP:
2139 texture_ref = info.bound_texture_cube_map;
2140 break;
2141 case GL_TEXTURE_EXTERNAL_OES:
2142 texture_ref = info.bound_texture_external_oes;
2143 break;
2144 case GL_TEXTURE_RECTANGLE_ARB:
2145 texture_ref = info.bound_texture_rectangle_arb;
2146 break;
2147 default:
2148 NOTREACHED();
2149 break;
2151 if (texture_ref.get()) {
2152 last_id = texture_ref->service_id();
2153 } else {
2154 last_id = 0;
2157 glBindTexture(target, last_id);
2158 glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
2161 ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
2162 GLuint id,
2163 GLenum target)
2164 : state_(state),
2165 target_(target) {
2166 ScopedGLErrorSuppressor suppressor(
2167 "ScopedTextureBinder::ctor", state_->GetErrorState());
2169 // TODO(apatrick): Check if there are any other states that need to be reset
2170 // before binding a new texture.
2171 glActiveTexture(GL_TEXTURE0);
2172 glBindTexture(target, id);
2175 ScopedTextureBinder::~ScopedTextureBinder() {
2176 ScopedGLErrorSuppressor suppressor(
2177 "ScopedTextureBinder::dtor", state_->GetErrorState());
2178 RestoreCurrentTextureBindings(state_, target_);
2181 ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
2182 GLuint id)
2183 : state_(state) {
2184 ScopedGLErrorSuppressor suppressor(
2185 "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
2186 glBindRenderbufferEXT(GL_RENDERBUFFER, id);
2189 ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
2190 ScopedGLErrorSuppressor suppressor(
2191 "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
2192 state_->RestoreRenderbufferBindings();
2195 ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
2196 GLuint id)
2197 : decoder_(decoder) {
2198 ScopedGLErrorSuppressor suppressor(
2199 "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
2200 glBindFramebufferEXT(GL_FRAMEBUFFER, id);
2201 decoder->OnFboChanged();
2204 ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
2205 ScopedGLErrorSuppressor suppressor(
2206 "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
2207 decoder_->RestoreCurrentFramebufferBindings();
2210 ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
2211 GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
2212 : decoder_(decoder) {
2213 resolve_and_bind_ = (
2214 decoder_->offscreen_target_frame_buffer_.get() &&
2215 decoder_->IsOffscreenBufferMultisampled() &&
2216 (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
2217 enforce_internal_framebuffer));
2218 if (!resolve_and_bind_)
2219 return;
2221 ScopedGLErrorSuppressor suppressor(
2222 "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
2223 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
2224 decoder_->offscreen_target_frame_buffer_->id());
2225 GLuint targetid;
2226 if (internal) {
2227 if (!decoder_->offscreen_resolved_frame_buffer_.get()) {
2228 decoder_->offscreen_resolved_frame_buffer_.reset(
2229 new BackFramebuffer(decoder_));
2230 decoder_->offscreen_resolved_frame_buffer_->Create();
2231 decoder_->offscreen_resolved_color_texture_.reset(
2232 new BackTexture(decoder->memory_tracker(), &decoder->state_));
2233 decoder_->offscreen_resolved_color_texture_->Create();
2235 DCHECK(decoder_->offscreen_saved_color_format_);
2236 decoder_->offscreen_resolved_color_texture_->AllocateStorage(
2237 decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_,
2238 false);
2239 decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture(
2240 decoder_->offscreen_resolved_color_texture_.get());
2241 if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() !=
2242 GL_FRAMEBUFFER_COMPLETE) {
2243 LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed "
2244 << "because offscreen resolved FBO was incomplete.";
2245 return;
2248 targetid = decoder_->offscreen_resolved_frame_buffer_->id();
2249 } else {
2250 targetid = decoder_->offscreen_saved_frame_buffer_->id();
2252 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
2253 const int width = decoder_->offscreen_size_.width();
2254 const int height = decoder_->offscreen_size_.height();
2255 decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
2256 decoder->BlitFramebufferHelper(0,
2258 width,
2259 height,
2262 width,
2263 height,
2264 GL_COLOR_BUFFER_BIT,
2265 GL_NEAREST);
2266 glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
2269 ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
2270 if (!resolve_and_bind_)
2271 return;
2273 ScopedGLErrorSuppressor suppressor(
2274 "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
2275 decoder_->RestoreCurrentFramebufferBindings();
2276 if (decoder_->state_.enable_flags.scissor_test) {
2277 decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
2281 BackTexture::BackTexture(
2282 MemoryTracker* memory_tracker,
2283 ContextState* state)
2284 : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2285 state_(state),
2286 bytes_allocated_(0),
2287 id_(0) {
2290 BackTexture::~BackTexture() {
2291 // This does not destroy the render texture because that would require that
2292 // the associated GL context was current. Just check that it was explicitly
2293 // destroyed.
2294 DCHECK_EQ(id_, 0u);
2297 void BackTexture::Create() {
2298 ScopedGLErrorSuppressor suppressor("BackTexture::Create",
2299 state_->GetErrorState());
2300 Destroy();
2301 glGenTextures(1, &id_);
2302 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2303 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2304 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2305 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2306 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2308 // TODO(apatrick): Attempt to diagnose crbug.com/97775. If SwapBuffers is
2309 // never called on an offscreen context, no data will ever be uploaded to the
2310 // saved offscreen color texture (it is deferred until to when SwapBuffers
2311 // is called). My idea is that some nvidia drivers might have a bug where
2312 // deleting a texture that has never been populated might cause a
2313 // crash.
2314 glTexImage2D(
2315 GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2317 bytes_allocated_ = 16u * 16u * 4u;
2318 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2321 bool BackTexture::AllocateStorage(
2322 const gfx::Size& size, GLenum format, bool zero) {
2323 DCHECK_NE(id_, 0u);
2324 ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
2325 state_->GetErrorState());
2326 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2327 uint32 image_size = 0;
2328 GLES2Util::ComputeImageDataSizes(
2329 size.width(), size.height(), 1, format, GL_UNSIGNED_BYTE, 8, &image_size,
2330 NULL, NULL);
2332 if (!memory_tracker_.EnsureGPUMemoryAvailable(image_size)) {
2333 return false;
2336 scoped_ptr<char[]> zero_data;
2337 if (zero) {
2338 zero_data.reset(new char[image_size]);
2339 memset(zero_data.get(), 0, image_size);
2342 glTexImage2D(GL_TEXTURE_2D,
2343 0, // mip level
2344 format,
2345 size.width(),
2346 size.height(),
2347 0, // border
2348 format,
2349 GL_UNSIGNED_BYTE,
2350 zero_data.get());
2352 size_ = size;
2354 bool success = glGetError() == GL_NO_ERROR;
2355 if (success) {
2356 memory_tracker_.TrackMemFree(bytes_allocated_);
2357 bytes_allocated_ = image_size;
2358 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2360 return success;
2363 void BackTexture::Copy(const gfx::Size& size, GLenum format) {
2364 DCHECK_NE(id_, 0u);
2365 ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
2366 state_->GetErrorState());
2367 ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
2368 glCopyTexImage2D(GL_TEXTURE_2D,
2369 0, // level
2370 format,
2371 0, 0,
2372 size.width(),
2373 size.height(),
2374 0); // border
2377 void BackTexture::Destroy() {
2378 if (id_ != 0) {
2379 ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
2380 state_->GetErrorState());
2381 glDeleteTextures(1, &id_);
2382 id_ = 0;
2384 memory_tracker_.TrackMemFree(bytes_allocated_);
2385 bytes_allocated_ = 0;
2388 void BackTexture::Invalidate() {
2389 id_ = 0;
2392 BackRenderbuffer::BackRenderbuffer(
2393 RenderbufferManager* renderbuffer_manager,
2394 MemoryTracker* memory_tracker,
2395 ContextState* state)
2396 : renderbuffer_manager_(renderbuffer_manager),
2397 memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
2398 state_(state),
2399 bytes_allocated_(0),
2400 id_(0) {
2403 BackRenderbuffer::~BackRenderbuffer() {
2404 // This does not destroy the render buffer because that would require that
2405 // the associated GL context was current. Just check that it was explicitly
2406 // destroyed.
2407 DCHECK_EQ(id_, 0u);
2410 void BackRenderbuffer::Create() {
2411 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
2412 state_->GetErrorState());
2413 Destroy();
2414 glGenRenderbuffersEXT(1, &id_);
2417 bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
2418 const gfx::Size& size,
2419 GLenum format,
2420 GLsizei samples) {
2421 ScopedGLErrorSuppressor suppressor(
2422 "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
2423 ScopedRenderBufferBinder binder(state_, id_);
2425 uint32 estimated_size = 0;
2426 if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
2427 size.width(), size.height(), samples, format, &estimated_size)) {
2428 return false;
2431 if (!memory_tracker_.EnsureGPUMemoryAvailable(estimated_size)) {
2432 return false;
2435 if (samples <= 1) {
2436 glRenderbufferStorageEXT(GL_RENDERBUFFER,
2437 format,
2438 size.width(),
2439 size.height());
2440 } else {
2441 GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
2442 GL_RENDERBUFFER,
2443 samples,
2444 format,
2445 size.width(),
2446 size.height());
2448 bool success = glGetError() == GL_NO_ERROR;
2449 if (success) {
2450 // Mark the previously allocated bytes as free.
2451 memory_tracker_.TrackMemFree(bytes_allocated_);
2452 bytes_allocated_ = estimated_size;
2453 // Track the newly allocated bytes.
2454 memory_tracker_.TrackMemAlloc(bytes_allocated_);
2456 return success;
2459 void BackRenderbuffer::Destroy() {
2460 if (id_ != 0) {
2461 ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
2462 state_->GetErrorState());
2463 glDeleteRenderbuffersEXT(1, &id_);
2464 id_ = 0;
2466 memory_tracker_.TrackMemFree(bytes_allocated_);
2467 bytes_allocated_ = 0;
2470 void BackRenderbuffer::Invalidate() {
2471 id_ = 0;
2474 BackFramebuffer::BackFramebuffer(GLES2DecoderImpl* decoder)
2475 : decoder_(decoder),
2476 id_(0) {
2479 BackFramebuffer::~BackFramebuffer() {
2480 // This does not destroy the frame buffer because that would require that
2481 // the associated GL context was current. Just check that it was explicitly
2482 // destroyed.
2483 DCHECK_EQ(id_, 0u);
2486 void BackFramebuffer::Create() {
2487 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
2488 decoder_->GetErrorState());
2489 Destroy();
2490 glGenFramebuffersEXT(1, &id_);
2493 void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
2494 DCHECK_NE(id_, 0u);
2495 ScopedGLErrorSuppressor suppressor(
2496 "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
2497 ScopedFrameBufferBinder binder(decoder_, id_);
2498 GLuint attach_id = texture ? texture->id() : 0;
2499 glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
2500 GL_COLOR_ATTACHMENT0,
2501 GL_TEXTURE_2D,
2502 attach_id,
2506 void BackFramebuffer::AttachRenderBuffer(GLenum target,
2507 BackRenderbuffer* render_buffer) {
2508 DCHECK_NE(id_, 0u);
2509 ScopedGLErrorSuppressor suppressor(
2510 "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
2511 ScopedFrameBufferBinder binder(decoder_, id_);
2512 GLuint attach_id = render_buffer ? render_buffer->id() : 0;
2513 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
2514 target,
2515 GL_RENDERBUFFER,
2516 attach_id);
2519 void BackFramebuffer::Destroy() {
2520 if (id_ != 0) {
2521 ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
2522 decoder_->GetErrorState());
2523 glDeleteFramebuffersEXT(1, &id_);
2524 id_ = 0;
2528 void BackFramebuffer::Invalidate() {
2529 id_ = 0;
2532 GLenum BackFramebuffer::CheckStatus() {
2533 DCHECK_NE(id_, 0u);
2534 ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
2535 decoder_->GetErrorState());
2536 ScopedFrameBufferBinder binder(decoder_, id_);
2537 return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
2540 GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
2541 return new GLES2DecoderImpl(group);
2544 GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
2545 : GLES2Decoder(),
2546 group_(group),
2547 logger_(&debug_marker_manager_),
2548 state_(group_->feature_info(), this, &logger_),
2549 attrib_0_buffer_id_(0),
2550 attrib_0_buffer_matches_value_(true),
2551 attrib_0_size_(0),
2552 fixed_attrib_buffer_id_(0),
2553 fixed_attrib_buffer_size_(0),
2554 offscreen_target_color_format_(0),
2555 offscreen_target_depth_format_(0),
2556 offscreen_target_stencil_format_(0),
2557 offscreen_target_samples_(0),
2558 offscreen_target_buffer_preserved_(true),
2559 offscreen_saved_color_format_(0),
2560 back_buffer_color_format_(0),
2561 back_buffer_has_depth_(false),
2562 back_buffer_has_stencil_(false),
2563 back_buffer_read_buffer_(GL_BACK),
2564 back_buffer_draw_buffer_(GL_BACK),
2565 surfaceless_(false),
2566 backbuffer_needs_clear_bits_(0),
2567 current_decoder_error_(error::kNoError),
2568 use_shader_translator_(true),
2569 validators_(group_->feature_info()->validators()),
2570 feature_info_(group_->feature_info()),
2571 frame_number_(0),
2572 has_robustness_extension_(false),
2573 context_lost_reason_(error::kUnknown),
2574 context_was_lost_(false),
2575 reset_by_robustness_extension_(false),
2576 supports_post_sub_buffer_(false),
2577 webgl_version_(0),
2578 derivatives_explicitly_enabled_(false),
2579 frag_depth_explicitly_enabled_(false),
2580 draw_buffers_explicitly_enabled_(false),
2581 shader_texture_lod_explicitly_enabled_(false),
2582 compile_shader_always_succeeds_(false),
2583 lose_context_when_out_of_memory_(false),
2584 service_logging_(base::CommandLine::InitializedForCurrentProcess()
2585 ? base::CommandLine::ForCurrentProcess()->HasSwitch(
2586 switches::kEnableGPUServiceLoggingGPU)
2587 : false),
2588 viewport_max_width_(0),
2589 viewport_max_height_(0),
2590 texture_state_(group_->feature_info()
2591 ->workarounds()
2592 .texsubimage_faster_than_teximage),
2593 cb_command_trace_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2594 TRACE_DISABLED_BY_DEFAULT("cb_command"))),
2595 gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
2596 TRACE_DISABLED_BY_DEFAULT("gpu_decoder"))),
2597 gpu_trace_level_(2),
2598 gpu_trace_commands_(false),
2599 gpu_debug_commands_(false),
2600 validation_texture_(0),
2601 validation_fbo_multisample_(0),
2602 validation_fbo_(0) {
2603 DCHECK(group);
2605 // The shader translator is used for WebGL even when running on EGL
2606 // because additional restrictions are needed (like only enabling
2607 // GL_OES_standard_derivatives on demand). It is used for the unit
2608 // tests because GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes
2609 // the empty string to CompileShader and this is not a valid shader.
2610 bool disable_translator =
2611 base::CommandLine::InitializedForCurrentProcess()
2612 ? base::CommandLine::ForCurrentProcess()->HasSwitch(
2613 switches::kDisableGLSLTranslator)
2614 : false;
2615 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL ||
2616 disable_translator) {
2617 use_shader_translator_ = false;
2621 GLES2DecoderImpl::~GLES2DecoderImpl() {
2624 bool GLES2DecoderImpl::Initialize(
2625 const scoped_refptr<gfx::GLSurface>& surface,
2626 const scoped_refptr<gfx::GLContext>& context,
2627 bool offscreen,
2628 const gfx::Size& offscreen_size,
2629 const DisallowedFeatures& disallowed_features,
2630 const std::vector<int32>& attribs) {
2631 TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
2632 DCHECK(context->IsCurrent(surface.get()));
2633 DCHECK(!context_.get());
2634 DCHECK(!offscreen || !offscreen_size.IsEmpty());
2636 ContextCreationAttribHelper attrib_parser;
2637 if (!attrib_parser.Parse(attribs))
2638 return false;
2639 webgl_version_ = attrib_parser.webgl_version;
2641 surfaceless_ = surface->IsSurfaceless() && !offscreen;
2643 set_initialized();
2644 gpu_state_tracer_ = GPUStateTracer::Create(&state_);
2646 if (base::CommandLine::InitializedForCurrentProcess()) {
2647 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2648 switches::kEnableGPUDebugging)) {
2649 set_debug(true);
2652 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2653 switches::kEnableGPUCommandLogging)) {
2654 set_log_commands(true);
2657 compile_shader_always_succeeds_ =
2658 base::CommandLine::ForCurrentProcess()->HasSwitch(
2659 switches::kCompileShaderAlwaysSucceeds);
2662 // Take ownership of the context and surface. The surface can be replaced with
2663 // SetSurface.
2664 context_ = context;
2665 surface_ = surface;
2667 // Create GPU Tracer for timing values.
2668 gpu_tracer_.reset(new GPUTracer(this));
2670 if (feature_info_->workarounds().disable_timestamp_queries) {
2671 // Forcing time elapsed query for any GPU Timing Client forces it for all
2672 // clients in the context.
2673 GetGLContext()->CreateGPUTimingClient()->ForceTimeElapsedQuery();
2676 // Save the loseContextWhenOutOfMemory context creation attribute.
2677 lose_context_when_out_of_memory_ =
2678 attrib_parser.lose_context_when_out_of_memory;
2680 // If the failIfMajorPerformanceCaveat context creation attribute was true
2681 // and we are using a software renderer, fail.
2682 if (attrib_parser.fail_if_major_perf_caveat &&
2683 feature_info_->feature_flags().is_swiftshader) {
2684 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2685 Destroy(true);
2686 return false;
2689 disallowed_features_ = disallowed_features;
2690 if (webgl_version_ == 1) {
2691 disallowed_features_.npot_support = true;
2694 if (!group_->Initialize(this,
2695 ContextGroup::GetContextType(webgl_version_),
2696 disallowed_features_)) {
2697 group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
2698 Destroy(true);
2699 return false;
2701 CHECK_GL_ERROR();
2703 if (webgl_version_ == 2) {
2704 if (!feature_info_->IsES3Capable()) {
2705 LOG(ERROR) << "Underlying driver does not support ES3.";
2706 Destroy(true);
2707 return false;
2709 feature_info_->EnableES3Validators();
2710 set_unsafe_es3_apis_enabled(true);
2713 state_.attrib_values.resize(group_->max_vertex_attribs());
2714 vertex_array_manager_.reset(new VertexArrayManager());
2716 GLuint default_vertex_attrib_service_id = 0;
2717 if (features().native_vertex_array_object) {
2718 glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
2719 glBindVertexArrayOES(default_vertex_attrib_service_id);
2722 state_.default_vertex_attrib_manager =
2723 CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
2725 state_.default_vertex_attrib_manager->Initialize(
2726 group_->max_vertex_attribs(),
2727 feature_info_->workarounds().init_vertex_attributes);
2729 // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
2730 DoBindVertexArrayOES(0);
2732 query_manager_.reset(new QueryManager(this, feature_info_.get()));
2734 image_manager_.reset(new ImageManager);
2736 util_.set_num_compressed_texture_formats(
2737 validators_->compressed_texture_format.GetValues().size());
2739 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
2740 // We have to enable vertex array 0 on OpenGL or it won't render. Note that
2741 // OpenGL ES 2.0 does not have this issue.
2742 glEnableVertexAttribArray(0);
2744 glGenBuffersARB(1, &attrib_0_buffer_id_);
2745 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
2746 glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
2747 glBindBuffer(GL_ARRAY_BUFFER, 0);
2748 glGenBuffersARB(1, &fixed_attrib_buffer_id_);
2750 state_.texture_units.resize(group_->max_texture_units());
2751 for (uint32 tt = 0; tt < state_.texture_units.size(); ++tt) {
2752 glActiveTexture(GL_TEXTURE0 + tt);
2753 // We want the last bind to be 2D.
2754 TextureRef* ref;
2755 if (features().oes_egl_image_external) {
2756 ref = texture_manager()->GetDefaultTextureInfo(
2757 GL_TEXTURE_EXTERNAL_OES);
2758 state_.texture_units[tt].bound_texture_external_oes = ref;
2759 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
2761 if (features().arb_texture_rectangle) {
2762 ref = texture_manager()->GetDefaultTextureInfo(
2763 GL_TEXTURE_RECTANGLE_ARB);
2764 state_.texture_units[tt].bound_texture_rectangle_arb = ref;
2765 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
2767 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
2768 state_.texture_units[tt].bound_texture_cube_map = ref;
2769 glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
2770 ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
2771 state_.texture_units[tt].bound_texture_2d = ref;
2772 glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
2774 glActiveTexture(GL_TEXTURE0);
2775 CHECK_GL_ERROR();
2777 // cache ALPHA_BITS result for re-use with clear behaviour
2778 GLint alpha_bits = 0;
2780 if (offscreen) {
2781 if (attrib_parser.samples > 0 && attrib_parser.sample_buffers > 0 &&
2782 features().chromium_framebuffer_multisample) {
2783 // Per ext_framebuffer_multisample spec, need max bound on sample count.
2784 // max_sample_count must be initialized to a sane value. If
2785 // glGetIntegerv() throws a GL error, it leaves its argument unchanged.
2786 GLint max_sample_count = 1;
2787 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count);
2788 offscreen_target_samples_ = std::min(attrib_parser.samples,
2789 max_sample_count);
2790 } else {
2791 offscreen_target_samples_ = 1;
2793 offscreen_target_buffer_preserved_ = attrib_parser.buffer_preserved;
2795 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
2796 const bool rgb8_supported =
2797 context_->HasExtension("GL_OES_rgb8_rgba8");
2798 // The only available default render buffer formats in GLES2 have very
2799 // little precision. Don't enable multisampling unless 8-bit render
2800 // buffer formats are available--instead fall back to 8-bit textures.
2801 if (rgb8_supported && offscreen_target_samples_ > 1) {
2802 offscreen_target_color_format_ = attrib_parser.alpha_size > 0 ?
2803 GL_RGBA8 : GL_RGB8;
2804 } else {
2805 offscreen_target_samples_ = 1;
2806 offscreen_target_color_format_ =
2807 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2808 ? GL_RGBA
2809 : GL_RGB;
2812 // ANGLE only supports packed depth/stencil formats, so use it if it is
2813 // available.
2814 const bool depth24_stencil8_supported =
2815 feature_info_->feature_flags().packed_depth24_stencil8;
2816 VLOG(1) << "GL_OES_packed_depth_stencil "
2817 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2818 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2819 depth24_stencil8_supported) {
2820 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2821 offscreen_target_stencil_format_ = 0;
2822 } else {
2823 // It may be the case that this depth/stencil combination is not
2824 // supported, but this will be checked later by CheckFramebufferStatus.
2825 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2826 GL_DEPTH_COMPONENT16 : 0;
2827 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2828 GL_STENCIL_INDEX8 : 0;
2830 } else {
2831 offscreen_target_color_format_ =
2832 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2833 ? GL_RGBA
2834 : GL_RGB;
2836 // If depth is requested at all, use the packed depth stencil format if
2837 // it's available, as some desktop GL drivers don't support any non-packed
2838 // formats for depth attachments.
2839 const bool depth24_stencil8_supported =
2840 feature_info_->feature_flags().packed_depth24_stencil8;
2841 VLOG(1) << "GL_EXT_packed_depth_stencil "
2842 << (depth24_stencil8_supported ? "" : "not ") << "supported.";
2844 if ((attrib_parser.depth_size > 0 || attrib_parser.stencil_size > 0) &&
2845 depth24_stencil8_supported) {
2846 offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8;
2847 offscreen_target_stencil_format_ = 0;
2848 } else {
2849 offscreen_target_depth_format_ = attrib_parser.depth_size > 0 ?
2850 GL_DEPTH_COMPONENT : 0;
2851 offscreen_target_stencil_format_ = attrib_parser.stencil_size > 0 ?
2852 GL_STENCIL_INDEX : 0;
2856 offscreen_saved_color_format_ =
2857 attrib_parser.alpha_size > 0 || workarounds().disable_gl_rgb_format
2858 ? GL_RGBA
2859 : GL_RGB;
2861 // Create the target frame buffer. This is the one that the client renders
2862 // directly to.
2863 offscreen_target_frame_buffer_.reset(new BackFramebuffer(this));
2864 offscreen_target_frame_buffer_->Create();
2865 // Due to GLES2 format limitations, either the color texture (for
2866 // non-multisampling) or the color render buffer (for multisampling) will be
2867 // attached to the offscreen frame buffer. The render buffer has more
2868 // limited formats available to it, but the texture can't do multisampling.
2869 if (IsOffscreenBufferMultisampled()) {
2870 offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
2871 renderbuffer_manager(), memory_tracker(), &state_));
2872 offscreen_target_color_render_buffer_->Create();
2873 } else {
2874 offscreen_target_color_texture_.reset(new BackTexture(
2875 memory_tracker(), &state_));
2876 offscreen_target_color_texture_->Create();
2878 offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
2879 renderbuffer_manager(), memory_tracker(), &state_));
2880 offscreen_target_depth_render_buffer_->Create();
2881 offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
2882 renderbuffer_manager(), memory_tracker(), &state_));
2883 offscreen_target_stencil_render_buffer_->Create();
2885 // Create the saved offscreen texture. The target frame buffer is copied
2886 // here when SwapBuffers is called.
2887 offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
2888 offscreen_saved_frame_buffer_->Create();
2890 offscreen_saved_color_texture_.reset(new BackTexture(
2891 memory_tracker(), &state_));
2892 offscreen_saved_color_texture_->Create();
2894 // Allocate the render buffers at their initial size and check the status
2895 // of the frame buffers is okay.
2896 if (!ResizeOffscreenFrameBuffer(offscreen_size)) {
2897 LOG(ERROR) << "Could not allocate offscreen buffer storage.";
2898 Destroy(true);
2899 return false;
2902 state_.viewport_width = offscreen_size.width();
2903 state_.viewport_height = offscreen_size.height();
2905 // Allocate the offscreen saved color texture.
2906 DCHECK(offscreen_saved_color_format_);
2907 offscreen_saved_color_texture_->AllocateStorage(
2908 gfx::Size(1, 1), offscreen_saved_color_format_, true);
2910 offscreen_saved_frame_buffer_->AttachRenderTexture(
2911 offscreen_saved_color_texture_.get());
2912 if (offscreen_saved_frame_buffer_->CheckStatus() !=
2913 GL_FRAMEBUFFER_COMPLETE) {
2914 LOG(ERROR) << "Offscreen saved FBO was incomplete.";
2915 Destroy(true);
2916 return false;
2919 // Bind to the new default frame buffer (the offscreen target frame buffer).
2920 // This should now be associated with ID zero.
2921 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
2922 } else {
2923 glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId());
2924 // These are NOT if the back buffer has these proprorties. They are
2925 // if we want the command buffer to enforce them regardless of what
2926 // the real backbuffer is assuming the real back buffer gives us more than
2927 // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
2928 // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
2929 // can't do anything about that.
2931 if (!surfaceless_) {
2932 GLint depth_bits = 0;
2933 GLint stencil_bits = 0;
2935 bool default_fb = (GetBackbufferServiceId() == 0);
2937 if (feature_info_->gl_version_info().is_desktop_core_profile) {
2938 glGetFramebufferAttachmentParameterivEXT(
2939 GL_FRAMEBUFFER,
2940 default_fb ? GL_BACK_LEFT : GL_COLOR_ATTACHMENT0,
2941 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &alpha_bits);
2942 glGetFramebufferAttachmentParameterivEXT(
2943 GL_FRAMEBUFFER,
2944 default_fb ? GL_DEPTH : GL_DEPTH_ATTACHMENT,
2945 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depth_bits);
2946 glGetFramebufferAttachmentParameterivEXT(
2947 GL_FRAMEBUFFER,
2948 default_fb ? GL_STENCIL : GL_STENCIL_ATTACHMENT,
2949 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits);
2950 } else {
2951 glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
2952 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
2953 glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
2956 // This checks if the user requested RGBA and we have RGBA then RGBA. If
2957 // the user requested RGB then RGB. If the user did not specify a
2958 // preference than use whatever we were given. Same for DEPTH and STENCIL.
2959 back_buffer_color_format_ =
2960 (attrib_parser.alpha_size != 0 && alpha_bits > 0) ? GL_RGBA : GL_RGB;
2961 back_buffer_has_depth_ = attrib_parser.depth_size != 0 && depth_bits > 0;
2962 back_buffer_has_stencil_ =
2963 attrib_parser.stencil_size != 0 && stencil_bits > 0;
2966 state_.viewport_width = surface->GetSize().width();
2967 state_.viewport_height = surface->GetSize().height();
2970 // OpenGL ES 2.0 implicitly enables the desktop GL capability
2971 // VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact
2972 // isn't well documented; it was discovered in the Khronos OpenGL ES
2973 // mailing list archives. It also implicitly enables the desktop GL
2974 // capability GL_POINT_SPRITE to provide access to the gl_PointCoord
2975 // variable in fragment shaders.
2976 if (!feature_info_->gl_version_info().BehavesLikeGLES()) {
2977 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
2978 glEnable(GL_POINT_SPRITE);
2981 has_robustness_extension_ =
2982 context->HasExtension("GL_ARB_robustness") ||
2983 context->HasExtension("GL_KHR_robustness") ||
2984 context->HasExtension("GL_EXT_robustness");
2986 if (!InitializeShaderTranslator()) {
2987 return false;
2990 GLint viewport_params[4] = { 0 };
2991 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
2992 viewport_max_width_ = viewport_params[0];
2993 viewport_max_height_ = viewport_params[1];
2995 state_.scissor_width = state_.viewport_width;
2996 state_.scissor_height = state_.viewport_height;
2998 // Set all the default state because some GL drivers get it wrong.
2999 state_.InitCapabilities(NULL);
3000 state_.InitState(NULL);
3001 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
3003 DoBindBuffer(GL_ARRAY_BUFFER, 0);
3004 DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
3005 DoBindFramebuffer(GL_FRAMEBUFFER, 0);
3006 DoBindRenderbuffer(GL_RENDERBUFFER, 0);
3007 DoBindValueBufferCHROMIUM(GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, 0);
3009 bool call_gl_clear = !surfaceless_;
3010 #if defined(OS_ANDROID)
3011 // Temporary workaround for Android WebView because this clear ignores the
3012 // clip and corrupts that external UI of the App. Not calling glClear is ok
3013 // because the system already clears the buffer before each draw. Proper
3014 // fix might be setting the scissor clip properly before initialize. See
3015 // crbug.com/259023 for details.
3016 call_gl_clear = surface_->GetHandle();
3017 #endif
3018 if (call_gl_clear) {
3019 // On configs where we report no alpha, if the underlying surface has
3020 // alpha, clear the surface alpha to 1.0 to be correct on ReadPixels/etc.
3021 bool clear_alpha = back_buffer_color_format_ == GL_RGB && alpha_bits > 0;
3022 if (clear_alpha) {
3023 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
3026 // Clear the backbuffer.
3027 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3029 // Restore alpha clear value if we changed it.
3030 if (clear_alpha) {
3031 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
3035 supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
3036 if (feature_info_->workarounds()
3037 .disable_post_sub_buffers_for_onscreen_surfaces &&
3038 !surface->IsOffscreen())
3039 supports_post_sub_buffer_ = false;
3041 if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
3042 glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
3045 if (feature_info_->workarounds().unbind_fbo_on_context_switch) {
3046 context_->SetUnbindFboOnMakeCurrent();
3049 // Only compositor contexts are known to use only the subset of GL
3050 // that can be safely migrated between the iGPU and the dGPU. Mark
3051 // those contexts as safe to forcibly transition between the GPUs.
3052 // http://crbug.com/180876, http://crbug.com/227228
3053 if (!offscreen)
3054 context_->SetSafeToForceGpuSwitch();
3056 async_pixel_transfer_manager_.reset(
3057 AsyncPixelTransferManager::Create(context.get()));
3058 async_pixel_transfer_manager_->Initialize(texture_manager());
3060 if (workarounds().gl_clear_broken) {
3061 DCHECK(!clear_framebuffer_blit_.get());
3062 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit");
3063 clear_framebuffer_blit_.reset(new ClearFramebufferResourceManager(this));
3064 if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR)
3065 return false;
3068 framebuffer_manager()->AddObserver(this);
3070 return true;
3073 Capabilities GLES2DecoderImpl::GetCapabilities() {
3074 DCHECK(initialized());
3075 Capabilities caps;
3076 caps.VisitPrecisions([](GLenum shader, GLenum type,
3077 Capabilities::ShaderPrecision* shader_precision) {
3078 GLint range[2] = {0, 0};
3079 GLint precision = 0;
3080 GetShaderPrecisionFormatImpl(shader, type, range, &precision);
3081 shader_precision->min_range = range[0];
3082 shader_precision->max_range = range[1];
3083 shader_precision->precision = precision;
3085 DoGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
3086 &caps.max_combined_texture_image_units);
3087 DoGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &caps.max_cube_map_texture_size);
3088 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
3089 &caps.max_fragment_uniform_vectors);
3090 DoGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &caps.max_renderbuffer_size);
3091 DoGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &caps.max_texture_image_units);
3092 DoGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.max_texture_size);
3093 DoGetIntegerv(GL_MAX_VARYING_VECTORS, &caps.max_varying_vectors);
3094 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.max_vertex_attribs);
3095 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
3096 &caps.max_vertex_texture_image_units);
3097 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
3098 &caps.max_vertex_uniform_vectors);
3099 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS,
3100 &caps.num_compressed_texture_formats);
3101 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats);
3102 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM,
3103 &caps.bind_generates_resource_chromium);
3104 if (unsafe_es3_apis_enabled()) {
3105 // TODO(zmo): Note that some parameter values could be more than 32-bit,
3106 // but for now we clamp them to 32-bit max.
3107 DoGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &caps.max_3d_texture_size);
3108 DoGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &caps.max_array_texture_layers);
3109 DoGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &caps.max_color_attachments);
3110 DoGetInteger64v(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,
3111 &caps.max_combined_fragment_uniform_components);
3112 DoGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS,
3113 &caps.max_combined_uniform_blocks);
3114 DoGetInteger64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,
3115 &caps.max_combined_vertex_uniform_components);
3116 DoGetIntegerv(GL_MAX_DRAW_BUFFERS, &caps.max_draw_buffers);
3117 DoGetInteger64v(GL_MAX_ELEMENT_INDEX, &caps.max_element_index);
3118 DoGetIntegerv(GL_MAX_ELEMENTS_INDICES, &caps.max_elements_indices);
3119 DoGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &caps.max_elements_vertices);
3120 DoGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS,
3121 &caps.max_fragment_input_components);
3122 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
3123 &caps.max_fragment_uniform_blocks);
3124 DoGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,
3125 &caps.max_fragment_uniform_components);
3126 DoGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET,
3127 &caps.max_program_texel_offset);
3128 DoGetInteger64v(GL_MAX_SERVER_WAIT_TIMEOUT, &caps.max_server_wait_timeout);
3129 // Work around Linux NVIDIA driver bug where GL_TIMEOUT_IGNORED is
3130 // returned.
3131 if (caps.max_server_wait_timeout < 0)
3132 caps.max_server_wait_timeout = 0;
3133 DoGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &caps.max_texture_lod_bias);
3134 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
3135 &caps.max_transform_feedback_interleaved_components);
3136 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
3137 &caps.max_transform_feedback_separate_attribs);
3138 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
3139 &caps.max_transform_feedback_separate_components);
3140 DoGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &caps.max_uniform_block_size);
3141 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
3142 &caps.max_uniform_buffer_bindings);
3143 DoGetIntegerv(GL_MAX_VARYING_COMPONENTS, &caps.max_varying_components);
3144 DoGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
3145 &caps.max_vertex_output_components);
3146 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS,
3147 &caps.max_vertex_uniform_blocks);
3148 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS,
3149 &caps.max_vertex_uniform_components);
3150 DoGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &caps.min_program_texel_offset);
3151 DoGetIntegerv(GL_NUM_EXTENSIONS, &caps.num_extensions);
3152 DoGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS,
3153 &caps.num_program_binary_formats);
3154 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
3155 &caps.uniform_buffer_offset_alignment);
3156 // TODO(zmo): once we switch to MANGLE, we should query version numbers.
3157 caps.major_version = 3;
3158 caps.minor_version = 0;
3160 if (feature_info_->feature_flags().multisampled_render_to_texture ||
3161 feature_info_->feature_flags().chromium_framebuffer_multisample ||
3162 unsafe_es3_apis_enabled()) {
3163 DoGetIntegerv(GL_MAX_SAMPLES, &caps.max_samples);
3166 caps.egl_image_external =
3167 feature_info_->feature_flags().oes_egl_image_external;
3168 caps.texture_format_atc =
3169 feature_info_->feature_flags().ext_texture_format_atc;
3170 caps.texture_format_bgra8888 =
3171 feature_info_->feature_flags().ext_texture_format_bgra8888;
3172 caps.texture_format_dxt1 =
3173 feature_info_->feature_flags().ext_texture_format_dxt1;
3174 caps.texture_format_dxt5 =
3175 feature_info_->feature_flags().ext_texture_format_dxt5;
3176 caps.texture_format_etc1 =
3177 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
3178 caps.texture_format_etc1_npot =
3179 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only;
3180 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
3181 caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
3182 caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
3183 caps.discard_framebuffer =
3184 feature_info_->feature_flags().ext_discard_framebuffer;
3185 caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
3187 #if defined(OS_MACOSX)
3188 // This is unconditionally true on mac, no need to test for it at runtime.
3189 caps.iosurface = true;
3190 #endif
3192 caps.post_sub_buffer = supports_post_sub_buffer_;
3193 caps.image = true;
3194 caps.surfaceless = surfaceless_;
3196 caps.blend_equation_advanced =
3197 feature_info_->feature_flags().blend_equation_advanced;
3198 caps.blend_equation_advanced_coherent =
3199 feature_info_->feature_flags().blend_equation_advanced_coherent;
3200 caps.texture_rg = feature_info_->feature_flags().ext_texture_rg;
3201 caps.max_copy_texture_chromium_size =
3202 feature_info_->workarounds().max_copy_texture_chromium_size;
3203 caps.render_buffer_format_bgra8888 =
3204 feature_info_->feature_flags().ext_render_buffer_format_bgra8888;
3205 caps.occlusion_query_boolean =
3206 feature_info_->feature_flags().occlusion_query_boolean;
3207 caps.timer_queries =
3208 query_manager_->GPUTimingAvailable();
3209 return caps;
3212 void GLES2DecoderImpl::UpdateCapabilities() {
3213 util_.set_num_compressed_texture_formats(
3214 validators_->compressed_texture_format.GetValues().size());
3215 util_.set_num_shader_binary_formats(
3216 validators_->shader_binary_format.GetValues().size());
3219 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3220 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3222 if (!use_shader_translator_) {
3223 return true;
3225 ShBuiltInResources resources;
3226 ShInitBuiltInResources(&resources);
3227 resources.MaxVertexAttribs = group_->max_vertex_attribs();
3228 resources.MaxVertexUniformVectors =
3229 group_->max_vertex_uniform_vectors();
3230 resources.MaxVaryingVectors = group_->max_varying_vectors();
3231 resources.MaxVertexTextureImageUnits =
3232 group_->max_vertex_texture_image_units();
3233 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
3234 resources.MaxTextureImageUnits = group_->max_texture_image_units();
3235 resources.MaxFragmentUniformVectors =
3236 group_->max_fragment_uniform_vectors();
3237 resources.MaxDrawBuffers = group_->max_draw_buffers();
3238 resources.MaxExpressionComplexity = 256;
3239 resources.MaxCallStackDepth = 256;
3241 GLint range[2] = { 0, 0 };
3242 GLint precision = 0;
3243 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
3244 range, &precision);
3245 resources.FragmentPrecisionHigh =
3246 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
3248 if (IsWebGLContext()) {
3249 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
3250 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
3251 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
3252 if (!draw_buffers_explicitly_enabled_)
3253 resources.MaxDrawBuffers = 1;
3254 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
3255 resources.NV_draw_buffers =
3256 draw_buffers_explicitly_enabled_ && features().nv_draw_buffers;
3257 } else {
3258 resources.OES_standard_derivatives =
3259 features().oes_standard_derivatives ? 1 : 0;
3260 resources.ARB_texture_rectangle =
3261 features().arb_texture_rectangle ? 1 : 0;
3262 resources.OES_EGL_image_external =
3263 features().oes_egl_image_external ? 1 : 0;
3264 resources.EXT_draw_buffers =
3265 features().ext_draw_buffers ? 1 : 0;
3266 resources.EXT_frag_depth =
3267 features().ext_frag_depth ? 1 : 0;
3268 resources.EXT_shader_texture_lod =
3269 features().ext_shader_texture_lod ? 1 : 0;
3270 resources.NV_draw_buffers =
3271 features().nv_draw_buffers ? 1 : 0;
3274 ShShaderSpec shader_spec;
3275 if (IsWebGLContext()) {
3276 shader_spec = webgl_version_ == 2 ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC;
3277 } else {
3278 shader_spec = unsafe_es3_apis_enabled() ? SH_GLES3_SPEC : SH_GLES2_SPEC;
3281 if ((shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) &&
3282 features().enable_shader_name_hashing)
3283 resources.HashFunction = &CityHash64;
3284 else
3285 resources.HashFunction = NULL;
3287 int driver_bug_workarounds = 0;
3288 if (workarounds().needs_glsl_built_in_function_emulation)
3289 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
3290 if (workarounds().init_gl_position_in_vertex_shader)
3291 driver_bug_workarounds |= SH_INIT_GL_POSITION;
3292 if (workarounds().unfold_short_circuit_as_ternary_operation)
3293 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
3294 if (workarounds().init_varyings_without_static_use)
3295 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
3296 if (workarounds().unroll_for_loop_with_sampler_array_index)
3297 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
3298 if (workarounds().scalarize_vec_and_mat_constructor_args)
3299 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
3300 if (workarounds().regenerate_struct_names)
3301 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
3302 if (workarounds().remove_pow_with_constant_exponent)
3303 driver_bug_workarounds |= SH_REMOVE_POW_WITH_CONSTANT_EXPONENT;
3305 if (base::CommandLine::InitializedForCurrentProcess() &&
3306 base::CommandLine::ForCurrentProcess()->HasSwitch(
3307 switches::kEmulateShaderPrecision))
3308 resources.WEBGL_debug_shader_precision = true;
3310 ShShaderOutput shader_output_language =
3311 ShaderTranslator::GetShaderOutputLanguageForContext(
3312 feature_info_->gl_version_info());
3314 vertex_translator_ = shader_translator_cache()->GetTranslator(
3315 GL_VERTEX_SHADER, shader_spec, &resources, shader_output_language,
3316 static_cast<ShCompileOptions>(driver_bug_workarounds));
3317 if (!vertex_translator_.get()) {
3318 LOG(ERROR) << "Could not initialize vertex shader translator.";
3319 Destroy(true);
3320 return false;
3323 fragment_translator_ = shader_translator_cache()->GetTranslator(
3324 GL_FRAGMENT_SHADER, shader_spec, &resources, shader_output_language,
3325 static_cast<ShCompileOptions>(driver_bug_workarounds));
3326 if (!fragment_translator_.get()) {
3327 LOG(ERROR) << "Could not initialize fragment shader translator.";
3328 Destroy(true);
3329 return false;
3331 return true;
3334 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
3335 for (GLsizei ii = 0; ii < n; ++ii) {
3336 if (GetBuffer(client_ids[ii])) {
3337 return false;
3340 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3341 glGenBuffersARB(n, service_ids.get());
3342 for (GLsizei ii = 0; ii < n; ++ii) {
3343 CreateBuffer(client_ids[ii], service_ids[ii]);
3345 return true;
3348 bool GLES2DecoderImpl::GenFramebuffersHelper(
3349 GLsizei n, const GLuint* client_ids) {
3350 for (GLsizei ii = 0; ii < n; ++ii) {
3351 if (GetFramebuffer(client_ids[ii])) {
3352 return false;
3355 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3356 glGenFramebuffersEXT(n, service_ids.get());
3357 for (GLsizei ii = 0; ii < n; ++ii) {
3358 CreateFramebuffer(client_ids[ii], service_ids[ii]);
3360 return true;
3363 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3364 GLsizei n, const GLuint* client_ids) {
3365 for (GLsizei ii = 0; ii < n; ++ii) {
3366 if (GetRenderbuffer(client_ids[ii])) {
3367 return false;
3370 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3371 glGenRenderbuffersEXT(n, service_ids.get());
3372 for (GLsizei ii = 0; ii < n; ++ii) {
3373 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
3375 return true;
3378 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n,
3379 const GLuint* client_ids) {
3380 for (GLsizei ii = 0; ii < n; ++ii) {
3381 if (GetValuebuffer(client_ids[ii])) {
3382 return false;
3385 for (GLsizei ii = 0; ii < n; ++ii) {
3386 CreateValuebuffer(client_ids[ii]);
3388 return true;
3391 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
3392 for (GLsizei ii = 0; ii < n; ++ii) {
3393 if (GetTexture(client_ids[ii])) {
3394 return false;
3397 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3398 glGenTextures(n, service_ids.get());
3399 for (GLsizei ii = 0; ii < n; ++ii) {
3400 CreateTexture(client_ids[ii], service_ids[ii]);
3402 return true;
3405 bool GLES2DecoderImpl::GenPathsCHROMIUMHelper(GLuint first_client_id,
3406 GLsizei range) {
3407 GLuint last_client_id;
3408 if (!SafeAddUint32(first_client_id, range - 1, &last_client_id))
3409 return false;
3411 if (path_manager()->HasPathsInRange(first_client_id, last_client_id))
3412 return false;
3414 GLuint first_service_id = glGenPathsNV(range);
3415 if (first_service_id == 0) {
3416 // We have to fail the connection here, because client has already
3417 // succeeded in allocating the ids. This happens if we allocate
3418 // the whole path id space (two allocations of 0x7FFFFFFF paths, for
3419 // example).
3420 return false;
3422 // GenPathsNV does not wrap.
3423 DCHECK(first_service_id + range - 1 >= first_service_id);
3425 path_manager()->CreatePathRange(first_client_id, last_client_id,
3426 first_service_id);
3428 return true;
3431 bool GLES2DecoderImpl::DeletePathsCHROMIUMHelper(GLuint first_client_id,
3432 GLsizei range) {
3433 GLuint last_client_id;
3434 if (!SafeAddUint32(first_client_id, range - 1, &last_client_id))
3435 return false;
3437 path_manager()->RemovePaths(first_client_id, last_client_id);
3438 return true;
3441 void GLES2DecoderImpl::DeleteBuffersHelper(
3442 GLsizei n, const GLuint* client_ids) {
3443 for (GLsizei ii = 0; ii < n; ++ii) {
3444 Buffer* buffer = GetBuffer(client_ids[ii]);
3445 if (buffer && !buffer->IsDeleted()) {
3446 buffer->RemoveMappedRange();
3447 state_.RemoveBoundBuffer(buffer);
3448 RemoveBuffer(client_ids[ii]);
3453 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3454 GLsizei n, const GLuint* client_ids) {
3455 bool supports_separate_framebuffer_binds =
3456 features().chromium_framebuffer_multisample;
3458 for (GLsizei ii = 0; ii < n; ++ii) {
3459 Framebuffer* framebuffer =
3460 GetFramebuffer(client_ids[ii]);
3461 if (framebuffer && !framebuffer->IsDeleted()) {
3462 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
3463 GLenum target = supports_separate_framebuffer_binds ?
3464 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3466 // Unbind attachments on FBO before deletion.
3467 if (workarounds().unbind_attachments_on_bound_render_fbo_delete)
3468 framebuffer->DoUnbindGLAttachmentsForWorkaround(target);
3470 glBindFramebufferEXT(target, GetBackbufferServiceId());
3471 framebuffer_state_.bound_draw_framebuffer = NULL;
3472 framebuffer_state_.clear_state_dirty = true;
3474 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
3475 framebuffer_state_.bound_read_framebuffer = NULL;
3476 GLenum target = supports_separate_framebuffer_binds ?
3477 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3478 glBindFramebufferEXT(target, GetBackbufferServiceId());
3480 OnFboChanged();
3481 RemoveFramebuffer(client_ids[ii]);
3486 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3487 GLsizei n, const GLuint* client_ids) {
3488 bool supports_separate_framebuffer_binds =
3489 features().chromium_framebuffer_multisample;
3490 for (GLsizei ii = 0; ii < n; ++ii) {
3491 Renderbuffer* renderbuffer =
3492 GetRenderbuffer(client_ids[ii]);
3493 if (renderbuffer && !renderbuffer->IsDeleted()) {
3494 if (state_.bound_renderbuffer.get() == renderbuffer) {
3495 state_.bound_renderbuffer = NULL;
3497 // Unbind from current framebuffers.
3498 if (supports_separate_framebuffer_binds) {
3499 if (framebuffer_state_.bound_read_framebuffer.get()) {
3500 framebuffer_state_.bound_read_framebuffer
3501 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
3503 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3504 framebuffer_state_.bound_draw_framebuffer
3505 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
3507 } else {
3508 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3509 framebuffer_state_.bound_draw_framebuffer
3510 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
3513 framebuffer_state_.clear_state_dirty = true;
3514 RemoveRenderbuffer(client_ids[ii]);
3519 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3520 GLsizei n,
3521 const GLuint* client_ids) {
3522 for (GLsizei ii = 0; ii < n; ++ii) {
3523 Valuebuffer* valuebuffer = GetValuebuffer(client_ids[ii]);
3524 if (valuebuffer) {
3525 if (state_.bound_valuebuffer.get() == valuebuffer) {
3526 state_.bound_valuebuffer = NULL;
3528 RemoveValuebuffer(client_ids[ii]);
3533 void GLES2DecoderImpl::DeleteTexturesHelper(
3534 GLsizei n, const GLuint* client_ids) {
3535 bool supports_separate_framebuffer_binds =
3536 features().chromium_framebuffer_multisample;
3537 for (GLsizei ii = 0; ii < n; ++ii) {
3538 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3539 if (texture_ref) {
3540 Texture* texture = texture_ref->texture();
3541 if (texture->IsAttachedToFramebuffer()) {
3542 framebuffer_state_.clear_state_dirty = true;
3544 // Unbind texture_ref from texture_ref units.
3545 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
3546 state_.texture_units[jj].Unbind(texture_ref);
3548 // Unbind from current framebuffers.
3549 if (supports_separate_framebuffer_binds) {
3550 if (framebuffer_state_.bound_read_framebuffer.get()) {
3551 framebuffer_state_.bound_read_framebuffer
3552 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3554 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3555 framebuffer_state_.bound_draw_framebuffer
3556 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3558 } else {
3559 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3560 framebuffer_state_.bound_draw_framebuffer
3561 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3564 #if defined(OS_MACOSX)
3565 GLuint service_id = texture->service_id();
3566 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3567 ReleaseIOSurfaceForTexture(service_id);
3569 #endif
3570 RemoveTexture(client_ids[ii]);
3575 // } // anonymous namespace
3577 bool GLES2DecoderImpl::MakeCurrent() {
3578 if (!context_.get())
3579 return false;
3581 if (WasContextLost()) {
3582 LOG(ERROR) << " GLES2DecoderImpl: Trying to make lost context current.";
3583 return false;
3586 if (!context_->MakeCurrent(surface_.get())) {
3587 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3588 MarkContextLost(error::kMakeCurrentFailed);
3589 group_->LoseContexts(error::kUnknown);
3590 return false;
3593 if (CheckResetStatus()) {
3594 LOG(ERROR)
3595 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3596 group_->LoseContexts(error::kUnknown);
3597 return false;
3600 ProcessFinishedAsyncTransfers();
3602 // Rebind the FBO if it was unbound by the context.
3603 if (workarounds().unbind_fbo_on_context_switch)
3604 RestoreFramebufferBindings();
3606 framebuffer_state_.clear_state_dirty = true;
3608 return true;
3611 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3612 ProcessPendingReadPixels(false);
3613 if (engine() && query_manager_.get())
3614 query_manager_->ProcessPendingTransferQueries();
3616 // TODO(epenner): Is there a better place to do this?
3617 // This needs to occur before we execute any batch of commands
3618 // from the client, as the client may have recieved an async
3619 // completion while issuing those commands.
3620 // "DidFlushStart" would be ideal if we had such a callback.
3621 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3624 static void RebindCurrentFramebuffer(
3625 GLenum target,
3626 Framebuffer* framebuffer,
3627 GLuint back_buffer_service_id) {
3628 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3630 if (framebuffer_id == 0) {
3631 framebuffer_id = back_buffer_service_id;
3634 glBindFramebufferEXT(target, framebuffer_id);
3637 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3638 framebuffer_state_.clear_state_dirty = true;
3640 if (!features().chromium_framebuffer_multisample) {
3641 RebindCurrentFramebuffer(
3642 GL_FRAMEBUFFER,
3643 framebuffer_state_.bound_draw_framebuffer.get(),
3644 GetBackbufferServiceId());
3645 } else {
3646 RebindCurrentFramebuffer(
3647 GL_READ_FRAMEBUFFER_EXT,
3648 framebuffer_state_.bound_read_framebuffer.get(),
3649 GetBackbufferServiceId());
3650 RebindCurrentFramebuffer(
3651 GL_DRAW_FRAMEBUFFER_EXT,
3652 framebuffer_state_.bound_draw_framebuffer.get(),
3653 GetBackbufferServiceId());
3655 OnFboChanged();
3658 bool GLES2DecoderImpl::CheckFramebufferValid(
3659 Framebuffer* framebuffer,
3660 GLenum target, const char* func_name) {
3661 if (!framebuffer) {
3662 if (surfaceless_)
3663 return false;
3664 if (backbuffer_needs_clear_bits_) {
3665 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3666 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3667 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3668 glClearStencil(0);
3669 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3670 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3671 glClearDepth(1.0f);
3672 state_.SetDeviceDepthMask(GL_TRUE);
3673 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3674 bool reset_draw_buffer = false;
3675 if ((backbuffer_needs_clear_bits_ & GL_COLOR_BUFFER_BIT) != 0 &&
3676 back_buffer_draw_buffer_ == GL_NONE) {
3677 reset_draw_buffer = true;
3678 GLenum buf = GL_BACK;
3679 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3680 buf = GL_COLOR_ATTACHMENT0;
3681 glDrawBuffersARB(1, &buf);
3683 glClear(backbuffer_needs_clear_bits_);
3684 if (reset_draw_buffer) {
3685 GLenum buf = GL_NONE;
3686 glDrawBuffersARB(1, &buf);
3688 backbuffer_needs_clear_bits_ = 0;
3689 RestoreClearState();
3691 return true;
3694 if (framebuffer_manager()->IsComplete(framebuffer)) {
3695 return true;
3698 GLenum completeness = framebuffer->IsPossiblyComplete();
3699 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3700 LOCAL_SET_GL_ERROR(
3701 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3702 return false;
3705 // Are all the attachments cleared?
3706 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3707 texture_manager()->HaveUnclearedMips()) {
3708 if (!framebuffer->IsCleared()) {
3709 // Can we clear them?
3710 if (framebuffer->GetStatus(texture_manager(), target) !=
3711 GL_FRAMEBUFFER_COMPLETE) {
3712 LOCAL_SET_GL_ERROR(
3713 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3714 "framebuffer incomplete (clear)");
3715 return false;
3717 ClearUnclearedAttachments(target, framebuffer);
3721 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3722 if (framebuffer->GetStatus(texture_manager(), target) !=
3723 GL_FRAMEBUFFER_COMPLETE) {
3724 LOCAL_SET_GL_ERROR(
3725 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3726 "framebuffer incomplete (check)");
3727 return false;
3729 framebuffer_manager()->MarkAsComplete(framebuffer);
3732 // NOTE: At this point we don't know if the framebuffer is complete but
3733 // we DO know that everything that needs to be cleared has been cleared.
3734 return true;
3737 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3738 if (!features().chromium_framebuffer_multisample) {
3739 bool valid = CheckFramebufferValid(
3740 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3741 func_name);
3743 if (valid)
3744 OnUseFramebuffer();
3746 return valid;
3748 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3749 GL_DRAW_FRAMEBUFFER_EXT,
3750 func_name) &&
3751 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3752 GL_READ_FRAMEBUFFER_EXT,
3753 func_name);
3756 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3757 const char* func_name) {
3758 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3759 framebuffer_state_.bound_read_framebuffer.get() :
3760 framebuffer_state_.bound_draw_framebuffer.get();
3761 if (!framebuffer)
3762 return true;
3763 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3764 LOCAL_SET_GL_ERROR(
3765 GL_INVALID_OPERATION, func_name, "no color image attached");
3766 return false;
3768 return true;
3771 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3772 TextureRef* texture, GLint level) {
3773 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3774 framebuffer_state_.bound_read_framebuffer.get() :
3775 framebuffer_state_.bound_draw_framebuffer.get();
3776 if (!framebuffer)
3777 return false;
3778 const Framebuffer::Attachment* attachment = framebuffer->GetAttachment(
3779 GL_COLOR_ATTACHMENT0);
3780 if (!attachment)
3781 return false;
3782 return attachment->FormsFeedbackLoop(texture, level);
3785 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3786 Framebuffer* framebuffer =
3787 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3788 if (framebuffer != NULL) {
3789 const Framebuffer::Attachment* attachment =
3790 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3791 if (attachment) {
3792 return gfx::Size(attachment->width(), attachment->height());
3794 return gfx::Size(0, 0);
3795 } else if (offscreen_target_frame_buffer_.get()) {
3796 return offscreen_size_;
3797 } else {
3798 return surface_->GetSize();
3802 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3803 Framebuffer* framebuffer =
3804 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3805 if (framebuffer) {
3806 return framebuffer->GetReadBufferTextureType();
3807 } else { // Back buffer.
3808 if (back_buffer_read_buffer_ == GL_NONE)
3809 return 0;
3810 return GL_UNSIGNED_BYTE;
3814 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3815 Framebuffer* framebuffer =
3816 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3817 if (framebuffer) {
3818 return framebuffer->GetReadBufferInternalFormat();
3819 } else { // Back buffer.
3820 if (back_buffer_read_buffer_ == GL_NONE)
3821 return 0;
3822 if (offscreen_target_frame_buffer_.get()) {
3823 return offscreen_target_color_format_;
3825 return back_buffer_color_format_;
3829 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3830 if (!offscreen_saved_color_texture_info_.get())
3831 return;
3832 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3833 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3834 texture_manager()->SetLevelInfo(
3835 offscreen_saved_color_texture_info_.get(), GL_TEXTURE_2D,
3836 0, // level
3837 GL_RGBA, offscreen_size_.width(), offscreen_size_.height(),
3838 1, // depth
3839 0, // border
3840 GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(offscreen_size_));
3841 texture_manager()->SetParameteri(
3842 "UpdateParentTextureInfo",
3843 GetErrorState(),
3844 offscreen_saved_color_texture_info_.get(),
3845 GL_TEXTURE_MAG_FILTER,
3846 GL_LINEAR);
3847 texture_manager()->SetParameteri(
3848 "UpdateParentTextureInfo",
3849 GetErrorState(),
3850 offscreen_saved_color_texture_info_.get(),
3851 GL_TEXTURE_MIN_FILTER,
3852 GL_LINEAR);
3853 texture_manager()->SetParameteri(
3854 "UpdateParentTextureInfo",
3855 GetErrorState(),
3856 offscreen_saved_color_texture_info_.get(),
3857 GL_TEXTURE_WRAP_S,
3858 GL_CLAMP_TO_EDGE);
3859 texture_manager()->SetParameteri(
3860 "UpdateParentTextureInfo",
3861 GetErrorState(),
3862 offscreen_saved_color_texture_info_.get(),
3863 GL_TEXTURE_WRAP_T,
3864 GL_CLAMP_TO_EDGE);
3865 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3866 &state_, target);
3867 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3870 void GLES2DecoderImpl::SetResizeCallback(
3871 const base::Callback<void(gfx::Size, float)>& callback) {
3872 resize_callback_ = callback;
3875 Logger* GLES2DecoderImpl::GetLogger() {
3876 return &logger_;
3879 void GLES2DecoderImpl::BeginDecoding() {
3880 gpu_tracer_->BeginDecoding();
3881 gpu_trace_commands_ = gpu_tracer_->IsTracing() && *gpu_decoder_category_;
3882 gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_ ||
3883 (*cb_command_trace_category_ != 0);
3884 query_manager_->ProcessFrameBeginUpdates();
3887 void GLES2DecoderImpl::EndDecoding() {
3888 gpu_tracer_->EndDecoding();
3891 ErrorState* GLES2DecoderImpl::GetErrorState() {
3892 return state_.GetErrorState();
3895 void GLES2DecoderImpl::SetShaderCacheCallback(
3896 const ShaderCacheCallback& callback) {
3897 shader_cache_callback_ = callback;
3900 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3901 const WaitSyncPointCallback& callback) {
3902 wait_sync_point_callback_ = callback;
3905 AsyncPixelTransferManager*
3906 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3907 return async_pixel_transfer_manager_.get();
3910 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3911 async_pixel_transfer_manager_.reset();
3914 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3915 AsyncPixelTransferManager* manager) {
3916 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3919 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3920 uint32* service_texture_id) {
3921 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3922 if (texture_ref) {
3923 *service_texture_id = texture_ref->service_id();
3924 return true;
3926 return false;
3929 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3930 return texture_state_.texture_upload_count +
3931 async_pixel_transfer_manager_->GetTextureUploadCount();
3934 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3935 return texture_state_.total_texture_upload_time +
3936 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3939 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3940 return total_processing_commands_time_;
3943 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3944 total_processing_commands_time_ += time;
3947 void GLES2DecoderImpl::Destroy(bool have_context) {
3948 if (!initialized())
3949 return;
3951 DCHECK(!have_context || context_->IsCurrent(NULL));
3953 // Unbind everything.
3954 state_.vertex_attrib_manager = NULL;
3955 state_.default_vertex_attrib_manager = NULL;
3956 state_.texture_units.clear();
3957 state_.bound_array_buffer = NULL;
3958 state_.bound_copy_read_buffer = NULL;
3959 state_.bound_copy_write_buffer = NULL;
3960 state_.bound_pixel_pack_buffer = NULL;
3961 state_.bound_pixel_unpack_buffer = NULL;
3962 state_.bound_transform_feedback_buffer = NULL;
3963 state_.bound_uniform_buffer = NULL;
3964 framebuffer_state_.bound_read_framebuffer = NULL;
3965 framebuffer_state_.bound_draw_framebuffer = NULL;
3966 state_.bound_renderbuffer = NULL;
3967 state_.bound_valuebuffer = NULL;
3969 if (offscreen_saved_color_texture_info_.get()) {
3970 DCHECK(offscreen_target_color_texture_);
3971 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3972 offscreen_saved_color_texture_->id());
3973 offscreen_saved_color_texture_->Invalidate();
3974 offscreen_saved_color_texture_info_ = NULL;
3976 if (have_context) {
3977 if (copy_texture_CHROMIUM_.get()) {
3978 copy_texture_CHROMIUM_->Destroy();
3979 copy_texture_CHROMIUM_.reset();
3982 clear_framebuffer_blit_.reset();
3984 if (state_.current_program.get()) {
3985 program_manager()->UnuseProgram(shader_manager(),
3986 state_.current_program.get());
3989 if (attrib_0_buffer_id_) {
3990 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3992 if (fixed_attrib_buffer_id_) {
3993 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3996 if (validation_texture_) {
3997 glDeleteTextures(1, &validation_texture_);
3998 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
3999 glDeleteFramebuffersEXT(1, &validation_fbo_);
4002 if (offscreen_target_frame_buffer_.get())
4003 offscreen_target_frame_buffer_->Destroy();
4004 if (offscreen_target_color_texture_.get())
4005 offscreen_target_color_texture_->Destroy();
4006 if (offscreen_target_color_render_buffer_.get())
4007 offscreen_target_color_render_buffer_->Destroy();
4008 if (offscreen_target_depth_render_buffer_.get())
4009 offscreen_target_depth_render_buffer_->Destroy();
4010 if (offscreen_target_stencil_render_buffer_.get())
4011 offscreen_target_stencil_render_buffer_->Destroy();
4012 if (offscreen_saved_frame_buffer_.get())
4013 offscreen_saved_frame_buffer_->Destroy();
4014 if (offscreen_saved_color_texture_.get())
4015 offscreen_saved_color_texture_->Destroy();
4016 if (offscreen_resolved_frame_buffer_.get())
4017 offscreen_resolved_frame_buffer_->Destroy();
4018 if (offscreen_resolved_color_texture_.get())
4019 offscreen_resolved_color_texture_->Destroy();
4020 } else {
4021 if (offscreen_target_frame_buffer_.get())
4022 offscreen_target_frame_buffer_->Invalidate();
4023 if (offscreen_target_color_texture_.get())
4024 offscreen_target_color_texture_->Invalidate();
4025 if (offscreen_target_color_render_buffer_.get())
4026 offscreen_target_color_render_buffer_->Invalidate();
4027 if (offscreen_target_depth_render_buffer_.get())
4028 offscreen_target_depth_render_buffer_->Invalidate();
4029 if (offscreen_target_stencil_render_buffer_.get())
4030 offscreen_target_stencil_render_buffer_->Invalidate();
4031 if (offscreen_saved_frame_buffer_.get())
4032 offscreen_saved_frame_buffer_->Invalidate();
4033 if (offscreen_saved_color_texture_.get())
4034 offscreen_saved_color_texture_->Invalidate();
4035 if (offscreen_resolved_frame_buffer_.get())
4036 offscreen_resolved_frame_buffer_->Invalidate();
4037 if (offscreen_resolved_color_texture_.get())
4038 offscreen_resolved_color_texture_->Invalidate();
4041 // Current program must be cleared after calling ProgramManager::UnuseProgram.
4042 // Otherwise, we can leak objects. http://crbug.com/258772.
4043 // state_.current_program must be reset before group_ is reset because
4044 // the later deletes the ProgramManager object that referred by
4045 // state_.current_program object.
4046 state_.current_program = NULL;
4048 copy_texture_CHROMIUM_.reset();
4049 clear_framebuffer_blit_.reset();
4051 if (query_manager_.get()) {
4052 query_manager_->Destroy(have_context);
4053 query_manager_.reset();
4056 if (vertex_array_manager_ .get()) {
4057 vertex_array_manager_->Destroy(have_context);
4058 vertex_array_manager_.reset();
4061 if (image_manager_.get()) {
4062 image_manager_->Destroy(have_context);
4063 image_manager_.reset();
4066 offscreen_target_frame_buffer_.reset();
4067 offscreen_target_color_texture_.reset();
4068 offscreen_target_color_render_buffer_.reset();
4069 offscreen_target_depth_render_buffer_.reset();
4070 offscreen_target_stencil_render_buffer_.reset();
4071 offscreen_saved_frame_buffer_.reset();
4072 offscreen_saved_color_texture_.reset();
4073 offscreen_resolved_frame_buffer_.reset();
4074 offscreen_resolved_color_texture_.reset();
4076 // Need to release these before releasing |group_| which may own the
4077 // ShaderTranslatorCache.
4078 fragment_translator_ = NULL;
4079 vertex_translator_ = NULL;
4081 // Should destroy the transfer manager before the texture manager held
4082 // by the context group.
4083 async_pixel_transfer_manager_.reset();
4085 // Destroy the GPU Tracer which may own some in process GPU Timings.
4086 if (gpu_tracer_) {
4087 gpu_tracer_->Destroy(have_context);
4088 gpu_tracer_.reset();
4091 if (group_.get()) {
4092 framebuffer_manager()->RemoveObserver(this);
4093 group_->Destroy(this, have_context);
4094 group_ = NULL;
4097 if (context_.get()) {
4098 context_->ReleaseCurrent(NULL);
4099 context_ = NULL;
4102 #if defined(OS_MACOSX)
4103 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
4104 it != texture_to_io_surface_map_.end(); ++it) {
4105 CFRelease(it->second);
4107 texture_to_io_surface_map_.clear();
4108 #endif
4111 void GLES2DecoderImpl::SetSurface(
4112 const scoped_refptr<gfx::GLSurface>& surface) {
4113 DCHECK(context_->IsCurrent(NULL));
4114 DCHECK(surface_.get());
4115 surface_ = surface;
4116 RestoreCurrentFramebufferBindings();
4119 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
4120 if (!offscreen_saved_color_texture_.get()) {
4121 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
4122 return;
4124 if (!offscreen_saved_color_texture_info_.get()) {
4125 GLuint service_id = offscreen_saved_color_texture_->id();
4126 offscreen_saved_color_texture_info_ = TextureRef::Create(
4127 texture_manager(), 0, service_id);
4128 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
4129 GL_TEXTURE_2D);
4130 UpdateParentTextureInfo();
4132 mailbox_manager()->ProduceTexture(
4133 mailbox, offscreen_saved_color_texture_info_->texture());
4136 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
4137 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4138 if (!is_offscreen) {
4139 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
4140 << " with an onscreen framebuffer.";
4141 return false;
4144 if (offscreen_size_ == size)
4145 return true;
4147 offscreen_size_ = size;
4148 int w = offscreen_size_.width();
4149 int h = offscreen_size_.height();
4150 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
4151 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4152 << "to allocate storage due to excessive dimensions.";
4153 return false;
4156 // Reallocate the offscreen target buffers.
4157 DCHECK(offscreen_target_color_format_);
4158 if (IsOffscreenBufferMultisampled()) {
4159 if (!offscreen_target_color_render_buffer_->AllocateStorage(
4160 feature_info_.get(),
4161 offscreen_size_,
4162 offscreen_target_color_format_,
4163 offscreen_target_samples_)) {
4164 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4165 << "to allocate storage for offscreen target color buffer.";
4166 return false;
4168 } else {
4169 if (!offscreen_target_color_texture_->AllocateStorage(
4170 offscreen_size_, offscreen_target_color_format_, false)) {
4171 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4172 << "to allocate storage for offscreen target color texture.";
4173 return false;
4176 if (offscreen_target_depth_format_ &&
4177 !offscreen_target_depth_render_buffer_->AllocateStorage(
4178 feature_info_.get(),
4179 offscreen_size_,
4180 offscreen_target_depth_format_,
4181 offscreen_target_samples_)) {
4182 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4183 << "to allocate storage for offscreen target depth buffer.";
4184 return false;
4186 if (offscreen_target_stencil_format_ &&
4187 !offscreen_target_stencil_render_buffer_->AllocateStorage(
4188 feature_info_.get(),
4189 offscreen_size_,
4190 offscreen_target_stencil_format_,
4191 offscreen_target_samples_)) {
4192 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4193 << "to allocate storage for offscreen target stencil buffer.";
4194 return false;
4197 // Attach the offscreen target buffers to the target frame buffer.
4198 if (IsOffscreenBufferMultisampled()) {
4199 offscreen_target_frame_buffer_->AttachRenderBuffer(
4200 GL_COLOR_ATTACHMENT0,
4201 offscreen_target_color_render_buffer_.get());
4202 } else {
4203 offscreen_target_frame_buffer_->AttachRenderTexture(
4204 offscreen_target_color_texture_.get());
4206 if (offscreen_target_depth_format_) {
4207 offscreen_target_frame_buffer_->AttachRenderBuffer(
4208 GL_DEPTH_ATTACHMENT,
4209 offscreen_target_depth_render_buffer_.get());
4211 const bool packed_depth_stencil =
4212 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4213 if (packed_depth_stencil) {
4214 offscreen_target_frame_buffer_->AttachRenderBuffer(
4215 GL_STENCIL_ATTACHMENT,
4216 offscreen_target_depth_render_buffer_.get());
4217 } else if (offscreen_target_stencil_format_) {
4218 offscreen_target_frame_buffer_->AttachRenderBuffer(
4219 GL_STENCIL_ATTACHMENT,
4220 offscreen_target_stencil_render_buffer_.get());
4223 if (offscreen_target_frame_buffer_->CheckStatus() !=
4224 GL_FRAMEBUFFER_COMPLETE) {
4225 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4226 << "because offscreen FBO was incomplete.";
4227 return false;
4230 // Clear the target frame buffer.
4232 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
4233 glClearColor(0, 0, 0, BackBufferHasAlpha() ? 0 : 1.f);
4234 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4235 glClearStencil(0);
4236 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
4237 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
4238 glClearDepth(0);
4239 state_.SetDeviceDepthMask(GL_TRUE);
4240 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
4241 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4242 RestoreClearState();
4245 // Destroy the offscreen resolved framebuffers.
4246 if (offscreen_resolved_frame_buffer_.get())
4247 offscreen_resolved_frame_buffer_->Destroy();
4248 if (offscreen_resolved_color_texture_.get())
4249 offscreen_resolved_color_texture_->Destroy();
4250 offscreen_resolved_color_texture_.reset();
4251 offscreen_resolved_frame_buffer_.reset();
4253 return true;
4256 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size,
4257 const void* cmd_data) {
4258 const gles2::cmds::ResizeCHROMIUM& c =
4259 *static_cast<const gles2::cmds::ResizeCHROMIUM*>(cmd_data);
4260 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
4261 return error::kDeferCommandUntilLater;
4263 GLuint width = static_cast<GLuint>(c.width);
4264 GLuint height = static_cast<GLuint>(c.height);
4265 GLfloat scale_factor = c.scale_factor;
4266 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
4268 width = std::max(1U, width);
4269 height = std::max(1U, height);
4271 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4272 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4273 // Make sure that we are done drawing to the back buffer before resizing.
4274 glFinish();
4275 #endif
4276 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4277 if (is_offscreen) {
4278 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
4279 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
4280 << "ResizeOffscreenFrameBuffer failed.";
4281 return error::kLostContext;
4285 if (!resize_callback_.is_null()) {
4286 resize_callback_.Run(gfx::Size(width, height), scale_factor);
4287 DCHECK(context_->IsCurrent(surface_.get()));
4288 if (!context_->IsCurrent(surface_.get())) {
4289 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
4290 << "current after resize callback.";
4291 return error::kLostContext;
4295 return error::kNoError;
4298 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
4299 if (command_id > kStartPoint && command_id < kNumCommands) {
4300 return gles2::GetCommandName(static_cast<CommandId>(command_id));
4302 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
4305 // Decode a command, and call the corresponding GL functions.
4306 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4307 // of commands at once, and is now only used for tests that need to track
4308 // individual commands.
4309 error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
4310 unsigned int arg_count,
4311 const void* cmd_data) {
4312 return DoCommands(1, cmd_data, arg_count + 1, 0);
4315 // Decode multiple commands, and call the corresponding GL functions.
4316 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4317 // changed by a (malicious) client at any time, so if validation has to happen,
4318 // it should operate on a copy of them.
4319 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4320 // interest of performance in this critical execution loop.
4321 template <bool DebugImpl>
4322 error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands,
4323 const void* buffer,
4324 int num_entries,
4325 int* entries_processed) {
4326 commands_to_process_ = num_commands;
4327 error::Error result = error::kNoError;
4328 const CommandBufferEntry* cmd_data =
4329 static_cast<const CommandBufferEntry*>(buffer);
4330 int process_pos = 0;
4331 unsigned int command = 0;
4333 while (process_pos < num_entries && result == error::kNoError &&
4334 commands_to_process_--) {
4335 const unsigned int size = cmd_data->value_header.size;
4336 command = cmd_data->value_header.command;
4338 if (size == 0) {
4339 result = error::kInvalidSize;
4340 break;
4343 if (static_cast<int>(size) + process_pos > num_entries) {
4344 result = error::kOutOfBounds;
4345 break;
4348 if (DebugImpl) {
4349 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4350 GetCommandName(command));
4352 if (log_commands()) {
4353 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
4354 << "cmd: " << GetCommandName(command);
4358 const unsigned int arg_count = size - 1;
4359 unsigned int command_index = command - kStartPoint - 1;
4360 if (command_index < arraysize(command_info)) {
4361 const CommandInfo& info = command_info[command_index];
4362 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
4363 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
4364 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
4365 bool doing_gpu_trace = false;
4366 if (DebugImpl && gpu_trace_commands_) {
4367 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
4368 doing_gpu_trace = true;
4369 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4370 GetCommandName(command),
4371 kTraceDecoder);
4375 uint32 immediate_data_size = (arg_count - info_arg_count) *
4376 sizeof(CommandBufferEntry); // NOLINT
4378 result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
4380 if (DebugImpl && doing_gpu_trace)
4381 gpu_tracer_->End(kTraceDecoder);
4383 if (DebugImpl && debug()) {
4384 GLenum error;
4385 while ((error = glGetError()) != GL_NO_ERROR) {
4386 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
4387 << "GL ERROR: " << GLES2Util::GetStringEnum(error)
4388 << " : " << GetCommandName(command);
4389 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
4392 } else {
4393 result = error::kInvalidArguments;
4395 } else {
4396 result = DoCommonCommand(command, arg_count, cmd_data);
4399 if (DebugImpl) {
4400 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4401 GetCommandName(command));
4404 if (result == error::kNoError &&
4405 current_decoder_error_ != error::kNoError) {
4406 result = current_decoder_error_;
4407 current_decoder_error_ = error::kNoError;
4410 if (result != error::kDeferCommandUntilLater) {
4411 process_pos += size;
4412 cmd_data += size;
4416 if (entries_processed)
4417 *entries_processed = process_pos;
4419 if (error::IsError(result)) {
4420 LOG(ERROR) << "Error: " << result << " for Command "
4421 << GetCommandName(command);
4424 return result;
4427 error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
4428 const void* buffer,
4429 int num_entries,
4430 int* entries_processed) {
4431 if (gpu_debug_commands_) {
4432 return DoCommandsImpl<true>(
4433 num_commands, buffer, num_entries, entries_processed);
4434 } else {
4435 return DoCommandsImpl<false>(
4436 num_commands, buffer, num_entries, entries_processed);
4440 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
4441 buffer_manager()->RemoveBuffer(client_id);
4444 void GLES2DecoderImpl::DoFinish() {
4445 glFinish();
4446 ProcessPendingReadPixels(true);
4447 ProcessPendingQueries(true);
4450 void GLES2DecoderImpl::DoFlush() {
4451 glFlush();
4452 ProcessPendingQueries(false);
4455 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
4456 GLuint texture_index = texture_unit - GL_TEXTURE0;
4457 if (texture_index >= state_.texture_units.size()) {
4458 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4459 "glActiveTexture", texture_unit, "texture_unit");
4460 return;
4462 state_.active_texture_unit = texture_index;
4463 glActiveTexture(texture_unit);
4466 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
4467 Buffer* buffer = NULL;
4468 GLuint service_id = 0;
4469 if (client_id != 0) {
4470 buffer = GetBuffer(client_id);
4471 if (!buffer) {
4472 if (!group_->bind_generates_resource()) {
4473 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4474 "glBindBuffer",
4475 "id not generated by glGenBuffers");
4476 return;
4479 // It's a new id so make a buffer buffer for it.
4480 glGenBuffersARB(1, &service_id);
4481 CreateBuffer(client_id, service_id);
4482 buffer = GetBuffer(client_id);
4485 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
4486 if (buffer) {
4487 if (!buffer_manager()->SetTarget(buffer, target)) {
4488 LOCAL_SET_GL_ERROR(
4489 GL_INVALID_OPERATION,
4490 "glBindBuffer", "buffer bound to more than 1 target");
4491 return;
4493 service_id = buffer->service_id();
4495 state_.SetBoundBuffer(target, buffer);
4496 glBindBuffer(target, service_id);
4499 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
4500 Framebuffer* framebuffer =
4501 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4502 if (framebuffer)
4503 return framebuffer->HasAlphaMRT();
4504 return BackBufferHasAlpha();
4507 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4508 Framebuffer* framebuffer =
4509 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4510 if (framebuffer) {
4511 return framebuffer->HasDepthAttachment();
4513 if (offscreen_target_frame_buffer_.get()) {
4514 return offscreen_target_depth_format_ != 0;
4516 return back_buffer_has_depth_;
4519 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4520 Framebuffer* framebuffer =
4521 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4522 if (framebuffer) {
4523 return framebuffer->HasStencilAttachment();
4525 if (offscreen_target_frame_buffer_.get()) {
4526 return offscreen_target_stencil_format_ != 0 ||
4527 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4529 return back_buffer_has_stencil_;
4532 void GLES2DecoderImpl::ApplyDirtyState() {
4533 if (framebuffer_state_.clear_state_dirty) {
4534 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha();
4535 state_.SetDeviceColorMask(state_.color_mask_red,
4536 state_.color_mask_green,
4537 state_.color_mask_blue,
4538 state_.color_mask_alpha && have_alpha);
4540 bool have_depth = BoundFramebufferHasDepthAttachment();
4541 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
4543 bool have_stencil = BoundFramebufferHasStencilAttachment();
4544 state_.SetDeviceStencilMaskSeparate(
4545 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
4546 state_.SetDeviceStencilMaskSeparate(
4547 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
4549 state_.SetDeviceCapabilityState(
4550 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
4551 state_.SetDeviceCapabilityState(
4552 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
4553 framebuffer_state_.clear_state_dirty = false;
4557 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
4558 return (offscreen_target_frame_buffer_.get())
4559 ? offscreen_target_frame_buffer_->id()
4560 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
4563 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
4564 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4565 "context", logger_.GetLogPrefix());
4566 // Restore the Framebuffer first because of bugs in Intel drivers.
4567 // Intel drivers incorrectly clip the viewport settings to
4568 // the size of the current framebuffer object.
4569 RestoreFramebufferBindings();
4570 state_.RestoreState(prev_state);
4573 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4574 GLuint service_id =
4575 framebuffer_state_.bound_draw_framebuffer.get()
4576 ? framebuffer_state_.bound_draw_framebuffer->service_id()
4577 : GetBackbufferServiceId();
4578 if (!features().chromium_framebuffer_multisample) {
4579 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
4580 } else {
4581 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
4582 service_id = framebuffer_state_.bound_read_framebuffer.get()
4583 ? framebuffer_state_.bound_read_framebuffer->service_id()
4584 : GetBackbufferServiceId();
4585 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
4587 OnFboChanged();
4590 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4591 state_.RestoreRenderbufferBindings();
4594 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4595 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4596 if (texture) {
4597 GLenum target = texture->target();
4598 glBindTexture(target, service_id);
4599 glTexParameteri(
4600 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4601 glTexParameteri(
4602 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4603 glTexParameteri(
4604 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4605 glTexParameteri(
4606 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4607 RestoreTextureUnitBindings(state_.active_texture_unit);
4611 void GLES2DecoderImpl::ClearAllAttributes() const {
4612 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4613 // other VAOs.
4614 if (feature_info_->feature_flags().native_vertex_array_object)
4615 glBindVertexArrayOES(0);
4617 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4618 if (i != 0) // Never disable attribute 0
4619 glDisableVertexAttribArray(i);
4620 if (features().angle_instanced_arrays)
4621 glVertexAttribDivisorANGLE(i, 0);
4625 void GLES2DecoderImpl::RestoreAllAttributes() const {
4626 state_.RestoreVertexAttribs();
4629 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4630 state_.SetIgnoreCachedStateForTest(ignore);
4633 void GLES2DecoderImpl::OnFboChanged() const {
4634 if (workarounds().restore_scissor_on_fbo_change)
4635 state_.fbo_binding_for_scissor_workaround_dirty = true;
4637 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer) {
4638 GLint bound_fbo_unsigned = -1;
4639 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &bound_fbo_unsigned);
4640 GLuint bound_fbo = static_cast<GLuint>(bound_fbo_unsigned);
4641 if (surface_ && surface_->GetBackingFrameBufferObject() == bound_fbo)
4642 surface_->NotifyWasBound();
4646 // Called after the FBO is checked for completeness.
4647 void GLES2DecoderImpl::OnUseFramebuffer() const {
4648 if (state_.fbo_binding_for_scissor_workaround_dirty) {
4649 state_.fbo_binding_for_scissor_workaround_dirty = false;
4650 // The driver forgets the correct scissor when modifying the FBO binding.
4651 glScissor(state_.scissor_x,
4652 state_.scissor_y,
4653 state_.scissor_width,
4654 state_.scissor_height);
4656 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4657 // it's unclear how this bug works.
4658 glFlush();
4662 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4663 Framebuffer* framebuffer = NULL;
4664 GLuint service_id = 0;
4665 if (client_id != 0) {
4666 framebuffer = GetFramebuffer(client_id);
4667 if (!framebuffer) {
4668 if (!group_->bind_generates_resource()) {
4669 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4670 "glBindFramebuffer",
4671 "id not generated by glGenFramebuffers");
4672 return;
4675 // It's a new id so make a framebuffer framebuffer for it.
4676 glGenFramebuffersEXT(1, &service_id);
4677 CreateFramebuffer(client_id, service_id);
4678 framebuffer = GetFramebuffer(client_id);
4679 } else {
4680 service_id = framebuffer->service_id();
4682 framebuffer->MarkAsValid();
4684 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4686 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4687 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4690 // vmiura: This looks like dup code
4691 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4692 framebuffer_state_.bound_read_framebuffer = framebuffer;
4695 framebuffer_state_.clear_state_dirty = true;
4697 // If we are rendering to the backbuffer get the FBO id for any simulated
4698 // backbuffer.
4699 if (framebuffer == NULL) {
4700 service_id = GetBackbufferServiceId();
4703 glBindFramebufferEXT(target, service_id);
4704 OnFboChanged();
4707 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4708 Renderbuffer* renderbuffer = NULL;
4709 GLuint service_id = 0;
4710 if (client_id != 0) {
4711 renderbuffer = GetRenderbuffer(client_id);
4712 if (!renderbuffer) {
4713 if (!group_->bind_generates_resource()) {
4714 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4715 "glBindRenderbuffer",
4716 "id not generated by glGenRenderbuffers");
4717 return;
4720 // It's a new id so make a renderbuffer for it.
4721 glGenRenderbuffersEXT(1, &service_id);
4722 CreateRenderbuffer(client_id, service_id);
4723 renderbuffer = GetRenderbuffer(client_id);
4724 } else {
4725 service_id = renderbuffer->service_id();
4727 renderbuffer->MarkAsValid();
4729 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4730 state_.bound_renderbuffer = renderbuffer;
4731 state_.bound_renderbuffer_valid = true;
4732 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4735 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4736 TextureRef* texture_ref = NULL;
4737 GLuint service_id = 0;
4738 if (client_id != 0) {
4739 texture_ref = GetTexture(client_id);
4740 if (!texture_ref) {
4741 if (!group_->bind_generates_resource()) {
4742 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4743 "glBindTexture",
4744 "id not generated by glGenTextures");
4745 return;
4748 // It's a new id so make a texture texture for it.
4749 glGenTextures(1, &service_id);
4750 DCHECK_NE(0u, service_id);
4751 CreateTexture(client_id, service_id);
4752 texture_ref = GetTexture(client_id);
4754 } else {
4755 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4758 // Check the texture exists
4759 if (texture_ref) {
4760 Texture* texture = texture_ref->texture();
4761 // Check that we are not trying to bind it to a different target.
4762 if (texture->target() != 0 && texture->target() != target) {
4763 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4764 "glBindTexture",
4765 "texture bound to more than 1 target.");
4766 return;
4768 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4769 if (texture->target() == 0) {
4770 texture_manager()->SetTarget(texture_ref, target);
4772 glBindTexture(target, texture->service_id());
4773 } else {
4774 glBindTexture(target, 0);
4777 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4778 unit.bind_target = target;
4779 switch (target) {
4780 case GL_TEXTURE_2D:
4781 unit.bound_texture_2d = texture_ref;
4782 break;
4783 case GL_TEXTURE_CUBE_MAP:
4784 unit.bound_texture_cube_map = texture_ref;
4785 break;
4786 case GL_TEXTURE_EXTERNAL_OES:
4787 unit.bound_texture_external_oes = texture_ref;
4788 break;
4789 case GL_TEXTURE_RECTANGLE_ARB:
4790 unit.bound_texture_rectangle_arb = texture_ref;
4791 break;
4792 case GL_TEXTURE_3D:
4793 unit.bound_texture_3d = texture_ref;
4794 break;
4795 case GL_TEXTURE_2D_ARRAY:
4796 unit.bound_texture_2d_array = texture_ref;
4797 break;
4798 default:
4799 NOTREACHED(); // Validation should prevent us getting here.
4800 break;
4804 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4805 if (state_.vertex_attrib_manager->Enable(index, false)) {
4806 if (index != 0 ||
4807 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4808 glDisableVertexAttribArray(index);
4810 } else {
4811 LOCAL_SET_GL_ERROR(
4812 GL_INVALID_VALUE,
4813 "glDisableVertexAttribArray", "index out of range");
4817 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4818 GLsizei numAttachments,
4819 const GLenum* attachments) {
4820 if (workarounds().disable_discard_framebuffer)
4821 return;
4823 Framebuffer* framebuffer =
4824 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4826 // Validates the attachments. If one of them fails
4827 // the whole command fails.
4828 for (GLsizei i = 0; i < numAttachments; ++i) {
4829 if ((framebuffer &&
4830 !validators_->attachment.IsValid(attachments[i])) ||
4831 (!framebuffer &&
4832 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4833 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4834 "glDiscardFramebufferEXT", attachments[i], "attachments");
4835 return;
4839 // Marks each one of them as not cleared
4840 for (GLsizei i = 0; i < numAttachments; ++i) {
4841 if (framebuffer) {
4842 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4843 texture_manager(),
4844 attachments[i],
4845 false);
4846 } else {
4847 switch (attachments[i]) {
4848 case GL_COLOR_EXT:
4849 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4850 break;
4851 case GL_DEPTH_EXT:
4852 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4853 case GL_STENCIL_EXT:
4854 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4855 break;
4856 default:
4857 NOTREACHED();
4858 break;
4863 // If the default framebuffer is bound but we are still rendering to an
4864 // FBO, translate attachment names that refer to default framebuffer
4865 // channels to corresponding framebuffer attachments.
4866 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4867 for (GLsizei i = 0; i < numAttachments; ++i) {
4868 GLenum attachment = attachments[i];
4869 if (!framebuffer && GetBackbufferServiceId()) {
4870 switch (attachment) {
4871 case GL_COLOR_EXT:
4872 attachment = GL_COLOR_ATTACHMENT0;
4873 break;
4874 case GL_DEPTH_EXT:
4875 attachment = GL_DEPTH_ATTACHMENT;
4876 break;
4877 case GL_STENCIL_EXT:
4878 attachment = GL_STENCIL_ATTACHMENT;
4879 break;
4880 default:
4881 NOTREACHED();
4882 return;
4885 translated_attachments[i] = attachment;
4888 ScopedRenderTo do_render(framebuffer);
4889 if (feature_info_->gl_version_info().is_es3) {
4890 glInvalidateFramebuffer(
4891 target, numAttachments, translated_attachments.get());
4892 } else {
4893 glDiscardFramebufferEXT(
4894 target, numAttachments, translated_attachments.get());
4898 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4899 if (state_.vertex_attrib_manager->Enable(index, true)) {
4900 glEnableVertexAttribArray(index);
4901 } else {
4902 LOCAL_SET_GL_ERROR(
4903 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4907 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4908 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4909 &state_, target);
4910 if (!texture_ref ||
4911 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4912 LOCAL_SET_GL_ERROR(
4913 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4914 return;
4917 if (target == GL_TEXTURE_CUBE_MAP) {
4918 for (int i = 0; i < 6; ++i) {
4919 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4920 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4921 LOCAL_SET_GL_ERROR(
4922 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4923 return;
4926 } else {
4927 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4928 LOCAL_SET_GL_ERROR(
4929 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4930 return;
4934 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4935 // Workaround for Mac driver bug. In the large scheme of things setting
4936 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4937 // hit so there's probably no need to make this conditional. The bug appears
4938 // to be that if the filtering mode is set to something that doesn't require
4939 // mipmaps for rendering, or is never set to something other than the default,
4940 // then glGenerateMipmap misbehaves.
4941 if (workarounds().set_texture_filter_before_generating_mipmap) {
4942 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4944 glGenerateMipmapEXT(target);
4945 if (workarounds().set_texture_filter_before_generating_mipmap) {
4946 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4947 texture_ref->texture()->min_filter());
4949 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4950 if (error == GL_NO_ERROR) {
4951 texture_manager()->MarkMipmapsGenerated(texture_ref);
4955 bool GLES2DecoderImpl::GetHelper(
4956 GLenum pname, GLint* params, GLsizei* num_written) {
4957 DCHECK(num_written);
4958 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4959 switch (pname) {
4960 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4961 *num_written = 1;
4962 // Return the GL implementation's preferred format and (see below type)
4963 // if we have the GL extension that exposes this. This allows the GPU
4964 // client to use the implementation's preferred format for glReadPixels
4965 // for optimisation.
4967 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4968 // case when requested on integer/floating point buffers but which is
4969 // acceptable on GLES2 and with the GL_OES_read_format extension.
4971 // Therefore if an error occurs we swallow the error and use the
4972 // internal implementation.
4973 if (params) {
4974 if (context_->HasExtension("GL_OES_read_format")) {
4975 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4976 GetErrorState());
4977 glGetIntegerv(pname, params);
4978 if (glGetError() == GL_NO_ERROR)
4979 return true;
4981 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4982 GetBoundReadFrameBufferInternalFormat());
4984 return true;
4985 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4986 *num_written = 1;
4987 if (params) {
4988 if (context_->HasExtension("GL_OES_read_format")) {
4989 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4990 GetErrorState());
4991 glGetIntegerv(pname, params);
4992 if (glGetError() == GL_NO_ERROR)
4993 return true;
4995 *params = GLES2Util::GetPreferredGLReadPixelsType(
4996 GetBoundReadFrameBufferInternalFormat(),
4997 GetBoundReadFrameBufferTextureType());
4999 return true;
5000 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
5001 *num_written = 1;
5002 if (params) {
5003 *params = group_->max_fragment_uniform_vectors();
5005 return true;
5006 case GL_MAX_VARYING_VECTORS:
5007 *num_written = 1;
5008 if (params) {
5009 *params = group_->max_varying_vectors();
5011 return true;
5012 case GL_MAX_VERTEX_UNIFORM_VECTORS:
5013 *num_written = 1;
5014 if (params) {
5015 *params = group_->max_vertex_uniform_vectors();
5017 return true;
5020 if (unsafe_es3_apis_enabled()) {
5021 switch (pname) {
5022 case GL_MAX_VARYING_COMPONENTS: {
5023 if (feature_info_->gl_version_info().is_es) {
5024 // We can just delegate this query to the driver.
5025 return false;
5028 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
5029 // OpenGL core profile, so for simplicity, just compute it
5030 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
5031 // configurations.
5032 GLint max_varying_vectors = 0;
5033 glGetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors);
5034 *num_written = 1;
5035 if (params) {
5036 *params = max_varying_vectors * 4;
5038 return true;
5040 case GL_READ_BUFFER:
5041 *num_written = 1;
5042 if (params) {
5043 Framebuffer* framebuffer =
5044 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
5045 GLenum read_buffer;
5046 if (framebuffer) {
5047 read_buffer = framebuffer->read_buffer();
5048 } else {
5049 read_buffer = back_buffer_read_buffer_;
5051 *params = static_cast<GLint>(read_buffer);
5053 return true;
5056 switch (pname) {
5057 case GL_MAX_VIEWPORT_DIMS:
5058 if (offscreen_target_frame_buffer_.get()) {
5059 *num_written = 2;
5060 if (params) {
5061 params[0] = renderbuffer_manager()->max_renderbuffer_size();
5062 params[1] = renderbuffer_manager()->max_renderbuffer_size();
5064 return true;
5066 return false;
5067 case GL_MAX_SAMPLES:
5068 *num_written = 1;
5069 if (params) {
5070 params[0] = renderbuffer_manager()->max_samples();
5072 return true;
5073 case GL_MAX_RENDERBUFFER_SIZE:
5074 *num_written = 1;
5075 if (params) {
5076 params[0] = renderbuffer_manager()->max_renderbuffer_size();
5078 return true;
5079 case GL_MAX_TEXTURE_SIZE:
5080 *num_written = 1;
5081 if (params) {
5082 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
5084 return true;
5085 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
5086 *num_written = 1;
5087 if (params) {
5088 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
5090 return true;
5091 case GL_MAX_COLOR_ATTACHMENTS_EXT:
5092 *num_written = 1;
5093 if (params) {
5094 params[0] = group_->max_color_attachments();
5096 return true;
5097 case GL_MAX_DRAW_BUFFERS_ARB:
5098 *num_written = 1;
5099 if (params) {
5100 params[0] = group_->max_draw_buffers();
5102 return true;
5103 case GL_ALPHA_BITS:
5104 *num_written = 1;
5105 if (params) {
5106 GLint v = 0;
5107 Framebuffer* framebuffer =
5108 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5109 if (framebuffer) {
5110 if (framebuffer->HasAlphaMRT() &&
5111 framebuffer->HasSameInternalFormatsMRT()) {
5112 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5113 glGetFramebufferAttachmentParameterivEXT(
5114 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5115 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &v);
5116 } else {
5117 glGetIntegerv(GL_ALPHA_BITS, &v);
5120 } else {
5121 v = (BackBufferHasAlpha() ? 8 : 0);
5123 params[0] = v;
5125 return true;
5126 case GL_DEPTH_BITS:
5127 *num_written = 1;
5128 if (params) {
5129 GLint v = 0;
5130 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5131 Framebuffer* framebuffer =
5132 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5133 if (framebuffer) {
5134 glGetFramebufferAttachmentParameterivEXT(
5135 GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
5136 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &v);
5137 } else {
5138 v = (back_buffer_has_depth_ ? 24 : 0);
5140 } else {
5141 glGetIntegerv(GL_DEPTH_BITS, &v);
5143 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
5145 return true;
5146 case GL_RED_BITS:
5147 case GL_GREEN_BITS:
5148 case GL_BLUE_BITS:
5149 *num_written = 1;
5150 if (params) {
5151 GLint v = 0;
5152 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5153 Framebuffer* framebuffer =
5154 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5155 if (framebuffer) {
5156 GLenum framebuffer_enum = 0;
5157 switch (pname) {
5158 case GL_RED_BITS:
5159 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
5160 break;
5161 case GL_GREEN_BITS:
5162 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
5163 break;
5164 case GL_BLUE_BITS:
5165 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
5166 break;
5168 glGetFramebufferAttachmentParameterivEXT(
5169 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, framebuffer_enum, &v);
5170 } else {
5171 v = 8;
5173 } else {
5174 glGetIntegerv(pname, &v);
5176 params[0] = v;
5178 return true;
5179 case GL_STENCIL_BITS:
5180 *num_written = 1;
5181 if (params) {
5182 GLint v = 0;
5183 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5184 Framebuffer* framebuffer =
5185 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5186 if (framebuffer) {
5187 glGetFramebufferAttachmentParameterivEXT(
5188 GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
5189 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &v);
5190 } else {
5191 v = (back_buffer_has_stencil_ ? 8 : 0);
5193 } else {
5194 glGetIntegerv(GL_STENCIL_BITS, &v);
5196 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
5198 return true;
5199 case GL_COMPRESSED_TEXTURE_FORMATS:
5200 *num_written = validators_->compressed_texture_format.GetValues().size();
5201 if (params) {
5202 for (GLint ii = 0; ii < *num_written; ++ii) {
5203 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
5206 return true;
5207 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
5208 *num_written = 1;
5209 if (params) {
5210 *params = validators_->compressed_texture_format.GetValues().size();
5212 return true;
5213 case GL_NUM_SHADER_BINARY_FORMATS:
5214 *num_written = 1;
5215 if (params) {
5216 *params = validators_->shader_binary_format.GetValues().size();
5218 return true;
5219 case GL_SHADER_BINARY_FORMATS:
5220 *num_written = validators_->shader_binary_format.GetValues().size();
5221 if (params) {
5222 for (GLint ii = 0; ii < *num_written; ++ii) {
5223 params[ii] = validators_->shader_binary_format.GetValues()[ii];
5226 return true;
5227 case GL_SHADER_COMPILER:
5228 *num_written = 1;
5229 if (params) {
5230 *params = GL_TRUE;
5232 return true;
5233 case GL_ARRAY_BUFFER_BINDING:
5234 *num_written = 1;
5235 if (params) {
5236 *params = GetClientId(
5237 buffer_manager(), state_.bound_array_buffer.get());
5239 return true;
5240 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5241 *num_written = 1;
5242 if (params) {
5243 *params = GetClientId(
5244 buffer_manager(),
5245 state_.vertex_attrib_manager->element_array_buffer());
5247 return true;
5248 case GL_COPY_READ_BUFFER_BINDING:
5249 *num_written = 1;
5250 if (params) {
5251 *params = GetClientId(
5252 buffer_manager(), state_.bound_copy_read_buffer.get());
5254 return true;
5255 case GL_COPY_WRITE_BUFFER_BINDING:
5256 *num_written = 1;
5257 if (params) {
5258 *params = GetClientId(
5259 buffer_manager(), state_.bound_copy_write_buffer.get());
5261 return true;
5262 case GL_PIXEL_PACK_BUFFER_BINDING:
5263 *num_written = 1;
5264 if (params) {
5265 *params = GetClientId(
5266 buffer_manager(), state_.bound_pixel_pack_buffer.get());
5268 return true;
5269 case GL_PIXEL_UNPACK_BUFFER_BINDING:
5270 *num_written = 1;
5271 if (params) {
5272 *params = GetClientId(
5273 buffer_manager(), state_.bound_pixel_unpack_buffer.get());
5275 return true;
5276 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
5277 *num_written = 1;
5278 if (params) {
5279 *params = GetClientId(
5280 buffer_manager(), state_.bound_transform_feedback_buffer.get());
5282 return true;
5283 case GL_UNIFORM_BUFFER_BINDING:
5284 *num_written = 1;
5285 if (params) {
5286 *params = GetClientId(
5287 buffer_manager(), state_.bound_uniform_buffer.get());
5289 return true;
5290 case GL_FRAMEBUFFER_BINDING:
5291 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5292 *num_written = 1;
5293 if (params) {
5294 *params = GetClientId(
5295 framebuffer_manager(),
5296 GetFramebufferInfoForTarget(GL_FRAMEBUFFER));
5298 return true;
5299 case GL_READ_FRAMEBUFFER_BINDING_EXT:
5300 *num_written = 1;
5301 if (params) {
5302 *params = GetClientId(
5303 framebuffer_manager(),
5304 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT));
5306 return true;
5307 case GL_RENDERBUFFER_BINDING:
5308 *num_written = 1;
5309 if (params) {
5310 Renderbuffer* renderbuffer =
5311 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5312 if (renderbuffer) {
5313 *params = renderbuffer->client_id();
5314 } else {
5315 *params = 0;
5318 return true;
5319 case GL_CURRENT_PROGRAM:
5320 *num_written = 1;
5321 if (params) {
5322 *params = GetClientId(program_manager(), state_.current_program.get());
5324 return true;
5325 case GL_VERTEX_ARRAY_BINDING_OES:
5326 *num_written = 1;
5327 if (params) {
5328 if (state_.vertex_attrib_manager.get() !=
5329 state_.default_vertex_attrib_manager.get()) {
5330 GLuint client_id = 0;
5331 vertex_array_manager_->GetClientId(
5332 state_.vertex_attrib_manager->service_id(), &client_id);
5333 *params = client_id;
5334 } else {
5335 *params = 0;
5338 return true;
5339 case GL_TEXTURE_BINDING_2D:
5340 *num_written = 1;
5341 if (params) {
5342 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5343 if (unit.bound_texture_2d.get()) {
5344 *params = unit.bound_texture_2d->client_id();
5345 } else {
5346 *params = 0;
5349 return true;
5350 case GL_TEXTURE_BINDING_CUBE_MAP:
5351 *num_written = 1;
5352 if (params) {
5353 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5354 if (unit.bound_texture_cube_map.get()) {
5355 *params = unit.bound_texture_cube_map->client_id();
5356 } else {
5357 *params = 0;
5360 return true;
5361 case GL_TEXTURE_BINDING_EXTERNAL_OES:
5362 *num_written = 1;
5363 if (params) {
5364 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5365 if (unit.bound_texture_external_oes.get()) {
5366 *params = unit.bound_texture_external_oes->client_id();
5367 } else {
5368 *params = 0;
5371 return true;
5372 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
5373 *num_written = 1;
5374 if (params) {
5375 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5376 if (unit.bound_texture_rectangle_arb.get()) {
5377 *params = unit.bound_texture_rectangle_arb->client_id();
5378 } else {
5379 *params = 0;
5382 return true;
5383 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
5384 *num_written = 1;
5385 if (params) {
5386 params[0] = group_->bind_generates_resource() ? 1 : 0;
5388 return true;
5389 default:
5390 if (pname >= GL_DRAW_BUFFER0_ARB &&
5391 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
5392 *num_written = 1;
5393 if (params) {
5394 Framebuffer* framebuffer =
5395 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
5396 if (framebuffer) {
5397 params[0] = framebuffer->GetDrawBuffer(pname);
5398 } else { // backbuffer
5399 if (pname == GL_DRAW_BUFFER0_ARB)
5400 params[0] = back_buffer_draw_buffer_;
5401 else
5402 params[0] = GL_NONE;
5405 return true;
5407 *num_written = util_.GLGetNumValuesReturned(pname);
5408 return false;
5412 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5413 GLenum pname, GLsizei* num_values) {
5414 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
5415 return true;
5417 return GetHelper(pname, NULL, num_values);
5420 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
5421 if (GL_MAX_SAMPLES == pname &&
5422 features().use_img_for_multisampled_render_to_texture) {
5423 return GL_MAX_SAMPLES_IMG;
5425 return pname;
5428 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
5429 DCHECK(params);
5430 GLsizei num_written = 0;
5431 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
5432 scoped_ptr<GLint[]> values(new GLint[num_written]);
5433 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
5434 GetHelper(pname, values.get(), &num_written);
5436 for (GLsizei ii = 0; ii < num_written; ++ii) {
5437 params[ii] = static_cast<GLboolean>(values[ii]);
5439 } else {
5440 pname = AdjustGetPname(pname);
5441 glGetBooleanv(pname, params);
5445 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
5446 DCHECK(params);
5447 GLsizei num_written = 0;
5448 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
5449 if (GetHelper(pname, NULL, &num_written)) {
5450 scoped_ptr<GLint[]> values(new GLint[num_written]);
5451 GetHelper(pname, values.get(), &num_written);
5452 for (GLsizei ii = 0; ii < num_written; ++ii) {
5453 params[ii] = static_cast<GLfloat>(values[ii]);
5455 } else {
5456 pname = AdjustGetPname(pname);
5457 glGetFloatv(pname, params);
5462 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname, GLint64* params) {
5463 DCHECK(params);
5464 if (unsafe_es3_apis_enabled()) {
5465 switch (pname) {
5466 case GL_MAX_ELEMENT_INDEX: {
5467 if (feature_info_->gl_version_info().IsAtLeastGLES(3, 0) ||
5468 feature_info_->gl_version_info().IsAtLeastGL(4, 3)) {
5469 glGetInteger64v(GL_MAX_ELEMENT_INDEX, params);
5470 } else {
5471 // Assume that desktop GL implementations can generally support
5472 // 32-bit indices.
5473 if (params) {
5474 *params = std::numeric_limits<unsigned int>::max();
5477 return;
5481 pname = AdjustGetPname(pname);
5482 glGetInteger64v(pname, params);
5485 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
5486 DCHECK(params);
5487 GLsizei num_written;
5488 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
5489 !GetHelper(pname, params, &num_written)) {
5490 pname = AdjustGetPname(pname);
5491 glGetIntegerv(pname, params);
5495 void GLES2DecoderImpl::DoGetProgramiv(
5496 GLuint program_id, GLenum pname, GLint* params) {
5497 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
5498 if (!program) {
5499 return;
5501 program->GetProgramiv(pname, params);
5504 void GLES2DecoderImpl::DoGetBufferParameteri64v(
5505 GLenum target, GLenum pname, GLint64* params) {
5506 // Just delegate it. Some validation is actually done before this.
5507 buffer_manager()->ValidateAndDoGetBufferParameteri64v(
5508 &state_, target, pname, params);
5511 void GLES2DecoderImpl::DoGetBufferParameteriv(
5512 GLenum target, GLenum pname, GLint* params) {
5513 // Just delegate it. Some validation is actually done before this.
5514 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5515 &state_, target, pname, params);
5518 void GLES2DecoderImpl::DoBindAttribLocation(
5519 GLuint program_id, GLuint index, const char* name) {
5520 if (!StringIsValidForGLES(name)) {
5521 LOCAL_SET_GL_ERROR(
5522 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
5523 return;
5525 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5526 LOCAL_SET_GL_ERROR(
5527 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
5528 return;
5530 if (index >= group_->max_vertex_attribs()) {
5531 LOCAL_SET_GL_ERROR(
5532 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
5533 return;
5535 Program* program = GetProgramInfoNotShader(
5536 program_id, "glBindAttribLocation");
5537 if (!program) {
5538 return;
5540 // At this point, the program's shaders may not be translated yet,
5541 // therefore, we may not find the hashed attribute name.
5542 // glBindAttribLocation call with original name is useless.
5543 // So instead, we should simply cache the binding, and then call
5544 // Program::ExecuteBindAttribLocationCalls() right before link.
5545 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
5546 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5547 glBindAttribLocation(program->service_id(), index, name);
5550 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
5551 uint32 immediate_data_size,
5552 const void* cmd_data) {
5553 const gles2::cmds::BindAttribLocationBucket& c =
5554 *static_cast<const gles2::cmds::BindAttribLocationBucket*>(cmd_data);
5555 GLuint program = static_cast<GLuint>(c.program);
5556 GLuint index = static_cast<GLuint>(c.index);
5557 Bucket* bucket = GetBucket(c.name_bucket_id);
5558 if (!bucket || bucket->size() == 0) {
5559 return error::kInvalidArguments;
5561 std::string name_str;
5562 if (!bucket->GetAsString(&name_str)) {
5563 return error::kInvalidArguments;
5565 DoBindAttribLocation(program, index, name_str.c_str());
5566 return error::kNoError;
5569 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5570 GLuint program_id, GLint location, const char* name) {
5571 if (!StringIsValidForGLES(name)) {
5572 LOCAL_SET_GL_ERROR(
5573 GL_INVALID_VALUE,
5574 "glBindUniformLocationCHROMIUM", "Invalid character");
5575 return;
5577 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5578 LOCAL_SET_GL_ERROR(
5579 GL_INVALID_OPERATION,
5580 "glBindUniformLocationCHROMIUM", "reserved prefix");
5581 return;
5583 if (location < 0 || static_cast<uint32>(location) >=
5584 (group_->max_fragment_uniform_vectors() +
5585 group_->max_vertex_uniform_vectors()) * 4) {
5586 LOCAL_SET_GL_ERROR(
5587 GL_INVALID_VALUE,
5588 "glBindUniformLocationCHROMIUM", "location out of range");
5589 return;
5591 Program* program = GetProgramInfoNotShader(
5592 program_id, "glBindUniformLocationCHROMIUM");
5593 if (!program) {
5594 return;
5596 if (!program->SetUniformLocationBinding(name, location)) {
5597 LOCAL_SET_GL_ERROR(
5598 GL_INVALID_VALUE,
5599 "glBindUniformLocationCHROMIUM", "location out of range");
5603 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5604 uint32 immediate_data_size,
5605 const void* cmd_data) {
5606 const gles2::cmds::BindUniformLocationCHROMIUMBucket& c =
5607 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket*>(
5608 cmd_data);
5609 GLuint program = static_cast<GLuint>(c.program);
5610 GLint location = static_cast<GLint>(c.location);
5611 Bucket* bucket = GetBucket(c.name_bucket_id);
5612 if (!bucket || bucket->size() == 0) {
5613 return error::kInvalidArguments;
5615 std::string name_str;
5616 if (!bucket->GetAsString(&name_str)) {
5617 return error::kInvalidArguments;
5619 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
5620 return error::kNoError;
5623 error::Error GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size,
5624 const void* cmd_data) {
5625 const gles2::cmds::DeleteShader& c =
5626 *static_cast<const gles2::cmds::DeleteShader*>(cmd_data);
5627 GLuint client_id = c.shader;
5628 if (client_id) {
5629 Shader* shader = GetShader(client_id);
5630 if (shader) {
5631 if (!shader->IsDeleted()) {
5632 shader_manager()->Delete(shader);
5634 } else {
5635 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
5638 return error::kNoError;
5641 error::Error GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size,
5642 const void* cmd_data) {
5643 const gles2::cmds::DeleteProgram& c =
5644 *static_cast<const gles2::cmds::DeleteProgram*>(cmd_data);
5645 GLuint client_id = c.program;
5646 if (client_id) {
5647 Program* program = GetProgram(client_id);
5648 if (program) {
5649 if (!program->IsDeleted()) {
5650 program_manager()->MarkAsDeleted(shader_manager(), program);
5652 } else {
5653 LOCAL_SET_GL_ERROR(
5654 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
5657 return error::kNoError;
5660 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5661 DCHECK(!ShouldDeferDraws());
5662 if (CheckBoundFramebuffersValid("glClear")) {
5663 ApplyDirtyState();
5664 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5665 if (workarounds().gl_clear_broken) {
5666 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::ClearWorkaround",
5667 GetErrorState());
5668 if (!BoundFramebufferHasDepthAttachment())
5669 mask &= ~GL_DEPTH_BUFFER_BIT;
5670 if (!BoundFramebufferHasStencilAttachment())
5671 mask &= ~GL_STENCIL_BUFFER_BIT;
5672 clear_framebuffer_blit_->ClearFramebuffer(
5673 this, GetBoundReadFrameBufferSize(), mask, state_.color_clear_red,
5674 state_.color_clear_green, state_.color_clear_blue,
5675 state_.color_clear_alpha, state_.depth_clear, state_.stencil_clear);
5676 return error::kNoError;
5678 glClear(mask);
5680 return error::kNoError;
5683 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5684 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5685 GLuint client_renderbuffer_id) {
5686 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5687 if (!framebuffer) {
5688 LOCAL_SET_GL_ERROR(
5689 GL_INVALID_OPERATION,
5690 "glFramebufferRenderbuffer", "no framebuffer bound");
5691 return;
5693 GLuint service_id = 0;
5694 Renderbuffer* renderbuffer = NULL;
5695 if (client_renderbuffer_id) {
5696 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5697 if (!renderbuffer) {
5698 LOCAL_SET_GL_ERROR(
5699 GL_INVALID_OPERATION,
5700 "glFramebufferRenderbuffer", "unknown renderbuffer");
5701 return;
5703 service_id = renderbuffer->service_id();
5705 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5706 glFramebufferRenderbufferEXT(
5707 target, attachment, renderbuffertarget, service_id);
5708 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5709 if (error == GL_NO_ERROR) {
5710 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5712 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5713 framebuffer_state_.clear_state_dirty = true;
5715 OnFboChanged();
5718 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5719 if (SetCapabilityState(cap, false)) {
5720 glDisable(cap);
5724 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5725 if (SetCapabilityState(cap, true)) {
5726 glEnable(cap);
5730 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5731 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5732 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5733 glDepthRange(znear, zfar);
5736 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5737 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5738 state_.sample_coverage_invert = (invert != 0);
5739 glSampleCoverage(state_.sample_coverage_value, invert);
5742 // Assumes framebuffer is complete.
5743 void GLES2DecoderImpl::ClearUnclearedAttachments(
5744 GLenum target, Framebuffer* framebuffer) {
5745 if (target == GL_READ_FRAMEBUFFER_EXT) {
5746 // bind this to the DRAW point, clear then bind back to READ
5747 // TODO(gman): I don't think there is any guarantee that an FBO that
5748 // is complete on the READ attachment will be complete as a DRAW
5749 // attachment.
5750 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5751 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5753 GLbitfield clear_bits = 0;
5754 if (framebuffer->HasUnclearedColorAttachments()) {
5755 // We should always use alpha == 0 here, because 1) some draw buffers may
5756 // have alpha and some may not; 2) we won't have the same situation as the
5757 // back buffer where alpha channel exists but is not requested.
5758 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
5759 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5760 clear_bits |= GL_COLOR_BUFFER_BIT;
5761 if (feature_info_->feature_flags().ext_draw_buffers)
5762 framebuffer->PrepareDrawBuffersForClear();
5765 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5766 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5767 glClearStencil(0);
5768 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
5769 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
5770 clear_bits |= GL_STENCIL_BUFFER_BIT;
5773 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5774 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5775 glClearDepth(1.0f);
5776 state_.SetDeviceDepthMask(GL_TRUE);
5777 clear_bits |= GL_DEPTH_BUFFER_BIT;
5780 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5781 glClear(clear_bits);
5783 if ((clear_bits & GL_COLOR_BUFFER_BIT) != 0 &&
5784 feature_info_->feature_flags().ext_draw_buffers)
5785 framebuffer->RestoreDrawBuffersAfterClear();
5787 framebuffer_manager()->MarkAttachmentsAsCleared(
5788 framebuffer, renderbuffer_manager(), texture_manager());
5790 RestoreClearState();
5792 if (target == GL_READ_FRAMEBUFFER_EXT) {
5793 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5794 Framebuffer* draw_framebuffer =
5795 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5796 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5797 GetBackbufferServiceId();
5798 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5802 void GLES2DecoderImpl::RestoreClearState() {
5803 framebuffer_state_.clear_state_dirty = true;
5804 glClearColor(
5805 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5806 state_.color_clear_alpha);
5807 glClearStencil(state_.stencil_clear);
5808 glClearDepth(state_.depth_clear);
5809 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5810 state_.enable_flags.scissor_test);
5811 glScissor(state_.scissor_x, state_.scissor_y, state_.scissor_width,
5812 state_.scissor_height);
5815 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5816 Framebuffer* framebuffer =
5817 GetFramebufferInfoForTarget(target);
5818 if (!framebuffer) {
5819 return GL_FRAMEBUFFER_COMPLETE;
5821 GLenum completeness = framebuffer->IsPossiblyComplete();
5822 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5823 return completeness;
5825 return framebuffer->GetStatus(texture_manager(), target);
5828 void GLES2DecoderImpl::DoFramebufferTexture2D(
5829 GLenum target, GLenum attachment, GLenum textarget,
5830 GLuint client_texture_id, GLint level) {
5831 DoFramebufferTexture2DCommon(
5832 "glFramebufferTexture2D", target, attachment,
5833 textarget, client_texture_id, level, 0);
5836 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5837 GLenum target, GLenum attachment, GLenum textarget,
5838 GLuint client_texture_id, GLint level, GLsizei samples) {
5839 DoFramebufferTexture2DCommon(
5840 "glFramebufferTexture2DMultisample", target, attachment,
5841 textarget, client_texture_id, level, samples);
5844 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5845 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5846 GLuint client_texture_id, GLint level, GLsizei samples) {
5847 if (samples > renderbuffer_manager()->max_samples()) {
5848 LOCAL_SET_GL_ERROR(
5849 GL_INVALID_VALUE,
5850 "glFramebufferTexture2DMultisample", "samples too large");
5851 return;
5853 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5854 if (!framebuffer) {
5855 LOCAL_SET_GL_ERROR(
5856 GL_INVALID_OPERATION,
5857 name, "no framebuffer bound.");
5858 return;
5860 GLuint service_id = 0;
5861 TextureRef* texture_ref = NULL;
5862 if (client_texture_id) {
5863 texture_ref = GetTexture(client_texture_id);
5864 if (!texture_ref) {
5865 LOCAL_SET_GL_ERROR(
5866 GL_INVALID_OPERATION,
5867 name, "unknown texture_ref");
5868 return;
5870 service_id = texture_ref->service_id();
5873 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5874 LOCAL_SET_GL_ERROR(
5875 GL_INVALID_VALUE,
5876 name, "level out of range");
5877 return;
5880 if (texture_ref)
5881 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5883 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5884 if (0 == samples) {
5885 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5886 } else {
5887 if (features().use_img_for_multisampled_render_to_texture) {
5888 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5889 service_id, level, samples);
5890 } else {
5891 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5892 service_id, level, samples);
5895 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5896 if (error == GL_NO_ERROR) {
5897 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5898 samples);
5900 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5901 framebuffer_state_.clear_state_dirty = true;
5904 if (texture_ref)
5905 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5907 OnFboChanged();
5910 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5911 GLenum target, GLenum attachment, GLuint client_texture_id,
5912 GLint level, GLint layer) {
5913 // TODO(zmo): Unsafe ES3 API, missing states update.
5914 GLuint service_id = 0;
5915 TextureRef* texture_ref = NULL;
5916 if (client_texture_id) {
5917 texture_ref = GetTexture(client_texture_id);
5918 if (!texture_ref) {
5919 LOCAL_SET_GL_ERROR(
5920 GL_INVALID_OPERATION,
5921 "glFramebufferTextureLayer", "unknown texture_ref");
5922 return;
5924 service_id = texture_ref->service_id();
5926 glFramebufferTextureLayer(target, attachment, service_id, level, layer);
5929 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5930 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5931 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5932 if (!framebuffer) {
5933 LOCAL_SET_GL_ERROR(
5934 GL_INVALID_OPERATION,
5935 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5936 return;
5938 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5939 const Framebuffer::Attachment* attachment_object =
5940 framebuffer->GetAttachment(attachment);
5941 *params = attachment_object ? attachment_object->object_name() : 0;
5942 } else {
5943 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5944 features().use_img_for_multisampled_render_to_texture) {
5945 pname = GL_TEXTURE_SAMPLES_IMG;
5947 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5951 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5952 GLenum target, GLenum pname, GLint* params) {
5953 Renderbuffer* renderbuffer =
5954 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5955 if (!renderbuffer) {
5956 LOCAL_SET_GL_ERROR(
5957 GL_INVALID_OPERATION,
5958 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5959 return;
5962 EnsureRenderbufferBound();
5963 switch (pname) {
5964 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5965 *params = renderbuffer->internal_format();
5966 break;
5967 case GL_RENDERBUFFER_WIDTH:
5968 *params = renderbuffer->width();
5969 break;
5970 case GL_RENDERBUFFER_HEIGHT:
5971 *params = renderbuffer->height();
5972 break;
5973 case GL_RENDERBUFFER_SAMPLES_EXT:
5974 if (features().use_img_for_multisampled_render_to_texture) {
5975 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5976 params);
5977 } else {
5978 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5979 params);
5981 default:
5982 glGetRenderbufferParameterivEXT(target, pname, params);
5983 break;
5987 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5988 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5989 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5990 GLbitfield mask, GLenum filter) {
5991 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5993 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5994 return;
5997 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5998 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5999 BlitFramebufferHelper(
6000 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6001 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
6002 state_.enable_flags.scissor_test);
6005 void GLES2DecoderImpl::EnsureRenderbufferBound() {
6006 if (!state_.bound_renderbuffer_valid) {
6007 state_.bound_renderbuffer_valid = true;
6008 glBindRenderbufferEXT(GL_RENDERBUFFER,
6009 state_.bound_renderbuffer.get()
6010 ? state_.bound_renderbuffer->service_id()
6011 : 0);
6015 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
6016 const FeatureInfo* feature_info,
6017 GLenum target,
6018 GLsizei samples,
6019 GLenum internal_format,
6020 GLsizei width,
6021 GLsizei height) {
6022 // TODO(sievers): This could be resolved at the GL binding level, but the
6023 // binding process is currently a bit too 'brute force'.
6024 if (feature_info->gl_version_info().is_angle) {
6025 glRenderbufferStorageMultisampleANGLE(
6026 target, samples, internal_format, width, height);
6027 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
6028 glRenderbufferStorageMultisample(
6029 target, samples, internal_format, width, height);
6030 } else {
6031 glRenderbufferStorageMultisampleEXT(
6032 target, samples, internal_format, width, height);
6036 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
6037 GLint srcY0,
6038 GLint srcX1,
6039 GLint srcY1,
6040 GLint dstX0,
6041 GLint dstY0,
6042 GLint dstX1,
6043 GLint dstY1,
6044 GLbitfield mask,
6045 GLenum filter) {
6046 // TODO(sievers): This could be resolved at the GL binding level, but the
6047 // binding process is currently a bit too 'brute force'.
6048 if (feature_info_->gl_version_info().is_angle) {
6049 glBlitFramebufferANGLE(
6050 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6051 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
6052 glBlitFramebuffer(
6053 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6054 } else {
6055 glBlitFramebufferEXT(
6056 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6060 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
6061 GLsizei samples,
6062 GLenum internalformat,
6063 GLsizei width,
6064 GLsizei height) {
6065 if (samples > renderbuffer_manager()->max_samples()) {
6066 LOCAL_SET_GL_ERROR(
6067 GL_INVALID_VALUE,
6068 "glRenderbufferStorageMultisample", "samples too large");
6069 return false;
6072 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6073 height > renderbuffer_manager()->max_renderbuffer_size()) {
6074 LOCAL_SET_GL_ERROR(
6075 GL_INVALID_VALUE,
6076 "glRenderbufferStorageMultisample", "dimensions too large");
6077 return false;
6080 uint32 estimated_size = 0;
6081 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6082 width, height, samples, internalformat, &estimated_size)) {
6083 LOCAL_SET_GL_ERROR(
6084 GL_OUT_OF_MEMORY,
6085 "glRenderbufferStorageMultisample", "dimensions too large");
6086 return false;
6089 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6090 LOCAL_SET_GL_ERROR(
6091 GL_OUT_OF_MEMORY,
6092 "glRenderbufferStorageMultisample", "out of memory");
6093 return false;
6096 return true;
6099 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
6100 GLenum target, GLsizei samples, GLenum internalformat,
6101 GLsizei width, GLsizei height) {
6102 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6103 if (!renderbuffer) {
6104 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
6105 "glRenderbufferStorageMultisampleCHROMIUM",
6106 "no renderbuffer bound");
6107 return;
6110 if (!ValidateRenderbufferStorageMultisample(
6111 samples, internalformat, width, height)) {
6112 return;
6115 EnsureRenderbufferBound();
6116 GLenum impl_format =
6117 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6118 internalformat);
6119 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
6120 "glRenderbufferStorageMultisampleCHROMIUM");
6121 RenderbufferStorageMultisampleHelper(
6122 feature_info_.get(), target, samples, impl_format, width, height);
6123 GLenum error =
6124 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
6125 if (error == GL_NO_ERROR) {
6126 if (workarounds().validate_multisample_buffer_allocation) {
6127 if (!VerifyMultisampleRenderbufferIntegrity(
6128 renderbuffer->service_id(), impl_format)) {
6129 LOCAL_SET_GL_ERROR(
6130 GL_OUT_OF_MEMORY,
6131 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
6132 return;
6136 // TODO(gman): If renderbuffers tracked which framebuffers they were
6137 // attached to we could just mark those framebuffers as not complete.
6138 framebuffer_manager()->IncFramebufferStateChangeCount();
6139 renderbuffer_manager()->SetInfo(
6140 renderbuffer, samples, internalformat, width, height);
6144 // This is the handler for multisampled_render_to_texture extensions.
6145 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6146 GLenum target, GLsizei samples, GLenum internalformat,
6147 GLsizei width, GLsizei height) {
6148 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6149 if (!renderbuffer) {
6150 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
6151 "glRenderbufferStorageMultisampleEXT",
6152 "no renderbuffer bound");
6153 return;
6156 if (!ValidateRenderbufferStorageMultisample(
6157 samples, internalformat, width, height)) {
6158 return;
6161 EnsureRenderbufferBound();
6162 GLenum impl_format =
6163 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6164 internalformat);
6165 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6166 if (features().use_img_for_multisampled_render_to_texture) {
6167 glRenderbufferStorageMultisampleIMG(
6168 target, samples, impl_format, width, height);
6169 } else {
6170 glRenderbufferStorageMultisampleEXT(
6171 target, samples, impl_format, width, height);
6173 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6174 if (error == GL_NO_ERROR) {
6175 // TODO(gman): If renderbuffers tracked which framebuffers they were
6176 // attached to we could just mark those framebuffers as not complete.
6177 framebuffer_manager()->IncFramebufferStateChangeCount();
6178 renderbuffer_manager()->SetInfo(
6179 renderbuffer, samples, internalformat, width, height);
6183 // This function validates the allocation of a multisampled renderbuffer
6184 // by clearing it to a key color, blitting the contents to a texture, and
6185 // reading back the color to ensure it matches the key.
6186 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6187 GLuint renderbuffer, GLenum format) {
6189 // Only validate color buffers.
6190 // These formats have been selected because they are very common or are known
6191 // to be used by the WebGL backbuffer. If problems are observed with other
6192 // color formats they can be added here.
6193 switch (format) {
6194 case GL_RGB:
6195 case GL_RGB8:
6196 case GL_RGBA:
6197 case GL_RGBA8:
6198 break;
6199 default:
6200 return true;
6203 GLint draw_framebuffer, read_framebuffer;
6205 // Cache framebuffer and texture bindings.
6206 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
6207 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
6209 if (!validation_texture_) {
6210 GLint bound_texture;
6211 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
6213 // Create additional resources needed for the verification.
6214 glGenTextures(1, &validation_texture_);
6215 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
6216 glGenFramebuffersEXT(1, &validation_fbo_);
6218 // Texture only needs to be 1x1.
6219 glBindTexture(GL_TEXTURE_2D, validation_texture_);
6220 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6221 // multisample will fail if the color format of the source and destination
6222 // do not match. Here, we assume that the source is GL_RGBA, and make the
6223 // destination GL_RGBA. http://crbug.com/484203
6224 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
6225 GL_UNSIGNED_BYTE, NULL);
6227 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6228 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6229 GL_TEXTURE_2D, validation_texture_, 0);
6231 glBindTexture(GL_TEXTURE_2D, bound_texture);
6234 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6235 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6236 GL_RENDERBUFFER, renderbuffer);
6238 // Cache current state and reset it to the values we require.
6239 GLboolean scissor_enabled = false;
6240 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
6241 if (scissor_enabled)
6242 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
6244 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
6245 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
6246 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6248 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
6249 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
6250 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
6252 // Clear the buffer to the desired key color.
6253 glClear(GL_COLOR_BUFFER_BIT);
6255 // Blit from the multisample buffer to a standard texture.
6256 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
6257 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
6259 BlitFramebufferHelper(
6260 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
6262 // Read a pixel from the buffer.
6263 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6265 unsigned char pixel[3] = {0, 0, 0};
6266 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
6268 // Detach the renderbuffer.
6269 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6270 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6271 GL_RENDERBUFFER, 0);
6273 // Restore cached state.
6274 if (scissor_enabled)
6275 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
6277 state_.SetDeviceColorMask(
6278 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
6279 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
6280 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
6281 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
6283 // Return true if the pixel matched the desired key color.
6284 return (pixel[0] == 0xFF &&
6285 pixel[1] == 0x00 &&
6286 pixel[2] == 0xFF);
6289 void GLES2DecoderImpl::DoRenderbufferStorage(
6290 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
6291 Renderbuffer* renderbuffer =
6292 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6293 if (!renderbuffer) {
6294 LOCAL_SET_GL_ERROR(
6295 GL_INVALID_OPERATION,
6296 "glRenderbufferStorage", "no renderbuffer bound");
6297 return;
6300 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6301 height > renderbuffer_manager()->max_renderbuffer_size()) {
6302 LOCAL_SET_GL_ERROR(
6303 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
6304 return;
6307 uint32 estimated_size = 0;
6308 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6309 width, height, 1, internalformat, &estimated_size)) {
6310 LOCAL_SET_GL_ERROR(
6311 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
6312 return;
6315 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6316 LOCAL_SET_GL_ERROR(
6317 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
6318 return;
6321 EnsureRenderbufferBound();
6322 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6323 glRenderbufferStorageEXT(
6324 target,
6325 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6326 internalformat),
6327 width,
6328 height);
6329 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6330 if (error == GL_NO_ERROR) {
6331 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6332 // we could just mark those framebuffers as not complete.
6333 framebuffer_manager()->IncFramebufferStateChangeCount();
6334 renderbuffer_manager()->SetInfo(
6335 renderbuffer, 1, internalformat, width, height);
6339 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
6340 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6341 SCOPED_UMA_HISTOGRAM_TIMER("GPU.DoLinkProgramTime");
6342 Program* program = GetProgramInfoNotShader(
6343 program_id, "glLinkProgram");
6344 if (!program) {
6345 return;
6348 LogClientServiceForInfo(program, program_id, "glLinkProgram");
6349 if (program->Link(shader_manager(),
6350 workarounds().count_all_in_varyings_packing ?
6351 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
6352 shader_cache_callback_)) {
6353 if (program == state_.current_program.get()) {
6354 if (workarounds().use_current_program_after_successful_link)
6355 glUseProgram(program->service_id());
6356 if (workarounds().clear_uniforms_before_first_program_use)
6357 program_manager()->ClearUniforms(program);
6361 // LinkProgram can be very slow. Exit command processing to allow for
6362 // context preemption and GPU watchdog checks.
6363 ExitCommandProcessingEarly();
6366 void GLES2DecoderImpl::DoReadBuffer(GLenum src) {
6367 switch (src) {
6368 case GL_NONE:
6369 case GL_BACK:
6370 break;
6371 default:
6373 GLenum upper_limit = static_cast<GLenum>(
6374 group_->max_color_attachments() + GL_COLOR_ATTACHMENT0);
6375 if (src < GL_COLOR_ATTACHMENT0 || src >= upper_limit) {
6376 LOCAL_SET_GL_ERROR(
6377 GL_INVALID_ENUM, "glReadBuffer", "invalid enum for src");
6378 return;
6381 break;
6384 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
6385 if (framebuffer) {
6386 if (src == GL_BACK) {
6387 LOCAL_SET_GL_ERROR(
6388 GL_INVALID_ENUM, "glReadBuffer",
6389 "invalid src for a named framebuffer");
6390 return;
6392 framebuffer->set_read_buffer(src);
6393 } else {
6394 if (src != GL_NONE && src != GL_BACK) {
6395 LOCAL_SET_GL_ERROR(
6396 GL_INVALID_ENUM, "glReadBuffer",
6397 "invalid src for the default framebuffer");
6398 return;
6400 back_buffer_read_buffer_ = src;
6401 if (GetBackbufferServiceId() && src == GL_BACK)
6402 src = GL_COLOR_ATTACHMENT0;
6404 glReadBuffer(src);
6407 void GLES2DecoderImpl::DoSamplerParameterfv(
6408 GLuint sampler, GLenum pname, const GLfloat* params) {
6409 DCHECK(params);
6410 glSamplerParameterf(sampler, pname, params[0]);
6413 void GLES2DecoderImpl::DoSamplerParameteriv(
6414 GLuint sampler, GLenum pname, const GLint* params) {
6415 DCHECK(params);
6416 glSamplerParameteri(sampler, pname, params[0]);
6419 void GLES2DecoderImpl::DoTexParameterf(
6420 GLenum target, GLenum pname, GLfloat param) {
6421 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6422 &state_, target);
6423 if (!texture) {
6424 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
6425 return;
6428 texture_manager()->SetParameterf(
6429 "glTexParameterf", GetErrorState(), texture, pname, param);
6432 void GLES2DecoderImpl::DoTexParameteri(
6433 GLenum target, GLenum pname, GLint param) {
6434 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6435 &state_, target);
6436 if (!texture) {
6437 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
6438 return;
6441 texture_manager()->SetParameteri(
6442 "glTexParameteri", GetErrorState(), texture, pname, param);
6445 void GLES2DecoderImpl::DoTexParameterfv(
6446 GLenum target, GLenum pname, const GLfloat* params) {
6447 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6448 &state_, target);
6449 if (!texture) {
6450 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
6451 return;
6454 texture_manager()->SetParameterf(
6455 "glTexParameterfv", GetErrorState(), texture, pname, *params);
6458 void GLES2DecoderImpl::DoTexParameteriv(
6459 GLenum target, GLenum pname, const GLint* params) {
6460 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6461 &state_, target);
6462 if (!texture) {
6463 LOCAL_SET_GL_ERROR(
6464 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
6465 return;
6468 texture_manager()->SetParameteri(
6469 "glTexParameteriv", GetErrorState(), texture, pname, *params);
6472 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name) {
6473 if (!state_.bound_valuebuffer.get()) {
6474 // There is no valuebuffer bound
6475 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6476 "no valuebuffer in use");
6477 return false;
6479 return true;
6482 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6483 GLenum subscription,
6484 const char* function_name) {
6485 if (!CheckCurrentValuebuffer(function_name)) {
6486 return false;
6488 if (!state_.bound_valuebuffer.get()->IsSubscribed(subscription)) {
6489 // The valuebuffer is not subscribed to the target
6490 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6491 "valuebuffer is not subscribed");
6492 return false;
6494 return true;
6497 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location,
6498 GLenum subscription,
6499 const char* function_name) {
6500 if (!CheckCurrentProgramForUniform(location, function_name)) {
6501 return false;
6503 GLint real_location = -1;
6504 GLint array_index = -1;
6505 const Program::UniformInfo* info =
6506 state_.current_program->GetUniformInfoByFakeLocation(
6507 location, &real_location, &array_index);
6508 if (!info) {
6509 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "unknown location");
6510 return false;
6512 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription) &
6513 info->accepts_api_type) == 0) {
6514 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6515 "wrong type for subscription");
6516 return false;
6518 return true;
6521 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
6522 if (!state_.current_program.get()) {
6523 // The program does not exist.
6524 LOCAL_SET_GL_ERROR(
6525 GL_INVALID_OPERATION, function_name, "no program in use");
6526 return false;
6528 if (!state_.current_program->InUse()) {
6529 LOCAL_SET_GL_ERROR(
6530 GL_INVALID_OPERATION, function_name, "program not linked");
6531 return false;
6533 return true;
6536 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6537 GLint location, const char* function_name) {
6538 if (!CheckCurrentProgram(function_name)) {
6539 return false;
6541 return location != -1;
6544 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6545 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
6546 if (!framebuffer)
6547 return false;
6548 const Framebuffer::Attachment* attachment =
6549 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
6550 if (!attachment)
6551 return false;
6553 DCHECK(state_.current_program.get());
6554 const Program::SamplerIndices& sampler_indices =
6555 state_.current_program->sampler_indices();
6556 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6557 const Program::UniformInfo* uniform_info =
6558 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6559 DCHECK(uniform_info);
6560 if (uniform_info->type != GL_SAMPLER_2D)
6561 continue;
6562 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6563 GLuint texture_unit_index = uniform_info->texture_units[jj];
6564 if (texture_unit_index >= state_.texture_units.size())
6565 continue;
6566 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6567 TextureRef* texture_ref =
6568 texture_unit.GetInfoForSamplerType(GL_SAMPLER_2D).get();
6569 if (attachment->IsTexture(texture_ref))
6570 return true;
6573 return false;
6576 bool GLES2DecoderImpl::CheckUniformForApiType(
6577 const Program::UniformInfo* info,
6578 const char* function_name,
6579 Program::UniformApiType api_type) {
6580 DCHECK(info);
6581 if ((api_type & info->accepts_api_type) == 0) {
6582 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6583 "wrong uniform function for type");
6584 return false;
6586 return true;
6589 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6590 GLint fake_location,
6591 const char* function_name,
6592 Program::UniformApiType api_type,
6593 GLint* real_location,
6594 GLenum* type,
6595 GLsizei* count) {
6596 DCHECK(type);
6597 DCHECK(count);
6598 DCHECK(real_location);
6600 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
6601 return false;
6603 GLint array_index = -1;
6604 const Program::UniformInfo* info =
6605 state_.current_program->GetUniformInfoByFakeLocation(
6606 fake_location, real_location, &array_index);
6607 if (!info) {
6608 LOCAL_SET_GL_ERROR(
6609 GL_INVALID_OPERATION, function_name, "unknown location");
6610 return false;
6612 if (!CheckUniformForApiType(info, function_name, api_type)) {
6613 return false;
6615 if (*count > 1 && !info->is_array) {
6616 LOCAL_SET_GL_ERROR(
6617 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
6618 return false;
6620 *count = std::min(info->size - array_index, *count);
6621 if (*count <= 0) {
6622 return false;
6624 *type = info->type;
6625 return true;
6628 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
6629 GLenum type = 0;
6630 GLsizei count = 1;
6631 GLint real_location = -1;
6632 if (!PrepForSetUniformByLocation(fake_location,
6633 "glUniform1i",
6634 Program::kUniform1i,
6635 &real_location,
6636 &type,
6637 &count)) {
6638 return;
6640 if (!state_.current_program->SetSamplers(
6641 state_.texture_units.size(), fake_location, 1, &v0)) {
6642 LOCAL_SET_GL_ERROR(
6643 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
6644 return;
6646 glUniform1i(real_location, v0);
6649 void GLES2DecoderImpl::DoUniform1iv(
6650 GLint fake_location, GLsizei count, const GLint *value) {
6651 GLenum type = 0;
6652 GLint real_location = -1;
6653 if (!PrepForSetUniformByLocation(fake_location,
6654 "glUniform1iv",
6655 Program::kUniform1i,
6656 &real_location,
6657 &type,
6658 &count)) {
6659 return;
6661 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
6662 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
6663 if (!state_.current_program->SetSamplers(
6664 state_.texture_units.size(), fake_location, count, value)) {
6665 LOCAL_SET_GL_ERROR(
6666 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
6667 return;
6670 glUniform1iv(real_location, count, value);
6673 void GLES2DecoderImpl::DoUniform1fv(
6674 GLint fake_location, GLsizei count, const GLfloat* value) {
6675 GLenum type = 0;
6676 GLint real_location = -1;
6677 if (!PrepForSetUniformByLocation(fake_location,
6678 "glUniform1fv",
6679 Program::kUniform1f,
6680 &real_location,
6681 &type,
6682 &count)) {
6683 return;
6685 if (type == GL_BOOL) {
6686 scoped_ptr<GLint[]> temp(new GLint[count]);
6687 for (GLsizei ii = 0; ii < count; ++ii) {
6688 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6690 DoUniform1iv(real_location, count, temp.get());
6691 } else {
6692 glUniform1fv(real_location, count, value);
6696 void GLES2DecoderImpl::DoUniform2fv(
6697 GLint fake_location, GLsizei count, const GLfloat* value) {
6698 GLenum type = 0;
6699 GLint real_location = -1;
6700 if (!PrepForSetUniformByLocation(fake_location,
6701 "glUniform2fv",
6702 Program::kUniform2f,
6703 &real_location,
6704 &type,
6705 &count)) {
6706 return;
6708 if (type == GL_BOOL_VEC2) {
6709 GLsizei num_values = count * 2;
6710 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6711 for (GLsizei ii = 0; ii < num_values; ++ii) {
6712 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6714 glUniform2iv(real_location, count, temp.get());
6715 } else {
6716 glUniform2fv(real_location, count, value);
6720 void GLES2DecoderImpl::DoUniform3fv(
6721 GLint fake_location, GLsizei count, const GLfloat* value) {
6722 GLenum type = 0;
6723 GLint real_location = -1;
6724 if (!PrepForSetUniformByLocation(fake_location,
6725 "glUniform3fv",
6726 Program::kUniform3f,
6727 &real_location,
6728 &type,
6729 &count)) {
6730 return;
6732 if (type == GL_BOOL_VEC3) {
6733 GLsizei num_values = count * 3;
6734 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6735 for (GLsizei ii = 0; ii < num_values; ++ii) {
6736 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6738 glUniform3iv(real_location, count, temp.get());
6739 } else {
6740 glUniform3fv(real_location, count, value);
6744 void GLES2DecoderImpl::DoUniform4fv(
6745 GLint fake_location, GLsizei count, const GLfloat* value) {
6746 GLenum type = 0;
6747 GLint real_location = -1;
6748 if (!PrepForSetUniformByLocation(fake_location,
6749 "glUniform4fv",
6750 Program::kUniform4f,
6751 &real_location,
6752 &type,
6753 &count)) {
6754 return;
6756 if (type == GL_BOOL_VEC4) {
6757 GLsizei num_values = count * 4;
6758 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6759 for (GLsizei ii = 0; ii < num_values; ++ii) {
6760 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6762 glUniform4iv(real_location, count, temp.get());
6763 } else {
6764 glUniform4fv(real_location, count, value);
6768 void GLES2DecoderImpl::DoUniform2iv(
6769 GLint fake_location, GLsizei count, const GLint* value) {
6770 GLenum type = 0;
6771 GLint real_location = -1;
6772 if (!PrepForSetUniformByLocation(fake_location,
6773 "glUniform2iv",
6774 Program::kUniform2i,
6775 &real_location,
6776 &type,
6777 &count)) {
6778 return;
6780 glUniform2iv(real_location, count, value);
6783 void GLES2DecoderImpl::DoUniform3iv(
6784 GLint fake_location, GLsizei count, const GLint* value) {
6785 GLenum type = 0;
6786 GLint real_location = -1;
6787 if (!PrepForSetUniformByLocation(fake_location,
6788 "glUniform3iv",
6789 Program::kUniform3i,
6790 &real_location,
6791 &type,
6792 &count)) {
6793 return;
6795 glUniform3iv(real_location, count, value);
6798 void GLES2DecoderImpl::DoUniform4iv(
6799 GLint fake_location, GLsizei count, const GLint* value) {
6800 GLenum type = 0;
6801 GLint real_location = -1;
6802 if (!PrepForSetUniformByLocation(fake_location,
6803 "glUniform4iv",
6804 Program::kUniform4i,
6805 &real_location,
6806 &type,
6807 &count)) {
6808 return;
6810 glUniform4iv(real_location, count, value);
6813 void GLES2DecoderImpl::DoUniformMatrix2fv(
6814 GLint fake_location, GLsizei count, GLboolean transpose,
6815 const GLfloat* value) {
6816 GLenum type = 0;
6817 GLint real_location = -1;
6818 if (!PrepForSetUniformByLocation(fake_location,
6819 "glUniformMatrix2fv",
6820 Program::kUniformMatrix2f,
6821 &real_location,
6822 &type,
6823 &count)) {
6824 return;
6826 glUniformMatrix2fv(real_location, count, transpose, value);
6829 void GLES2DecoderImpl::DoUniformMatrix3fv(
6830 GLint fake_location, GLsizei count, GLboolean transpose,
6831 const GLfloat* value) {
6832 GLenum type = 0;
6833 GLint real_location = -1;
6834 if (!PrepForSetUniformByLocation(fake_location,
6835 "glUniformMatrix3fv",
6836 Program::kUniformMatrix3f,
6837 &real_location,
6838 &type,
6839 &count)) {
6840 return;
6842 glUniformMatrix3fv(real_location, count, transpose, value);
6845 void GLES2DecoderImpl::DoUniformMatrix4fv(
6846 GLint fake_location, GLsizei count, GLboolean transpose,
6847 const GLfloat* value) {
6848 GLenum type = 0;
6849 GLint real_location = -1;
6850 if (!PrepForSetUniformByLocation(fake_location,
6851 "glUniformMatrix4fv",
6852 Program::kUniformMatrix4f,
6853 &real_location,
6854 &type,
6855 &count)) {
6856 return;
6858 glUniformMatrix4fv(real_location, count, transpose, value);
6861 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
6862 GLuint service_id = 0;
6863 Program* program = NULL;
6864 if (program_id) {
6865 program = GetProgramInfoNotShader(program_id, "glUseProgram");
6866 if (!program) {
6867 return;
6869 if (!program->IsValid()) {
6870 // Program was not linked successfully. (ie, glLinkProgram)
6871 LOCAL_SET_GL_ERROR(
6872 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
6873 return;
6875 service_id = program->service_id();
6877 if (state_.current_program.get()) {
6878 program_manager()->UnuseProgram(shader_manager(),
6879 state_.current_program.get());
6881 state_.current_program = program;
6882 LogClientServiceMapping("glUseProgram", program_id, service_id);
6883 glUseProgram(service_id);
6884 if (state_.current_program.get()) {
6885 program_manager()->UseProgram(state_.current_program.get());
6886 if (workarounds().clear_uniforms_before_first_program_use)
6887 program_manager()->ClearUniforms(program);
6891 void GLES2DecoderImpl::RenderWarning(
6892 const char* filename, int line, const std::string& msg) {
6893 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6896 void GLES2DecoderImpl::PerformanceWarning(
6897 const char* filename, int line, const std::string& msg) {
6898 logger_.LogMessage(filename, line,
6899 std::string("PERFORMANCE WARNING: ") + msg);
6902 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6903 Texture* texture, GLenum textarget) {
6904 // Image is already in use if texture is attached to a framebuffer.
6905 if (texture && !texture->IsAttachedToFramebuffer()) {
6906 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6907 if (image) {
6908 ScopedGLErrorSuppressor suppressor(
6909 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6910 GetErrorState());
6911 glBindTexture(textarget, texture->service_id());
6912 image->WillUseTexImage();
6913 RestoreCurrentTextureBindings(&state_, textarget);
6918 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6919 Texture* texture, GLenum textarget) {
6920 // Image is still in use if texture is attached to a framebuffer.
6921 if (texture && !texture->IsAttachedToFramebuffer()) {
6922 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6923 if (image) {
6924 ScopedGLErrorSuppressor suppressor(
6925 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6926 GetErrorState());
6927 glBindTexture(textarget, texture->service_id());
6928 image->DidUseTexImage();
6929 RestoreCurrentTextureBindings(&state_, textarget);
6934 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6935 DCHECK(state_.current_program.get());
6936 if (!texture_manager()->HaveUnrenderableTextures() &&
6937 !texture_manager()->HaveImages()) {
6938 return true;
6941 bool textures_set = false;
6942 const Program::SamplerIndices& sampler_indices =
6943 state_.current_program->sampler_indices();
6944 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6945 const Program::UniformInfo* uniform_info =
6946 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6947 DCHECK(uniform_info);
6948 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6949 GLuint texture_unit_index = uniform_info->texture_units[jj];
6950 if (texture_unit_index < state_.texture_units.size()) {
6951 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6952 TextureRef* texture_ref =
6953 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6954 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6955 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6956 textures_set = true;
6957 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6958 glBindTexture(
6959 textarget,
6960 texture_manager()->black_texture_id(uniform_info->type));
6961 if (!texture_ref) {
6962 LOCAL_RENDER_WARNING(
6963 std::string("there is no texture bound to the unit ") +
6964 base::IntToString(texture_unit_index));
6965 } else {
6966 LOCAL_RENDER_WARNING(
6967 std::string("texture bound to texture unit ") +
6968 base::IntToString(texture_unit_index) +
6969 " is not renderable. It maybe non-power-of-2 and have"
6970 " incompatible texture filtering.");
6972 continue;
6975 if (textarget != GL_TEXTURE_CUBE_MAP) {
6976 Texture* texture = texture_ref->texture();
6977 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6978 if (image && !texture->IsAttachedToFramebuffer()) {
6979 ScopedGLErrorSuppressor suppressor(
6980 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6981 textures_set = true;
6982 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6983 image->WillUseTexImage();
6984 continue;
6988 // else: should this be an error?
6991 return !textures_set;
6994 void GLES2DecoderImpl::RestoreStateForTextures() {
6995 DCHECK(state_.current_program.get());
6996 const Program::SamplerIndices& sampler_indices =
6997 state_.current_program->sampler_indices();
6998 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6999 const Program::UniformInfo* uniform_info =
7000 state_.current_program->GetUniformInfo(sampler_indices[ii]);
7001 DCHECK(uniform_info);
7002 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
7003 GLuint texture_unit_index = uniform_info->texture_units[jj];
7004 if (texture_unit_index < state_.texture_units.size()) {
7005 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
7006 TextureRef* texture_ref =
7007 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
7008 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
7009 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
7010 // Get the texture_ref info that was previously bound here.
7011 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
7012 ? texture_unit.bound_texture_2d.get()
7013 : texture_unit.bound_texture_cube_map.get();
7014 glBindTexture(texture_unit.bind_target,
7015 texture_ref ? texture_ref->service_id() : 0);
7016 continue;
7019 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
7020 Texture* texture = texture_ref->texture();
7021 gfx::GLImage* image =
7022 texture->GetLevelImage(texture_unit.bind_target, 0);
7023 if (image && !texture->IsAttachedToFramebuffer()) {
7024 ScopedGLErrorSuppressor suppressor(
7025 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
7026 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
7027 image->DidUseTexImage();
7028 continue;
7034 // Set the active texture back to whatever the user had it as.
7035 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
7038 bool GLES2DecoderImpl::ClearUnclearedTextures() {
7039 // Only check if there are some uncleared textures.
7040 if (!texture_manager()->HaveUnsafeTextures()) {
7041 return true;
7044 // 1: Check all textures we are about to render with.
7045 if (state_.current_program.get()) {
7046 const Program::SamplerIndices& sampler_indices =
7047 state_.current_program->sampler_indices();
7048 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
7049 const Program::UniformInfo* uniform_info =
7050 state_.current_program->GetUniformInfo(sampler_indices[ii]);
7051 DCHECK(uniform_info);
7052 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
7053 GLuint texture_unit_index = uniform_info->texture_units[jj];
7054 if (texture_unit_index < state_.texture_units.size()) {
7055 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
7056 TextureRef* texture_ref =
7057 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
7058 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
7059 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
7060 return false;
7067 return true;
7070 bool GLES2DecoderImpl::IsDrawValid(
7071 const char* function_name, GLuint max_vertex_accessed, bool instanced,
7072 GLsizei primcount) {
7073 DCHECK(instanced || primcount == 1);
7075 // NOTE: We specifically do not check current_program->IsValid() because
7076 // it could never be invalid since glUseProgram would have failed. While
7077 // glLinkProgram could later mark the program as invalid the previous
7078 // valid program will still function if it is still the current program.
7079 if (!state_.current_program.get()) {
7080 // The program does not exist.
7081 // But GL says no ERROR.
7082 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
7083 return false;
7086 if (CheckDrawingFeedbackLoops()) {
7087 LOCAL_SET_GL_ERROR(
7088 GL_INVALID_OPERATION, function_name,
7089 "Source and destination textures of the draw are the same.");
7090 return false;
7093 return state_.vertex_attrib_manager
7094 ->ValidateBindings(function_name,
7095 this,
7096 feature_info_.get(),
7097 state_.current_program.get(),
7098 max_vertex_accessed,
7099 instanced,
7100 primcount);
7103 bool GLES2DecoderImpl::SimulateAttrib0(
7104 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
7105 DCHECK(simulated);
7106 *simulated = false;
7108 if (feature_info_->gl_version_info().BehavesLikeGLES())
7109 return true;
7111 const VertexAttrib* attrib =
7112 state_.vertex_attrib_manager->GetVertexAttrib(0);
7113 // If it's enabled or it's not used then we don't need to do anything.
7114 bool attrib_0_used =
7115 state_.current_program->GetAttribInfoByLocation(0) != NULL;
7116 if (attrib->enabled() && attrib_0_used) {
7117 return true;
7120 // Make a buffer with a single repeated vec4 value enough to
7121 // simulate the constant value that is supposed to be here.
7122 // This is required to emulate GLES2 on GL.
7123 GLuint num_vertices = max_vertex_accessed + 1;
7124 uint32 size_needed = 0;
7126 if (num_vertices == 0 ||
7127 !SafeMultiplyUint32(num_vertices, sizeof(Vec4f), &size_needed) ||
7128 size_needed > 0x7FFFFFFFU) {
7129 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7130 return false;
7133 LOCAL_PERFORMANCE_WARNING(
7134 "Attribute 0 is disabled. This has signficant performance penalty");
7136 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
7137 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
7139 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
7140 if (new_buffer) {
7141 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
7142 GLenum error = glGetError();
7143 if (error != GL_NO_ERROR) {
7144 LOCAL_SET_GL_ERROR(
7145 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7146 return false;
7150 const Vec4& value = state_.attrib_values[0];
7151 if (new_buffer ||
7152 (attrib_0_used &&
7153 (!attrib_0_buffer_matches_value_ || !value.Equal(attrib_0_value_)))){
7154 // TODO(zmo): This is not 100% correct because we might lose data when
7155 // casting to float type, but it is a corner case and once we migrate to
7156 // core profiles on desktop GL, it is no longer relevant.
7157 Vec4f fvalue(value);
7158 std::vector<Vec4f> temp(num_vertices, fvalue);
7159 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
7160 attrib_0_buffer_matches_value_ = true;
7161 attrib_0_value_ = value;
7162 attrib_0_size_ = size_needed;
7165 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
7167 if (attrib->divisor())
7168 glVertexAttribDivisorANGLE(0, 0);
7170 *simulated = true;
7171 return true;
7174 void GLES2DecoderImpl::RestoreStateForAttrib(
7175 GLuint attrib_index, bool restore_array_binding) {
7176 const VertexAttrib* attrib =
7177 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
7178 if (restore_array_binding) {
7179 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
7180 Buffer* buffer = attrib->buffer();
7181 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
7182 glVertexAttribPointer(
7183 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
7184 attrib->gl_stride(), ptr);
7186 if (attrib->divisor())
7187 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
7188 glBindBuffer(
7189 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
7190 state_.bound_array_buffer->service_id() : 0);
7192 // Never touch vertex attribute 0's state (in particular, never
7193 // disable it) when running on desktop GL because it will never be
7194 // re-enabled.
7195 if (attrib_index != 0 ||
7196 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
7197 if (attrib->enabled()) {
7198 glEnableVertexAttribArray(attrib_index);
7199 } else {
7200 glDisableVertexAttribArray(attrib_index);
7205 bool GLES2DecoderImpl::SimulateFixedAttribs(
7206 const char* function_name,
7207 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
7208 DCHECK(simulated);
7209 *simulated = false;
7210 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
7211 return true;
7213 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
7214 return true;
7217 LOCAL_PERFORMANCE_WARNING(
7218 "GL_FIXED attributes have a signficant performance penalty");
7220 // NOTE: we could be smart and try to check if a buffer is used
7221 // twice in 2 different attribs, find the overlapping parts and therefore
7222 // duplicate the minimum amount of data but this whole code path is not meant
7223 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7224 // tests so we just add to the buffer attrib used.
7226 GLuint elements_needed = 0;
7227 const VertexAttribManager::VertexAttribList& enabled_attribs =
7228 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
7229 for (VertexAttribManager::VertexAttribList::const_iterator it =
7230 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7231 const VertexAttrib* attrib = *it;
7232 const Program::VertexAttrib* attrib_info =
7233 state_.current_program->GetAttribInfoByLocation(attrib->index());
7234 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7235 max_vertex_accessed);
7236 GLuint num_vertices = max_accessed + 1;
7237 if (num_vertices == 0) {
7238 LOCAL_SET_GL_ERROR(
7239 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7240 return false;
7242 if (attrib_info &&
7243 attrib->CanAccess(max_accessed) &&
7244 attrib->type() == GL_FIXED) {
7245 uint32 elements_used = 0;
7246 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
7247 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
7248 LOCAL_SET_GL_ERROR(
7249 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7250 return false;
7255 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
7256 uint32 size_needed = 0;
7257 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
7258 size_needed > 0x7FFFFFFFU) {
7259 LOCAL_SET_GL_ERROR(
7260 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7261 return false;
7264 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
7266 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
7267 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
7268 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
7269 GLenum error = glGetError();
7270 if (error != GL_NO_ERROR) {
7271 LOCAL_SET_GL_ERROR(
7272 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7273 return false;
7277 // Copy the elements and convert to float
7278 GLintptr offset = 0;
7279 for (VertexAttribManager::VertexAttribList::const_iterator it =
7280 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7281 const VertexAttrib* attrib = *it;
7282 const Program::VertexAttrib* attrib_info =
7283 state_.current_program->GetAttribInfoByLocation(attrib->index());
7284 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7285 max_vertex_accessed);
7286 GLuint num_vertices = max_accessed + 1;
7287 if (num_vertices == 0) {
7288 LOCAL_SET_GL_ERROR(
7289 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7290 return false;
7292 if (attrib_info &&
7293 attrib->CanAccess(max_accessed) &&
7294 attrib->type() == GL_FIXED) {
7295 int num_elements = attrib->size() * num_vertices;
7296 const int src_size = num_elements * sizeof(int32);
7297 const int dst_size = num_elements * sizeof(float);
7298 scoped_ptr<float[]> data(new float[num_elements]);
7299 const int32* src = reinterpret_cast<const int32 *>(
7300 attrib->buffer()->GetRange(attrib->offset(), src_size));
7301 const int32* end = src + num_elements;
7302 float* dst = data.get();
7303 while (src != end) {
7304 *dst++ = static_cast<float>(*src++) / 65536.0f;
7306 glBufferSubData(GL_ARRAY_BUFFER, offset, dst_size, data.get());
7307 glVertexAttribPointer(
7308 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
7309 reinterpret_cast<GLvoid*>(offset));
7310 offset += dst_size;
7313 *simulated = true;
7314 return true;
7317 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7318 // There's no need to call glVertexAttribPointer because we shadow all the
7319 // settings and passing GL_FIXED to it will not work.
7320 glBindBuffer(
7321 GL_ARRAY_BUFFER,
7322 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
7323 : 0);
7326 error::Error GLES2DecoderImpl::DoDrawArrays(
7327 const char* function_name,
7328 bool instanced,
7329 GLenum mode,
7330 GLint first,
7331 GLsizei count,
7332 GLsizei primcount) {
7333 error::Error error = WillAccessBoundFramebufferForDraw();
7334 if (error != error::kNoError)
7335 return error;
7336 if (!validators_->draw_mode.IsValid(mode)) {
7337 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7338 return error::kNoError;
7340 if (count < 0) {
7341 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7342 return error::kNoError;
7344 if (primcount < 0) {
7345 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7346 return error::kNoError;
7348 if (!CheckBoundFramebuffersValid(function_name)) {
7349 return error::kNoError;
7351 // We have to check this here because the prototype for glDrawArrays
7352 // is GLint not GLsizei.
7353 if (first < 0) {
7354 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
7355 return error::kNoError;
7358 if (count == 0 || primcount == 0) {
7359 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7360 return error::kNoError;
7363 GLuint max_vertex_accessed = first + count - 1;
7364 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7365 if (!ClearUnclearedTextures()) {
7366 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7367 return error::kNoError;
7369 bool simulated_attrib_0 = false;
7370 if (!SimulateAttrib0(
7371 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7372 return error::kNoError;
7374 bool simulated_fixed_attribs = false;
7375 if (SimulateFixedAttribs(
7376 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7377 primcount)) {
7378 bool textures_set = !PrepareTexturesForRender();
7379 ApplyDirtyState();
7380 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7381 if (!instanced) {
7382 glDrawArrays(mode, first, count);
7383 } else {
7384 glDrawArraysInstancedANGLE(mode, first, count, primcount);
7386 if (textures_set) {
7387 RestoreStateForTextures();
7389 if (simulated_fixed_attribs) {
7390 RestoreStateForSimulatedFixedAttribs();
7393 if (simulated_attrib_0) {
7394 // We don't have to restore attrib 0 generic data at the end of this
7395 // function even if it is simulated. This is because we will simulate
7396 // it in each draw call, and attrib 0 generic data queries use cached
7397 // values instead of passing down to the underlying driver.
7398 RestoreStateForAttrib(0, false);
7401 return error::kNoError;
7404 error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size,
7405 const void* cmd_data) {
7406 // TODO(zmo): crbug.com/481184
7407 // On Desktop GL with versions lower than 4.3, we need to emulate
7408 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7409 const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data);
7410 return DoDrawArrays("glDrawArrays",
7411 false,
7412 static_cast<GLenum>(c.mode),
7413 static_cast<GLint>(c.first),
7414 static_cast<GLsizei>(c.count),
7418 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7419 uint32 immediate_data_size,
7420 const void* cmd_data) {
7421 const gles2::cmds::DrawArraysInstancedANGLE& c =
7422 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE*>(cmd_data);
7423 if (!features().angle_instanced_arrays) {
7424 LOCAL_SET_GL_ERROR(
7425 GL_INVALID_OPERATION,
7426 "glDrawArraysInstancedANGLE", "function not available");
7427 return error::kNoError;
7429 return DoDrawArrays("glDrawArraysIntancedANGLE",
7430 true,
7431 static_cast<GLenum>(c.mode),
7432 static_cast<GLint>(c.first),
7433 static_cast<GLsizei>(c.count),
7434 static_cast<GLsizei>(c.primcount));
7437 error::Error GLES2DecoderImpl::DoDrawElements(
7438 const char* function_name,
7439 bool instanced,
7440 GLenum mode,
7441 GLsizei count,
7442 GLenum type,
7443 int32 offset,
7444 GLsizei primcount) {
7445 error::Error error = WillAccessBoundFramebufferForDraw();
7446 if (error != error::kNoError)
7447 return error;
7448 if (!state_.vertex_attrib_manager->element_array_buffer()) {
7449 LOCAL_SET_GL_ERROR(
7450 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
7451 return error::kNoError;
7454 if (count < 0) {
7455 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7456 return error::kNoError;
7458 if (offset < 0) {
7459 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
7460 return error::kNoError;
7462 if (!validators_->draw_mode.IsValid(mode)) {
7463 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7464 return error::kNoError;
7466 if (!validators_->index_type.IsValid(type)) {
7467 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
7468 return error::kNoError;
7470 if (primcount < 0) {
7471 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7472 return error::kNoError;
7475 if (!CheckBoundFramebuffersValid(function_name)) {
7476 return error::kNoError;
7479 if (count == 0 || primcount == 0) {
7480 return error::kNoError;
7483 GLuint max_vertex_accessed;
7484 Buffer* element_array_buffer =
7485 state_.vertex_attrib_manager->element_array_buffer();
7487 if (!element_array_buffer->GetMaxValueForRange(
7488 offset, count, type, &max_vertex_accessed)) {
7489 LOCAL_SET_GL_ERROR(
7490 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
7491 return error::kNoError;
7494 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7495 if (!ClearUnclearedTextures()) {
7496 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7497 return error::kNoError;
7499 bool simulated_attrib_0 = false;
7500 if (!SimulateAttrib0(
7501 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7502 return error::kNoError;
7504 bool simulated_fixed_attribs = false;
7505 if (SimulateFixedAttribs(
7506 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7507 primcount)) {
7508 bool textures_set = !PrepareTexturesForRender();
7509 ApplyDirtyState();
7510 // TODO(gman): Refactor to hide these details in BufferManager or
7511 // VertexAttribManager.
7512 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
7513 bool used_client_side_array = false;
7514 if (element_array_buffer->IsClientSideArray()) {
7515 used_client_side_array = true;
7516 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
7517 indices = element_array_buffer->GetRange(offset, 0);
7520 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7521 if (!instanced) {
7522 glDrawElements(mode, count, type, indices);
7523 } else {
7524 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
7527 if (used_client_side_array) {
7528 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
7529 element_array_buffer->service_id());
7532 if (textures_set) {
7533 RestoreStateForTextures();
7535 if (simulated_fixed_attribs) {
7536 RestoreStateForSimulatedFixedAttribs();
7539 if (simulated_attrib_0) {
7540 // We don't have to restore attrib 0 generic data at the end of this
7541 // function even if it is simulated. This is because we will simulate
7542 // it in each draw call, and attrib 0 generic data queries use cached
7543 // values instead of passing down to the underlying driver.
7544 RestoreStateForAttrib(0, false);
7547 return error::kNoError;
7550 error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size,
7551 const void* cmd_data) {
7552 // TODO(zmo): crbug.com/481184
7553 // On Desktop GL with versions lower than 4.3, we need to emulate
7554 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7555 const gles2::cmds::DrawElements& c =
7556 *static_cast<const gles2::cmds::DrawElements*>(cmd_data);
7557 return DoDrawElements("glDrawElements",
7558 false,
7559 static_cast<GLenum>(c.mode),
7560 static_cast<GLsizei>(c.count),
7561 static_cast<GLenum>(c.type),
7562 static_cast<int32>(c.index_offset),
7566 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7567 uint32 immediate_data_size,
7568 const void* cmd_data) {
7569 const gles2::cmds::DrawElementsInstancedANGLE& c =
7570 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE*>(cmd_data);
7571 if (!features().angle_instanced_arrays) {
7572 LOCAL_SET_GL_ERROR(
7573 GL_INVALID_OPERATION,
7574 "glDrawElementsInstancedANGLE", "function not available");
7575 return error::kNoError;
7577 return DoDrawElements("glDrawElementsInstancedANGLE",
7578 true,
7579 static_cast<GLenum>(c.mode),
7580 static_cast<GLsizei>(c.count),
7581 static_cast<GLenum>(c.type),
7582 static_cast<int32>(c.index_offset),
7583 static_cast<GLsizei>(c.primcount));
7586 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7587 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
7588 GLuint max_vertex_accessed = 0;
7589 Buffer* buffer = GetBuffer(buffer_id);
7590 if (!buffer) {
7591 // TODO(gman): Should this be a GL error or a command buffer error?
7592 LOCAL_SET_GL_ERROR(
7593 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7594 } else {
7595 if (!buffer->GetMaxValueForRange(
7596 offset, count, type, &max_vertex_accessed)) {
7597 // TODO(gman): Should this be a GL error or a command buffer error?
7598 LOCAL_SET_GL_ERROR(
7599 GL_INVALID_OPERATION,
7600 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7603 return max_vertex_accessed;
7606 void GLES2DecoderImpl::DoShaderSource(
7607 GLuint client_id, GLsizei count, const char** data, const GLint* length) {
7608 std::string str;
7609 for (GLsizei ii = 0; ii < count; ++ii) {
7610 if (length && length[ii] > 0)
7611 str.append(data[ii], length[ii]);
7612 else
7613 str.append(data[ii]);
7615 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
7616 if (!shader) {
7617 return;
7619 // Note: We don't actually call glShaderSource here. We wait until
7620 // we actually compile the shader.
7621 shader->set_source(str);
7624 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7625 GLuint client_program_id, GLsizei count, const char* const* varyings,
7626 GLenum buffer_mode) {
7627 Program* program = GetProgramInfoNotShader(
7628 client_program_id, "glTransformFeedbackVaryings");
7629 if (!program) {
7630 return;
7632 program->TransformFeedbackVaryings(count, varyings, buffer_mode);
7633 glTransformFeedbackVaryings(
7634 program->service_id(), count, varyings, buffer_mode);
7637 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
7638 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7639 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
7640 if (!shader) {
7641 return;
7644 scoped_refptr<ShaderTranslatorInterface> translator;
7645 if (use_shader_translator_) {
7646 translator = shader->shader_type() == GL_VERTEX_SHADER ?
7647 vertex_translator_ : fragment_translator_;
7650 const Shader::TranslatedShaderSourceType source_type =
7651 feature_info_->feature_flags().angle_translated_shader_source ?
7652 Shader::kANGLE : Shader::kGL;
7653 shader->RequestCompile(translator, source_type);
7656 void GLES2DecoderImpl::DoGetShaderiv(
7657 GLuint shader_id, GLenum pname, GLint* params) {
7658 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
7659 if (!shader) {
7660 return;
7663 // Compile now for statuses that require it.
7664 switch (pname) {
7665 case GL_COMPILE_STATUS:
7666 case GL_INFO_LOG_LENGTH:
7667 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7668 shader->DoCompile();
7669 break;
7671 default:
7672 break;
7675 switch (pname) {
7676 case GL_SHADER_SOURCE_LENGTH:
7677 *params = shader->source().size();
7678 if (*params)
7679 ++(*params);
7680 return;
7681 case GL_COMPILE_STATUS:
7682 *params = compile_shader_always_succeeds_ ? true : shader->valid();
7683 return;
7684 case GL_INFO_LOG_LENGTH:
7685 *params = shader->log_info().size();
7686 if (*params)
7687 ++(*params);
7688 return;
7689 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7690 *params = shader->translated_source().size();
7691 if (*params)
7692 ++(*params);
7693 return;
7694 default:
7695 break;
7697 glGetShaderiv(shader->service_id(), pname, params);
7700 error::Error GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size,
7701 const void* cmd_data) {
7702 const gles2::cmds::GetShaderSource& c =
7703 *static_cast<const gles2::cmds::GetShaderSource*>(cmd_data);
7704 GLuint shader_id = c.shader;
7705 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7706 Bucket* bucket = CreateBucket(bucket_id);
7707 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
7708 if (!shader || shader->source().empty()) {
7709 bucket->SetSize(0);
7710 return error::kNoError;
7712 bucket->SetFromString(shader->source().c_str());
7713 return error::kNoError;
7716 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7717 uint32 immediate_data_size,
7718 const void* cmd_data) {
7719 const gles2::cmds::GetTranslatedShaderSourceANGLE& c =
7720 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE*>(
7721 cmd_data);
7722 GLuint shader_id = c.shader;
7723 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7724 Bucket* bucket = CreateBucket(bucket_id);
7725 Shader* shader = GetShaderInfoNotProgram(
7726 shader_id, "glGetTranslatedShaderSourceANGLE");
7727 if (!shader) {
7728 bucket->SetSize(0);
7729 return error::kNoError;
7732 // Make sure translator has been utilized in compile.
7733 shader->DoCompile();
7735 bucket->SetFromString(shader->translated_source().c_str());
7736 return error::kNoError;
7739 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
7740 uint32 immediate_data_size,
7741 const void* cmd_data) {
7742 const gles2::cmds::GetProgramInfoLog& c =
7743 *static_cast<const gles2::cmds::GetProgramInfoLog*>(cmd_data);
7744 GLuint program_id = c.program;
7745 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7746 Bucket* bucket = CreateBucket(bucket_id);
7747 Program* program = GetProgramInfoNotShader(
7748 program_id, "glGetProgramInfoLog");
7749 if (!program || !program->log_info()) {
7750 bucket->SetFromString("");
7751 return error::kNoError;
7753 bucket->SetFromString(program->log_info()->c_str());
7754 return error::kNoError;
7757 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
7758 uint32 immediate_data_size,
7759 const void* cmd_data) {
7760 const gles2::cmds::GetShaderInfoLog& c =
7761 *static_cast<const gles2::cmds::GetShaderInfoLog*>(cmd_data);
7762 GLuint shader_id = c.shader;
7763 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7764 Bucket* bucket = CreateBucket(bucket_id);
7765 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
7766 if (!shader) {
7767 bucket->SetFromString("");
7768 return error::kNoError;
7771 // Shader must be compiled in order to get the info log.
7772 shader->DoCompile();
7774 bucket->SetFromString(shader->log_info().c_str());
7775 return error::kNoError;
7778 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
7779 return state_.GetEnabled(cap);
7782 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
7783 const Buffer* buffer = GetBuffer(client_id);
7784 return buffer && buffer->IsValid() && !buffer->IsDeleted();
7787 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
7788 const Framebuffer* framebuffer =
7789 GetFramebuffer(client_id);
7790 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
7793 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
7794 // IsProgram is true for programs as soon as they are created, until they are
7795 // deleted and no longer in use.
7796 const Program* program = GetProgram(client_id);
7797 return program != NULL && !program->IsDeleted();
7800 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
7801 const Renderbuffer* renderbuffer =
7802 GetRenderbuffer(client_id);
7803 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
7806 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
7807 // IsShader is true for shaders as soon as they are created, until they
7808 // are deleted and not attached to any programs.
7809 const Shader* shader = GetShader(client_id);
7810 return shader != NULL && !shader->IsDeleted();
7813 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
7814 const TextureRef* texture_ref = GetTexture(client_id);
7815 return texture_ref && texture_ref->texture()->IsValid();
7818 void GLES2DecoderImpl::DoAttachShader(
7819 GLuint program_client_id, GLint shader_client_id) {
7820 Program* program = GetProgramInfoNotShader(
7821 program_client_id, "glAttachShader");
7822 if (!program) {
7823 return;
7825 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
7826 if (!shader) {
7827 return;
7829 if (!program->AttachShader(shader_manager(), shader)) {
7830 LOCAL_SET_GL_ERROR(
7831 GL_INVALID_OPERATION,
7832 "glAttachShader",
7833 "can not attach more than one shader of the same type.");
7834 return;
7836 glAttachShader(program->service_id(), shader->service_id());
7839 void GLES2DecoderImpl::DoDetachShader(
7840 GLuint program_client_id, GLint shader_client_id) {
7841 Program* program = GetProgramInfoNotShader(
7842 program_client_id, "glDetachShader");
7843 if (!program) {
7844 return;
7846 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
7847 if (!shader) {
7848 return;
7850 if (!program->DetachShader(shader_manager(), shader)) {
7851 LOCAL_SET_GL_ERROR(
7852 GL_INVALID_OPERATION,
7853 "glDetachShader", "shader not attached to program");
7854 return;
7856 glDetachShader(program->service_id(), shader->service_id());
7859 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
7860 Program* program = GetProgramInfoNotShader(
7861 program_client_id, "glValidateProgram");
7862 if (!program) {
7863 return;
7865 program->Validate();
7868 void GLES2DecoderImpl::GetVertexAttribHelper(
7869 const VertexAttrib* attrib, GLenum pname, GLint* params) {
7870 switch (pname) {
7871 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
7873 Buffer* buffer = attrib->buffer();
7874 if (buffer && !buffer->IsDeleted()) {
7875 GLuint client_id;
7876 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
7877 *params = client_id;
7879 break;
7881 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
7882 *params = attrib->enabled();
7883 break;
7884 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
7885 *params = attrib->size();
7886 break;
7887 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
7888 *params = attrib->gl_stride();
7889 break;
7890 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7891 *params = attrib->type();
7892 break;
7893 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7894 *params = attrib->normalized();
7895 break;
7896 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
7897 *params = attrib->divisor();
7898 break;
7899 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
7900 *params = attrib->integer();
7901 break;
7902 default:
7903 NOTREACHED();
7904 break;
7908 void GLES2DecoderImpl::DoGetTexParameterfv(
7909 GLenum target, GLenum pname, GLfloat* params) {
7910 InitTextureMaxAnisotropyIfNeeded(target, pname);
7911 glGetTexParameterfv(target, pname, params);
7914 void GLES2DecoderImpl::DoGetTexParameteriv(
7915 GLenum target, GLenum pname, GLint* params) {
7916 InitTextureMaxAnisotropyIfNeeded(target, pname);
7917 glGetTexParameteriv(target, pname, params);
7920 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7921 GLenum target, GLenum pname) {
7922 if (!workarounds().init_texture_max_anisotropy)
7923 return;
7924 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
7925 !validators_->texture_parameter.IsValid(pname)) {
7926 return;
7929 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7930 &state_, target);
7931 if (!texture_ref) {
7932 LOCAL_SET_GL_ERROR(
7933 GL_INVALID_OPERATION,
7934 "glGetTexParamter{fi}v", "unknown texture for target");
7935 return;
7937 Texture* texture = texture_ref->texture();
7938 texture->InitTextureMaxAnisotropyIfNeeded(target);
7941 template <typename T>
7942 void GLES2DecoderImpl::DoGetVertexAttribImpl(
7943 GLuint index, GLenum pname, T* params) {
7944 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7945 if (!attrib) {
7946 LOCAL_SET_GL_ERROR(
7947 GL_INVALID_VALUE, "glGetVertexAttrib", "index out of range");
7948 return;
7950 switch (pname) {
7951 case GL_CURRENT_VERTEX_ATTRIB:
7952 state_.attrib_values[index].GetValues(params);
7953 break;
7954 default: {
7955 GLint value = 0;
7956 GetVertexAttribHelper(attrib, pname, &value);
7957 *params = static_cast<T>(value);
7958 break;
7963 void GLES2DecoderImpl::DoGetVertexAttribfv(
7964 GLuint index, GLenum pname, GLfloat* params) {
7965 DoGetVertexAttribImpl<GLfloat>(index, pname, params);
7968 void GLES2DecoderImpl::DoGetVertexAttribiv(
7969 GLuint index, GLenum pname, GLint* params) {
7970 DoGetVertexAttribImpl<GLint>(index, pname, params);
7973 void GLES2DecoderImpl::DoGetVertexAttribIiv(
7974 GLuint index, GLenum pname, GLint* params) {
7975 DoGetVertexAttribImpl<GLint>(index, pname, params);
7978 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
7979 GLuint index, GLenum pname, GLuint* params) {
7980 DoGetVertexAttribImpl<GLuint>(index, pname, params);
7983 template <typename T>
7984 bool GLES2DecoderImpl::SetVertexAttribValue(
7985 const char* function_name, GLuint index, const T* value) {
7986 if (index >= state_.attrib_values.size()) {
7987 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7988 return false;
7990 state_.attrib_values[index].SetValues(value);
7991 return true;
7994 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7995 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7996 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7997 glVertexAttrib1f(index, v0);
8001 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
8002 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
8003 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
8004 glVertexAttrib2f(index, v0, v1);
8008 void GLES2DecoderImpl::DoVertexAttrib3f(
8009 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
8010 GLfloat v[4] = { v0, v1, v2, 1.0f, };
8011 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
8012 glVertexAttrib3f(index, v0, v1, v2);
8016 void GLES2DecoderImpl::DoVertexAttrib4f(
8017 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
8018 GLfloat v[4] = { v0, v1, v2, v3, };
8019 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
8020 glVertexAttrib4f(index, v0, v1, v2, v3);
8024 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
8025 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
8026 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
8027 glVertexAttrib1fv(index, v);
8031 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
8032 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
8033 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
8034 glVertexAttrib2fv(index, v);
8038 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
8039 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
8040 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
8041 glVertexAttrib3fv(index, v);
8045 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
8046 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
8047 glVertexAttrib4fv(index, v);
8051 void GLES2DecoderImpl::DoVertexAttribI4i(
8052 GLuint index, GLint v0, GLint v1, GLint v2, GLint v3) {
8053 GLint v[4] = { v0, v1, v2, v3 };
8054 if (SetVertexAttribValue("glVertexAttribI4i", index, v)) {
8055 glVertexAttribI4i(index, v0, v1, v2, v3);
8059 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index, const GLint* v) {
8060 if (SetVertexAttribValue("glVertexAttribI4iv", index, v)) {
8061 glVertexAttribI4iv(index, v);
8065 void GLES2DecoderImpl::DoVertexAttribI4ui(
8066 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
8067 GLuint v[4] = { v0, v1, v2, v3 };
8068 if (SetVertexAttribValue("glVertexAttribI4ui", index, v)) {
8069 glVertexAttribI4ui(index, v0, v1, v2, v3);
8073 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index, const GLuint* v) {
8074 if (SetVertexAttribValue("glVertexAttribI4uiv", index, v)) {
8075 glVertexAttribI4uiv(index, v);
8079 error::Error GLES2DecoderImpl::HandleVertexAttribIPointer(
8080 uint32 immediate_data_size,
8081 const void* cmd_data) {
8082 if (!unsafe_es3_apis_enabled())
8083 return error::kUnknownCommand;
8084 const gles2::cmds::VertexAttribIPointer& c =
8085 *static_cast<const gles2::cmds::VertexAttribIPointer*>(cmd_data);
8087 if (!state_.bound_array_buffer.get() ||
8088 state_.bound_array_buffer->IsDeleted()) {
8089 if (state_.vertex_attrib_manager.get() ==
8090 state_.default_vertex_attrib_manager.get()) {
8091 LOCAL_SET_GL_ERROR(
8092 GL_INVALID_VALUE, "glVertexAttribIPointer", "no array buffer bound");
8093 return error::kNoError;
8094 } else if (c.offset != 0) {
8095 LOCAL_SET_GL_ERROR(
8096 GL_INVALID_VALUE,
8097 "glVertexAttribIPointer", "client side arrays are not allowed");
8098 return error::kNoError;
8102 GLuint indx = c.indx;
8103 GLint size = c.size;
8104 GLenum type = c.type;
8105 GLsizei stride = c.stride;
8106 GLsizei offset = c.offset;
8107 const void* ptr = reinterpret_cast<const void*>(offset);
8108 if (!validators_->vertex_attrib_i_type.IsValid(type)) {
8109 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type, "type");
8110 return error::kNoError;
8112 if (!validators_->vertex_attrib_size.IsValid(size)) {
8113 LOCAL_SET_GL_ERROR(
8114 GL_INVALID_VALUE, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
8115 return error::kNoError;
8117 if (indx >= group_->max_vertex_attribs()) {
8118 LOCAL_SET_GL_ERROR(
8119 GL_INVALID_VALUE, "glVertexAttribIPointer", "index out of range");
8120 return error::kNoError;
8122 if (stride < 0) {
8123 LOCAL_SET_GL_ERROR(
8124 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride < 0");
8125 return error::kNoError;
8127 if (stride > 255) {
8128 LOCAL_SET_GL_ERROR(
8129 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride > 255");
8130 return error::kNoError;
8132 if (offset < 0) {
8133 LOCAL_SET_GL_ERROR(
8134 GL_INVALID_VALUE, "glVertexAttribIPointer", "offset < 0");
8135 return error::kNoError;
8137 GLsizei component_size =
8138 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
8139 // component_size must be a power of two to use & as optimized modulo.
8140 DCHECK(GLES2Util::IsPOT(component_size));
8141 if (offset & (component_size - 1)) {
8142 LOCAL_SET_GL_ERROR(
8143 GL_INVALID_OPERATION,
8144 "glVertexAttribIPointer", "offset not valid for type");
8145 return error::kNoError;
8147 if (stride & (component_size - 1)) {
8148 LOCAL_SET_GL_ERROR(
8149 GL_INVALID_OPERATION,
8150 "glVertexAttribIPointer", "stride not valid for type");
8151 return error::kNoError;
8153 state_.vertex_attrib_manager
8154 ->SetAttribInfo(indx,
8155 state_.bound_array_buffer.get(),
8156 size,
8157 type,
8158 GL_FALSE,
8159 stride,
8160 stride != 0 ? stride : component_size * size,
8161 offset,
8162 GL_TRUE);
8163 glVertexAttribIPointer(indx, size, type, stride, ptr);
8164 return error::kNoError;
8167 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
8168 uint32 immediate_data_size,
8169 const void* cmd_data) {
8170 const gles2::cmds::VertexAttribPointer& c =
8171 *static_cast<const gles2::cmds::VertexAttribPointer*>(cmd_data);
8173 if (!state_.bound_array_buffer.get() ||
8174 state_.bound_array_buffer->IsDeleted()) {
8175 if (state_.vertex_attrib_manager.get() ==
8176 state_.default_vertex_attrib_manager.get()) {
8177 LOCAL_SET_GL_ERROR(
8178 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
8179 return error::kNoError;
8180 } else if (c.offset != 0) {
8181 LOCAL_SET_GL_ERROR(
8182 GL_INVALID_VALUE,
8183 "glVertexAttribPointer", "client side arrays are not allowed");
8184 return error::kNoError;
8188 GLuint indx = c.indx;
8189 GLint size = c.size;
8190 GLenum type = c.type;
8191 GLboolean normalized = static_cast<GLboolean>(c.normalized);
8192 GLsizei stride = c.stride;
8193 GLsizei offset = c.offset;
8194 const void* ptr = reinterpret_cast<const void*>(offset);
8195 if (!validators_->vertex_attrib_type.IsValid(type)) {
8196 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
8197 return error::kNoError;
8199 if (!validators_->vertex_attrib_size.IsValid(size)) {
8200 LOCAL_SET_GL_ERROR(
8201 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8202 return error::kNoError;
8204 if (indx >= group_->max_vertex_attribs()) {
8205 LOCAL_SET_GL_ERROR(
8206 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
8207 return error::kNoError;
8209 if (stride < 0) {
8210 LOCAL_SET_GL_ERROR(
8211 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
8212 return error::kNoError;
8214 if (stride > 255) {
8215 LOCAL_SET_GL_ERROR(
8216 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
8217 return error::kNoError;
8219 if (offset < 0) {
8220 LOCAL_SET_GL_ERROR(
8221 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
8222 return error::kNoError;
8224 GLsizei component_size =
8225 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
8226 // component_size must be a power of two to use & as optimized modulo.
8227 DCHECK(GLES2Util::IsPOT(component_size));
8228 if (offset & (component_size - 1)) {
8229 LOCAL_SET_GL_ERROR(
8230 GL_INVALID_OPERATION,
8231 "glVertexAttribPointer", "offset not valid for type");
8232 return error::kNoError;
8234 if (stride & (component_size - 1)) {
8235 LOCAL_SET_GL_ERROR(
8236 GL_INVALID_OPERATION,
8237 "glVertexAttribPointer", "stride not valid for type");
8238 return error::kNoError;
8240 state_.vertex_attrib_manager
8241 ->SetAttribInfo(indx,
8242 state_.bound_array_buffer.get(),
8243 size,
8244 type,
8245 normalized,
8246 stride,
8247 stride != 0 ? stride : component_size * size,
8248 offset,
8249 GL_FALSE);
8250 // We support GL_FIXED natively on EGL/GLES2 implementations
8251 if (type != GL_FIXED || feature_info_->gl_version_info().is_es) {
8252 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
8254 return error::kNoError;
8257 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
8258 GLsizei height) {
8259 state_.viewport_x = x;
8260 state_.viewport_y = y;
8261 state_.viewport_width = std::min(width, viewport_max_width_);
8262 state_.viewport_height = std::min(height, viewport_max_height_);
8263 glViewport(x, y, width, height);
8266 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8267 uint32 immediate_data_size,
8268 const void* cmd_data) {
8269 const gles2::cmds::VertexAttribDivisorANGLE& c =
8270 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE*>(cmd_data);
8271 if (!features().angle_instanced_arrays) {
8272 LOCAL_SET_GL_ERROR(
8273 GL_INVALID_OPERATION,
8274 "glVertexAttribDivisorANGLE", "function not available");
8275 return error::kNoError;
8277 GLuint index = c.index;
8278 GLuint divisor = c.divisor;
8279 if (index >= group_->max_vertex_attribs()) {
8280 LOCAL_SET_GL_ERROR(
8281 GL_INVALID_VALUE,
8282 "glVertexAttribDivisorANGLE", "index out of range");
8283 return error::kNoError;
8286 state_.vertex_attrib_manager->SetDivisor(
8287 index,
8288 divisor);
8289 glVertexAttribDivisorANGLE(index, divisor);
8290 return error::kNoError;
8293 template <typename pixel_data_type>
8294 static void WriteAlphaData(
8295 void* pixels, uint32 row_count, uint32 channel_count,
8296 uint32 alpha_channel_index, uint32 unpadded_row_size,
8297 uint32 padded_row_size, pixel_data_type alpha_value) {
8298 DCHECK_GT(channel_count, 0U);
8299 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
8300 uint32 unpadded_row_size_in_elements =
8301 unpadded_row_size / sizeof(pixel_data_type);
8302 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
8303 uint32 padded_row_size_in_elements =
8304 padded_row_size / sizeof(pixel_data_type);
8305 pixel_data_type* dst =
8306 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
8307 for (uint32 yy = 0; yy < row_count; ++yy) {
8308 pixel_data_type* end = dst + unpadded_row_size_in_elements;
8309 for (pixel_data_type* d = dst; d < end; d += channel_count) {
8310 *d = alpha_value;
8312 dst += padded_row_size_in_elements;
8316 void GLES2DecoderImpl::FinishReadPixels(
8317 const cmds::ReadPixels& c,
8318 GLuint buffer) {
8319 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8320 GLsizei width = c.width;
8321 GLsizei height = c.height;
8322 GLenum format = c.format;
8323 GLenum type = c.type;
8324 typedef cmds::ReadPixels::Result Result;
8325 uint32 pixels_size;
8326 Result* result = NULL;
8327 if (c.result_shm_id != 0) {
8328 result = GetSharedMemoryAs<Result*>(
8329 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8330 if (!result) {
8331 if (buffer != 0) {
8332 glDeleteBuffersARB(1, &buffer);
8334 return;
8337 GLES2Util::ComputeImageDataSizes(
8338 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8339 NULL, NULL);
8340 void* pixels = GetSharedMemoryAs<void*>(
8341 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8342 if (!pixels) {
8343 if (buffer != 0) {
8344 glDeleteBuffersARB(1, &buffer);
8346 return;
8349 if (buffer != 0) {
8350 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8351 void* data;
8352 if (features().map_buffer_range) {
8353 data = glMapBufferRange(
8354 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
8355 } else {
8356 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
8358 if (!data) {
8359 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glMapBuffer",
8360 "Unable to map memory for readback.");
8361 return;
8363 memcpy(pixels, data, pixels_size);
8364 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8365 // have to restore the state.
8366 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
8367 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8368 glDeleteBuffersARB(1, &buffer);
8371 if (result != NULL) {
8372 *result = true;
8375 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8376 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8377 if ((channels_exist & 0x0008) == 0 &&
8378 workarounds().clear_alpha_in_readpixels) {
8379 // Set the alpha to 255 because some drivers are buggy in this regard.
8380 uint32 temp_size;
8382 uint32 unpadded_row_size;
8383 uint32 padded_row_size;
8384 if (!GLES2Util::ComputeImageDataSizes(
8385 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8386 &unpadded_row_size, &padded_row_size)) {
8387 return;
8390 uint32 channel_count = 0;
8391 uint32 alpha_channel = 0;
8392 switch (format) {
8393 case GL_RGBA:
8394 case GL_BGRA_EXT:
8395 channel_count = 4;
8396 alpha_channel = 3;
8397 break;
8398 case GL_ALPHA:
8399 channel_count = 1;
8400 alpha_channel = 0;
8401 break;
8404 if (channel_count > 0) {
8405 switch (type) {
8406 case GL_UNSIGNED_BYTE:
8407 WriteAlphaData<uint8>(
8408 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8409 padded_row_size, 0xFF);
8410 break;
8411 case GL_FLOAT:
8412 WriteAlphaData<float>(
8413 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8414 padded_row_size, 1.0f);
8415 break;
8416 case GL_HALF_FLOAT:
8417 WriteAlphaData<uint16>(
8418 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8419 padded_row_size, 0x3C00);
8420 break;
8426 error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
8427 const void* cmd_data) {
8428 const gles2::cmds::ReadPixels& c =
8429 *static_cast<const gles2::cmds::ReadPixels*>(cmd_data);
8430 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8431 error::Error fbo_error = WillAccessBoundFramebufferForRead();
8432 if (fbo_error != error::kNoError)
8433 return fbo_error;
8434 GLint x = c.x;
8435 GLint y = c.y;
8436 GLsizei width = c.width;
8437 GLsizei height = c.height;
8438 GLenum format = c.format;
8439 GLenum type = c.type;
8440 GLboolean async = static_cast<GLboolean>(c.async);
8441 if (width < 0 || height < 0) {
8442 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
8443 return error::kNoError;
8445 typedef cmds::ReadPixels::Result Result;
8446 uint32 pixels_size;
8447 if (!GLES2Util::ComputeImageDataSizes(
8448 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8449 NULL, NULL)) {
8450 return error::kOutOfBounds;
8452 void* pixels = GetSharedMemoryAs<void*>(
8453 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8454 if (!pixels) {
8455 return error::kOutOfBounds;
8457 Result* result = NULL;
8458 if (c.result_shm_id != 0) {
8459 result = GetSharedMemoryAs<Result*>(
8460 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8461 if (!result) {
8462 return error::kOutOfBounds;
8466 if (!validators_->read_pixel_format.IsValid(format)) {
8467 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
8468 return error::kNoError;
8470 if (!validators_->read_pixel_type.IsValid(type)) {
8471 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
8472 return error::kNoError;
8475 GLenum src_internal_format = GetBoundReadFrameBufferInternalFormat();
8476 if (src_internal_format == 0) {
8477 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels",
8478 "no valid read buffer source");
8479 return error::kNoError;
8481 std::vector<GLenum> accepted_formats;
8482 std::vector<GLenum> accepted_types;
8483 switch (src_internal_format) {
8484 case GL_RGB10_A2UI:
8485 accepted_formats.push_back(GL_RGBA);
8486 accepted_types.push_back(GL_UNSIGNED_INT_2_10_10_10_REV);
8487 case GL_R8UI:
8488 case GL_R16UI:
8489 case GL_R32UI:
8490 case GL_RG8UI:
8491 case GL_RG16UI:
8492 case GL_RG32UI:
8493 // All the RGB_INTEGER formats are not renderable.
8494 case GL_RGBA8UI:
8495 case GL_RGBA16UI:
8496 case GL_RGBA32UI:
8497 accepted_formats.push_back(GL_RGBA_INTEGER);
8498 accepted_types.push_back(GL_UNSIGNED_INT);
8499 break;
8500 case GL_R8I:
8501 case GL_R16I:
8502 case GL_R32I:
8503 case GL_RG8I:
8504 case GL_RG16I:
8505 case GL_RG32I:
8506 case GL_RGBA8I:
8507 case GL_RGBA16I:
8508 case GL_RGBA32I:
8509 accepted_formats.push_back(GL_RGBA_INTEGER);
8510 accepted_types.push_back(GL_INT);
8511 break;
8512 default:
8513 accepted_formats.push_back(GL_RGBA);
8515 GLenum src_type = GetBoundReadFrameBufferTextureType();
8516 switch (src_type) {
8517 case GL_HALF_FLOAT:
8518 case GL_HALF_FLOAT_OES:
8519 case GL_FLOAT:
8520 case GL_UNSIGNED_INT_10F_11F_11F_REV:
8521 accepted_types.push_back(GL_FLOAT);
8522 break;
8523 default:
8524 accepted_types.push_back(GL_UNSIGNED_BYTE);
8525 break;
8528 break;
8530 if (!IsWebGLContext()) {
8531 accepted_formats.push_back(GL_BGRA_EXT);
8532 accepted_types.push_back(GL_UNSIGNED_BYTE);
8534 DCHECK_EQ(accepted_formats.size(), accepted_types.size());
8535 bool format_type_acceptable = false;
8536 for (size_t ii = 0; ii < accepted_formats.size(); ++ii) {
8537 if (format == accepted_formats[ii] && type == accepted_types[ii]) {
8538 format_type_acceptable = true;
8539 break;
8542 if (!format_type_acceptable) {
8543 // format and type are acceptable enums but not guaranteed to be supported
8544 // for this framebuffer. Have to ask gl if they are valid.
8545 GLint preferred_format = 0;
8546 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
8547 GLint preferred_type = 0;
8548 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
8549 if (format == static_cast<GLenum>(preferred_format) &&
8550 type == static_cast<GLenum>(preferred_type)) {
8551 format_type_acceptable = true;
8554 if (!format_type_acceptable) {
8555 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glReadPixels",
8556 "format and type incompatible with the current read framebuffer");
8557 return error::kNoError;
8559 if (width == 0 || height == 0) {
8560 return error::kNoError;
8563 // Get the size of the current fbo or backbuffer.
8564 gfx::Size max_size = GetBoundReadFrameBufferSize();
8566 int32 max_x;
8567 int32 max_y;
8568 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
8569 LOCAL_SET_GL_ERROR(
8570 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8571 return error::kNoError;
8574 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8575 return error::kNoError;
8578 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8580 ScopedResolvedFrameBufferBinder binder(this, false, true);
8582 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
8583 // The user requested an out of range area. Get the results 1 line
8584 // at a time.
8585 uint32 temp_size;
8586 uint32 unpadded_row_size;
8587 uint32 padded_row_size;
8588 if (!GLES2Util::ComputeImageDataSizes(
8589 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8590 &unpadded_row_size, &padded_row_size)) {
8591 LOCAL_SET_GL_ERROR(
8592 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8593 return error::kNoError;
8596 GLint dest_x_offset = std::max(-x, 0);
8597 uint32 dest_row_offset;
8598 if (!GLES2Util::ComputeImageDataSizes(
8599 dest_x_offset, 1, 1, format, type, state_.pack_alignment,
8600 &dest_row_offset, NULL, NULL)) {
8601 LOCAL_SET_GL_ERROR(
8602 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8603 return error::kNoError;
8606 // Copy each row into the larger dest rect.
8607 int8* dst = static_cast<int8*>(pixels);
8608 GLint read_x = std::max(0, x);
8609 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
8610 GLint read_width = read_end_x - read_x;
8611 for (GLint yy = 0; yy < height; ++yy) {
8612 GLint ry = y + yy;
8614 // Clear the row.
8615 memset(dst, 0, unpadded_row_size);
8617 // If the row is in range, copy it.
8618 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
8619 glReadPixels(
8620 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
8622 dst += padded_row_size;
8624 } else {
8625 if (async && features().use_async_readpixels) {
8626 GLuint buffer = 0;
8627 glGenBuffersARB(1, &buffer);
8628 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8629 // For ANGLE client version 2, GL_STREAM_READ is not available.
8630 const GLenum usage_hint = feature_info_->gl_version_info().is_angle ?
8631 GL_STATIC_DRAW : GL_STREAM_READ;
8632 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, usage_hint);
8633 GLenum error = glGetError();
8634 if (error == GL_NO_ERROR) {
8635 glReadPixels(x, y, width, height, format, type, 0);
8636 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
8637 new FenceCallback()));
8638 WaitForReadPixels(base::Bind(
8639 &GLES2DecoderImpl::FinishReadPixels,
8640 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8641 <GLES2DecoderImpl>(this),
8642 c, buffer));
8643 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8644 return error::kNoError;
8645 } else {
8646 // On error, unbind pack buffer and fall through to sync readpixels
8647 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8648 glDeleteBuffersARB(1, &buffer);
8651 glReadPixels(x, y, width, height, format, type, pixels);
8653 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
8654 if (error == GL_NO_ERROR) {
8655 if (result != NULL) {
8656 *result = true;
8658 FinishReadPixels(c, 0);
8661 return error::kNoError;
8664 error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size,
8665 const void* cmd_data) {
8666 const gles2::cmds::PixelStorei& c =
8667 *static_cast<const gles2::cmds::PixelStorei*>(cmd_data);
8668 GLenum pname = c.pname;
8669 GLenum param = c.param;
8670 if (!validators_->pixel_store.IsValid(pname)) {
8671 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
8672 return error::kNoError;
8674 switch (pname) {
8675 case GL_PACK_ALIGNMENT:
8676 case GL_UNPACK_ALIGNMENT:
8677 if (!validators_->pixel_store_alignment.IsValid(param)) {
8678 LOCAL_SET_GL_ERROR(
8679 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
8680 return error::kNoError;
8682 break;
8683 default:
8684 break;
8686 glPixelStorei(pname, param);
8687 switch (pname) {
8688 case GL_PACK_ALIGNMENT:
8689 state_.pack_alignment = param;
8690 break;
8691 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
8692 state_.pack_reverse_row_order = (param != 0);
8693 break;
8694 case GL_UNPACK_ALIGNMENT:
8695 state_.unpack_alignment = param;
8696 break;
8697 default:
8698 // Validation should have prevented us from getting here.
8699 NOTREACHED();
8700 break;
8702 return error::kNoError;
8705 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8706 uint32 immediate_data_size,
8707 const void* cmd_data) {
8708 const gles2::cmds::PostSubBufferCHROMIUM& c =
8709 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM*>(cmd_data);
8710 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8712 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8714 if (!supports_post_sub_buffer_) {
8715 LOCAL_SET_GL_ERROR(
8716 GL_INVALID_OPERATION,
8717 "glPostSubBufferCHROMIUM", "command not supported by surface");
8718 return error::kNoError;
8720 bool is_tracing;
8721 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8722 &is_tracing);
8723 if (is_tracing) {
8724 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8725 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8726 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8727 is_offscreen ? offscreen_size_ : surface_->GetSize());
8729 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height) !=
8730 gfx::SwapResult::SWAP_FAILED) {
8731 return error::kNoError;
8732 } else {
8733 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
8734 return error::kLostContext;
8738 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8739 uint32 immediate_data_size,
8740 const void* cmd_data) {
8741 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM& c =
8742 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM*>(cmd_data);
8743 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
8744 if (!ref) {
8745 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8746 "glScheduleOverlayPlaneCHROMIUM",
8747 "unknown texture");
8748 return error::kNoError;
8750 gfx::GLImage* image =
8751 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
8752 if (!image) {
8753 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8754 "glScheduleOverlayPlaneCHROMIUM",
8755 "unsupported texture format");
8756 return error::kNoError;
8758 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
8759 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
8760 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
8761 "glScheduleOverlayPlaneCHROMIUM",
8762 "invalid transform enum");
8763 return error::kNoError;
8765 if (!surface_->ScheduleOverlayPlane(
8766 c.plane_z_order,
8767 transform,
8768 image,
8769 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
8770 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
8771 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8772 "glScheduleOverlayPlaneCHROMIUM",
8773 "failed to schedule overlay");
8775 return error::kNoError;
8778 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
8779 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8780 const std::string& name_str) {
8781 if (!StringIsValidForGLES(name_str.c_str())) {
8782 LOCAL_SET_GL_ERROR(
8783 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
8784 return error::kNoError;
8786 Program* program = GetProgramInfoNotShader(
8787 client_id, "glGetAttribLocation");
8788 if (!program) {
8789 return error::kNoError;
8791 if (!program->IsValid()) {
8792 LOCAL_SET_GL_ERROR(
8793 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
8794 return error::kNoError;
8796 GLint* location = GetSharedMemoryAs<GLint*>(
8797 location_shm_id, location_shm_offset, sizeof(GLint));
8798 if (!location) {
8799 return error::kOutOfBounds;
8801 // Require the client to init this incase the context is lost and we are no
8802 // longer executing commands.
8803 if (*location != -1) {
8804 return error::kGenericError;
8806 *location = program->GetAttribLocation(name_str);
8807 return error::kNoError;
8810 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
8811 uint32 immediate_data_size,
8812 const void* cmd_data) {
8813 const gles2::cmds::GetAttribLocation& c =
8814 *static_cast<const gles2::cmds::GetAttribLocation*>(cmd_data);
8815 Bucket* bucket = GetBucket(c.name_bucket_id);
8816 if (!bucket) {
8817 return error::kInvalidArguments;
8819 std::string name_str;
8820 if (!bucket->GetAsString(&name_str)) {
8821 return error::kInvalidArguments;
8823 return GetAttribLocationHelper(
8824 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8827 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
8828 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8829 const std::string& name_str) {
8830 if (!StringIsValidForGLES(name_str.c_str())) {
8831 LOCAL_SET_GL_ERROR(
8832 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
8833 return error::kNoError;
8835 Program* program = GetProgramInfoNotShader(
8836 client_id, "glGetUniformLocation");
8837 if (!program) {
8838 return error::kNoError;
8840 if (!program->IsValid()) {
8841 LOCAL_SET_GL_ERROR(
8842 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
8843 return error::kNoError;
8845 GLint* location = GetSharedMemoryAs<GLint*>(
8846 location_shm_id, location_shm_offset, sizeof(GLint));
8847 if (!location) {
8848 return error::kOutOfBounds;
8850 // Require the client to init this incase the context is lost an we are no
8851 // longer executing commands.
8852 if (*location != -1) {
8853 return error::kGenericError;
8855 *location = program->GetUniformFakeLocation(name_str);
8856 return error::kNoError;
8859 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
8860 uint32 immediate_data_size,
8861 const void* cmd_data) {
8862 const gles2::cmds::GetUniformLocation& c =
8863 *static_cast<const gles2::cmds::GetUniformLocation*>(cmd_data);
8864 Bucket* bucket = GetBucket(c.name_bucket_id);
8865 if (!bucket) {
8866 return error::kInvalidArguments;
8868 std::string name_str;
8869 if (!bucket->GetAsString(&name_str)) {
8870 return error::kInvalidArguments;
8872 return GetUniformLocationHelper(
8873 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8876 error::Error GLES2DecoderImpl::HandleGetUniformIndices(
8877 uint32 immediate_data_size,
8878 const void* cmd_data) {
8879 if (!unsafe_es3_apis_enabled())
8880 return error::kUnknownCommand;
8881 const gles2::cmds::GetUniformIndices& c =
8882 *static_cast<const gles2::cmds::GetUniformIndices*>(cmd_data);
8883 Bucket* bucket = GetBucket(c.names_bucket_id);
8884 if (!bucket) {
8885 return error::kInvalidArguments;
8887 GLsizei count = 0;
8888 std::vector<char*> names;
8889 std::vector<GLint> len;
8890 if (!bucket->GetAsStrings(&count, &names, &len) || count <= 0) {
8891 return error::kInvalidArguments;
8893 typedef cmds::GetUniformIndices::Result Result;
8894 Result* result = GetSharedMemoryAs<Result*>(
8895 c.indices_shm_id, c.indices_shm_offset,
8896 Result::ComputeSize(static_cast<size_t>(count)));
8897 GLuint* indices = result ? result->GetData() : NULL;
8898 if (indices == NULL) {
8899 return error::kOutOfBounds;
8901 // Check that the client initialized the result.
8902 if (result->size != 0) {
8903 return error::kInvalidArguments;
8905 Program* program = GetProgramInfoNotShader(c.program, "glGetUniformIndices");
8906 if (!program) {
8907 return error::kNoError;
8909 GLuint service_id = program->service_id();
8910 GLint link_status = GL_FALSE;
8911 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
8912 if (link_status != GL_TRUE) {
8913 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8914 "glGetUniformIndices", "program not linked");
8915 return error::kNoError;
8917 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8918 glGetUniformIndices(service_id, count, &names[0], indices);
8919 GLenum error = glGetError();
8920 if (error == GL_NO_ERROR) {
8921 result->SetNumResults(count);
8922 } else {
8923 LOCAL_SET_GL_ERROR(error, "GetUniformIndices", "");
8925 return error::kNoError;
8928 error::Error GLES2DecoderImpl::GetFragDataLocationHelper(
8929 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8930 const std::string& name_str) {
8931 GLint* location = GetSharedMemoryAs<GLint*>(
8932 location_shm_id, location_shm_offset, sizeof(GLint));
8933 if (!location) {
8934 return error::kOutOfBounds;
8936 // Require the client to init this incase the context is lost and we are no
8937 // longer executing commands.
8938 if (*location != -1) {
8939 return error::kGenericError;
8941 Program* program = GetProgramInfoNotShader(
8942 client_id, "glGetFragDataLocation");
8943 if (!program) {
8944 return error::kNoError;
8946 *location = glGetFragDataLocation(program->service_id(), name_str.c_str());
8947 return error::kNoError;
8950 error::Error GLES2DecoderImpl::HandleGetFragDataLocation(
8951 uint32 immediate_data_size,
8952 const void* cmd_data) {
8953 if (!unsafe_es3_apis_enabled())
8954 return error::kUnknownCommand;
8955 const gles2::cmds::GetFragDataLocation& c =
8956 *static_cast<const gles2::cmds::GetFragDataLocation*>(cmd_data);
8957 Bucket* bucket = GetBucket(c.name_bucket_id);
8958 if (!bucket) {
8959 return error::kInvalidArguments;
8961 std::string name_str;
8962 if (!bucket->GetAsString(&name_str)) {
8963 return error::kInvalidArguments;
8965 return GetFragDataLocationHelper(
8966 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8969 error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex(
8970 uint32 immediate_data_size, const void* cmd_data) {
8971 if (!unsafe_es3_apis_enabled())
8972 return error::kUnknownCommand;
8973 const gles2::cmds::GetUniformBlockIndex& c =
8974 *static_cast<const gles2::cmds::GetUniformBlockIndex*>(cmd_data);
8975 Bucket* bucket = GetBucket(c.name_bucket_id);
8976 if (!bucket) {
8977 return error::kInvalidArguments;
8979 std::string name_str;
8980 if (!bucket->GetAsString(&name_str)) {
8981 return error::kInvalidArguments;
8983 GLuint* index = GetSharedMemoryAs<GLuint*>(
8984 c.index_shm_id, c.index_shm_offset, sizeof(GLuint));
8985 if (!index) {
8986 return error::kOutOfBounds;
8988 // Require the client to init this in case the context is lost and we are no
8989 // longer executing commands.
8990 if (*index != GL_INVALID_INDEX) {
8991 return error::kGenericError;
8993 Program* program = GetProgramInfoNotShader(
8994 c.program, "glGetUniformBlockIndex");
8995 if (!program) {
8996 return error::kNoError;
8998 *index = glGetUniformBlockIndex(program->service_id(), name_str.c_str());
8999 return error::kNoError;
9002 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
9003 const void* cmd_data) {
9004 const gles2::cmds::GetString& c =
9005 *static_cast<const gles2::cmds::GetString*>(cmd_data);
9006 GLenum name = static_cast<GLenum>(c.name);
9007 if (!validators_->string_type.IsValid(name)) {
9008 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
9009 return error::kNoError;
9012 const char* str = nullptr;
9013 std::string extensions;
9014 switch (name) {
9015 case GL_VERSION:
9016 if (unsafe_es3_apis_enabled())
9017 str = "OpenGL ES 3.0 Chromium";
9018 else
9019 str = "OpenGL ES 2.0 Chromium";
9020 break;
9021 case GL_SHADING_LANGUAGE_VERSION:
9022 if (unsafe_es3_apis_enabled())
9023 str = "OpenGL ES GLSL ES 3.0 Chromium";
9024 else
9025 str = "OpenGL ES GLSL ES 1.0 Chromium";
9026 break;
9027 case GL_RENDERER:
9028 case GL_VENDOR:
9029 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
9030 // They are used by WEBGL_debug_renderer_info.
9031 if (!IsWebGLContext())
9032 str = "Chromium";
9033 else
9034 str = reinterpret_cast<const char*>(glGetString(name));
9035 break;
9036 case GL_EXTENSIONS:
9038 // For WebGL contexts, strip out the OES derivatives and
9039 // EXT frag depth extensions if they have not been enabled.
9040 if (IsWebGLContext()) {
9041 extensions = feature_info_->extensions();
9042 if (!derivatives_explicitly_enabled_) {
9043 size_t offset = extensions.find(kOESDerivativeExtension);
9044 if (std::string::npos != offset) {
9045 extensions.replace(offset, arraysize(kOESDerivativeExtension),
9046 std::string());
9049 if (!frag_depth_explicitly_enabled_) {
9050 size_t offset = extensions.find(kEXTFragDepthExtension);
9051 if (std::string::npos != offset) {
9052 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
9053 std::string());
9056 if (!draw_buffers_explicitly_enabled_) {
9057 size_t offset = extensions.find(kEXTDrawBuffersExtension);
9058 if (std::string::npos != offset) {
9059 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
9060 std::string());
9063 if (!shader_texture_lod_explicitly_enabled_) {
9064 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
9065 if (std::string::npos != offset) {
9066 extensions.replace(offset,
9067 arraysize(kEXTShaderTextureLodExtension),
9068 std::string());
9071 } else {
9072 extensions = feature_info_->extensions().c_str();
9074 if (supports_post_sub_buffer_)
9075 extensions += " GL_CHROMIUM_post_sub_buffer";
9076 str = extensions.c_str();
9078 break;
9079 default:
9080 str = reinterpret_cast<const char*>(glGetString(name));
9081 break;
9083 Bucket* bucket = CreateBucket(c.bucket_id);
9084 bucket->SetFromString(str);
9085 return error::kNoError;
9088 error::Error GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size,
9089 const void* cmd_data) {
9090 const gles2::cmds::BufferData& c =
9091 *static_cast<const gles2::cmds::BufferData*>(cmd_data);
9092 GLenum target = static_cast<GLenum>(c.target);
9093 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
9094 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9095 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9096 GLenum usage = static_cast<GLenum>(c.usage);
9097 const void* data = NULL;
9098 if (data_shm_id != 0 || data_shm_offset != 0) {
9099 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
9100 if (!data) {
9101 return error::kOutOfBounds;
9104 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
9105 return error::kNoError;
9108 void GLES2DecoderImpl::DoBufferSubData(
9109 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
9110 // Just delegate it. Some validation is actually done before this.
9111 buffer_manager()->ValidateAndDoBufferSubData(
9112 &state_, target, offset, size, data);
9115 bool GLES2DecoderImpl::ClearLevel(Texture* texture,
9116 unsigned target,
9117 int level,
9118 unsigned format,
9119 unsigned type,
9120 int xoffset,
9121 int yoffset,
9122 int width,
9123 int height) {
9124 uint32 channels = GLES2Util::GetChannelsForFormat(format);
9125 if ((feature_info_->feature_flags().angle_depth_texture ||
9126 feature_info_->IsES3Enabled())
9127 && (channels & GLES2Util::kDepth) != 0) {
9128 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
9129 // on depth formats.
9130 GLuint fb = 0;
9131 glGenFramebuffersEXT(1, &fb);
9132 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
9134 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
9135 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
9136 GL_DEPTH_ATTACHMENT;
9138 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, attachment, target,
9139 texture->service_id(), level);
9140 // ANGLE promises a depth only attachment ok.
9141 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
9142 GL_FRAMEBUFFER_COMPLETE) {
9143 return false;
9145 glClearStencil(0);
9146 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
9147 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
9148 glClearDepth(1.0f);
9149 state_.SetDeviceDepthMask(GL_TRUE);
9150 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
9151 glScissor(xoffset, yoffset, width, height);
9152 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
9154 RestoreClearState();
9156 glDeleteFramebuffersEXT(1, &fb);
9157 Framebuffer* framebuffer =
9158 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
9159 GLuint fb_service_id =
9160 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
9161 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
9162 return true;
9165 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
9167 uint32 size;
9168 uint32 padded_row_size;
9169 if (!GLES2Util::ComputeImageDataSizes(
9170 width, height, 1, format, type, state_.unpack_alignment, &size,
9171 NULL, &padded_row_size)) {
9172 return false;
9175 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
9177 int tile_height;
9179 if (size > kMaxZeroSize) {
9180 if (kMaxZeroSize < padded_row_size) {
9181 // That'd be an awfully large texture.
9182 return false;
9184 // We should never have a large total size with a zero row size.
9185 DCHECK_GT(padded_row_size, 0U);
9186 tile_height = kMaxZeroSize / padded_row_size;
9187 if (!GLES2Util::ComputeImageDataSizes(
9188 width, tile_height, 1, format, type, state_.unpack_alignment, &size,
9189 NULL, NULL)) {
9190 return false;
9192 } else {
9193 tile_height = height;
9196 // Assumes the size has already been checked.
9197 scoped_ptr<char[]> zero(new char[size]);
9198 memset(zero.get(), 0, size);
9199 glBindTexture(texture->target(), texture->service_id());
9201 GLint y = 0;
9202 while (y < height) {
9203 GLint h = y + tile_height > height ? height - y : tile_height;
9204 glTexSubImage2D(target, level, xoffset, yoffset + y, width, h, format, type,
9205 zero.get());
9206 y += tile_height;
9208 TextureRef* bound_texture =
9209 texture_manager()->GetTextureInfoForTarget(&state_, texture->target());
9210 glBindTexture(texture->target(),
9211 bound_texture ? bound_texture->service_id() : 0);
9212 return true;
9215 namespace {
9217 const int kS3TCBlockWidth = 4;
9218 const int kS3TCBlockHeight = 4;
9219 const int kS3TCDXT1BlockSize = 8;
9220 const int kS3TCDXT3AndDXT5BlockSize = 16;
9221 const int kEACAndETC2BlockSize = 4;
9223 bool IsValidDXTSize(GLint level, GLsizei size) {
9224 return (size == 1) ||
9225 (size == 2) || !(size % kS3TCBlockWidth);
9228 bool IsValidPVRTCSize(GLint level, GLsizei size) {
9229 return GLES2Util::IsPOT(size);
9232 } // anonymous namespace.
9234 bool GLES2DecoderImpl::GetCompressedTexSizeInBytes(
9235 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
9236 GLenum format, GLsizei* size_in_bytes) {
9237 base::CheckedNumeric<GLsizei> bytes_required(0);
9239 switch (format) {
9240 case GL_ATC_RGB_AMD:
9241 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9242 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9243 case GL_ETC1_RGB8_OES:
9244 bytes_required =
9245 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9246 bytes_required *=
9247 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9248 bytes_required *= kS3TCDXT1BlockSize;
9249 break;
9250 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9251 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9252 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9253 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9254 bytes_required =
9255 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9256 bytes_required *=
9257 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9258 bytes_required *= kS3TCDXT3AndDXT5BlockSize;
9259 break;
9260 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9261 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9262 bytes_required = std::max(width, 8);
9263 bytes_required *= std::max(height, 8);
9264 bytes_required *= 4;
9265 bytes_required += 7;
9266 bytes_required /= 8;
9267 break;
9268 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9269 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9270 bytes_required = std::max(width, 16);
9271 bytes_required *= std::max(height, 8);
9272 bytes_required *= 2;
9273 bytes_required += 7;
9274 bytes_required /= 8;
9275 break;
9277 // ES3 formats.
9278 case GL_COMPRESSED_R11_EAC:
9279 case GL_COMPRESSED_SIGNED_R11_EAC:
9280 case GL_COMPRESSED_RGB8_ETC2:
9281 case GL_COMPRESSED_SRGB8_ETC2:
9282 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9283 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9284 bytes_required =
9285 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9286 bytes_required *=
9287 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9288 bytes_required *= 8;
9289 bytes_required *= depth;
9290 break;
9291 case GL_COMPRESSED_RG11_EAC:
9292 case GL_COMPRESSED_SIGNED_RG11_EAC:
9293 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9294 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9295 bytes_required =
9296 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9297 bytes_required *=
9298 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9299 bytes_required *= 16;
9300 bytes_required *= depth;
9301 break;
9302 default:
9303 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
9304 return false;
9307 if (!bytes_required.IsValid()) {
9308 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "invalid size");
9309 return false;
9312 *size_in_bytes = bytes_required.ValueOrDefault(0);
9313 return true;
9316 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
9317 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
9318 GLenum format, GLsizei size) {
9319 GLsizei bytes_required = 0;
9320 if (!GetCompressedTexSizeInBytes(
9321 function_name, width, height, depth, format, &bytes_required)) {
9322 return false;
9325 if (size != bytes_required) {
9326 LOCAL_SET_GL_ERROR(
9327 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
9328 return false;
9331 return true;
9334 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9335 const char* function_name, GLenum target, GLint level,
9336 GLsizei width, GLsizei height, GLsizei depth, GLenum format) {
9337 switch (format) {
9338 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9339 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9340 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9341 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9342 DCHECK_EQ(1, depth); // 2D formats.
9343 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
9344 LOCAL_SET_GL_ERROR(
9345 GL_INVALID_OPERATION, function_name,
9346 "width or height invalid for level");
9347 return false;
9349 return true;
9350 case GL_ATC_RGB_AMD:
9351 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9352 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9353 case GL_ETC1_RGB8_OES:
9354 DCHECK_EQ(1, depth); // 2D formats.
9355 if (width <= 0 || height <= 0) {
9356 LOCAL_SET_GL_ERROR(
9357 GL_INVALID_OPERATION, function_name,
9358 "width or height invalid for level");
9359 return false;
9361 return true;
9362 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9363 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9364 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9365 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9366 DCHECK_EQ(1, depth); // 2D formats.
9367 if (!IsValidPVRTCSize(level, width) ||
9368 !IsValidPVRTCSize(level, height)) {
9369 LOCAL_SET_GL_ERROR(
9370 GL_INVALID_OPERATION, function_name,
9371 "width or height invalid for level");
9372 return false;
9374 return true;
9376 // ES3 formats.
9377 case GL_COMPRESSED_R11_EAC:
9378 case GL_COMPRESSED_SIGNED_R11_EAC:
9379 case GL_COMPRESSED_RG11_EAC:
9380 case GL_COMPRESSED_SIGNED_RG11_EAC:
9381 case GL_COMPRESSED_RGB8_ETC2:
9382 case GL_COMPRESSED_SRGB8_ETC2:
9383 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9384 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9385 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9386 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9387 if (width <= 0 || height <= 0 || depth <= 0) {
9388 LOCAL_SET_GL_ERROR(
9389 GL_INVALID_OPERATION, function_name,
9390 "width, height, or depth invalid");
9391 return false;
9393 if (target == GL_TEXTURE_3D) {
9394 LOCAL_SET_GL_ERROR(
9395 GL_INVALID_OPERATION, function_name,
9396 "target invalid for format");
9397 return false;
9399 return true;
9400 default:
9401 return false;
9405 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9406 const char* function_name,
9407 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9408 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9409 Texture* texture) {
9410 if (xoffset < 0 || yoffset < 0 || zoffset < 0) {
9411 LOCAL_SET_GL_ERROR(
9412 GL_INVALID_VALUE, function_name, "x/y/z offset < 0");
9413 return false;
9416 switch (format) {
9417 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9418 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9419 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9420 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
9421 const int kBlockWidth = 4;
9422 const int kBlockHeight = 4;
9423 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
9424 LOCAL_SET_GL_ERROR(
9425 GL_INVALID_OPERATION, function_name,
9426 "xoffset or yoffset not multiple of 4");
9427 return false;
9429 GLsizei tex_width = 0;
9430 GLsizei tex_height = 0;
9431 if (!texture->GetLevelSize(target, level,
9432 &tex_width, &tex_height, nullptr) ||
9433 width - xoffset > tex_width ||
9434 height - yoffset > tex_height) {
9435 LOCAL_SET_GL_ERROR(
9436 GL_INVALID_OPERATION, function_name, "dimensions out of range");
9437 return false;
9439 return ValidateCompressedTexDimensions(
9440 function_name, target, level, width, height, 1, format);
9442 case GL_ATC_RGB_AMD:
9443 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9444 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
9445 LOCAL_SET_GL_ERROR(
9446 GL_INVALID_OPERATION, function_name,
9447 "not supported for ATC textures");
9448 return false;
9450 case GL_ETC1_RGB8_OES: {
9451 LOCAL_SET_GL_ERROR(
9452 GL_INVALID_OPERATION, function_name,
9453 "not supported for ECT1_RGB8_OES textures");
9454 return false;
9456 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9457 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9458 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9459 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
9460 if ((xoffset != 0) || (yoffset != 0)) {
9461 LOCAL_SET_GL_ERROR(
9462 GL_INVALID_OPERATION, function_name,
9463 "xoffset and yoffset must be zero");
9464 return false;
9466 GLsizei tex_width = 0;
9467 GLsizei tex_height = 0;
9468 if (!texture->GetLevelSize(target, level,
9469 &tex_width, &tex_height, nullptr) ||
9470 width != tex_width ||
9471 height != tex_height) {
9472 LOCAL_SET_GL_ERROR(
9473 GL_INVALID_OPERATION, function_name,
9474 "dimensions must match existing texture level dimensions");
9475 return false;
9477 return ValidateCompressedTexDimensions(
9478 function_name, target, level, width, height, 1, format);
9481 // ES3 formats
9482 case GL_COMPRESSED_R11_EAC:
9483 case GL_COMPRESSED_SIGNED_R11_EAC:
9484 case GL_COMPRESSED_RG11_EAC:
9485 case GL_COMPRESSED_SIGNED_RG11_EAC:
9486 case GL_COMPRESSED_RGB8_ETC2:
9487 case GL_COMPRESSED_SRGB8_ETC2:
9488 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9489 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9490 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9491 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9493 const int kBlockSize = 4;
9494 GLsizei tex_width, tex_height;
9495 if (target == GL_TEXTURE_3D ||
9496 !texture->GetLevelSize(target, level,
9497 &tex_width, &tex_height, nullptr) ||
9498 (xoffset % kBlockSize) || (yoffset % kBlockSize) ||
9499 ((width % kBlockSize) && xoffset + width != tex_width) ||
9500 ((height % kBlockSize) && yoffset + height != tex_height)) {
9501 LOCAL_SET_GL_ERROR(
9502 GL_INVALID_OPERATION, function_name,
9503 "dimensions must match existing texture level dimensions");
9504 return false;
9506 return true;
9508 default:
9509 return false;
9513 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
9514 GLenum target,
9515 GLint level,
9516 GLenum internal_format,
9517 GLsizei width,
9518 GLsizei height,
9519 GLint border,
9520 GLsizei image_size,
9521 const void* data) {
9522 if (!validators_->texture_target.IsValid(target)) {
9523 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9524 "glCompressedTexImage2D", target, "target");
9525 return error::kNoError;
9527 if (!validators_->compressed_texture_format.IsValid(
9528 internal_format)) {
9529 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9530 "glCompressedTexImage2D", internal_format, "internal_format");
9531 return error::kNoError;
9533 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
9534 border != 0) {
9535 LOCAL_SET_GL_ERROR(
9536 GL_INVALID_VALUE,
9537 "glCompressedTexImage2D", "dimensions out of range");
9538 return error::kNoError;
9540 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9541 &state_, target);
9542 if (!texture_ref) {
9543 LOCAL_SET_GL_ERROR(
9544 GL_INVALID_VALUE,
9545 "glCompressedTexImage2D", "unknown texture target");
9546 return error::kNoError;
9548 Texture* texture = texture_ref->texture();
9549 if (texture->IsImmutable()) {
9550 LOCAL_SET_GL_ERROR(
9551 GL_INVALID_OPERATION,
9552 "glCompressedTexImage2D", "texture is immutable");
9553 return error::kNoError;
9556 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target, level,
9557 width, height, 1, internal_format) ||
9558 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width, height,
9559 1, internal_format, image_size)) {
9560 return error::kNoError;
9563 if (!EnsureGPUMemoryAvailable(image_size)) {
9564 LOCAL_SET_GL_ERROR(
9565 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
9566 return error::kNoError;
9569 if (texture->IsAttachedToFramebuffer()) {
9570 framebuffer_state_.clear_state_dirty = true;
9573 scoped_ptr<int8[]> zero;
9574 if (!data) {
9575 zero.reset(new int8[image_size]);
9576 memset(zero.get(), 0, image_size);
9577 data = zero.get();
9579 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9580 glCompressedTexImage2D(
9581 target, level, internal_format, width, height, border, image_size, data);
9582 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9583 if (error == GL_NO_ERROR) {
9584 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
9585 width, height, 1, border, 0, 0,
9586 gfx::Rect(width, height));
9589 // This may be a slow command. Exit command processing to allow for
9590 // context preemption and GPU watchdog checks.
9591 ExitCommandProcessingEarly();
9592 return error::kNoError;
9595 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
9596 uint32 immediate_data_size,
9597 const void* cmd_data) {
9598 const gles2::cmds::CompressedTexImage2D& c =
9599 *static_cast<const gles2::cmds::CompressedTexImage2D*>(cmd_data);
9600 GLenum target = static_cast<GLenum>(c.target);
9601 GLint level = static_cast<GLint>(c.level);
9602 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9603 GLsizei width = static_cast<GLsizei>(c.width);
9604 GLsizei height = static_cast<GLsizei>(c.height);
9605 GLint border = static_cast<GLint>(c.border);
9606 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9607 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9608 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9609 const void* data = NULL;
9610 if (data_shm_id != 0 || data_shm_offset != 0) {
9611 data = GetSharedMemoryAs<const void*>(
9612 data_shm_id, data_shm_offset, image_size);
9613 if (!data) {
9614 return error::kOutOfBounds;
9617 return DoCompressedTexImage2D(
9618 target, level, internal_format, width, height, border, image_size, data);
9621 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9622 uint32 immediate_data_size,
9623 const void* cmd_data) {
9624 const gles2::cmds::CompressedTexImage2DBucket& c =
9625 *static_cast<const gles2::cmds::CompressedTexImage2DBucket*>(cmd_data);
9626 GLenum target = static_cast<GLenum>(c.target);
9627 GLint level = static_cast<GLint>(c.level);
9628 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9629 GLsizei width = static_cast<GLsizei>(c.width);
9630 GLsizei height = static_cast<GLsizei>(c.height);
9631 GLint border = static_cast<GLint>(c.border);
9632 Bucket* bucket = GetBucket(c.bucket_id);
9633 if (!bucket) {
9634 return error::kInvalidArguments;
9636 uint32 data_size = bucket->size();
9637 GLsizei imageSize = data_size;
9638 const void* data = bucket->GetData(0, data_size);
9639 if (!data) {
9640 return error::kInvalidArguments;
9642 return DoCompressedTexImage2D(
9643 target, level, internal_format, width, height, border,
9644 imageSize, data);
9647 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9648 uint32 immediate_data_size,
9649 const void* cmd_data) {
9650 const gles2::cmds::CompressedTexSubImage2DBucket& c =
9651 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket*>(cmd_data);
9652 GLenum target = static_cast<GLenum>(c.target);
9653 GLint level = static_cast<GLint>(c.level);
9654 GLint xoffset = static_cast<GLint>(c.xoffset);
9655 GLint yoffset = static_cast<GLint>(c.yoffset);
9656 GLsizei width = static_cast<GLsizei>(c.width);
9657 GLsizei height = static_cast<GLsizei>(c.height);
9658 GLenum format = static_cast<GLenum>(c.format);
9659 Bucket* bucket = GetBucket(c.bucket_id);
9660 if (!bucket) {
9661 return error::kInvalidArguments;
9663 uint32 data_size = bucket->size();
9664 GLsizei imageSize = data_size;
9665 const void* data = bucket->GetData(0, data_size);
9666 if (!data) {
9667 return error::kInvalidArguments;
9669 if (!validators_->texture_target.IsValid(target)) {
9670 LOCAL_SET_GL_ERROR(
9671 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
9672 return error::kNoError;
9674 if (!validators_->compressed_texture_format.IsValid(format)) {
9675 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9676 "glCompressedTexSubImage2D", format, "format");
9677 return error::kNoError;
9679 if (width < 0) {
9680 LOCAL_SET_GL_ERROR(
9681 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
9682 return error::kNoError;
9684 if (height < 0) {
9685 LOCAL_SET_GL_ERROR(
9686 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
9687 return error::kNoError;
9689 if (imageSize < 0) {
9690 LOCAL_SET_GL_ERROR(
9691 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
9692 return error::kNoError;
9694 DoCompressedTexSubImage2D(
9695 target, level, xoffset, yoffset, width, height, format, imageSize, data);
9696 return error::kNoError;
9699 error::Error GLES2DecoderImpl::DoCompressedTexImage3D(
9700 GLenum target,
9701 GLint level,
9702 GLenum internal_format,
9703 GLsizei width,
9704 GLsizei height,
9705 GLsizei depth,
9706 GLint border,
9707 GLsizei image_size,
9708 const void* data) {
9709 if (!validators_->texture_3_d_target.IsValid(target)) {
9710 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9711 "glCompressedTexImage3D", target, "target");
9712 return error::kNoError;
9714 if (!validators_->compressed_texture_format.IsValid(
9715 internal_format)) {
9716 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9717 "glCompressedTexImage3D", internal_format, "internal_format");
9718 return error::kNoError;
9720 if (!texture_manager()->ValidForTarget(target, level, width, height, depth) ||
9721 border != 0) {
9722 LOCAL_SET_GL_ERROR(
9723 GL_INVALID_VALUE,
9724 "glCompressedTexImage3D", "dimensions out of range");
9725 return error::kNoError;
9727 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9728 &state_, target);
9729 if (!texture_ref) {
9730 LOCAL_SET_GL_ERROR(
9731 GL_INVALID_VALUE,
9732 "glCompressedTexImage3D", "unknown texture target");
9733 return error::kNoError;
9735 Texture* texture = texture_ref->texture();
9736 if (texture->IsImmutable()) {
9737 LOCAL_SET_GL_ERROR(
9738 GL_INVALID_OPERATION,
9739 "glCompressedTexImage3D", "texture is immutable");
9740 return error::kNoError;
9743 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target, level,
9744 width, height, depth, internal_format) ||
9745 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width, height,
9746 depth, internal_format, image_size)) {
9747 return error::kNoError;
9750 if (!EnsureGPUMemoryAvailable(image_size)) {
9751 LOCAL_SET_GL_ERROR(
9752 GL_OUT_OF_MEMORY, "glCompressedTexImage3D", "out of memory");
9753 return error::kNoError;
9756 if (texture->IsAttachedToFramebuffer()) {
9757 framebuffer_state_.clear_state_dirty = true;
9760 scoped_ptr<int8[]> zero;
9761 if (!data) {
9762 zero.reset(new int8[image_size]);
9763 memset(zero.get(), 0, image_size);
9764 data = zero.get();
9766 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9767 glCompressedTexImage3D(target, level, internal_format, width, height, depth,
9768 border, image_size, data);
9769 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9770 if (error == GL_NO_ERROR) {
9771 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
9772 width, height, depth, border, 0, 0,
9773 gfx::Rect(width, height));
9776 // This may be a slow command. Exit command processing to allow for
9777 // context preemption and GPU watchdog checks.
9778 ExitCommandProcessingEarly();
9779 return error::kNoError;
9782 error::Error GLES2DecoderImpl::HandleCompressedTexImage3D(
9783 uint32 immediate_data_size, const void* cmd_data) {
9784 if (!unsafe_es3_apis_enabled())
9785 return error::kUnknownCommand;
9787 const gles2::cmds::CompressedTexImage3D& c =
9788 *static_cast<const gles2::cmds::CompressedTexImage3D*>(cmd_data);
9789 GLenum target = static_cast<GLenum>(c.target);
9790 GLint level = static_cast<GLint>(c.level);
9791 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9792 GLsizei width = static_cast<GLsizei>(c.width);
9793 GLsizei height = static_cast<GLsizei>(c.height);
9794 GLsizei depth = static_cast<GLsizei>(c.depth);
9795 GLint border = static_cast<GLint>(c.border);
9796 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9797 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9798 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9799 const void* data = NULL;
9800 if (data_shm_id != 0 || data_shm_offset != 0) {
9801 data = GetSharedMemoryAs<const void*>(
9802 data_shm_id, data_shm_offset, image_size);
9803 if (!data) {
9804 return error::kOutOfBounds;
9807 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9808 depth, border, image_size, data);
9811 error::Error GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9812 uint32 immediate_data_size, const void* cmd_data) {
9813 if (!unsafe_es3_apis_enabled())
9814 return error::kUnknownCommand;
9816 const gles2::cmds::CompressedTexImage3DBucket& c =
9817 *static_cast<const gles2::cmds::CompressedTexImage3DBucket*>(cmd_data);
9818 GLenum target = static_cast<GLenum>(c.target);
9819 GLint level = static_cast<GLint>(c.level);
9820 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9821 GLsizei width = static_cast<GLsizei>(c.width);
9822 GLsizei height = static_cast<GLsizei>(c.height);
9823 GLsizei depth = static_cast<GLsizei>(c.depth);
9824 GLint border = static_cast<GLint>(c.border);
9825 Bucket* bucket = GetBucket(c.bucket_id);
9826 if (!bucket) {
9827 return error::kInvalidArguments;
9829 uint32 data_size = bucket->size();
9830 GLsizei imageSize = data_size;
9831 const void* data = bucket->GetData(0, data_size);
9832 if (!data) {
9833 return error::kInvalidArguments;
9835 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9836 depth, border, imageSize, data);
9839 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
9840 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9841 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9842 GLsizei image_size, const void* data) {
9843 if (!validators_->texture_3_d_target.IsValid(target)) {
9844 LOCAL_SET_GL_ERROR(
9845 GL_INVALID_ENUM, "glCompressedTexSubImage3D", "target");
9846 return;
9848 if (!validators_->compressed_texture_format.IsValid(format)) {
9849 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9850 "glCompressedTexSubImage3D", format, "format");
9851 return;
9853 if (width < 0 || height < 0 || depth < 0) {
9854 LOCAL_SET_GL_ERROR(
9855 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "size < 0");
9856 return;
9858 if (image_size < 0) {
9859 LOCAL_SET_GL_ERROR(
9860 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "imageSize < 0");
9861 return;
9863 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9864 &state_, target);
9865 if (!texture_ref) {
9866 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9867 "unknown texture for target");
9868 return;
9870 Texture* texture = texture_ref->texture();
9871 GLenum type = 0, internal_format = 0;
9872 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
9873 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9874 "level does not exist");
9875 return;
9877 if (internal_format != format) {
9878 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9879 "format does not match internal format");
9880 return;
9882 if (!texture->ValidForTexture(target, level, xoffset, yoffset, zoffset,
9883 width, height, depth, type)) {
9884 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedTexSubImage3D",
9885 "bad dimensions");
9886 return;
9888 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
9889 width, height, depth, format,
9890 image_size) ||
9891 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
9892 target, level, xoffset, yoffset,
9893 zoffset, width, height, depth,
9894 format, texture)) {
9895 return;
9898 // Note: There is no need to deal with texture cleared tracking here
9899 // because the validation above means you can only get here if the level
9900 // is already a matching compressed format and in that case
9901 // CompressedTexImage3D already cleared the texture.
9902 glCompressedTexSubImage3D(
9903 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
9904 image_size, data);
9906 // This may be a slow command. Exit command processing to allow for
9907 // context preemption and GPU watchdog checks.
9908 ExitCommandProcessingEarly();
9911 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
9912 uint32 immediate_data_size, const void* cmd_data) {
9913 if (!unsafe_es3_apis_enabled())
9914 return error::kUnknownCommand;
9915 const gles2::cmds::CompressedTexSubImage3DBucket& c =
9916 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket*>(cmd_data);
9917 GLenum target = static_cast<GLenum>(c.target);
9918 GLint level = static_cast<GLint>(c.level);
9919 GLint xoffset = static_cast<GLint>(c.xoffset);
9920 GLint yoffset = static_cast<GLint>(c.yoffset);
9921 GLint zoffset = static_cast<GLint>(c.zoffset);
9922 GLsizei width = static_cast<GLsizei>(c.width);
9923 GLsizei height = static_cast<GLsizei>(c.height);
9924 GLsizei depth = static_cast<GLsizei>(c.depth);
9925 GLenum format = static_cast<GLenum>(c.format);
9926 Bucket* bucket = GetBucket(c.bucket_id);
9927 if (!bucket) {
9928 return error::kInvalidArguments;
9930 uint32 data_size = bucket->size();
9931 GLsizei image_size = data_size;
9932 const void* data = bucket->GetData(0, data_size);
9933 if (!data) {
9934 return error::kInvalidArguments;
9936 DoCompressedTexSubImage3D(
9937 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
9938 image_size, data);
9939 return error::kNoError;
9942 error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
9943 const void* cmd_data) {
9944 const gles2::cmds::TexImage2D& c =
9945 *static_cast<const gles2::cmds::TexImage2D*>(cmd_data);
9946 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9947 "width", c.width, "height", c.height);
9948 // Set as failed for now, but if it successed, this will be set to not failed.
9949 texture_state_.tex_image_failed = true;
9950 GLenum target = static_cast<GLenum>(c.target);
9951 GLint level = static_cast<GLint>(c.level);
9952 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9953 // for internalformat.
9954 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9955 GLsizei width = static_cast<GLsizei>(c.width);
9956 GLsizei height = static_cast<GLsizei>(c.height);
9957 GLint border = static_cast<GLint>(c.border);
9958 GLenum format = static_cast<GLenum>(c.format);
9959 GLenum type = static_cast<GLenum>(c.type);
9960 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
9961 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
9962 uint32 pixels_size;
9963 if (!GLES2Util::ComputeImageDataSizes(
9964 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
9965 NULL, NULL)) {
9966 return error::kOutOfBounds;
9968 const void* pixels = NULL;
9969 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
9970 pixels = GetSharedMemoryAs<const void*>(
9971 pixels_shm_id, pixels_shm_offset, pixels_size);
9972 if (!pixels) {
9973 return error::kOutOfBounds;
9977 // For testing only. Allows us to stress the ability to respond to OOM errors.
9978 if (workarounds().simulate_out_of_memory_on_large_textures &&
9979 (width * height >= 4096 * 4096)) {
9980 LOCAL_SET_GL_ERROR(
9981 GL_OUT_OF_MEMORY,
9982 "glTexImage2D", "synthetic out of memory");
9983 return error::kNoError;
9986 TextureManager::DoTexImageArguments args = {
9987 target, level, internal_format, width, height, 1, border, format, type,
9988 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
9989 texture_manager()->ValidateAndDoTexImage(
9990 &texture_state_, &state_, &framebuffer_state_, "glTexImage2D", args);
9992 // This may be a slow command. Exit command processing to allow for
9993 // context preemption and GPU watchdog checks.
9994 ExitCommandProcessingEarly();
9995 return error::kNoError;
9998 error::Error GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size,
9999 const void* cmd_data) {
10000 if (!unsafe_es3_apis_enabled())
10001 return error::kUnknownCommand;
10003 const gles2::cmds::TexImage3D& c =
10004 *static_cast<const gles2::cmds::TexImage3D*>(cmd_data);
10005 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
10006 "widthXheight", c.width * c.height, "depth", c.depth);
10007 // Set as failed for now, but if it successed, this will be set to not failed.
10008 texture_state_.tex_image_failed = true;
10009 GLenum target = static_cast<GLenum>(c.target);
10010 GLint level = static_cast<GLint>(c.level);
10011 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10012 GLsizei width = static_cast<GLsizei>(c.width);
10013 GLsizei height = static_cast<GLsizei>(c.height);
10014 GLsizei depth = static_cast<GLsizei>(c.depth);
10015 GLint border = static_cast<GLint>(c.border);
10016 GLenum format = static_cast<GLenum>(c.format);
10017 GLenum type = static_cast<GLenum>(c.type);
10018 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10019 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10020 uint32 pixels_size;
10021 if (!GLES2Util::ComputeImageDataSizes(
10022 width, height, depth, format, type, state_.unpack_alignment, &pixels_size,
10023 NULL, NULL)) {
10024 return error::kOutOfBounds;
10026 const void* pixels = NULL;
10027 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10028 pixels = GetSharedMemoryAs<const void*>(
10029 pixels_shm_id, pixels_shm_offset, pixels_size);
10030 if (!pixels) {
10031 return error::kOutOfBounds;
10035 // For testing only. Allows us to stress the ability to respond to OOM errors.
10036 if (workarounds().simulate_out_of_memory_on_large_textures &&
10037 (width * height * depth >= 4096 * 4096)) {
10038 LOCAL_SET_GL_ERROR(
10039 GL_OUT_OF_MEMORY,
10040 "glTexImage3D", "synthetic out of memory");
10041 return error::kNoError;
10044 TextureManager::DoTexImageArguments args = {
10045 target, level, internal_format, width, height, depth, border, format, type,
10046 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage3D };
10047 texture_manager()->ValidateAndDoTexImage(
10048 &texture_state_, &state_, &framebuffer_state_, "glTexImage3D", args);
10050 // This may be a slow command. Exit command processing to allow for
10051 // context preemption and GPU watchdog checks.
10052 ExitCommandProcessingEarly();
10053 return error::kNoError;
10056 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
10057 GLenum target,
10058 GLint level,
10059 GLint xoffset,
10060 GLint yoffset,
10061 GLsizei width,
10062 GLsizei height,
10063 GLenum format,
10064 GLsizei image_size,
10065 const void * data) {
10066 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10067 &state_, target);
10068 if (!texture_ref) {
10069 LOCAL_SET_GL_ERROR(
10070 GL_INVALID_OPERATION,
10071 "glCompressedTexSubImage2D", "unknown texture for target");
10072 return;
10074 Texture* texture = texture_ref->texture();
10075 GLenum type = 0;
10076 GLenum internal_format = 0;
10077 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
10078 LOCAL_SET_GL_ERROR(
10079 GL_INVALID_OPERATION,
10080 "glCompressedTexSubImage2D", "level does not exist.");
10081 return;
10083 if (internal_format != format) {
10084 LOCAL_SET_GL_ERROR(
10085 GL_INVALID_OPERATION,
10086 "glCompressedTexSubImage2D", "format does not match internal format.");
10087 return;
10089 if (!texture->ValidForTexture(target, level, xoffset, yoffset, 0, width,
10090 height, 1, type)) {
10091 LOCAL_SET_GL_ERROR(
10092 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
10093 return;
10096 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
10097 width, height, 1, format, image_size) ||
10098 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
10099 target, level, xoffset, yoffset, 0,
10100 width, height, 1, format, texture)) {
10101 return;
10105 // Note: There is no need to deal with texture cleared tracking here
10106 // because the validation above means you can only get here if the level
10107 // is already a matching compressed format and in that case
10108 // CompressedTexImage2D already cleared the texture.
10109 glCompressedTexSubImage2D(
10110 target, level, xoffset, yoffset, width, height, format, image_size, data);
10112 // This may be a slow command. Exit command processing to allow for
10113 // context preemption and GPU watchdog checks.
10114 ExitCommandProcessingEarly();
10117 static void Clip(
10118 GLint start, GLint range, GLint sourceRange,
10119 GLint* out_start, GLint* out_range) {
10120 DCHECK(out_start);
10121 DCHECK(out_range);
10122 if (start < 0) {
10123 range += start;
10124 start = 0;
10126 GLint end = start + range;
10127 if (end > sourceRange) {
10128 range -= end - sourceRange;
10130 *out_start = start;
10131 *out_range = range;
10134 void GLES2DecoderImpl::DoCopyTexImage2D(
10135 GLenum target,
10136 GLint level,
10137 GLenum internal_format,
10138 GLint x,
10139 GLint y,
10140 GLsizei width,
10141 GLsizei height,
10142 GLint border) {
10143 DCHECK(!ShouldDeferReads());
10144 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10145 &state_, target);
10146 if (!texture_ref) {
10147 LOCAL_SET_GL_ERROR(
10148 GL_INVALID_OPERATION,
10149 "glCopyTexImage2D", "unknown texture for target");
10150 return;
10152 Texture* texture = texture_ref->texture();
10153 if (texture->IsImmutable()) {
10154 LOCAL_SET_GL_ERROR(
10155 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
10156 return;
10158 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
10159 border != 0) {
10160 LOCAL_SET_GL_ERROR(
10161 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
10162 return;
10164 if (!texture_manager()->ValidateFormatAndTypeCombination(
10165 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
10166 GL_UNSIGNED_BYTE)) {
10167 return;
10170 // Check we have compatible formats.
10171 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
10172 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
10173 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
10175 if ((channels_needed & channels_exist) != channels_needed) {
10176 LOCAL_SET_GL_ERROR(
10177 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
10178 return;
10181 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10182 LOCAL_SET_GL_ERROR(
10183 GL_INVALID_OPERATION,
10184 "glCopyTexImage2D", "can not be used with depth or stencil textures");
10185 return;
10188 uint32 estimated_size = 0;
10189 if (!GLES2Util::ComputeImageDataSizes(
10190 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
10191 state_.unpack_alignment, &estimated_size, NULL, NULL)) {
10192 LOCAL_SET_GL_ERROR(
10193 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
10194 return;
10197 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10198 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
10199 return;
10202 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
10203 return;
10206 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
10207 LOCAL_SET_GL_ERROR(
10208 GL_INVALID_OPERATION,
10209 "glCopyTexImage2D", "source and destination textures are the same");
10210 return;
10213 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
10214 return;
10217 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
10218 ScopedResolvedFrameBufferBinder binder(this, false, true);
10219 gfx::Size size = GetBoundReadFrameBufferSize();
10221 if (texture->IsAttachedToFramebuffer()) {
10222 framebuffer_state_.clear_state_dirty = true;
10225 // Clip to size to source dimensions
10226 GLint copyX = 0;
10227 GLint copyY = 0;
10228 GLint copyWidth = 0;
10229 GLint copyHeight = 0;
10230 Clip(x, width, size.width(), &copyX, &copyWidth);
10231 Clip(y, height, size.height(), &copyY, &copyHeight);
10233 if (copyX != x ||
10234 copyY != y ||
10235 copyWidth != width ||
10236 copyHeight != height) {
10237 // some part was clipped so clear the rect.
10238 uint32 pixels_size = 0;
10239 if (!GLES2Util::ComputeImageDataSizes(
10240 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
10241 state_.unpack_alignment, &pixels_size, NULL, NULL)) {
10242 LOCAL_SET_GL_ERROR(
10243 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
10244 return;
10246 scoped_ptr<char[]> zero(new char[pixels_size]);
10247 memset(zero.get(), 0, pixels_size);
10248 ScopedModifyPixels modify(texture_ref);
10249 glTexImage2D(target, level, internal_format, width, height, border,
10250 internal_format, GL_UNSIGNED_BYTE, zero.get());
10251 if (copyHeight > 0 && copyWidth > 0) {
10252 GLint dx = copyX - x;
10253 GLint dy = copyY - y;
10254 GLint destX = dx;
10255 GLint destY = dy;
10256 glCopyTexSubImage2D(target, level,
10257 destX, destY, copyX, copyY,
10258 copyWidth, copyHeight);
10260 } else {
10261 ScopedModifyPixels modify(texture_ref);
10262 glCopyTexImage2D(target, level, internal_format,
10263 copyX, copyY, copyWidth, copyHeight, border);
10265 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
10266 if (error == GL_NO_ERROR) {
10267 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
10268 width, height, 1, border, internal_format,
10269 GL_UNSIGNED_BYTE, gfx::Rect(width, height));
10272 // This may be a slow command. Exit command processing to allow for
10273 // context preemption and GPU watchdog checks.
10274 ExitCommandProcessingEarly();
10277 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10278 GLenum target,
10279 GLint level,
10280 GLint xoffset,
10281 GLint yoffset,
10282 GLint x,
10283 GLint y,
10284 GLsizei width,
10285 GLsizei height) {
10286 DCHECK(!ShouldDeferReads());
10287 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10288 &state_, target);
10289 if (!texture_ref) {
10290 LOCAL_SET_GL_ERROR(
10291 GL_INVALID_OPERATION,
10292 "glCopyTexSubImage2D", "unknown texture for target");
10293 return;
10295 Texture* texture = texture_ref->texture();
10296 GLenum type = 0;
10297 GLenum format = 0;
10298 if (!texture->GetLevelType(target, level, &type, &format) ||
10299 !texture->ValidForTexture(
10300 target, level, xoffset, yoffset, 0, width, height, 1, type)) {
10301 LOCAL_SET_GL_ERROR(
10302 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
10303 return;
10305 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10306 LOCAL_SET_GL_ERROR(
10307 GL_INVALID_OPERATION,
10308 "glCopyTexSubImage2D", "async upload pending for texture");
10309 return;
10312 // Check we have compatible formats.
10313 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
10314 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
10315 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
10317 if (!channels_needed ||
10318 (channels_needed & channels_exist) != channels_needed) {
10319 LOCAL_SET_GL_ERROR(
10320 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
10321 return;
10324 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10325 LOCAL_SET_GL_ERROR(
10326 GL_INVALID_OPERATION,
10327 "glCopySubImage2D", "can not be used with depth or stencil textures");
10328 return;
10331 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10332 return;
10335 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
10336 LOCAL_SET_GL_ERROR(
10337 GL_INVALID_OPERATION,
10338 "glCopyTexSubImage2D", "source and destination textures are the same");
10339 return;
10342 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10343 return;
10346 ScopedResolvedFrameBufferBinder binder(this, false, true);
10347 gfx::Size size = GetBoundReadFrameBufferSize();
10348 GLint copyX = 0;
10349 GLint copyY = 0;
10350 GLint copyWidth = 0;
10351 GLint copyHeight = 0;
10352 Clip(x, width, size.width(), &copyX, &copyWidth);
10353 Clip(y, height, size.height(), &copyY, &copyHeight);
10355 if (xoffset != 0 || yoffset != 0 || width != size.width() ||
10356 height != size.height()) {
10357 gfx::Rect cleared_rect;
10358 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
10359 gfx::Rect(xoffset, yoffset, width, height),
10360 &cleared_rect)) {
10361 DCHECK_GE(cleared_rect.size().GetArea(),
10362 texture->GetLevelClearedRect(target, level).size().GetArea());
10363 texture_manager()->SetLevelClearedRect(texture_ref, target, level,
10364 cleared_rect);
10365 } else {
10366 // Otherwise clear part of texture level that is not already cleared.
10367 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
10368 level)) {
10369 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D",
10370 "dimensions too big");
10371 return;
10374 } else {
10375 // Write all pixels in below.
10376 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10379 if (copyX != x ||
10380 copyY != y ||
10381 copyWidth != width ||
10382 copyHeight != height) {
10383 // some part was clipped so clear the sub rect.
10384 uint32 pixels_size = 0;
10385 if (!GLES2Util::ComputeImageDataSizes(
10386 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
10387 NULL, NULL)) {
10388 LOCAL_SET_GL_ERROR(
10389 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
10390 return;
10392 scoped_ptr<char[]> zero(new char[pixels_size]);
10393 memset(zero.get(), 0, pixels_size);
10394 ScopedModifyPixels modify(texture_ref);
10395 glTexSubImage2D(
10396 target, level, xoffset, yoffset, width, height,
10397 format, type, zero.get());
10400 if (copyHeight > 0 && copyWidth > 0) {
10401 GLint dx = copyX - x;
10402 GLint dy = copyY - y;
10403 GLint destX = xoffset + dx;
10404 GLint destY = yoffset + dy;
10405 ScopedModifyPixels modify(texture_ref);
10406 glCopyTexSubImage2D(target, level,
10407 destX, destY, copyX, copyY,
10408 copyWidth, copyHeight);
10411 // This may be a slow command. Exit command processing to allow for
10412 // context preemption and GPU watchdog checks.
10413 ExitCommandProcessingEarly();
10416 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10417 error::Error* error,
10418 const char* function_name,
10419 GLenum target,
10420 GLint level,
10421 GLint xoffset,
10422 GLint yoffset,
10423 GLsizei width,
10424 GLsizei height,
10425 GLenum format,
10426 GLenum type,
10427 const void * data) {
10428 (*error) = error::kNoError;
10429 if (!validators_->texture_target.IsValid(target)) {
10430 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10431 return false;
10433 if (width < 0) {
10434 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
10435 return false;
10437 if (height < 0) {
10438 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
10439 return false;
10441 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10442 &state_, target);
10443 if (!texture_ref) {
10444 LOCAL_SET_GL_ERROR(
10445 GL_INVALID_OPERATION,
10446 function_name, "unknown texture for target");
10447 return false;
10449 Texture* texture = texture_ref->texture();
10450 GLenum current_type = 0;
10451 GLenum internal_format = 0;
10452 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
10453 LOCAL_SET_GL_ERROR(
10454 GL_INVALID_OPERATION, function_name, "level does not exist.");
10455 return false;
10457 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
10458 function_name, format, type, internal_format, level)) {
10459 return false;
10461 if (type != current_type) {
10462 LOCAL_SET_GL_ERROR(
10463 GL_INVALID_OPERATION,
10464 function_name, "type does not match type of texture.");
10465 return false;
10467 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10468 LOCAL_SET_GL_ERROR(
10469 GL_INVALID_OPERATION,
10470 function_name, "async upload pending for texture");
10471 return false;
10473 if (!texture->ValidForTexture(
10474 target, level, xoffset, yoffset, 0, width, height, 1, type)) {
10475 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
10476 return false;
10478 if ((GLES2Util::GetChannelsForFormat(format) &
10479 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0
10480 && !feature_info_->IsES3Enabled()) {
10481 LOCAL_SET_GL_ERROR(
10482 GL_INVALID_OPERATION,
10483 function_name, "can not supply data for depth or stencil textures");
10484 return false;
10486 if (data == NULL) {
10487 (*error) = error::kOutOfBounds;
10488 return false;
10490 return true;
10493 error::Error GLES2DecoderImpl::DoTexSubImage2D(
10494 GLenum target,
10495 GLint level,
10496 GLint xoffset,
10497 GLint yoffset,
10498 GLsizei width,
10499 GLsizei height,
10500 GLenum format,
10501 GLenum type,
10502 const void * data) {
10503 error::Error error = error::kNoError;
10504 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
10505 xoffset, yoffset, width, height, format, type, data)) {
10506 return error;
10508 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10509 &state_, target);
10510 Texture* texture = texture_ref->texture();
10511 GLsizei tex_width = 0;
10512 GLsizei tex_height = 0;
10513 bool ok = texture->GetLevelSize(
10514 target, level, &tex_width, &tex_height, nullptr);
10515 DCHECK(ok);
10516 if (xoffset != 0 || yoffset != 0 ||
10517 width != tex_width || height != tex_height) {
10518 gfx::Rect cleared_rect;
10519 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
10520 gfx::Rect(xoffset, yoffset, width, height),
10521 &cleared_rect)) {
10522 DCHECK_GE(cleared_rect.size().GetArea(),
10523 texture->GetLevelClearedRect(target, level).size().GetArea());
10524 texture_manager()->SetLevelClearedRect(texture_ref, target, level,
10525 cleared_rect);
10526 } else {
10527 // Otherwise clear part of texture level that is not already cleared.
10528 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
10529 level)) {
10530 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexSubImage2D",
10531 "dimensions too big");
10532 return error::kNoError;
10535 ScopedTextureUploadTimer timer(&texture_state_);
10536 glTexSubImage2D(
10537 target, level, xoffset, yoffset, width, height, format, type, data);
10538 return error::kNoError;
10541 if (!texture_state_.texsubimage_faster_than_teximage &&
10542 !texture->IsImmutable() &&
10543 !texture->HasImages()) {
10544 ScopedTextureUploadTimer timer(&texture_state_);
10545 GLenum internal_format;
10546 GLenum tex_type;
10547 texture->GetLevelType(target, level, &tex_type, &internal_format);
10548 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
10549 // to look it up.
10550 glTexImage2D(
10551 target, level, internal_format, width, height, 0, format, type, data);
10552 } else {
10553 ScopedTextureUploadTimer timer(&texture_state_);
10554 glTexSubImage2D(
10555 target, level, xoffset, yoffset, width, height, format, type, data);
10557 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10559 // This may be a slow command. Exit command processing to allow for
10560 // context preemption and GPU watchdog checks.
10561 ExitCommandProcessingEarly();
10562 return error::kNoError;
10565 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
10566 const void* cmd_data) {
10567 const gles2::cmds::TexSubImage2D& c =
10568 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
10569 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
10570 "width", c.width, "height", c.height);
10571 GLboolean internal = static_cast<GLboolean>(c.internal);
10572 if (internal == GL_TRUE && texture_state_.tex_image_failed)
10573 return error::kNoError;
10575 GLenum target = static_cast<GLenum>(c.target);
10576 GLint level = static_cast<GLint>(c.level);
10577 GLint xoffset = static_cast<GLint>(c.xoffset);
10578 GLint yoffset = static_cast<GLint>(c.yoffset);
10579 GLsizei width = static_cast<GLsizei>(c.width);
10580 GLsizei height = static_cast<GLsizei>(c.height);
10581 GLenum format = static_cast<GLenum>(c.format);
10582 GLenum type = static_cast<GLenum>(c.type);
10583 uint32 data_size;
10584 if (!GLES2Util::ComputeImageDataSizes(
10585 width, height, 1, format, type, state_.unpack_alignment, &data_size,
10586 NULL, NULL)) {
10587 return error::kOutOfBounds;
10589 const void* pixels = GetSharedMemoryAs<const void*>(
10590 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10591 return DoTexSubImage2D(
10592 target, level, xoffset, yoffset, width, height, format, type, pixels);
10595 error::Error GLES2DecoderImpl::DoTexSubImage3D(
10596 GLenum target,
10597 GLint level,
10598 GLint xoffset,
10599 GLint yoffset,
10600 GLint zoffset,
10601 GLsizei width,
10602 GLsizei height,
10603 GLsizei depth,
10604 GLenum format,
10605 GLenum type,
10606 const void * data) {
10607 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10608 &state_, target);
10609 if (!texture_ref) {
10610 LOCAL_SET_GL_ERROR(
10611 GL_INVALID_ENUM, "glTexSubImage3D", "invalid target");
10614 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
10615 ScopedTextureUploadTimer timer(&texture_state_);
10616 glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
10617 depth, format, type, data);
10618 GLenum error = LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
10619 if (error == GL_NO_ERROR) {
10620 // TODO(zmo): This is not 100% correct because only part of the level
10621 // image is cleared.
10622 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10625 // This may be a slow command. Exit command processing to allow for
10626 // context preemption and GPU watchdog checks.
10627 ExitCommandProcessingEarly();
10628 return error::kNoError;
10631 error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size,
10632 const void* cmd_data) {
10633 if (!unsafe_es3_apis_enabled())
10634 return error::kUnknownCommand;
10636 const gles2::cmds::TexSubImage3D& c =
10637 *static_cast<const gles2::cmds::TexSubImage3D*>(cmd_data);
10638 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10639 "widthXheight", c.width * c.height, "depth", c.depth);
10640 GLboolean internal = static_cast<GLboolean>(c.internal);
10641 if (internal == GL_TRUE && texture_state_.tex_image_failed)
10642 return error::kNoError;
10644 GLenum target = static_cast<GLenum>(c.target);
10645 GLint level = static_cast<GLint>(c.level);
10646 GLint xoffset = static_cast<GLint>(c.xoffset);
10647 GLint yoffset = static_cast<GLint>(c.yoffset);
10648 GLint zoffset = static_cast<GLint>(c.zoffset);
10649 GLsizei width = static_cast<GLsizei>(c.width);
10650 GLsizei height = static_cast<GLsizei>(c.height);
10651 GLsizei depth = static_cast<GLsizei>(c.depth);
10652 GLenum format = static_cast<GLenum>(c.format);
10653 GLenum type = static_cast<GLenum>(c.type);
10654 uint32 data_size;
10655 if (!GLES2Util::ComputeImageDataSizes(
10656 width, height, depth, format, type, state_.unpack_alignment, &data_size,
10657 NULL, NULL)) {
10658 return error::kOutOfBounds;
10660 const void* pixels = GetSharedMemoryAs<const void*>(
10661 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10662 return DoTexSubImage3D(target, level, xoffset, yoffset, zoffset, width,
10663 height, depth, format, type, pixels);
10666 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10667 uint32 immediate_data_size,
10668 const void* cmd_data) {
10669 const gles2::cmds::GetVertexAttribPointerv& c =
10670 *static_cast<const gles2::cmds::GetVertexAttribPointerv*>(cmd_data);
10671 GLuint index = static_cast<GLuint>(c.index);
10672 GLenum pname = static_cast<GLenum>(c.pname);
10673 typedef cmds::GetVertexAttribPointerv::Result Result;
10674 Result* result = GetSharedMemoryAs<Result*>(
10675 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
10676 if (!result) {
10677 return error::kOutOfBounds;
10679 // Check that the client initialized the result.
10680 if (result->size != 0) {
10681 return error::kInvalidArguments;
10683 if (!validators_->vertex_pointer.IsValid(pname)) {
10684 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10685 "glGetVertexAttribPointerv", pname, "pname");
10686 return error::kNoError;
10688 if (index >= group_->max_vertex_attribs()) {
10689 LOCAL_SET_GL_ERROR(
10690 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
10691 return error::kNoError;
10693 result->SetNumResults(1);
10694 *result->GetData() =
10695 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
10696 return error::kNoError;
10699 template <class T>
10700 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id,
10701 GLint fake_location,
10702 uint32 shm_id,
10703 uint32 shm_offset,
10704 error::Error* error,
10705 GLint* real_location,
10706 GLuint* service_id,
10707 SizedResult<T>** result_pointer,
10708 GLenum* result_type,
10709 GLsizei* result_size) {
10710 DCHECK(error);
10711 DCHECK(service_id);
10712 DCHECK(result_pointer);
10713 DCHECK(result_type);
10714 DCHECK(result_size);
10715 DCHECK(real_location);
10716 *error = error::kNoError;
10717 // Make sure we have enough room for the result on failure.
10718 SizedResult<T>* result;
10719 result = GetSharedMemoryAs<SizedResult<T>*>(
10720 shm_id, shm_offset, SizedResult<T>::ComputeSize(0));
10721 if (!result) {
10722 *error = error::kOutOfBounds;
10723 return false;
10725 *result_pointer = result;
10726 // Set the result size to 0 so the client does not have to check for success.
10727 result->SetNumResults(0);
10728 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
10729 if (!program) {
10730 return false;
10732 if (!program->IsValid()) {
10733 // Program was not linked successfully. (ie, glLinkProgram)
10734 LOCAL_SET_GL_ERROR(
10735 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
10736 return false;
10738 *service_id = program->service_id();
10739 GLint array_index = -1;
10740 const Program::UniformInfo* uniform_info =
10741 program->GetUniformInfoByFakeLocation(
10742 fake_location, real_location, &array_index);
10743 if (!uniform_info) {
10744 // No such location.
10745 LOCAL_SET_GL_ERROR(
10746 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
10747 return false;
10749 GLenum type = uniform_info->type;
10750 uint32 num_elements = GLES2Util::GetElementCountForUniformType(type);
10751 if (num_elements == 0) {
10752 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
10753 return false;
10755 result = GetSharedMemoryAs<SizedResult<T>*>(
10756 shm_id, shm_offset, SizedResult<T>::ComputeSize(num_elements));
10757 if (!result) {
10758 *error = error::kOutOfBounds;
10759 return false;
10761 result->SetNumResults(num_elements);
10762 *result_size = num_elements * sizeof(T);
10763 *result_type = type;
10764 return true;
10767 error::Error GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size,
10768 const void* cmd_data) {
10769 const gles2::cmds::GetUniformiv& c =
10770 *static_cast<const gles2::cmds::GetUniformiv*>(cmd_data);
10771 GLuint program = c.program;
10772 GLint fake_location = c.location;
10773 GLuint service_id;
10774 GLenum result_type;
10775 GLsizei result_size;
10776 GLint real_location = -1;
10777 Error error;
10778 cmds::GetUniformiv::Result* result;
10779 if (GetUniformSetup<GLint>(program, fake_location, c.params_shm_id,
10780 c.params_shm_offset, &error, &real_location,
10781 &service_id, &result, &result_type,
10782 &result_size)) {
10783 glGetUniformiv(
10784 service_id, real_location, result->GetData());
10786 return error;
10789 error::Error GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size,
10790 const void* cmd_data) {
10791 if (!unsafe_es3_apis_enabled())
10792 return error::kUnknownCommand;
10794 const gles2::cmds::GetUniformuiv& c =
10795 *static_cast<const gles2::cmds::GetUniformuiv*>(cmd_data);
10796 GLuint program = c.program;
10797 GLint fake_location = c.location;
10798 GLuint service_id;
10799 GLenum result_type;
10800 GLsizei result_size;
10801 GLint real_location = -1;
10802 Error error;
10803 cmds::GetUniformuiv::Result* result;
10804 if (GetUniformSetup<GLuint>(program, fake_location, c.params_shm_id,
10805 c.params_shm_offset, &error, &real_location,
10806 &service_id, &result, &result_type,
10807 &result_size)) {
10808 glGetUniformuiv(
10809 service_id, real_location, result->GetData());
10811 return error;
10814 error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size,
10815 const void* cmd_data) {
10816 const gles2::cmds::GetUniformfv& c =
10817 *static_cast<const gles2::cmds::GetUniformfv*>(cmd_data);
10818 GLuint program = c.program;
10819 GLint fake_location = c.location;
10820 GLuint service_id;
10821 GLint real_location = -1;
10822 Error error;
10823 cmds::GetUniformfv::Result* result;
10824 GLenum result_type;
10825 GLsizei result_size;
10826 if (GetUniformSetup<GLfloat>(program, fake_location, c.params_shm_id,
10827 c.params_shm_offset, &error, &real_location,
10828 &service_id, &result, &result_type,
10829 &result_size)) {
10830 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
10831 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
10832 GLsizei num_values = result_size / sizeof(GLfloat);
10833 scoped_ptr<GLint[]> temp(new GLint[num_values]);
10834 glGetUniformiv(service_id, real_location, temp.get());
10835 GLfloat* dst = result->GetData();
10836 for (GLsizei ii = 0; ii < num_values; ++ii) {
10837 dst[ii] = (temp[ii] != 0);
10839 } else {
10840 glGetUniformfv(service_id, real_location, result->GetData());
10843 return error;
10846 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10847 uint32 immediate_data_size,
10848 const void* cmd_data) {
10849 const gles2::cmds::GetShaderPrecisionFormat& c =
10850 *static_cast<const gles2::cmds::GetShaderPrecisionFormat*>(cmd_data);
10851 GLenum shader_type = static_cast<GLenum>(c.shadertype);
10852 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
10853 typedef cmds::GetShaderPrecisionFormat::Result Result;
10854 Result* result = GetSharedMemoryAs<Result*>(
10855 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10856 if (!result) {
10857 return error::kOutOfBounds;
10859 // Check that the client initialized the result.
10860 if (result->success != 0) {
10861 return error::kInvalidArguments;
10863 if (!validators_->shader_type.IsValid(shader_type)) {
10864 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10865 "glGetShaderPrecisionFormat", shader_type, "shader_type");
10866 return error::kNoError;
10868 if (!validators_->shader_precision.IsValid(precision_type)) {
10869 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10870 "glGetShaderPrecisionFormat", precision_type, "precision_type");
10871 return error::kNoError;
10874 result->success = 1; // true
10876 GLint range[2] = { 0, 0 };
10877 GLint precision = 0;
10878 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
10880 result->min_range = range[0];
10881 result->max_range = range[1];
10882 result->precision = precision;
10884 return error::kNoError;
10887 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
10888 uint32 immediate_data_size,
10889 const void* cmd_data) {
10890 const gles2::cmds::GetAttachedShaders& c =
10891 *static_cast<const gles2::cmds::GetAttachedShaders*>(cmd_data);
10892 uint32 result_size = c.result_size;
10893 GLuint program_id = static_cast<GLuint>(c.program);
10894 Program* program = GetProgramInfoNotShader(
10895 program_id, "glGetAttachedShaders");
10896 if (!program) {
10897 return error::kNoError;
10899 typedef cmds::GetAttachedShaders::Result Result;
10900 uint32 max_count = Result::ComputeMaxResults(result_size);
10901 Result* result = GetSharedMemoryAs<Result*>(
10902 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
10903 if (!result) {
10904 return error::kOutOfBounds;
10906 // Check that the client initialized the result.
10907 if (result->size != 0) {
10908 return error::kInvalidArguments;
10910 GLsizei count = 0;
10911 glGetAttachedShaders(
10912 program->service_id(), max_count, &count, result->GetData());
10913 for (GLsizei ii = 0; ii < count; ++ii) {
10914 if (!shader_manager()->GetClientId(result->GetData()[ii],
10915 &result->GetData()[ii])) {
10916 NOTREACHED();
10917 return error::kGenericError;
10920 result->SetNumResults(count);
10921 return error::kNoError;
10924 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
10925 uint32 immediate_data_size,
10926 const void* cmd_data) {
10927 const gles2::cmds::GetActiveUniform& c =
10928 *static_cast<const gles2::cmds::GetActiveUniform*>(cmd_data);
10929 GLuint program_id = c.program;
10930 GLuint index = c.index;
10931 uint32 name_bucket_id = c.name_bucket_id;
10932 typedef cmds::GetActiveUniform::Result Result;
10933 Result* result = GetSharedMemoryAs<Result*>(
10934 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10935 if (!result) {
10936 return error::kOutOfBounds;
10938 // Check that the client initialized the result.
10939 if (result->success != 0) {
10940 return error::kInvalidArguments;
10942 Program* program = GetProgramInfoNotShader(
10943 program_id, "glGetActiveUniform");
10944 if (!program) {
10945 return error::kNoError;
10947 const Program::UniformInfo* uniform_info =
10948 program->GetUniformInfo(index);
10949 if (!uniform_info) {
10950 LOCAL_SET_GL_ERROR(
10951 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
10952 return error::kNoError;
10954 result->success = 1; // true.
10955 result->size = uniform_info->size;
10956 result->type = uniform_info->type;
10957 Bucket* bucket = CreateBucket(name_bucket_id);
10958 bucket->SetFromString(uniform_info->name.c_str());
10959 return error::kNoError;
10962 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10963 uint32 immediate_data_size, const void* cmd_data) {
10964 if (!unsafe_es3_apis_enabled())
10965 return error::kUnknownCommand;
10966 const gles2::cmds::GetActiveUniformBlockiv& c =
10967 *static_cast<const gles2::cmds::GetActiveUniformBlockiv*>(cmd_data);
10968 GLuint program_id = c.program;
10969 GLuint index = static_cast<GLuint>(c.index);
10970 GLenum pname = static_cast<GLenum>(c.pname);
10971 Program* program = GetProgramInfoNotShader(
10972 program_id, "glGetActiveUniformBlockiv");
10973 if (!program) {
10974 return error::kNoError;
10976 GLuint service_id = program->service_id();
10977 GLint link_status = GL_FALSE;
10978 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10979 if (link_status != GL_TRUE) {
10980 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10981 "glGetActiveActiveUniformBlockiv", "program not linked");
10982 return error::kNoError;
10984 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10985 GLsizei num_values = 1;
10986 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
10987 GLint num = 0;
10988 glGetActiveUniformBlockiv(
10989 service_id, index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &num);
10990 GLenum error = glGetError();
10991 if (error != GL_NO_ERROR) {
10992 // Assume this will the same error if calling with pname.
10993 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
10994 return error::kNoError;
10996 num_values = static_cast<GLsizei>(num);
10998 typedef cmds::GetActiveUniformBlockiv::Result Result;
10999 Result* result = GetSharedMemoryAs<Result*>(
11000 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
11001 GLint* params = result ? result->GetData() : NULL;
11002 if (params == NULL) {
11003 return error::kOutOfBounds;
11005 // Check that the client initialized the result.
11006 if (result->size != 0) {
11007 return error::kInvalidArguments;
11009 glGetActiveUniformBlockiv(service_id, index, pname, params);
11010 GLenum error = glGetError();
11011 if (error == GL_NO_ERROR) {
11012 result->SetNumResults(num_values);
11013 } else {
11014 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
11016 return error::kNoError;
11019 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName(
11020 uint32 immediate_data_size, const void* cmd_data) {
11021 if (!unsafe_es3_apis_enabled())
11022 return error::kUnknownCommand;
11023 const gles2::cmds::GetActiveUniformBlockName& c =
11024 *static_cast<const gles2::cmds::GetActiveUniformBlockName*>(cmd_data);
11025 GLuint program_id = c.program;
11026 GLuint index = c.index;
11027 uint32 name_bucket_id = c.name_bucket_id;
11028 typedef cmds::GetActiveUniformBlockName::Result Result;
11029 Result* result = GetSharedMemoryAs<Result*>(
11030 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11031 if (!result) {
11032 return error::kOutOfBounds;
11034 // Check that the client initialized the result.
11035 if (*result != 0) {
11036 return error::kInvalidArguments;
11038 Program* program = GetProgramInfoNotShader(
11039 program_id, "glGetActiveUniformBlockName");
11040 if (!program) {
11041 return error::kNoError;
11043 GLuint service_id = program->service_id();
11044 GLint link_status = GL_FALSE;
11045 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11046 if (link_status != GL_TRUE) {
11047 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11048 "glGetActiveActiveUniformBlockName", "program not linked");
11049 return error::kNoError;
11051 GLint max_length = 0;
11052 glGetProgramiv(
11053 service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_length);
11054 // Increase one so &buffer[0] is always valid.
11055 GLsizei buf_size = static_cast<GLsizei>(max_length) + 1;
11056 std::vector<char> buffer(buf_size);
11057 GLsizei length = 0;
11058 glGetActiveUniformBlockName(
11059 service_id, index, buf_size, &length, &buffer[0]);
11060 if (length == 0) {
11061 *result = 0;
11062 return error::kNoError;
11064 *result = 1;
11065 Bucket* bucket = CreateBucket(name_bucket_id);
11066 DCHECK_GT(buf_size, length);
11067 DCHECK_EQ(0, buffer[length]);
11068 bucket->SetFromString(&buffer[0]);
11069 return error::kNoError;
11072 error::Error GLES2DecoderImpl::HandleGetActiveUniformsiv(
11073 uint32 immediate_data_size, const void* cmd_data) {
11074 if (!unsafe_es3_apis_enabled())
11075 return error::kUnknownCommand;
11076 const gles2::cmds::GetActiveUniformsiv& c =
11077 *static_cast<const gles2::cmds::GetActiveUniformsiv*>(cmd_data);
11078 GLuint program_id = c.program;
11079 GLenum pname = static_cast<GLenum>(c.pname);
11080 Bucket* bucket = GetBucket(c.indices_bucket_id);
11081 if (!bucket) {
11082 return error::kInvalidArguments;
11084 GLsizei count = static_cast<GLsizei>(bucket->size() / sizeof(GLuint));
11085 const GLuint* indices = bucket->GetDataAs<const GLuint*>(0, bucket->size());
11086 typedef cmds::GetActiveUniformsiv::Result Result;
11087 Result* result = GetSharedMemoryAs<Result*>(
11088 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(count));
11089 GLint* params = result ? result->GetData() : NULL;
11090 if (params == NULL) {
11091 return error::kOutOfBounds;
11093 // Check that the client initialized the result.
11094 if (result->size != 0) {
11095 return error::kInvalidArguments;
11097 Program* program = GetProgramInfoNotShader(
11098 program_id, "glGetActiveUniformsiv");
11099 if (!program) {
11100 return error::kNoError;
11102 GLuint service_id = program->service_id();
11103 GLint link_status = GL_FALSE;
11104 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11105 if (link_status != GL_TRUE) {
11106 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11107 "glGetActiveUniformsiv", "program not linked");
11108 return error::kNoError;
11110 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
11111 glGetActiveUniformsiv(service_id, count, indices, pname, params);
11112 GLenum error = glGetError();
11113 if (error == GL_NO_ERROR) {
11114 result->SetNumResults(count);
11115 } else {
11116 LOCAL_SET_GL_ERROR(error, "GetActiveUniformsiv", "");
11118 return error::kNoError;
11121 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
11122 const void* cmd_data) {
11123 const gles2::cmds::GetActiveAttrib& c =
11124 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data);
11125 GLuint program_id = c.program;
11126 GLuint index = c.index;
11127 uint32 name_bucket_id = c.name_bucket_id;
11128 typedef cmds::GetActiveAttrib::Result Result;
11129 Result* result = GetSharedMemoryAs<Result*>(
11130 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11131 if (!result) {
11132 return error::kOutOfBounds;
11134 // Check that the client initialized the result.
11135 if (result->success != 0) {
11136 return error::kInvalidArguments;
11138 Program* program = GetProgramInfoNotShader(
11139 program_id, "glGetActiveAttrib");
11140 if (!program) {
11141 return error::kNoError;
11143 const Program::VertexAttrib* attrib_info =
11144 program->GetAttribInfo(index);
11145 if (!attrib_info) {
11146 LOCAL_SET_GL_ERROR(
11147 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
11148 return error::kNoError;
11150 result->success = 1; // true.
11151 result->size = attrib_info->size;
11152 result->type = attrib_info->type;
11153 Bucket* bucket = CreateBucket(name_bucket_id);
11154 bucket->SetFromString(attrib_info->name.c_str());
11155 return error::kNoError;
11158 error::Error GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size,
11159 const void* cmd_data) {
11160 #if 1 // No binary shader support.
11161 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
11162 return error::kNoError;
11163 #else
11164 GLsizei n = static_cast<GLsizei>(c.n);
11165 if (n < 0) {
11166 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
11167 return error::kNoError;
11169 GLsizei length = static_cast<GLsizei>(c.length);
11170 if (length < 0) {
11171 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
11172 return error::kNoError;
11174 uint32 data_size;
11175 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
11176 return error::kOutOfBounds;
11178 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
11179 c.shaders_shm_id, c.shaders_shm_offset, data_size);
11180 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
11181 const void* binary = GetSharedMemoryAs<const void*>(
11182 c.binary_shm_id, c.binary_shm_offset, length);
11183 if (shaders == NULL || binary == NULL) {
11184 return error::kOutOfBounds;
11186 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
11187 for (GLsizei ii = 0; ii < n; ++ii) {
11188 Shader* shader = GetShader(shaders[ii]);
11189 if (!shader) {
11190 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
11191 return error::kNoError;
11193 service_ids[ii] = shader->service_id();
11195 // TODO(gman): call glShaderBinary
11196 return error::kNoError;
11197 #endif
11200 void GLES2DecoderImpl::DoSwapBuffers() {
11201 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
11203 int this_frame_number = frame_number_++;
11204 // TRACE_EVENT for gpu tests:
11205 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
11206 TRACE_EVENT_SCOPE_THREAD,
11207 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
11208 "width", (is_offscreen ? offscreen_size_.width() :
11209 surface_->GetSize().width()));
11210 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
11211 "offscreen", is_offscreen,
11212 "frame", this_frame_number);
11214 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
11217 ScopedGPUTrace scoped_gpu_trace(gpu_tracer_.get(), kTraceDecoder,
11218 "GLES2Decoder", "SwapBuffer");
11220 bool is_tracing;
11221 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
11222 &is_tracing);
11223 if (is_tracing) {
11224 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
11225 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
11226 is_offscreen ? offscreen_size_ : surface_->GetSize());
11229 // If offscreen then don't actually SwapBuffers to the display. Just copy
11230 // the rendered frame to another frame buffer.
11231 if (is_offscreen) {
11232 TRACE_EVENT2("gpu", "Offscreen",
11233 "width", offscreen_size_.width(), "height", offscreen_size_.height());
11234 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
11235 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
11236 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
11237 // fix this.
11238 if (workarounds().needs_offscreen_buffer_workaround) {
11239 offscreen_saved_frame_buffer_->Create();
11240 glFinish();
11243 // Allocate the offscreen saved color texture.
11244 DCHECK(offscreen_saved_color_format_);
11245 offscreen_saved_color_texture_->AllocateStorage(
11246 offscreen_size_, offscreen_saved_color_format_, false);
11248 offscreen_saved_frame_buffer_->AttachRenderTexture(
11249 offscreen_saved_color_texture_.get());
11250 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
11251 if (offscreen_saved_frame_buffer_->CheckStatus() !=
11252 GL_FRAMEBUFFER_COMPLETE) {
11253 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
11254 << "because offscreen saved FBO was incomplete.";
11255 MarkContextLost(error::kUnknown);
11256 group_->LoseContexts(error::kUnknown);
11257 return;
11260 // Clear the offscreen color texture.
11261 // TODO(piman): Is this still necessary?
11263 ScopedFrameBufferBinder binder(this,
11264 offscreen_saved_frame_buffer_->id());
11265 glClearColor(0, 0, 0, 0);
11266 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
11267 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
11268 glClear(GL_COLOR_BUFFER_BIT);
11269 RestoreClearState();
11273 UpdateParentTextureInfo();
11276 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
11277 return;
11278 ScopedGLErrorSuppressor suppressor(
11279 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
11281 if (IsOffscreenBufferMultisampled()) {
11282 // For multisampled buffers, resolve the frame buffer.
11283 ScopedResolvedFrameBufferBinder binder(this, true, false);
11284 } else {
11285 ScopedFrameBufferBinder binder(this,
11286 offscreen_target_frame_buffer_->id());
11288 if (offscreen_target_buffer_preserved_) {
11289 // Copy the target frame buffer to the saved offscreen texture.
11290 offscreen_saved_color_texture_->Copy(
11291 offscreen_saved_color_texture_->size(),
11292 offscreen_saved_color_format_);
11293 } else {
11294 // Flip the textures in the parent context via the texture manager.
11295 if (!!offscreen_saved_color_texture_info_.get())
11296 offscreen_saved_color_texture_info_->texture()->
11297 SetServiceId(offscreen_target_color_texture_->id());
11299 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
11300 offscreen_target_frame_buffer_->AttachRenderTexture(
11301 offscreen_target_color_texture_.get());
11304 // Ensure the side effects of the copy are visible to the parent
11305 // context. There is no need to do this for ANGLE because it uses a
11306 // single D3D device for all contexts.
11307 if (!feature_info_->gl_version_info().is_angle)
11308 glFlush();
11310 } else {
11311 if (surface_->SwapBuffers() == gfx::SwapResult::SWAP_FAILED) {
11312 LOG(ERROR) << "Context lost because SwapBuffers failed.";
11313 if (!CheckResetStatus()) {
11314 MarkContextLost(error::kUnknown);
11315 group_->LoseContexts(error::kUnknown);
11320 // This may be a slow command. Exit command processing to allow for
11321 // context preemption and GPU watchdog checks.
11322 ExitCommandProcessingEarly();
11325 void GLES2DecoderImpl::DoSwapInterval(int interval) {
11326 context_->SetSwapInterval(interval);
11329 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11330 uint32 immediate_data_size,
11331 const void* cmd_data) {
11332 const gles2::cmds::EnableFeatureCHROMIUM& c =
11333 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM*>(cmd_data);
11334 Bucket* bucket = GetBucket(c.bucket_id);
11335 if (!bucket || bucket->size() == 0) {
11336 return error::kInvalidArguments;
11338 typedef cmds::EnableFeatureCHROMIUM::Result Result;
11339 Result* result = GetSharedMemoryAs<Result*>(
11340 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11341 if (!result) {
11342 return error::kOutOfBounds;
11344 // Check that the client initialized the result.
11345 if (*result != 0) {
11346 return error::kInvalidArguments;
11348 std::string feature_str;
11349 if (!bucket->GetAsString(&feature_str)) {
11350 return error::kInvalidArguments;
11353 // TODO(gman): make this some kind of table to function pointer thingy.
11354 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11355 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11356 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
11357 buffer_manager()->set_allow_fixed_attribs(true);
11358 // TODO(gman): decide how to remove the need for this const_cast.
11359 // I could make validators_ non const but that seems bad as this is the only
11360 // place it is needed. I could make some special friend class of validators
11361 // just to allow this to set them. That seems silly. I could refactor this
11362 // code to use the extension mechanism or the initialization attributes to
11363 // turn this feature on. Given that the only real point of this is to make
11364 // the conformance tests pass and given that there is lots of real work that
11365 // needs to be done it seems like refactoring for one to one of those
11366 // methods is a very low priority.
11367 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
11368 } else {
11369 return error::kNoError;
11372 *result = 1; // true.
11373 return error::kNoError;
11376 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11377 uint32 immediate_data_size,
11378 const void* cmd_data) {
11379 const gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
11380 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
11381 cmd_data);
11382 Bucket* bucket = CreateBucket(c.bucket_id);
11383 scoped_refptr<FeatureInfo> info(new FeatureInfo());
11384 info->Initialize(disallowed_features_);
11385 bucket->SetFromString(info->extensions().c_str());
11386 return error::kNoError;
11389 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11390 uint32 immediate_data_size,
11391 const void* cmd_data) {
11392 const gles2::cmds::RequestExtensionCHROMIUM& c =
11393 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM*>(cmd_data);
11394 Bucket* bucket = GetBucket(c.bucket_id);
11395 if (!bucket || bucket->size() == 0) {
11396 return error::kInvalidArguments;
11398 std::string feature_str;
11399 if (!bucket->GetAsString(&feature_str)) {
11400 return error::kInvalidArguments;
11403 bool desire_standard_derivatives = false;
11404 bool desire_frag_depth = false;
11405 bool desire_draw_buffers = false;
11406 bool desire_shader_texture_lod = false;
11407 if (IsWebGLContext()) {
11408 desire_standard_derivatives =
11409 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
11410 desire_frag_depth =
11411 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
11412 desire_draw_buffers =
11413 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
11414 desire_shader_texture_lod =
11415 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
11418 if (desire_standard_derivatives != derivatives_explicitly_enabled_ ||
11419 desire_frag_depth != frag_depth_explicitly_enabled_ ||
11420 desire_draw_buffers != draw_buffers_explicitly_enabled_ ||
11421 desire_shader_texture_lod != shader_texture_lod_explicitly_enabled_) {
11422 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
11423 frag_depth_explicitly_enabled_ |= desire_frag_depth;
11424 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
11425 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
11426 InitializeShaderTranslator();
11429 UpdateCapabilities();
11431 return error::kNoError;
11434 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11435 uint32 immediate_data_size,
11436 const void* cmd_data) {
11437 const gles2::cmds::GetProgramInfoCHROMIUM& c =
11438 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM*>(cmd_data);
11439 GLuint program_id = static_cast<GLuint>(c.program);
11440 uint32 bucket_id = c.bucket_id;
11441 Bucket* bucket = CreateBucket(bucket_id);
11442 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
11443 Program* program = NULL;
11444 program = GetProgram(program_id);
11445 if (!program || !program->IsValid()) {
11446 return error::kNoError;
11448 program->GetProgramInfo(program_manager(), bucket);
11449 return error::kNoError;
11452 error::Error GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
11453 uint32 immediate_data_size, const void* cmd_data) {
11454 if (!unsafe_es3_apis_enabled())
11455 return error::kUnknownCommand;
11456 const gles2::cmds::GetUniformBlocksCHROMIUM& c =
11457 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM*>(cmd_data);
11458 GLuint program_id = static_cast<GLuint>(c.program);
11459 uint32 bucket_id = c.bucket_id;
11460 Bucket* bucket = CreateBucket(bucket_id);
11461 bucket->SetSize(sizeof(UniformBlocksHeader)); // in case we fail.
11462 Program* program = NULL;
11463 program = GetProgram(program_id);
11464 if (!program || !program->IsValid()) {
11465 return error::kNoError;
11467 program->GetUniformBlocks(bucket);
11468 return error::kNoError;
11471 error::Error GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
11472 uint32 immediate_data_size, const void* cmd_data) {
11473 if (!unsafe_es3_apis_enabled())
11474 return error::kUnknownCommand;
11475 const gles2::cmds::GetUniformsES3CHROMIUM& c =
11476 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM*>(cmd_data);
11477 GLuint program_id = static_cast<GLuint>(c.program);
11478 uint32 bucket_id = c.bucket_id;
11479 Bucket* bucket = CreateBucket(bucket_id);
11480 bucket->SetSize(sizeof(UniformsES3Header)); // in case we fail.
11481 Program* program = NULL;
11482 program = GetProgram(program_id);
11483 if (!program || !program->IsValid()) {
11484 return error::kNoError;
11486 program->GetUniformsES3(bucket);
11487 return error::kNoError;
11490 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
11491 uint32 immediate_data_size,
11492 const void* cmd_data) {
11493 if (!unsafe_es3_apis_enabled())
11494 return error::kUnknownCommand;
11495 const gles2::cmds::GetTransformFeedbackVarying& c =
11496 *static_cast<const gles2::cmds::GetTransformFeedbackVarying*>(cmd_data);
11497 GLuint program_id = c.program;
11498 GLuint index = c.index;
11499 uint32 name_bucket_id = c.name_bucket_id;
11500 typedef cmds::GetTransformFeedbackVarying::Result Result;
11501 Result* result = GetSharedMemoryAs<Result*>(
11502 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11503 if (!result) {
11504 return error::kOutOfBounds;
11506 // Check that the client initialized the result.
11507 if (result->success != 0) {
11508 return error::kInvalidArguments;
11510 Program* program = GetProgramInfoNotShader(
11511 program_id, "glGetTransformFeedbackVarying");
11512 if (!program) {
11513 return error::kNoError;
11515 GLuint service_id = program->service_id();
11516 GLint link_status = GL_FALSE;
11517 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11518 if (link_status != GL_TRUE) {
11519 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11520 "glGetTransformFeedbackVarying", "program not linked");
11521 return error::kNoError;
11523 GLint max_length = 0;
11524 glGetProgramiv(
11525 service_id, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_length);
11526 max_length = std::max(1, max_length);
11527 std::vector<char> buffer(max_length);
11528 GLsizei length = 0;
11529 GLsizei size = 0;
11530 GLenum type = 0;
11531 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
11532 glGetTransformFeedbackVarying(
11533 service_id, index, max_length, &length, &size, &type, &buffer[0]);
11534 GLenum error = glGetError();
11535 if (error != GL_NO_ERROR) {
11536 LOCAL_SET_GL_ERROR(error, "glGetTransformFeedbackVarying", "");
11537 return error::kNoError;
11539 result->success = 1; // true.
11540 result->size = static_cast<int32_t>(size);
11541 result->type = static_cast<uint32_t>(type);
11542 Bucket* bucket = CreateBucket(name_bucket_id);
11543 DCHECK(length >= 0 && length < max_length);
11544 buffer[length] = '\0'; // Just to be safe.
11545 bucket->SetFromString(&buffer[0]);
11546 return error::kNoError;
11549 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
11550 uint32 immediate_data_size, const void* cmd_data) {
11551 if (!unsafe_es3_apis_enabled())
11552 return error::kUnknownCommand;
11553 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM& c =
11554 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM*>(
11555 cmd_data);
11556 GLuint program_id = static_cast<GLuint>(c.program);
11557 uint32 bucket_id = c.bucket_id;
11558 Bucket* bucket = CreateBucket(bucket_id);
11559 bucket->SetSize(sizeof(TransformFeedbackVaryingsHeader)); // in case we fail.
11560 Program* program = NULL;
11561 program = GetProgram(program_id);
11562 if (!program || !program->IsValid()) {
11563 return error::kNoError;
11565 program->GetTransformFeedbackVaryings(bucket);
11566 return error::kNoError;
11569 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
11570 return context_lost_reason_;
11573 error::ContextLostReason GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
11574 GLenum reset_status) const {
11575 switch (reset_status) {
11576 case GL_NO_ERROR:
11577 // TODO(kbr): improve the precision of the error code in this case.
11578 // Consider delegating to context for error code if MakeCurrent fails.
11579 return error::kUnknown;
11580 case GL_GUILTY_CONTEXT_RESET_ARB:
11581 return error::kGuilty;
11582 case GL_INNOCENT_CONTEXT_RESET_ARB:
11583 return error::kInnocent;
11584 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11585 return error::kUnknown;
11588 NOTREACHED();
11589 return error::kUnknown;
11592 bool GLES2DecoderImpl::WasContextLost() const {
11593 return context_was_lost_;
11596 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
11597 return WasContextLost() && reset_by_robustness_extension_;
11600 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason) {
11601 // Only lose the context once.
11602 if (WasContextLost())
11603 return;
11605 // Don't make GL calls in here, the context might not be current.
11606 context_lost_reason_ = reason;
11607 current_decoder_error_ = error::kLostContext;
11608 context_was_lost_ = true;
11611 bool GLES2DecoderImpl::CheckResetStatus() {
11612 DCHECK(!WasContextLost());
11613 DCHECK(context_->IsCurrent(NULL));
11615 if (IsRobustnessSupported()) {
11616 // If the reason for the call was a GL error, we can try to determine the
11617 // reset status more accurately.
11618 GLenum driver_status = glGetGraphicsResetStatusARB();
11619 if (driver_status == GL_NO_ERROR)
11620 return false;
11622 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
11623 << " context lost via ARB/EXT_robustness. Reset status = "
11624 << GLES2Util::GetStringEnum(driver_status);
11626 // Don't pretend we know which client was responsible.
11627 if (workarounds().use_virtualized_gl_contexts)
11628 driver_status = GL_UNKNOWN_CONTEXT_RESET_ARB;
11630 switch (driver_status) {
11631 case GL_GUILTY_CONTEXT_RESET_ARB:
11632 MarkContextLost(error::kGuilty);
11633 break;
11634 case GL_INNOCENT_CONTEXT_RESET_ARB:
11635 MarkContextLost(error::kInnocent);
11636 break;
11637 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11638 MarkContextLost(error::kUnknown);
11639 break;
11640 default:
11641 NOTREACHED();
11642 return false;
11644 reset_by_robustness_extension_ = true;
11645 return true;
11647 return false;
11650 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11651 uint32 immediate_data_size,
11652 const void* cmd_data) {
11653 return error::kUnknownCommand;
11656 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11657 uint32 immediate_data_size,
11658 const void* cmd_data) {
11659 const gles2::cmds::WaitSyncPointCHROMIUM& c =
11660 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
11661 uint32 sync_point = c.sync_point;
11662 if (wait_sync_point_callback_.is_null())
11663 return error::kNoError;
11665 return wait_sync_point_callback_.Run(sync_point) ?
11666 error::kNoError : error::kDeferCommandUntilLater;
11669 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11670 uint32 immediate_data_size,
11671 const void* cmd_data) {
11672 if (surface_->DeferDraws())
11673 return error::kDeferCommandUntilLater;
11674 if (!surface_->SetBackbufferAllocation(false))
11675 return error::kLostContext;
11676 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
11677 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
11678 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
11679 return error::kNoError;
11682 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11683 GLsizei n, const GLuint* client_ids) {
11684 for (GLsizei ii = 0; ii < n; ++ii) {
11685 if (query_manager_->GetQuery(client_ids[ii])) {
11686 return false;
11689 query_manager_->GenQueries(n, client_ids);
11690 return true;
11693 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11694 GLsizei n, const GLuint* client_ids) {
11695 for (GLsizei ii = 0; ii < n; ++ii) {
11696 query_manager_->RemoveQuery(client_ids[ii]);
11700 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish) {
11701 if (query_manager_.get() == NULL) {
11702 return false;
11704 if (!query_manager_->ProcessPendingQueries(did_finish)) {
11705 current_decoder_error_ = error::kOutOfBounds;
11707 return query_manager_->HavePendingQueries();
11710 // Note that if there are no pending readpixels right now,
11711 // this function will call the callback immediately.
11712 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
11713 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
11714 pending_readpixel_fences_.back()->callbacks.push_back(callback);
11715 } else {
11716 callback.Run();
11720 void GLES2DecoderImpl::ProcessPendingReadPixels(bool did_finish) {
11721 // Note: |did_finish| guarantees that the GPU has passed the fence but
11722 // we cannot assume that GLFence::HasCompleted() will return true yet as
11723 // that's not guaranteed by all GLFence implementations.
11724 while (!pending_readpixel_fences_.empty() &&
11725 (did_finish ||
11726 pending_readpixel_fences_.front()->fence->HasCompleted())) {
11727 std::vector<base::Closure> callbacks =
11728 pending_readpixel_fences_.front()->callbacks;
11729 pending_readpixel_fences_.pop();
11730 for (size_t i = 0; i < callbacks.size(); i++) {
11731 callbacks[i].Run();
11736 bool GLES2DecoderImpl::HasMoreIdleWork() {
11737 return !pending_readpixel_fences_.empty() ||
11738 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers() ||
11739 gpu_tracer_->HasTracesToProcess();
11742 void GLES2DecoderImpl::PerformIdleWork() {
11743 gpu_tracer_->ProcessTraces();
11744 ProcessPendingReadPixels(false);
11745 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
11746 return;
11747 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
11748 ProcessFinishedAsyncTransfers();
11751 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size,
11752 const void* cmd_data) {
11753 const gles2::cmds::BeginQueryEXT& c =
11754 *static_cast<const gles2::cmds::BeginQueryEXT*>(cmd_data);
11755 GLenum target = static_cast<GLenum>(c.target);
11756 GLuint client_id = static_cast<GLuint>(c.id);
11757 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11758 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11760 switch (target) {
11761 case GL_COMMANDS_ISSUED_CHROMIUM:
11762 case GL_LATENCY_QUERY_CHROMIUM:
11763 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
11764 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
11765 case GL_GET_ERROR_QUERY_CHROMIUM:
11766 break;
11767 case GL_COMMANDS_COMPLETED_CHROMIUM:
11768 if (!features().chromium_sync_query) {
11769 LOCAL_SET_GL_ERROR(
11770 GL_INVALID_OPERATION, "glBeginQueryEXT",
11771 "not enabled for commands completed queries");
11772 return error::kNoError;
11774 break;
11775 case GL_SAMPLES_PASSED:
11776 case GL_ANY_SAMPLES_PASSED:
11777 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
11778 if (!features().occlusion_query_boolean) {
11779 LOCAL_SET_GL_ERROR(
11780 GL_INVALID_OPERATION, "glBeginQueryEXT",
11781 "not enabled for occlusion queries");
11782 return error::kNoError;
11784 break;
11785 case GL_TIME_ELAPSED:
11786 if (!query_manager_->GPUTimingAvailable()) {
11787 LOCAL_SET_GL_ERROR(
11788 GL_INVALID_OPERATION, "glBeginQueryEXT",
11789 "not enabled for timing queries");
11790 return error::kNoError;
11792 break;
11793 default:
11794 LOCAL_SET_GL_ERROR(
11795 GL_INVALID_ENUM, "glBeginQueryEXT",
11796 "unknown query target");
11797 return error::kNoError;
11800 if (query_manager_->GetActiveQuery(target)) {
11801 LOCAL_SET_GL_ERROR(
11802 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
11803 return error::kNoError;
11806 if (client_id == 0) {
11807 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
11808 return error::kNoError;
11811 QueryManager::Query* query = query_manager_->GetQuery(client_id);
11812 if (!query) {
11813 if (!query_manager_->IsValidQuery(client_id)) {
11814 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11815 "glBeginQueryEXT",
11816 "id not made by glGenQueriesEXT");
11817 return error::kNoError;
11819 query = query_manager_->CreateQuery(
11820 target, client_id, sync_shm_id, sync_shm_offset);
11823 if (query->target() != target) {
11824 LOCAL_SET_GL_ERROR(
11825 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
11826 return error::kNoError;
11827 } else if (query->shm_id() != sync_shm_id ||
11828 query->shm_offset() != sync_shm_offset) {
11829 DLOG(ERROR) << "Shared memory used by query not the same as before";
11830 return error::kInvalidArguments;
11833 if (!query_manager_->BeginQuery(query)) {
11834 return error::kOutOfBounds;
11837 return error::kNoError;
11840 error::Error GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size,
11841 const void* cmd_data) {
11842 const gles2::cmds::EndQueryEXT& c =
11843 *static_cast<const gles2::cmds::EndQueryEXT*>(cmd_data);
11844 GLenum target = static_cast<GLenum>(c.target);
11845 uint32 submit_count = static_cast<GLuint>(c.submit_count);
11847 QueryManager::Query* query = query_manager_->GetActiveQuery(target);
11848 if (!query) {
11849 LOCAL_SET_GL_ERROR(
11850 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
11851 return error::kNoError;
11854 if (!query_manager_->EndQuery(query, submit_count)) {
11855 return error::kOutOfBounds;
11858 query_manager_->ProcessPendingTransferQueries();
11860 return error::kNoError;
11863 error::Error GLES2DecoderImpl::HandleQueryCounterEXT(uint32 immediate_data_size,
11864 const void* cmd_data) {
11865 const gles2::cmds::QueryCounterEXT& c =
11866 *static_cast<const gles2::cmds::QueryCounterEXT*>(cmd_data);
11867 GLuint client_id = static_cast<GLuint>(c.id);
11868 GLenum target = static_cast<GLenum>(c.target);
11869 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11870 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11871 uint32 submit_count = static_cast<GLuint>(c.submit_count);
11873 switch (target) {
11874 case GL_TIMESTAMP:
11875 if (!query_manager_->GPUTimingAvailable()) {
11876 LOCAL_SET_GL_ERROR(
11877 GL_INVALID_OPERATION, "glQueryCounterEXT",
11878 "not enabled for timing queries");
11879 return error::kNoError;
11881 break;
11882 default:
11883 LOCAL_SET_GL_ERROR(
11884 GL_INVALID_ENUM, "glQueryCounterEXT",
11885 "unknown query target");
11886 return error::kNoError;
11889 QueryManager::Query* query = query_manager_->GetQuery(client_id);
11890 if (!query) {
11891 if (!query_manager_->IsValidQuery(client_id)) {
11892 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11893 "glQueryCounterEXT",
11894 "id not made by glGenQueriesEXT");
11895 return error::kNoError;
11897 query = query_manager_->CreateQuery(
11898 target, client_id, sync_shm_id, sync_shm_offset);
11900 if (!query_manager_->QueryCounter(query, submit_count)) {
11901 return error::kOutOfBounds;
11904 return error::kNoError;
11907 error::Error GLES2DecoderImpl::HandleSetDisjointValueSyncCHROMIUM(
11908 uint32 immediate_data_size, const void* cmd_data) {
11909 const gles2::cmds::SetDisjointValueSyncCHROMIUM& c =
11910 *static_cast<const gles2::cmds::SetDisjointValueSyncCHROMIUM*>(cmd_data);
11911 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11912 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11914 query_manager_->SetDisjointSync(sync_shm_id, sync_shm_offset);
11915 return error::kNoError;
11918 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11919 GLsizei n, const GLuint* client_ids) {
11920 for (GLsizei ii = 0; ii < n; ++ii) {
11921 if (GetVertexAttribManager(client_ids[ii])) {
11922 return false;
11926 if (!features().native_vertex_array_object) {
11927 // Emulated VAO
11928 for (GLsizei ii = 0; ii < n; ++ii) {
11929 CreateVertexAttribManager(client_ids[ii], 0, true);
11931 } else {
11932 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
11934 glGenVertexArraysOES(n, service_ids.get());
11935 for (GLsizei ii = 0; ii < n; ++ii) {
11936 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
11940 return true;
11943 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11944 GLsizei n, const GLuint* client_ids) {
11945 for (GLsizei ii = 0; ii < n; ++ii) {
11946 VertexAttribManager* vao =
11947 GetVertexAttribManager(client_ids[ii]);
11948 if (vao && !vao->IsDeleted()) {
11949 if (state_.vertex_attrib_manager.get() == vao) {
11950 DoBindVertexArrayOES(0);
11952 RemoveVertexAttribManager(client_ids[ii]);
11957 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
11958 VertexAttribManager* vao = NULL;
11959 if (client_id != 0) {
11960 vao = GetVertexAttribManager(client_id);
11961 if (!vao) {
11962 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11963 // only allows names that have been previously generated. As such, we do
11964 // not generate new names here.
11965 LOCAL_SET_GL_ERROR(
11966 GL_INVALID_OPERATION,
11967 "glBindVertexArrayOES", "bad vertex array id.");
11968 current_decoder_error_ = error::kNoError;
11969 return;
11971 } else {
11972 vao = state_.default_vertex_attrib_manager.get();
11975 // Only set the VAO state if it's changed
11976 if (state_.vertex_attrib_manager.get() != vao) {
11977 state_.vertex_attrib_manager = vao;
11978 if (!features().native_vertex_array_object) {
11979 EmulateVertexArrayState();
11980 } else {
11981 GLuint service_id = vao->service_id();
11982 glBindVertexArrayOES(service_id);
11987 // Used when OES_vertex_array_object isn't natively supported
11988 void GLES2DecoderImpl::EmulateVertexArrayState() {
11989 // Setup the Vertex attribute state
11990 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
11991 RestoreStateForAttrib(vv, true);
11994 // Setup the element buffer
11995 Buffer* element_array_buffer =
11996 state_.vertex_attrib_manager->element_array_buffer();
11997 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
11998 element_array_buffer ? element_array_buffer->service_id() : 0);
12001 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
12002 const VertexAttribManager* vao =
12003 GetVertexAttribManager(client_id);
12004 return vao && vao->IsValid() && !vao->IsDeleted();
12007 bool GLES2DecoderImpl::DoIsPathCHROMIUM(GLuint client_id) {
12008 GLuint service_id = 0;
12009 return path_manager()->GetPath(client_id, &service_id) &&
12010 glIsPathNV(service_id) == GL_TRUE;
12013 #if defined(OS_MACOSX)
12014 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
12015 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
12016 texture_id);
12017 if (it != texture_to_io_surface_map_.end()) {
12018 // Found a previous IOSurface bound to this texture; release it.
12019 IOSurfaceRef surface = it->second;
12020 CFRelease(surface);
12021 texture_to_io_surface_map_.erase(it);
12024 #endif
12026 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
12027 GLenum target, GLsizei width, GLsizei height,
12028 GLuint io_surface_id, GLuint plane) {
12029 #if defined(OS_MACOSX)
12030 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
12031 LOCAL_SET_GL_ERROR(
12032 GL_INVALID_OPERATION,
12033 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
12034 return;
12037 if (target != GL_TEXTURE_RECTANGLE_ARB) {
12038 // This might be supported in the future, and if we could require
12039 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
12040 // could delete a lot of code. For now, perform strict validation so we
12041 // know what's going on.
12042 LOCAL_SET_GL_ERROR(
12043 GL_INVALID_OPERATION,
12044 "glTexImageIOSurface2DCHROMIUM",
12045 "requires TEXTURE_RECTANGLE_ARB target");
12046 return;
12049 // Default target might be conceptually valid, but disallow it to avoid
12050 // accidents.
12051 TextureRef* texture_ref =
12052 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12053 if (!texture_ref) {
12054 LOCAL_SET_GL_ERROR(
12055 GL_INVALID_OPERATION,
12056 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
12057 return;
12060 // Look up the new IOSurface. Note that because of asynchrony
12061 // between processes this might fail; during live resizing the
12062 // plugin process might allocate and release an IOSurface before
12063 // this process gets a chance to look it up. Hold on to any old
12064 // IOSurface in this case.
12065 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
12066 if (!surface) {
12067 LOCAL_SET_GL_ERROR(
12068 GL_INVALID_OPERATION,
12069 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
12070 return;
12073 // Release any IOSurface previously bound to this texture.
12074 ReleaseIOSurfaceForTexture(texture_ref->service_id());
12076 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
12077 texture_to_io_surface_map_.insert(
12078 std::make_pair(texture_ref->service_id(), surface));
12080 CGLContextObj context =
12081 static_cast<CGLContextObj>(context_->GetHandle());
12083 CGLError err = CGLTexImageIOSurface2D(
12084 context,
12085 target,
12086 GL_RGBA,
12087 width,
12088 height,
12089 GL_BGRA,
12090 GL_UNSIGNED_INT_8_8_8_8_REV,
12091 surface,
12092 plane);
12094 if (err != kCGLNoError) {
12095 LOCAL_SET_GL_ERROR(
12096 GL_INVALID_OPERATION,
12097 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
12098 return;
12101 texture_manager()->SetLevelInfo(
12102 texture_ref, target, 0, GL_RGBA, width, height, 1, 0, GL_BGRA,
12103 GL_UNSIGNED_INT_8_8_8_8_REV, gfx::Rect(width, height));
12105 #else
12106 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12107 "glTexImageIOSurface2DCHROMIUM", "not supported.");
12108 #endif
12111 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
12112 switch (internalformat) {
12113 case GL_R8:
12114 case GL_R8_SNORM:
12115 case GL_R16F:
12116 case GL_R32F:
12117 return GL_RED;
12118 case GL_R8UI:
12119 case GL_R8I:
12120 case GL_R16UI:
12121 case GL_R16I:
12122 case GL_R32UI:
12123 case GL_R32I:
12124 return GL_RED_INTEGER;
12125 case GL_RG8:
12126 case GL_RG8_SNORM:
12127 case GL_RG16F:
12128 case GL_RG32F:
12129 return GL_RG;
12130 case GL_RG8UI:
12131 case GL_RG8I:
12132 case GL_RG16UI:
12133 case GL_RG16I:
12134 case GL_RG32UI:
12135 case GL_RG32I:
12136 return GL_RG_INTEGER;
12137 case GL_ATC_RGB_AMD:
12138 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
12139 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
12140 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
12141 case GL_ETC1_RGB8_OES:
12142 case GL_RGB8:
12143 case GL_R11F_G11F_B10F:
12144 case GL_RGB565:
12145 case GL_RGB8_SNORM:
12146 case GL_RGB9_E5:
12147 case GL_RGB16F:
12148 case GL_RGB32F:
12149 return GL_RGB;
12150 case GL_RGB8UI:
12151 case GL_RGB8I:
12152 case GL_RGB16UI:
12153 case GL_RGB16I:
12154 case GL_RGB32UI:
12155 case GL_RGB32I:
12156 return GL_RGB_INTEGER;
12157 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
12158 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
12159 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
12160 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
12161 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
12162 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
12163 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
12164 case GL_RGBA8:
12165 case GL_SRGB8_ALPHA8:
12166 case GL_RGBA8_SNORM:
12167 case GL_RGBA4:
12168 case GL_RGB5_A1:
12169 case GL_RGB10_A2:
12170 case GL_RGBA16F:
12171 case GL_RGBA32F:
12172 return GL_RGBA;
12173 case GL_RGBA8UI:
12174 case GL_RGBA8I:
12175 case GL_RGB10_A2UI:
12176 case GL_RGBA16UI:
12177 case GL_RGBA16I:
12178 case GL_RGBA32UI:
12179 case GL_RGBA32I:
12180 return GL_RGBA_INTEGER;
12181 case GL_DEPTH_COMPONENT16:
12182 case GL_DEPTH_COMPONENT24:
12183 case GL_DEPTH_COMPONENT32F:
12184 return GL_DEPTH_COMPONENT;
12185 case GL_DEPTH24_STENCIL8:
12186 case GL_DEPTH32F_STENCIL8:
12187 return GL_DEPTH_STENCIL;
12188 case GL_LUMINANCE8_ALPHA8_EXT:
12189 return GL_LUMINANCE_ALPHA;
12190 case GL_LUMINANCE8_EXT:
12191 return GL_LUMINANCE;
12192 case GL_ALPHA8_EXT:
12193 return GL_ALPHA;
12194 case GL_ALPHA32F_EXT:
12195 return GL_ALPHA;
12196 case GL_LUMINANCE32F_EXT:
12197 return GL_LUMINANCE;
12198 case GL_LUMINANCE_ALPHA32F_EXT:
12199 return GL_LUMINANCE_ALPHA;
12200 case GL_ALPHA16F_EXT:
12201 return GL_ALPHA;
12202 case GL_LUMINANCE16F_EXT:
12203 return GL_LUMINANCE;
12204 case GL_LUMINANCE_ALPHA16F_EXT:
12205 return GL_LUMINANCE_ALPHA;
12206 case GL_BGRA8_EXT:
12207 return GL_BGRA_EXT;
12208 default:
12209 return GL_NONE;
12213 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
12214 const char* function_name,
12215 GLenum target,
12216 TextureRef* source_texture_ref,
12217 TextureRef* dest_texture_ref,
12218 GLenum dest_internal_format) {
12219 if (!source_texture_ref || !dest_texture_ref) {
12220 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
12221 return false;
12224 if (GL_TEXTURE_2D != target) {
12225 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12226 "invalid texture target");
12227 return false;
12230 Texture* source_texture = source_texture_ref->texture();
12231 Texture* dest_texture = dest_texture_ref->texture();
12232 if (source_texture == dest_texture) {
12233 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12234 "source and destination textures are the same");
12235 return false;
12238 if (dest_texture->target() != GL_TEXTURE_2D ||
12239 (source_texture->target() != GL_TEXTURE_2D &&
12240 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
12241 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
12242 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12243 "invalid texture target binding");
12244 return false;
12247 GLenum source_type = 0;
12248 GLenum source_internal_format = 0;
12249 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12250 &source_internal_format);
12252 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
12253 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
12254 // renderable on some platforms.
12255 bool valid_dest_format = dest_internal_format == GL_RGB ||
12256 dest_internal_format == GL_RGBA ||
12257 dest_internal_format == GL_BGRA_EXT;
12258 bool valid_source_format =
12259 source_internal_format == GL_R8 || source_internal_format == GL_ALPHA ||
12260 source_internal_format == GL_RGB || source_internal_format == GL_RGBA ||
12261 source_internal_format == GL_LUMINANCE ||
12262 source_internal_format == GL_LUMINANCE_ALPHA ||
12263 source_internal_format == GL_BGRA_EXT;
12264 if (!valid_source_format || !valid_dest_format) {
12265 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12266 "invalid internal format");
12267 return false;
12269 return true;
12272 bool GLES2DecoderImpl::ValidateCompressedCopyTextureCHROMIUM(
12273 const char* function_name,
12274 GLenum target,
12275 TextureRef* source_texture_ref,
12276 TextureRef* dest_texture_ref) {
12277 if (!source_texture_ref || !dest_texture_ref) {
12278 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
12279 return false;
12282 if (GL_TEXTURE_2D != target) {
12283 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12284 "invalid texture target");
12285 return false;
12288 Texture* source_texture = source_texture_ref->texture();
12289 Texture* dest_texture = dest_texture_ref->texture();
12290 if (source_texture == dest_texture) {
12291 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12292 "source and destination textures are the same");
12293 return false;
12296 if (dest_texture->target() != GL_TEXTURE_2D ||
12297 (source_texture->target() != GL_TEXTURE_2D &&
12298 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
12299 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
12300 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12301 "invalid texture target binding");
12302 return false;
12305 GLenum source_type = 0;
12306 GLenum source_internal_format = 0;
12307 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12308 &source_internal_format);
12310 bool valid_format =
12311 source_internal_format == GL_ATC_RGB_AMD ||
12312 source_internal_format == GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD ||
12313 source_internal_format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
12314 source_internal_format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ||
12315 source_internal_format == GL_ETC1_RGB8_OES;
12317 if (!valid_format) {
12318 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12319 "invalid internal format");
12320 return false;
12323 return true;
12326 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
12327 GLenum target,
12328 GLuint source_id,
12329 GLuint dest_id,
12330 GLenum internal_format,
12331 GLenum dest_type,
12332 GLboolean unpack_flip_y,
12333 GLboolean unpack_premultiply_alpha,
12334 GLboolean unpack_unmultiply_alpha) {
12335 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
12337 TextureRef* source_texture_ref = GetTexture(source_id);
12338 TextureRef* dest_texture_ref = GetTexture(dest_id);
12339 Texture* source_texture = source_texture_ref->texture();
12340 Texture* dest_texture = dest_texture_ref->texture();
12341 int source_width = 0;
12342 int source_height = 0;
12343 gfx::GLImage* image =
12344 source_texture->GetLevelImage(source_texture->target(), 0);
12345 if (image) {
12346 gfx::Size size = image->GetSize();
12347 source_width = size.width();
12348 source_height = size.height();
12349 if (source_width <= 0 || source_height <= 0) {
12350 LOCAL_SET_GL_ERROR(
12351 GL_INVALID_VALUE,
12352 "glCopyTextureChromium", "invalid image size");
12353 return;
12355 } else {
12356 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12357 &source_width, &source_height, nullptr)) {
12358 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
12359 "glCopyTextureChromium",
12360 "source texture has no level 0");
12361 return;
12364 // Check that this type of texture is allowed.
12365 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12366 source_width, source_height, 1)) {
12367 LOCAL_SET_GL_ERROR(
12368 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
12369 return;
12373 GLenum source_type = 0;
12374 GLenum source_internal_format = 0;
12375 source_texture->GetLevelType(
12376 source_texture->target(), 0, &source_type, &source_internal_format);
12378 if (dest_texture->IsImmutable()) {
12379 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyTextureCHROMIUM",
12380 "texture is immutable");
12381 return;
12384 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target,
12385 source_texture_ref, dest_texture_ref,
12386 internal_format)) {
12387 return;
12390 // Clear the source texture if necessary.
12391 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12392 source_texture->target(), 0)) {
12393 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM",
12394 "dimensions too big");
12395 return;
12398 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12399 // needed because it takes 10s of milliseconds to initialize.
12400 if (!copy_texture_CHROMIUM_.get()) {
12401 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12402 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12403 copy_texture_CHROMIUM_->Initialize(this);
12404 RestoreCurrentFramebufferBindings();
12405 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
12406 return;
12409 GLenum dest_type_previous = dest_type;
12410 GLenum dest_internal_format = internal_format;
12411 int dest_width = 0;
12412 int dest_height = 0;
12413 bool dest_level_defined = dest_texture->GetLevelSize(
12414 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12416 if (dest_level_defined) {
12417 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type_previous,
12418 &dest_internal_format);
12421 // Resize the destination texture to the dimensions of the source texture.
12422 if (!dest_level_defined || dest_width != source_width ||
12423 dest_height != source_height ||
12424 dest_internal_format != internal_format ||
12425 dest_type_previous != dest_type) {
12426 // Ensure that the glTexImage2D succeeds.
12427 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12428 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12429 glTexImage2D(GL_TEXTURE_2D, 0, internal_format, source_width, source_height,
12430 0, internal_format, dest_type, NULL);
12431 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
12432 if (error != GL_NO_ERROR) {
12433 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12434 return;
12437 texture_manager()->SetLevelInfo(
12438 dest_texture_ref, GL_TEXTURE_2D, 0, internal_format, source_width,
12439 source_height, 1, 0, internal_format, dest_type,
12440 gfx::Rect(source_width, source_height));
12441 } else {
12442 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12443 true);
12446 ScopedModifyPixels modify(dest_texture_ref);
12448 // Try using GLImage::CopyTexSubImage when possible.
12449 bool unpack_premultiply_alpha_change =
12450 (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0;
12451 if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) {
12452 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12453 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0),
12454 gfx::Rect(0, 0, source_width, source_height))) {
12455 return;
12459 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12461 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12462 // before presenting.
12463 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
12464 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12465 // instead of using kIdentityMatrix crbug.com/226218.
12466 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
12467 this, source_texture->target(), source_texture->service_id(),
12468 dest_texture->service_id(), source_width, source_height,
12469 unpack_flip_y == GL_TRUE,
12470 unpack_premultiply_alpha == GL_TRUE,
12471 unpack_unmultiply_alpha == GL_TRUE,
12472 kIdentityMatrix);
12473 } else {
12474 copy_texture_CHROMIUM_->DoCopyTexture(
12475 this, source_texture->target(), source_texture->service_id(),
12476 source_internal_format, dest_texture->service_id(), internal_format,
12477 source_width, source_height,
12478 unpack_flip_y == GL_TRUE,
12479 unpack_premultiply_alpha == GL_TRUE,
12480 unpack_unmultiply_alpha == GL_TRUE);
12483 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12486 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(
12487 GLenum target,
12488 GLuint source_id,
12489 GLuint dest_id,
12490 GLint xoffset,
12491 GLint yoffset,
12492 GLint x,
12493 GLint y,
12494 GLsizei width,
12495 GLsizei height,
12496 GLboolean unpack_flip_y,
12497 GLboolean unpack_premultiply_alpha,
12498 GLboolean unpack_unmultiply_alpha) {
12499 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
12501 TextureRef* source_texture_ref = GetTexture(source_id);
12502 TextureRef* dest_texture_ref = GetTexture(dest_id);
12503 Texture* source_texture = source_texture_ref->texture();
12504 Texture* dest_texture = dest_texture_ref->texture();
12505 int source_width = 0;
12506 int source_height = 0;
12507 gfx::GLImage* image =
12508 source_texture->GetLevelImage(source_texture->target(), 0);
12509 if (image) {
12510 gfx::Size size = image->GetSize();
12511 source_width = size.width();
12512 source_height = size.height();
12513 if (source_width <= 0 || source_height <= 0) {
12514 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12515 "invalid image size");
12516 return;
12518 } else {
12519 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12520 &source_width, &source_height, nullptr)) {
12521 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12522 "source texture has no level 0");
12523 return;
12526 // Check that this type of texture is allowed.
12527 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12528 source_width, source_height, 1)) {
12529 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12530 "source texture bad dimensions");
12531 return;
12535 GLenum source_type = 0;
12536 GLenum source_internal_format = 0;
12537 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12538 &source_internal_format);
12539 if (!source_texture->ValidForTexture(source_texture->target(), 0, x, y, 0,
12540 width, height, 1, source_type)) {
12541 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12542 "source texture bad dimensions.");
12543 return;
12546 GLenum dest_type = 0;
12547 GLenum dest_internal_format = 0;
12548 bool dest_level_defined = dest_texture->GetLevelType(
12549 dest_texture->target(), 0, &dest_type, &dest_internal_format);
12550 if (!dest_level_defined) {
12551 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopySubTextureCHROMIUM",
12552 "destination texture is not defined");
12553 return;
12555 if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
12556 yoffset, 0, width, height, 1, dest_type)) {
12557 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12558 "destination texture bad dimensions.");
12559 return;
12562 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target,
12563 source_texture_ref, dest_texture_ref,
12564 dest_internal_format)) {
12565 return;
12568 // Clear the source texture if necessary.
12569 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12570 source_texture->target(), 0)) {
12571 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
12572 "source texture dimensions too big");
12573 return;
12576 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12577 // needed because it takes 10s of milliseconds to initialize.
12578 if (!copy_texture_CHROMIUM_.get()) {
12579 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
12580 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12581 copy_texture_CHROMIUM_->Initialize(this);
12582 RestoreCurrentFramebufferBindings();
12583 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR)
12584 return;
12587 int dest_width = 0;
12588 int dest_height = 0;
12589 bool ok = dest_texture->GetLevelSize(
12590 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12591 DCHECK(ok);
12592 if (xoffset != 0 || yoffset != 0 || width != dest_width ||
12593 height != dest_height) {
12594 gfx::Rect cleared_rect;
12595 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0),
12596 gfx::Rect(xoffset, yoffset, width, height),
12597 &cleared_rect)) {
12598 DCHECK_GE(cleared_rect.size().GetArea(),
12599 dest_texture->GetLevelClearedRect(target, 0).size().GetArea());
12600 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0,
12601 cleared_rect);
12602 } else {
12603 // Otherwise clear part of texture level that is not already cleared.
12604 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
12605 0)) {
12606 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
12607 "destination texture dimensions too big");
12608 return;
12611 } else {
12612 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12613 true);
12616 ScopedModifyPixels modify(dest_texture_ref);
12618 // Try using GLImage::CopyTexSubImage when possible.
12619 bool unpack_premultiply_alpha_change =
12620 (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0;
12621 if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) {
12622 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12623 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset),
12624 gfx::Rect(x, y, width, height))) {
12625 return;
12629 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12631 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
12632 // crbug.com/226218.
12633 copy_texture_CHROMIUM_->DoCopySubTexture(
12634 this, source_texture->target(), source_texture->service_id(),
12635 source_internal_format, dest_texture->service_id(), dest_internal_format,
12636 xoffset, yoffset, x, y, width, height, dest_width, dest_height,
12637 source_width, source_height,
12638 unpack_flip_y == GL_TRUE,
12639 unpack_premultiply_alpha == GL_TRUE,
12640 unpack_unmultiply_alpha == GL_TRUE);
12642 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12645 void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target,
12646 GLuint source_id,
12647 GLuint dest_id) {
12648 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM");
12650 TextureRef* source_texture_ref = GetTexture(source_id);
12651 TextureRef* dest_texture_ref = GetTexture(dest_id);
12652 Texture* source_texture = source_texture_ref->texture();
12653 Texture* dest_texture = dest_texture_ref->texture();
12654 int source_width = 0;
12655 int source_height = 0;
12656 gfx::GLImage* image =
12657 source_texture->GetLevelImage(source_texture->target(), 0);
12658 if (image) {
12659 gfx::Size size = image->GetSize();
12660 source_width = size.width();
12661 source_height = size.height();
12662 if (source_width <= 0 || source_height <= 0) {
12663 LOCAL_SET_GL_ERROR(
12664 GL_INVALID_VALUE,
12665 "glCompressedCopyTextureCHROMIUM", "invalid image size");
12666 return;
12668 } else {
12669 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12670 &source_width, &source_height, nullptr)) {
12671 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
12672 "glCompressedCopyTextureCHROMIUM",
12673 "source texture has no level 0");
12674 return;
12677 // Check that this type of texture is allowed.
12678 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12679 source_width, source_height, 1)) {
12680 LOCAL_SET_GL_ERROR(
12681 GL_INVALID_VALUE, "glCompressedCopyTextureCHROMIUM",
12682 "Bad dimensions");
12683 return;
12687 GLenum source_type = 0;
12688 GLenum source_internal_format = 0;
12689 source_texture->GetLevelType(
12690 source_texture->target(), 0, &source_type, &source_internal_format);
12692 if (dest_texture->IsImmutable()) {
12693 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12694 "glCompressedCopyTextureCHROMIUM",
12695 "texture is immutable");
12696 return;
12699 if (!ValidateCompressedCopyTextureCHROMIUM(
12700 "glCompressedCopyTextureCHROMIUM",
12701 target,
12702 source_texture_ref, dest_texture_ref)) {
12703 return;
12706 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12707 // needed because it takes 10s of milliseconds to initialize.
12708 if (!copy_texture_CHROMIUM_.get()) {
12709 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12710 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12711 copy_texture_CHROMIUM_->Initialize(this);
12712 RestoreCurrentFramebufferBindings();
12713 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
12714 return;
12717 // Clear the source texture if necessary.
12718 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12719 source_texture->target(), 0)) {
12720 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCompressedCopyTextureCHROMIUM",
12721 "dimensions too big");
12722 return;
12725 ScopedTextureBinder binder(
12726 &state_, dest_texture->service_id(), GL_TEXTURE_2D);
12728 ScopedModifyPixels modify(dest_texture_ref);
12730 // Try using GLImage::CopyTexImage when possible.
12731 if (image) {
12732 GLenum dest_type = 0;
12733 GLenum dest_internal_format = 0;
12734 int dest_width = 0;
12735 int dest_height = 0;
12736 bool dest_level_defined = dest_texture->GetLevelSize(
12737 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12739 if (dest_level_defined) {
12740 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type,
12741 &dest_internal_format);
12744 // Resize the destination texture to the dimensions of the source texture.
12745 if (!dest_level_defined || dest_width != source_width ||
12746 dest_height != source_height ||
12747 dest_internal_format != source_internal_format) {
12748 GLsizei source_size = 0;
12750 bool did_get_size = GetCompressedTexSizeInBytes(
12751 "glCompressedCopyTextureCHROMIUM", source_width, source_height,
12752 1, source_internal_format, &source_size);
12753 DCHECK(did_get_size);
12755 // Ensure that the glCompressedTexImage2D succeeds.
12756 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12757 glCompressedTexImage2D(GL_TEXTURE_2D, 0, source_internal_format,
12758 source_width, source_height, 0, source_size,
12759 NULL);
12760 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12761 if (error != GL_NO_ERROR) {
12762 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12763 return;
12766 texture_manager()->SetLevelInfo(
12767 dest_texture_ref, GL_TEXTURE_2D, 0, source_internal_format,
12768 source_width, source_height, 1, 0, source_internal_format,
12769 source_type, gfx::Rect(source_width, source_height));
12770 } else {
12771 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12772 true);
12775 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0),
12776 gfx::Rect(0, 0, source_width, source_height))) {
12777 return;
12781 TRACE_EVENT0(
12782 "gpu",
12783 "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM, fallback");
12785 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12787 // As a fallback, copy into a non-compressed GL_RGBA texture.
12788 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12789 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, source_width, source_height,
12790 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
12791 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12792 if (error != GL_NO_ERROR) {
12793 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12794 return;
12797 texture_manager()->SetLevelInfo(
12798 dest_texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, source_width,
12799 source_height, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12800 gfx::Rect(source_width, source_height));
12802 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12803 // before presenting.
12804 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
12805 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12806 // instead of using kIdentityMatrix crbug.com/226218.
12807 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
12808 this, source_texture->target(), source_texture->service_id(),
12809 dest_texture->service_id(), source_width, source_height,
12810 false, false, false, kIdentityMatrix);
12811 } else {
12812 copy_texture_CHROMIUM_->DoCopyTexture(
12813 this, source_texture->target(), source_texture->service_id(),
12814 source_internal_format, dest_texture->service_id(), GL_RGBA,
12815 source_width, source_height, false, false, false);
12818 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12821 void GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM(GLenum target,
12822 GLuint source_id,
12823 GLuint dest_id,
12824 GLint xoffset,
12825 GLint yoffset,
12826 GLint x,
12827 GLint y,
12828 GLsizei width,
12829 GLsizei height) {
12830 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM");
12832 TextureRef* source_texture_ref = GetTexture(source_id);
12833 TextureRef* dest_texture_ref = GetTexture(dest_id);
12834 Texture* source_texture = source_texture_ref->texture();
12835 Texture* dest_texture = dest_texture_ref->texture();
12836 int source_width = 0;
12837 int source_height = 0;
12838 gfx::GLImage* image =
12839 source_texture->GetLevelImage(source_texture->target(), 0);
12840 if (image) {
12841 gfx::Size size = image->GetSize();
12842 source_width = size.width();
12843 source_height = size.height();
12844 if (source_width <= 0 || source_height <= 0) {
12845 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
12846 "invalid image size");
12847 return;
12849 } else {
12850 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12851 &source_width, &source_height, nullptr)) {
12852 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
12853 "source texture has no level 0");
12854 return;
12857 // Check that this type of texture is allowed.
12858 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12859 source_width, source_height, 1)) {
12860 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
12861 "source texture bad dimensions");
12862 return;
12866 GLenum source_type = 0;
12867 GLenum source_internal_format = 0;
12868 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12869 &source_internal_format);
12870 if (!source_texture->ValidForTexture(source_texture->target(), 0, x, y, 0,
12871 width, height, 1, source_type)) {
12872 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
12873 "source texture bad dimensions.");
12874 return;
12877 GLenum dest_type = 0;
12878 GLenum dest_internal_format = 0;
12879 bool dest_level_defined = dest_texture->GetLevelType(
12880 dest_texture->target(), 0, &dest_type, &dest_internal_format);
12881 if (!dest_level_defined) {
12882 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12883 "glCompressedCopySubTextureCHROMIUM",
12884 "destination texture is not defined");
12885 return;
12887 if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
12888 yoffset, 0, width, height, 1, dest_type)) {
12889 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
12890 "destination texture bad dimensions.");
12891 return;
12894 if (!ValidateCompressedCopyTextureCHROMIUM(
12895 "glCompressedCopySubTextureCHROMIUM", target, source_texture_ref,
12896 dest_texture_ref)) {
12897 return;
12900 if (!ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM",
12901 source_texture->target(), 0, x, y, 0,
12902 width, height, 1,
12903 source_internal_format,
12904 source_texture) ||
12905 !ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM",
12906 dest_texture->target(), 0,
12907 xoffset, yoffset, 0, width, height, 1,
12908 dest_internal_format,
12909 dest_texture)) {
12910 return;
12913 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12914 // needed because it takes 10s of milliseconds to initialize.
12915 if (!copy_texture_CHROMIUM_.get()) {
12916 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopySubTextureCHROMIUM");
12917 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12918 copy_texture_CHROMIUM_->Initialize(this);
12919 RestoreCurrentFramebufferBindings();
12920 if (LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM") !=
12921 GL_NO_ERROR) {
12922 return;
12926 // Clear the source texture if necessary.
12927 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12928 source_texture->target(), 0)) {
12929 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCompressedCopySubTextureCHROMIUM",
12930 "source texture dimensions too big");
12931 return;
12934 int dest_width = 0;
12935 int dest_height = 0;
12936 bool ok = dest_texture->GetLevelSize(
12937 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12938 DCHECK(ok);
12939 if (xoffset != 0 || yoffset != 0 || width != dest_width ||
12940 height != dest_height) {
12941 gfx::Rect cleared_rect;
12942 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0),
12943 gfx::Rect(xoffset, yoffset, width, height),
12944 &cleared_rect)) {
12945 DCHECK_GE(cleared_rect.size().GetArea(),
12946 dest_texture->GetLevelClearedRect(target, 0).size().GetArea());
12947 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0,
12948 cleared_rect);
12949 } else {
12950 // Otherwise clear part of texture level that is not already cleared.
12951 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
12952 0)) {
12953 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY,
12954 "glCompressedCopySubTextureCHROMIUM",
12955 "destination texture dimensions too big");
12956 return;
12959 } else {
12960 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12961 true);
12964 ScopedTextureBinder binder(
12965 &state_, dest_texture->service_id(), GL_TEXTURE_2D);
12967 ScopedModifyPixels modify(dest_texture_ref);
12969 // Try using GLImage::CopyTexSubImage when possible.
12970 if (image) {
12971 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset),
12972 gfx::Rect(x, y, width, height))) {
12973 return;
12977 TRACE_EVENT0(
12978 "gpu",
12979 "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM, fallback");
12981 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12983 // As a fallback, copy into a non-compressed GL_RGBA texture.
12984 if (dest_internal_format != GL_RGBA) {
12985 // To preserve the contents of the original destination texture we must
12986 // first copy the original destination texture to a temporary storage, then
12987 // copy it back to the original destination texture.
12988 GLuint tmp_service_id;
12989 glGenTextures(1, &tmp_service_id);
12990 DCHECK_NE(0u, tmp_service_id);
12992 glBindTexture(GL_TEXTURE_2D, tmp_service_id);
12994 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12995 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dest_width, dest_height, 0, GL_RGBA,
12996 GL_UNSIGNED_BYTE, NULL);
12997 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM");
12998 if (error != GL_NO_ERROR)
12999 return;
13001 copy_texture_CHROMIUM_->DoCopyTexture(
13002 this, dest_texture->target(), dest_texture->service_id(),
13003 dest_internal_format, tmp_service_id, GL_RGBA,
13004 dest_width, dest_height, false, false, false);
13006 // Redefine destination texture to use RGBA.
13007 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
13008 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13009 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dest_width, dest_height, 0, GL_RGBA,
13010 GL_UNSIGNED_BYTE, NULL);
13011 error = LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM");
13012 if (error != GL_NO_ERROR)
13013 return;
13015 texture_manager()->SetLevelInfo(
13016 dest_texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, dest_width, dest_height,
13017 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(dest_width, dest_height));
13019 copy_texture_CHROMIUM_->DoCopyTexture(
13020 this, GL_TEXTURE_2D, tmp_service_id, GL_RGBA,
13021 dest_texture->service_id(), GL_RGBA,
13022 dest_width, dest_height, false, false, false);
13024 glDeleteTextures(1, &tmp_service_id);
13027 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
13028 // crbug.com/226218.
13029 copy_texture_CHROMIUM_->DoCopySubTexture(
13030 this, source_texture->target(), source_texture->service_id(),
13031 source_internal_format, dest_texture->service_id(), GL_RGBA,
13032 xoffset, yoffset, x, y, width, height, dest_width, dest_height,
13033 source_width, source_height, false, false, false);
13035 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
13038 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
13039 switch (internalformat) {
13040 case GL_R8:
13041 return GL_UNSIGNED_BYTE;
13042 case GL_R8_SNORM:
13043 return GL_BYTE;
13044 case GL_R16F:
13045 return GL_HALF_FLOAT;
13046 case GL_R32F:
13047 return GL_FLOAT;
13048 case GL_R8UI:
13049 return GL_UNSIGNED_BYTE;
13050 case GL_R8I:
13051 return GL_BYTE;
13052 case GL_R16UI:
13053 return GL_UNSIGNED_SHORT;
13054 case GL_R16I:
13055 return GL_SHORT;
13056 case GL_R32UI:
13057 return GL_UNSIGNED_INT;
13058 case GL_R32I:
13059 return GL_INT;
13060 case GL_RG8:
13061 return GL_UNSIGNED_BYTE;
13062 case GL_RG8_SNORM:
13063 return GL_BYTE;
13064 case GL_RG16F:
13065 return GL_HALF_FLOAT;
13066 case GL_RG32F:
13067 return GL_FLOAT;
13068 case GL_RG8UI:
13069 return GL_UNSIGNED_BYTE;
13070 case GL_RG8I:
13071 return GL_BYTE;
13072 case GL_RG16UI:
13073 return GL_UNSIGNED_SHORT;
13074 case GL_RG16I:
13075 return GL_SHORT;
13076 case GL_RG32UI:
13077 return GL_UNSIGNED_INT;
13078 case GL_RG32I:
13079 return GL_INT;
13080 case GL_RGB8:
13081 case GL_SRGB8:
13082 return GL_UNSIGNED_BYTE;
13083 case GL_R11F_G11F_B10F:
13084 return GL_UNSIGNED_INT_10F_11F_11F_REV;
13085 case GL_RGB565:
13086 return GL_UNSIGNED_SHORT_5_6_5;
13087 case GL_RGB8_SNORM:
13088 return GL_BYTE;
13089 case GL_RGB9_E5:
13090 return GL_UNSIGNED_INT_5_9_9_9_REV;
13091 case GL_RGB16F:
13092 return GL_HALF_FLOAT;
13093 case GL_RGB32F:
13094 return GL_FLOAT;
13095 case GL_RGB8UI:
13096 return GL_UNSIGNED_BYTE;
13097 case GL_RGB8I:
13098 return GL_BYTE;
13099 case GL_RGB16UI:
13100 return GL_UNSIGNED_SHORT;
13101 case GL_RGB16I:
13102 return GL_SHORT;
13103 case GL_RGB32UI:
13104 return GL_UNSIGNED_INT;
13105 case GL_RGB32I:
13106 return GL_INT;
13107 case GL_RGBA8:
13108 return GL_UNSIGNED_BYTE;
13109 case GL_SRGB8_ALPHA8:
13110 return GL_UNSIGNED_BYTE;
13111 case GL_RGBA8_SNORM:
13112 return GL_BYTE;
13113 case GL_RGBA4:
13114 return GL_UNSIGNED_SHORT_4_4_4_4;
13115 case GL_RGB10_A2:
13116 return GL_UNSIGNED_INT_2_10_10_10_REV;
13117 case GL_RGB5_A1:
13118 return GL_UNSIGNED_SHORT_5_5_5_1;
13119 case GL_RGBA16F:
13120 return GL_HALF_FLOAT;
13121 case GL_RGBA32F:
13122 return GL_FLOAT;
13123 case GL_RGBA8UI:
13124 return GL_UNSIGNED_BYTE;
13125 case GL_RGBA8I:
13126 return GL_BYTE;
13127 case GL_RGB10_A2UI:
13128 return GL_UNSIGNED_INT_2_10_10_10_REV;
13129 case GL_RGBA16UI:
13130 return GL_UNSIGNED_SHORT;
13131 case GL_RGBA16I:
13132 return GL_SHORT;
13133 case GL_RGBA32I:
13134 return GL_INT;
13135 case GL_RGBA32UI:
13136 return GL_UNSIGNED_INT;
13137 case GL_DEPTH_COMPONENT16:
13138 return GL_UNSIGNED_SHORT;
13139 case GL_DEPTH_COMPONENT24:
13140 return GL_UNSIGNED_INT;
13141 case GL_DEPTH_COMPONENT32F:
13142 return GL_FLOAT;
13143 case GL_DEPTH24_STENCIL8:
13144 return GL_UNSIGNED_INT_24_8;
13145 case GL_DEPTH32F_STENCIL8:
13146 return GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
13147 case GL_LUMINANCE8_ALPHA8_EXT:
13148 return GL_UNSIGNED_BYTE;
13149 case GL_LUMINANCE8_EXT:
13150 return GL_UNSIGNED_BYTE;
13151 case GL_ALPHA8_EXT:
13152 return GL_UNSIGNED_BYTE;
13153 case GL_ALPHA32F_EXT:
13154 return GL_FLOAT;
13155 case GL_LUMINANCE32F_EXT:
13156 return GL_FLOAT;
13157 case GL_LUMINANCE_ALPHA32F_EXT:
13158 return GL_FLOAT;
13159 case GL_ALPHA16F_EXT:
13160 return GL_HALF_FLOAT_OES;
13161 case GL_LUMINANCE16F_EXT:
13162 return GL_HALF_FLOAT_OES;
13163 case GL_LUMINANCE_ALPHA16F_EXT:
13164 return GL_HALF_FLOAT_OES;
13165 case GL_BGRA8_EXT:
13166 return GL_UNSIGNED_BYTE;
13167 default:
13168 return GL_NONE;
13172 void GLES2DecoderImpl::DoTexStorage2DEXT(
13173 GLenum target,
13174 GLint levels,
13175 GLenum internal_format,
13176 GLsizei width,
13177 GLsizei height) {
13178 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
13179 "width", width, "height", height);
13180 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
13181 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
13182 LOCAL_SET_GL_ERROR(
13183 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
13184 return;
13186 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13187 &state_, target);
13188 if (!texture_ref) {
13189 LOCAL_SET_GL_ERROR(
13190 GL_INVALID_OPERATION,
13191 "glTexStorage2DEXT", "unknown texture for target");
13192 return;
13194 Texture* texture = texture_ref->texture();
13195 if (texture->IsAttachedToFramebuffer()) {
13196 framebuffer_state_.clear_state_dirty = true;
13198 if (texture->IsImmutable()) {
13199 LOCAL_SET_GL_ERROR(
13200 GL_INVALID_OPERATION,
13201 "glTexStorage2DEXT", "texture is immutable");
13202 return;
13205 GLenum format = ExtractFormatFromStorageFormat(internal_format);
13206 GLenum type = ExtractTypeFromStorageFormat(internal_format);
13209 GLsizei level_width = width;
13210 GLsizei level_height = height;
13211 uint32 estimated_size = 0;
13212 for (int ii = 0; ii < levels; ++ii) {
13213 uint32 level_size = 0;
13214 if (!GLES2Util::ComputeImageDataSizes(
13215 level_width, level_height, 1, format, type, state_.unpack_alignment,
13216 &estimated_size, NULL, NULL) ||
13217 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
13218 LOCAL_SET_GL_ERROR(
13219 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
13220 return;
13222 level_width = std::max(1, level_width >> 1);
13223 level_height = std::max(1, level_height >> 1);
13225 if (!EnsureGPUMemoryAvailable(estimated_size)) {
13226 LOCAL_SET_GL_ERROR(
13227 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
13228 return;
13232 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
13233 glTexStorage2DEXT(target, levels, internal_format, width, height);
13234 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
13235 if (error == GL_NO_ERROR) {
13236 GLsizei level_width = width;
13237 GLsizei level_height = height;
13239 GLenum cur_format = feature_info_->IsES3Enabled() ?
13240 internal_format : format;
13241 for (int ii = 0; ii < levels; ++ii) {
13242 if (target == GL_TEXTURE_CUBE_MAP) {
13243 for (int jj = 0; jj < 6; ++jj) {
13244 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + jj;
13245 texture_manager()->SetLevelInfo(texture_ref, face, ii, cur_format,
13246 level_width, level_height, 1, 0,
13247 format, type, gfx::Rect());
13249 } else {
13250 texture_manager()->SetLevelInfo(texture_ref, target, ii, cur_format,
13251 level_width, level_height, 1, 0,
13252 format, type, gfx::Rect());
13254 level_width = std::max(1, level_width >> 1);
13255 level_height = std::max(1, level_height >> 1);
13257 texture->SetImmutable(true);
13261 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
13262 uint32 immediate_data_size,
13263 const void* cmd_data) {
13264 return error::kUnknownCommand;
13267 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
13268 const GLbyte* data) {
13269 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
13270 "context", logger_.GetLogPrefix(),
13271 "mailbox[0]", static_cast<unsigned char>(data[0]));
13273 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13274 &state_, target);
13275 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
13278 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
13279 GLenum target, const GLbyte* data) {
13280 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
13281 "context", logger_.GetLogPrefix(),
13282 "mailbox[0]", static_cast<unsigned char>(data[0]));
13284 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
13285 target, data);
13288 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
13289 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
13290 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13291 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
13292 "mailbox that was not generated by "
13293 "GenMailboxCHROMIUM.";
13295 if (!texture_ref) {
13296 LOCAL_SET_GL_ERROR(
13297 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
13298 return;
13301 Texture* produced = texture_manager()->Produce(texture_ref);
13302 if (!produced) {
13303 LOCAL_SET_GL_ERROR(
13304 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
13305 return;
13308 if (produced->target() != target) {
13309 LOCAL_SET_GL_ERROR(
13310 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
13311 return;
13314 group_->mailbox_manager()->ProduceTexture(mailbox, produced);
13317 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
13318 const GLbyte* data) {
13319 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
13320 "context", logger_.GetLogPrefix(),
13321 "mailbox[0]", static_cast<unsigned char>(data[0]));
13322 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13323 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
13324 "mailbox that was not generated by "
13325 "GenMailboxCHROMIUM.";
13327 scoped_refptr<TextureRef> texture_ref =
13328 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13329 if (!texture_ref.get()) {
13330 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13331 "glConsumeTextureCHROMIUM",
13332 "unknown texture for target");
13333 return;
13335 GLuint client_id = texture_ref->client_id();
13336 if (!client_id) {
13337 LOCAL_SET_GL_ERROR(
13338 GL_INVALID_OPERATION,
13339 "glConsumeTextureCHROMIUM", "unknown texture for target");
13340 return;
13342 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
13343 if (!texture) {
13344 LOCAL_SET_GL_ERROR(
13345 GL_INVALID_OPERATION,
13346 "glConsumeTextureCHROMIUM", "invalid mailbox name");
13347 return;
13349 if (texture->target() != target) {
13350 LOCAL_SET_GL_ERROR(
13351 GL_INVALID_OPERATION,
13352 "glConsumeTextureCHROMIUM", "invalid target");
13353 return;
13356 DeleteTexturesHelper(1, &client_id);
13357 texture_ref = texture_manager()->Consume(client_id, texture);
13358 glBindTexture(target, texture_ref->service_id());
13360 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
13361 unit.bind_target = target;
13362 switch (target) {
13363 case GL_TEXTURE_2D:
13364 unit.bound_texture_2d = texture_ref;
13365 break;
13366 case GL_TEXTURE_CUBE_MAP:
13367 unit.bound_texture_cube_map = texture_ref;
13368 break;
13369 case GL_TEXTURE_EXTERNAL_OES:
13370 unit.bound_texture_external_oes = texture_ref;
13371 break;
13372 case GL_TEXTURE_RECTANGLE_ARB:
13373 unit.bound_texture_rectangle_arb = texture_ref;
13374 break;
13375 default:
13376 NOTREACHED(); // Validation should prevent us getting here.
13377 break;
13381 void GLES2DecoderImpl::EnsureTextureForClientId(
13382 GLenum target,
13383 GLuint client_id) {
13384 TextureRef* texture_ref = GetTexture(client_id);
13385 if (!texture_ref) {
13386 GLuint service_id;
13387 glGenTextures(1, &service_id);
13388 DCHECK_NE(0u, service_id);
13389 texture_ref = CreateTexture(client_id, service_id);
13390 texture_manager()->SetTarget(texture_ref, target);
13391 glBindTexture(target, service_id);
13392 RestoreCurrentTextureBindings(&state_, target);
13396 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
13397 // provided is associated with a service_id/TextureRef for consistency, even if
13398 // the resulting texture is incomplete.
13399 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
13400 uint32_t immediate_data_size,
13401 const void* cmd_data) {
13402 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c =
13403 *static_cast<
13404 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate*>(
13405 cmd_data);
13406 GLenum target = static_cast<GLenum>(c.target);
13407 uint32_t data_size;
13408 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
13409 return error::kOutOfBounds;
13411 if (data_size > immediate_data_size) {
13412 return error::kOutOfBounds;
13414 const GLbyte* mailbox =
13415 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
13416 if (!validators_->texture_bind_target.IsValid(target)) {
13417 LOCAL_SET_GL_ERROR_INVALID_ENUM(
13418 "glCreateAndConsumeTextureCHROMIUM", target, "target");
13419 return error::kNoError;
13421 if (mailbox == NULL) {
13422 return error::kOutOfBounds;
13424 uint32_t client_id = c.client_id;
13425 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
13426 return error::kNoError;
13429 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
13430 const GLbyte* data, GLuint client_id) {
13431 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
13432 "context", logger_.GetLogPrefix(),
13433 "mailbox[0]", static_cast<unsigned char>(data[0]));
13434 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13435 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
13436 "passed a mailbox that was not "
13437 "generated by GenMailboxCHROMIUM.";
13439 TextureRef* texture_ref = GetTexture(client_id);
13440 if (texture_ref) {
13441 // No need to call EnsureTextureForClientId here, the client_id already has
13442 // an associated texture.
13443 LOCAL_SET_GL_ERROR(
13444 GL_INVALID_OPERATION,
13445 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
13446 return;
13448 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
13449 if (!texture) {
13450 EnsureTextureForClientId(target, client_id);
13451 LOCAL_SET_GL_ERROR(
13452 GL_INVALID_OPERATION,
13453 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
13454 return;
13457 if (texture->target() != target) {
13458 EnsureTextureForClientId(target, client_id);
13459 LOCAL_SET_GL_ERROR(
13460 GL_INVALID_OPERATION,
13461 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
13462 return;
13465 texture_ref = texture_manager()->Consume(client_id, texture);
13468 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id) {
13469 const Valuebuffer* valuebuffer = GetValuebuffer(client_id);
13470 return valuebuffer && valuebuffer->IsValid();
13473 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target,
13474 GLuint client_id) {
13475 Valuebuffer* valuebuffer = NULL;
13476 if (client_id != 0) {
13477 valuebuffer = GetValuebuffer(client_id);
13478 if (!valuebuffer) {
13479 if (!group_->bind_generates_resource()) {
13480 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindValuebufferCHROMIUM",
13481 "id not generated by glBindValuebufferCHROMIUM");
13482 return;
13485 // It's a new id so make a valuebuffer for it.
13486 CreateValuebuffer(client_id);
13487 valuebuffer = GetValuebuffer(client_id);
13489 valuebuffer->MarkAsValid();
13491 state_.bound_valuebuffer = valuebuffer;
13494 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target,
13495 GLenum subscription) {
13496 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
13497 return;
13499 state_.bound_valuebuffer.get()->AddSubscription(subscription);
13502 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target) {
13503 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
13504 return;
13506 valuebuffer_manager()->UpdateValuebufferState(state_.bound_valuebuffer.get());
13509 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location,
13510 GLenum target,
13511 GLenum subscription) {
13512 if (!CheckCurrentValuebufferForSubscription(
13513 subscription, "glPopulateSubscribedValuesCHROMIUM")) {
13514 return;
13516 if (!CheckSubscriptionTarget(location, subscription,
13517 "glPopulateSubscribedValuesCHROMIUM")) {
13518 return;
13520 const ValueState* state =
13521 state_.bound_valuebuffer.get()->GetState(subscription);
13522 if (state) {
13523 switch (subscription) {
13524 case GL_MOUSE_POSITION_CHROMIUM:
13525 DoUniform2iv(location, 1, state->int_value);
13526 break;
13527 default:
13528 NOTREACHED() << "Unhandled uniform subscription target "
13529 << subscription;
13530 break;
13535 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
13536 GLsizei length, const GLchar* marker) {
13537 if (!marker) {
13538 marker = "";
13540 debug_marker_manager_.SetMarker(
13541 length ? std::string(marker, length) : std::string(marker));
13544 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
13545 GLsizei /*length*/, const GLchar* /*marker*/) {
13548 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
13551 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
13552 GLenum target, GLint image_id) {
13553 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
13555 if (target == GL_TEXTURE_CUBE_MAP) {
13556 LOCAL_SET_GL_ERROR(
13557 GL_INVALID_ENUM,
13558 "glBindTexImage2DCHROMIUM", "invalid target");
13559 return;
13562 // Default target might be conceptually valid, but disallow it to avoid
13563 // accidents.
13564 TextureRef* texture_ref =
13565 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13566 if (!texture_ref) {
13567 LOCAL_SET_GL_ERROR(
13568 GL_INVALID_OPERATION,
13569 "glBindTexImage2DCHROMIUM", "no texture bound");
13570 return;
13573 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
13574 if (!gl_image) {
13575 LOCAL_SET_GL_ERROR(
13576 GL_INVALID_OPERATION,
13577 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
13578 return;
13582 ScopedGLErrorSuppressor suppressor(
13583 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
13584 if (!gl_image->BindTexImage(target)) {
13585 LOCAL_SET_GL_ERROR(
13586 GL_INVALID_OPERATION,
13587 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
13588 return;
13592 gfx::Size size = gl_image->GetSize();
13593 texture_manager()->SetLevelInfo(
13594 texture_ref, target, 0, gl_image->GetInternalFormat(), size.width(),
13595 size.height(), 1, 0, gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE,
13596 gfx::Rect(size));
13597 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
13600 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
13601 GLenum target, GLint image_id) {
13602 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
13604 // Default target might be conceptually valid, but disallow it to avoid
13605 // accidents.
13606 TextureRef* texture_ref =
13607 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13608 if (!texture_ref) {
13609 LOCAL_SET_GL_ERROR(
13610 GL_INVALID_OPERATION,
13611 "glReleaseTexImage2DCHROMIUM", "no texture bound");
13612 return;
13615 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
13616 if (!gl_image) {
13617 LOCAL_SET_GL_ERROR(
13618 GL_INVALID_OPERATION,
13619 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
13620 return;
13623 // Do nothing when image is not currently bound.
13624 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
13625 return;
13628 ScopedGLErrorSuppressor suppressor(
13629 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
13630 gl_image->ReleaseTexImage(target);
13633 texture_manager()->SetLevelInfo(
13634 texture_ref, target, 0, gl_image->GetInternalFormat(), 0, 0, 1, 0,
13635 gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, gfx::Rect());
13638 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
13639 uint32 immediate_data_size,
13640 const void* cmd_data) {
13641 const gles2::cmds::TraceBeginCHROMIUM& c =
13642 *static_cast<const gles2::cmds::TraceBeginCHROMIUM*>(cmd_data);
13643 Bucket* category_bucket = GetBucket(c.category_bucket_id);
13644 Bucket* name_bucket = GetBucket(c.name_bucket_id);
13645 if (!category_bucket || category_bucket->size() == 0 ||
13646 !name_bucket || name_bucket->size() == 0) {
13647 return error::kInvalidArguments;
13650 std::string category_name;
13651 std::string trace_name;
13652 if (!category_bucket->GetAsString(&category_name) ||
13653 !name_bucket->GetAsString(&trace_name)) {
13654 return error::kInvalidArguments;
13657 debug_marker_manager_.PushGroup(trace_name);
13658 if (!gpu_tracer_->Begin(category_name, trace_name, kTraceCHROMIUM)) {
13659 LOCAL_SET_GL_ERROR(
13660 GL_INVALID_OPERATION,
13661 "glTraceBeginCHROMIUM", "unable to create begin trace");
13662 return error::kNoError;
13664 return error::kNoError;
13667 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
13668 debug_marker_manager_.PopGroup();
13669 if (!gpu_tracer_->End(kTraceCHROMIUM)) {
13670 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13671 "glTraceEndCHROMIUM", "no trace begin found");
13672 return;
13676 void GLES2DecoderImpl::DoDrawBuffersEXT(
13677 GLsizei count, const GLenum* bufs) {
13678 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
13679 LOCAL_SET_GL_ERROR(
13680 GL_INVALID_VALUE,
13681 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
13682 return;
13685 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
13686 if (framebuffer) {
13687 for (GLsizei i = 0; i < count; ++i) {
13688 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
13689 bufs[i] != GL_NONE) {
13690 LOCAL_SET_GL_ERROR(
13691 GL_INVALID_OPERATION,
13692 "glDrawBuffersEXT",
13693 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
13694 return;
13697 glDrawBuffersARB(count, bufs);
13698 framebuffer->SetDrawBuffers(count, bufs);
13699 } else { // backbuffer
13700 if (count > 1 ||
13701 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
13702 LOCAL_SET_GL_ERROR(
13703 GL_INVALID_OPERATION,
13704 "glDrawBuffersEXT",
13705 "more than one buffer or bufs not GL_NONE or GL_BACK");
13706 return;
13708 GLenum mapped_buf = bufs[0];
13709 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
13710 bufs[0] == GL_BACK) {
13711 mapped_buf = GL_COLOR_ATTACHMENT0;
13713 glDrawBuffersARB(count, &mapped_buf);
13714 back_buffer_draw_buffer_ = bufs[0];
13718 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
13719 MarkContextLost(GetContextLostReasonFromResetStatus(current));
13720 group_->LoseContexts(GetContextLostReasonFromResetStatus(other));
13721 reset_by_robustness_extension_ = true;
13724 void GLES2DecoderImpl::DoFlushDriverCachesCHROMIUM(void) {
13725 // On Adreno Android devices we need to use a workaround to force caches to
13726 // clear.
13727 if (feature_info_->workarounds().unbind_egl_context_to_flush_driver_caches) {
13728 context_->ReleaseCurrent(nullptr);
13729 context_->MakeCurrent(surface_.get());
13733 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
13734 const GLfloat* matrix) {
13735 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
13736 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
13737 if (!features().chromium_path_rendering) {
13738 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13739 "glMatrixLoadfCHROMIUM",
13740 "function not available");
13741 return;
13744 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
13745 ? state_.projection_matrix
13746 : state_.modelview_matrix;
13747 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
13748 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13749 // since the values of the _NV and _CHROMIUM tokens match.
13750 glMatrixLoadfEXT(matrix_mode, matrix);
13753 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
13754 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
13755 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
13757 if (!features().chromium_path_rendering) {
13758 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13759 "glMatrixLoadIdentityCHROMIUM",
13760 "function not available");
13761 return;
13764 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
13765 ? state_.projection_matrix
13766 : state_.modelview_matrix;
13767 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
13768 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13769 // since the values of the _NV and _CHROMIUM tokens match.
13770 glMatrixLoadIdentityEXT(matrix_mode);
13773 bool GLES2DecoderImpl::ValidateAsyncTransfer(
13774 const char* function_name,
13775 TextureRef* texture_ref,
13776 GLenum target,
13777 GLint level,
13778 const void * data) {
13779 // We only support async uploads to 2D textures for now.
13780 if (GL_TEXTURE_2D != target) {
13781 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
13782 return false;
13784 // We only support uploads to level zero for now.
13785 if (level != 0) {
13786 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
13787 return false;
13789 // A transfer buffer must be bound, even for asyncTexImage2D.
13790 if (data == NULL) {
13791 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
13792 return false;
13794 // We only support one async transfer in progress.
13795 if (!texture_ref ||
13796 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
13797 LOCAL_SET_GL_ERROR(
13798 GL_INVALID_OPERATION,
13799 function_name, "transfer already in progress");
13800 return false;
13802 return true;
13805 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
13806 uint32 async_upload_token,
13807 uint32 sync_data_shm_id,
13808 uint32 sync_data_shm_offset) {
13809 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
13810 if (!buffer.get() ||
13811 !buffer->GetDataAddress(sync_data_shm_offset, sizeof(AsyncUploadSync)))
13812 return base::Closure();
13814 AsyncMemoryParams mem_params(buffer,
13815 sync_data_shm_offset,
13816 sizeof(AsyncUploadSync));
13818 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
13819 new AsyncUploadTokenCompletionObserver(async_upload_token));
13821 return base::Bind(
13822 &AsyncPixelTransferManager::AsyncNotifyCompletion,
13823 base::Unretained(GetAsyncPixelTransferManager()),
13824 mem_params,
13825 observer);
13828 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
13829 uint32 immediate_data_size,
13830 const void* cmd_data) {
13831 const gles2::cmds::AsyncTexImage2DCHROMIUM& c =
13832 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM*>(cmd_data);
13833 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
13834 GLenum target = static_cast<GLenum>(c.target);
13835 GLint level = static_cast<GLint>(c.level);
13836 GLenum internal_format = static_cast<GLenum>(c.internalformat);
13837 GLsizei width = static_cast<GLsizei>(c.width);
13838 GLsizei height = static_cast<GLsizei>(c.height);
13839 GLint border = static_cast<GLint>(c.border);
13840 GLenum format = static_cast<GLenum>(c.format);
13841 GLenum type = static_cast<GLenum>(c.type);
13842 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
13843 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
13844 uint32 pixels_size;
13845 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
13846 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
13847 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
13849 base::ScopedClosureRunner scoped_completion_callback;
13850 if (async_upload_token) {
13851 base::Closure completion_closure =
13852 AsyncUploadTokenCompletionClosure(async_upload_token,
13853 sync_data_shm_id,
13854 sync_data_shm_offset);
13855 if (completion_closure.is_null())
13856 return error::kInvalidArguments;
13858 scoped_completion_callback.Reset(completion_closure);
13861 // TODO(epenner): Move this and copies of this memory validation
13862 // into ValidateTexImage2D step.
13863 if (!GLES2Util::ComputeImageDataSizes(
13864 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
13865 NULL, NULL)) {
13866 return error::kOutOfBounds;
13868 const void* pixels = NULL;
13869 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
13870 pixels = GetSharedMemoryAs<const void*>(
13871 pixels_shm_id, pixels_shm_offset, pixels_size);
13872 if (!pixels) {
13873 return error::kOutOfBounds;
13877 TextureManager::DoTexImageArguments args = {
13878 target, level, internal_format, width, height, 1, border, format, type,
13879 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
13880 TextureRef* texture_ref;
13881 // All the normal glTexSubImage2D validation.
13882 if (!texture_manager()->ValidateTexImage(
13883 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
13884 return error::kNoError;
13887 // Extra async validation.
13888 Texture* texture = texture_ref->texture();
13889 if (!ValidateAsyncTransfer(
13890 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
13891 return error::kNoError;
13893 // Don't allow async redefinition of a textures.
13894 if (texture->IsDefined()) {
13895 LOCAL_SET_GL_ERROR(
13896 GL_INVALID_OPERATION,
13897 "glAsyncTexImage2DCHROMIUM", "already defined");
13898 return error::kNoError;
13901 if (!EnsureGPUMemoryAvailable(pixels_size)) {
13902 LOCAL_SET_GL_ERROR(
13903 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
13904 return error::kNoError;
13907 // Setup the parameters.
13908 AsyncTexImage2DParams tex_params = {
13909 target, level, static_cast<GLenum>(internal_format),
13910 width, height, border, format, type};
13911 AsyncMemoryParams mem_params(
13912 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
13914 // Set up the async state if needed, and make the texture
13915 // immutable so the async state stays valid. The level info
13916 // is set up lazily when the transfer completes.
13917 AsyncPixelTransferDelegate* delegate =
13918 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
13919 tex_params);
13920 texture->SetImmutable(true);
13922 delegate->AsyncTexImage2D(
13923 tex_params,
13924 mem_params,
13925 base::Bind(&TextureManager::SetLevelInfoFromParams,
13926 // The callback is only invoked if the transfer delegate still
13927 // exists, which implies through manager->texture_ref->state
13928 // ownership that both of these pointers are valid.
13929 base::Unretained(texture_manager()),
13930 base::Unretained(texture_ref),
13931 tex_params));
13932 return error::kNoError;
13935 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
13936 uint32 immediate_data_size,
13937 const void* cmd_data) {
13938 const gles2::cmds::AsyncTexSubImage2DCHROMIUM& c =
13939 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM*>(cmd_data);
13940 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
13941 GLenum target = static_cast<GLenum>(c.target);
13942 GLint level = static_cast<GLint>(c.level);
13943 GLint xoffset = static_cast<GLint>(c.xoffset);
13944 GLint yoffset = static_cast<GLint>(c.yoffset);
13945 GLsizei width = static_cast<GLsizei>(c.width);
13946 GLsizei height = static_cast<GLsizei>(c.height);
13947 GLenum format = static_cast<GLenum>(c.format);
13948 GLenum type = static_cast<GLenum>(c.type);
13949 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
13950 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
13951 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
13953 base::ScopedClosureRunner scoped_completion_callback;
13954 if (async_upload_token) {
13955 base::Closure completion_closure =
13956 AsyncUploadTokenCompletionClosure(async_upload_token,
13957 sync_data_shm_id,
13958 sync_data_shm_offset);
13959 if (completion_closure.is_null())
13960 return error::kInvalidArguments;
13962 scoped_completion_callback.Reset(completion_closure);
13965 // TODO(epenner): Move this and copies of this memory validation
13966 // into ValidateTexSubImage2D step.
13967 uint32 data_size;
13968 if (!GLES2Util::ComputeImageDataSizes(
13969 width, height, 1, format, type, state_.unpack_alignment, &data_size,
13970 NULL, NULL)) {
13971 return error::kOutOfBounds;
13973 const void* pixels = GetSharedMemoryAs<const void*>(
13974 c.data_shm_id, c.data_shm_offset, data_size);
13976 // All the normal glTexSubImage2D validation.
13977 error::Error error = error::kNoError;
13978 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
13979 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
13980 return error;
13983 // Extra async validation.
13984 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13985 &state_, target);
13986 Texture* texture = texture_ref->texture();
13987 if (!ValidateAsyncTransfer(
13988 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
13989 return error::kNoError;
13991 // Guarantee async textures are always 'cleared' as follows:
13992 // - AsyncTexImage2D can not redefine an existing texture
13993 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
13994 // - AsyncTexSubImage2D clears synchronously if not already cleared.
13995 // - Textures become immutable after an async call.
13996 // This way we know in all cases that an async texture is always clear.
13997 if (!texture->SafeToRenderFrom()) {
13998 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
13999 target, level)) {
14000 LOCAL_SET_GL_ERROR(
14001 GL_OUT_OF_MEMORY,
14002 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
14003 return error::kNoError;
14007 // Setup the parameters.
14008 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
14009 width, height, format, type};
14010 AsyncMemoryParams mem_params(
14011 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
14012 AsyncPixelTransferDelegate* delegate =
14013 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
14014 if (!delegate) {
14015 // TODO(epenner): We may want to enforce exclusive use
14016 // of async APIs in which case this should become an error,
14017 // (the texture should have been async defined).
14018 AsyncTexImage2DParams define_params = {target, level,
14019 0, 0, 0, 0, 0, 0};
14020 texture->GetLevelSize(
14021 target, level, &define_params.width, &define_params.height, nullptr);
14022 texture->GetLevelType(
14023 target, level, &define_params.type, &define_params.internal_format);
14024 // Set up the async state if needed, and make the texture
14025 // immutable so the async state stays valid.
14026 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
14027 texture_ref, define_params);
14028 texture->SetImmutable(true);
14031 delegate->AsyncTexSubImage2D(tex_params, mem_params);
14032 return error::kNoError;
14035 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
14036 uint32 immediate_data_size,
14037 const void* cmd_data) {
14038 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM& c =
14039 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM*>(cmd_data);
14040 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
14041 GLenum target = static_cast<GLenum>(c.target);
14043 if (GL_TEXTURE_2D != target) {
14044 LOCAL_SET_GL_ERROR(
14045 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
14046 return error::kNoError;
14048 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
14049 &state_, target);
14050 if (!texture_ref) {
14051 LOCAL_SET_GL_ERROR(
14052 GL_INVALID_OPERATION,
14053 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
14054 return error::kNoError;
14056 AsyncPixelTransferDelegate* delegate =
14057 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
14058 if (!delegate) {
14059 LOCAL_SET_GL_ERROR(
14060 GL_INVALID_OPERATION,
14061 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
14062 return error::kNoError;
14064 delegate->WaitForTransferCompletion();
14065 ProcessFinishedAsyncTransfers();
14066 return error::kNoError;
14069 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
14070 uint32 immediate_data_size,
14071 const void* data) {
14072 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
14074 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
14075 ProcessFinishedAsyncTransfers();
14076 return error::kNoError;
14079 error::Error GLES2DecoderImpl::HandleUniformBlockBinding(
14080 uint32_t immediate_data_size, const void* cmd_data) {
14081 if (!unsafe_es3_apis_enabled())
14082 return error::kUnknownCommand;
14083 const gles2::cmds::UniformBlockBinding& c =
14084 *static_cast<const gles2::cmds::UniformBlockBinding*>(cmd_data);
14085 GLuint client_id = c.program;
14086 GLuint index = static_cast<GLuint>(c.index);
14087 GLuint binding = static_cast<GLuint>(c.binding);
14088 Program* program = GetProgramInfoNotShader(
14089 client_id, "glUniformBlockBinding");
14090 if (!program) {
14091 return error::kNoError;
14093 GLuint service_id = program->service_id();
14094 glUniformBlockBinding(service_id, index, binding);
14095 return error::kNoError;
14098 error::Error GLES2DecoderImpl::HandleClientWaitSync(
14099 uint32_t immediate_data_size, const void* cmd_data) {
14100 if (!unsafe_es3_apis_enabled())
14101 return error::kUnknownCommand;
14102 const gles2::cmds::ClientWaitSync& c =
14103 *static_cast<const gles2::cmds::ClientWaitSync*>(cmd_data);
14104 GLuint sync = static_cast<GLuint>(c.sync);
14105 GLbitfield flags = static_cast<GLbitfield>(c.flags);
14106 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
14107 typedef cmds::ClientWaitSync::Result Result;
14108 Result* result_dst = GetSharedMemoryAs<Result*>(
14109 c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
14110 if (!result_dst) {
14111 return error::kOutOfBounds;
14113 if (*result_dst != GL_WAIT_FAILED) {
14114 return error::kInvalidArguments;
14116 GLsync service_sync = 0;
14117 if (!group_->GetSyncServiceId(sync, &service_sync)) {
14118 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "ClientWaitSync", "invalid sync");
14119 return error::kNoError;
14121 *result_dst = glClientWaitSync(service_sync, flags, timeout);
14122 return error::kNoError;
14125 error::Error GLES2DecoderImpl::HandleWaitSync(
14126 uint32_t immediate_data_size, const void* cmd_data) {
14127 if (!unsafe_es3_apis_enabled())
14128 return error::kUnknownCommand;
14129 const gles2::cmds::WaitSync& c =
14130 *static_cast<const gles2::cmds::WaitSync*>(cmd_data);
14131 GLuint sync = static_cast<GLuint>(c.sync);
14132 GLbitfield flags = static_cast<GLbitfield>(c.flags);
14133 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
14134 GLsync service_sync = 0;
14135 if (!group_->GetSyncServiceId(sync, &service_sync)) {
14136 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "WaitSync", "invalid sync");
14137 return error::kNoError;
14139 glWaitSync(service_sync, flags, timeout);
14140 return error::kNoError;
14143 error::Error GLES2DecoderImpl::HandleGetInternalformativ(
14144 uint32_t immediate_data_size, const void* cmd_data) {
14145 if (!unsafe_es3_apis_enabled())
14146 return error::kUnknownCommand;
14147 const gles2::cmds::GetInternalformativ& c =
14148 *static_cast<const gles2::cmds::GetInternalformativ*>(cmd_data);
14149 GLenum target = static_cast<GLenum>(c.target);
14150 GLenum format = static_cast<GLenum>(c.format);
14151 GLenum pname = static_cast<GLenum>(c.pname);
14152 if (!validators_->render_buffer_target.IsValid(target)) {
14153 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", target, "target");
14154 return error::kNoError;
14156 if (!validators_->render_buffer_format.IsValid(format)) {
14157 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", format, "format");
14158 return error::kNoError;
14160 if (!validators_->internal_format_parameter.IsValid(pname)) {
14161 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", pname, "pname");
14162 return error::kNoError;
14164 typedef cmds::GetInternalformativ::Result Result;
14165 GLsizei num_values = 0;
14166 switch (pname) {
14167 case GL_NUM_SAMPLE_COUNTS:
14168 num_values = 1;
14169 break;
14170 case GL_SAMPLES:
14172 GLint value = 0;
14173 glGetInternalformativ(target, format, GL_NUM_SAMPLE_COUNTS, 1, &value);
14174 num_values = static_cast<GLsizei>(value);
14176 break;
14177 default:
14178 NOTREACHED();
14179 break;
14181 Result* result = GetSharedMemoryAs<Result*>(
14182 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
14183 GLint* params = result ? result->GetData() : NULL;
14184 if (params == NULL) {
14185 return error::kOutOfBounds;
14187 // Check that the client initialized the result.
14188 if (result->size != 0) {
14189 return error::kInvalidArguments;
14191 glGetInternalformativ(target, format, pname, num_values, params);
14192 result->SetNumResults(num_values);
14193 return error::kNoError;
14196 error::Error GLES2DecoderImpl::HandleMapBufferRange(
14197 uint32_t immediate_data_size, const void* cmd_data) {
14198 if (!unsafe_es3_apis_enabled()) {
14199 return error::kUnknownCommand;
14201 const gles2::cmds::MapBufferRange& c =
14202 *static_cast<const gles2::cmds::MapBufferRange*>(cmd_data);
14203 GLenum target = static_cast<GLenum>(c.target);
14204 GLbitfield access = static_cast<GLbitfield>(c.access);
14205 GLintptr offset = static_cast<GLintptr>(c.offset);
14206 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
14208 typedef cmds::MapBufferRange::Result Result;
14209 Result* result = GetSharedMemoryAs<Result*>(
14210 c.result_shm_id, c.result_shm_offset, sizeof(*result));
14211 if (!result) {
14212 return error::kOutOfBounds;
14214 if (*result != 0) {
14215 *result = 0;
14216 return error::kInvalidArguments;
14218 int8_t* mem =
14219 GetSharedMemoryAs<int8_t*>(c.data_shm_id, c.data_shm_offset, size);
14220 if (!mem) {
14221 return error::kOutOfBounds;
14224 GLbitfield mask = GL_MAP_INVALIDATE_BUFFER_BIT;
14225 if ((access & mask) == mask) {
14226 // TODO(zmo): To be on the safe side, always map
14227 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
14228 access = (access & ~GL_MAP_INVALIDATE_BUFFER_BIT);
14229 access = (access | GL_MAP_INVALIDATE_RANGE_BIT);
14231 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
14232 // undefined behaviors.
14233 mask = GL_MAP_READ_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
14234 if ((access & mask) == mask) {
14235 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "MapBufferRange",
14236 "incompatible access bits");
14237 return error::kNoError;
14239 access = (access & ~GL_MAP_UNSYNCHRONIZED_BIT);
14240 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT &&
14241 (access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
14242 access = (access | GL_MAP_READ_BIT);
14244 void* ptr = glMapBufferRange(target, offset, size, access);
14245 if (ptr == nullptr) {
14246 return error::kNoError;
14248 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
14249 DCHECK(buffer);
14250 buffer->SetMappedRange(offset, size, access, ptr,
14251 GetSharedMemoryBuffer(c.data_shm_id));
14252 if ((access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
14253 memcpy(mem, ptr, size);
14255 *result = 1;
14256 return error::kNoError;
14259 error::Error GLES2DecoderImpl::HandleUnmapBuffer(
14260 uint32_t immediate_data_size, const void* cmd_data) {
14261 if (!unsafe_es3_apis_enabled()) {
14262 return error::kUnknownCommand;
14264 const gles2::cmds::UnmapBuffer& c =
14265 *static_cast<const gles2::cmds::UnmapBuffer*>(cmd_data);
14266 GLenum target = static_cast<GLenum>(c.target);
14268 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
14269 if (!buffer) {
14270 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", "no buffer bound");
14271 return error::kNoError;
14273 const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
14274 if (!mapped_range) {
14275 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer",
14276 "buffer is unmapped");
14277 return error::kNoError;
14279 if ((mapped_range->access & GL_MAP_WRITE_BIT) == 0 ||
14280 (mapped_range->access & GL_MAP_FLUSH_EXPLICIT_BIT) ==
14281 GL_MAP_FLUSH_EXPLICIT_BIT) {
14282 // If we don't need to write back, or explict flush is required, no copying
14283 // back is needed.
14284 } else {
14285 void* mem = mapped_range->GetShmPointer();
14286 if (!mem) {
14287 return error::kOutOfBounds;
14289 DCHECK(mapped_range->pointer);
14290 memcpy(mapped_range->pointer, mem, mapped_range->size);
14292 buffer->RemoveMappedRange();
14293 GLboolean rt = glUnmapBuffer(target);
14294 if (rt == GL_FALSE) {
14295 // At this point, we have already done the necessary validation, so
14296 // GL_FALSE indicates data corruption.
14297 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
14298 // the second unmap could still return GL_FALSE. For now, we simply lose
14299 // the contexts in the share group.
14300 LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE";
14301 // Need to lose current context before broadcasting!
14302 MarkContextLost(error::kGuilty);
14303 group_->LoseContexts(error::kInnocent);
14304 return error::kLostContext;
14306 return error::kNoError;
14309 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
14310 TextureRef* texture_ref) {
14311 Texture* texture = texture_ref->texture();
14312 DoDidUseTexImageIfNeeded(texture, texture->target());
14315 // Note that GL_LOST_CONTEXT is specific to GLES.
14316 // For desktop GL we have to query the reset status proactively.
14317 void GLES2DecoderImpl::OnContextLostError() {
14318 if (!WasContextLost()) {
14319 // Need to lose current context before broadcasting!
14320 CheckResetStatus();
14321 group_->LoseContexts(error::kUnknown);
14322 reset_by_robustness_extension_ = true;
14326 void GLES2DecoderImpl::OnOutOfMemoryError() {
14327 if (lose_context_when_out_of_memory_ && !WasContextLost()) {
14328 error::ContextLostReason other = error::kOutOfMemory;
14329 if (CheckResetStatus()) {
14330 other = error::kUnknown;
14331 } else {
14332 // Need to lose current context before broadcasting!
14333 MarkContextLost(error::kOutOfMemory);
14335 group_->LoseContexts(other);
14339 error::Error GLES2DecoderImpl::HandleGenPathsCHROMIUM(
14340 uint32 immediate_data_size,
14341 const void* cmd_data) {
14342 static const char kFunctionName[] = "glGenPathsCHROMIUM";
14343 const gles2::cmds::GenPathsCHROMIUM& c =
14344 *static_cast<const gles2::cmds::GenPathsCHROMIUM*>(cmd_data);
14345 if (!features().chromium_path_rendering) {
14346 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14347 "function not available");
14348 return error::kNoError;
14351 GLsizei range = static_cast<GLsizei>(c.range);
14352 if (range < 0) {
14353 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "range < 0");
14354 return error::kNoError;
14357 GLuint first_client_id = static_cast<GLuint>(c.first_client_id);
14358 if (first_client_id == 0)
14359 return error::kInvalidArguments;
14361 if (range == 0)
14362 return error::kNoError;
14364 if (!GenPathsCHROMIUMHelper(first_client_id, range))
14365 return error::kInvalidArguments;
14367 return error::kNoError;
14369 error::Error GLES2DecoderImpl::HandleDeletePathsCHROMIUM(
14370 uint32_t immediate_data_size,
14371 const void* cmd_data) {
14372 static const char kFunctionName[] = "glDeletePathsCHROMIUM";
14373 const gles2::cmds::DeletePathsCHROMIUM& c =
14374 *static_cast<const gles2::cmds::DeletePathsCHROMIUM*>(cmd_data);
14375 if (!features().chromium_path_rendering) {
14376 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14377 "function not available");
14378 return error::kNoError;
14381 GLsizei range = static_cast<GLsizei>(c.range);
14382 if (range < 0) {
14383 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "range < 0");
14384 return error::kNoError;
14387 if (range == 0)
14388 return error::kNoError;
14390 GLuint first_client_id = c.first_client_id;
14391 // first_client_id can be 0, because non-existing path ids are skipped.
14393 if (!DeletePathsCHROMIUMHelper(first_client_id, range))
14394 return error::kInvalidArguments;
14396 return error::kNoError;
14399 error::Error GLES2DecoderImpl::HandlePathCommandsCHROMIUM(
14400 uint32 immediate_data_size,
14401 const void* cmd_data) {
14402 static const char kFunctionName[] = "glPathCommandsCHROMIUM";
14403 const gles2::cmds::PathCommandsCHROMIUM& c =
14404 *static_cast<const gles2::cmds::PathCommandsCHROMIUM*>(cmd_data);
14405 if (!features().chromium_path_rendering) {
14406 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14407 "function not available");
14408 return error::kNoError;
14411 GLuint service_id = 0;
14412 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14413 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14414 "invalid path name");
14415 return error::kNoError;
14418 GLsizei num_commands = static_cast<GLsizei>(c.numCommands);
14419 if (num_commands < 0) {
14420 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numCommands < 0");
14421 return error::kNoError;
14424 GLsizei num_coords = static_cast<uint32>(c.numCoords);
14425 if (num_coords < 0) {
14426 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numCoords < 0");
14427 return error::kNoError;
14430 GLenum coord_type = static_cast<uint32>(c.coordType);
14431 if (!validators_->path_coord_type.IsValid(static_cast<GLint>(coord_type))) {
14432 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName, "invalid coordType");
14433 return error::kNoError;
14436 const GLubyte* commands = NULL;
14437 base::CheckedNumeric<GLsizei> num_coords_expected = 0;
14439 if (num_commands > 0) {
14440 uint32 commands_shm_id = static_cast<uint32>(c.commands_shm_id);
14441 uint32 commands_shm_offset = static_cast<uint32>(c.commands_shm_offset);
14442 if (commands_shm_id != 0 || commands_shm_offset != 0)
14443 commands = GetSharedMemoryAs<const GLubyte*>(
14444 commands_shm_id, commands_shm_offset, num_commands);
14446 if (!commands)
14447 return error::kOutOfBounds;
14449 for (GLsizei i = 0; i < num_commands; ++i) {
14450 switch (commands[i]) {
14451 case GL_CLOSE_PATH_CHROMIUM:
14452 // Close has no coords.
14453 break;
14454 case GL_MOVE_TO_CHROMIUM:
14455 // Fallthrough.
14456 case GL_LINE_TO_CHROMIUM:
14457 num_coords_expected += 2;
14458 break;
14459 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
14460 num_coords_expected += 4;
14461 break;
14462 case GL_CUBIC_CURVE_TO_CHROMIUM:
14463 num_coords_expected += 6;
14464 break;
14465 case GL_CONIC_CURVE_TO_CHROMIUM:
14466 num_coords_expected += 5;
14467 break;
14468 default:
14469 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName, "invalid command");
14470 return error::kNoError;
14475 if (!num_coords_expected.IsValid() ||
14476 num_coords != num_coords_expected.ValueOrDie()) {
14477 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14478 "numCoords does not match commands");
14479 return error::kNoError;
14482 const void* coords = NULL;
14484 if (num_coords > 0) {
14485 uint32 coords_size = 0;
14486 uint32 coord_type_size =
14487 GLES2Util::GetGLTypeSizeForPathCoordType(coord_type);
14488 if (!SafeMultiplyUint32(num_coords, coord_type_size, &coords_size))
14489 return error::kOutOfBounds;
14491 uint32 coords_shm_id = static_cast<uint32>(c.coords_shm_id);
14492 uint32 coords_shm_offset = static_cast<uint32>(c.coords_shm_offset);
14493 if (coords_shm_id != 0 || coords_shm_offset != 0)
14494 coords = GetSharedMemoryAs<const void*>(coords_shm_id, coords_shm_offset,
14495 coords_size);
14497 if (!coords)
14498 return error::kOutOfBounds;
14501 glPathCommandsNV(service_id, num_commands, commands, num_coords, coord_type,
14502 coords);
14504 return error::kNoError;
14507 error::Error GLES2DecoderImpl::HandlePathParameterfCHROMIUM(
14508 uint32 immediate_data_size,
14509 const void* cmd_data) {
14510 static const char kFunctionName[] = "glPathParameterfCHROMIUM";
14511 const gles2::cmds::PathParameterfCHROMIUM& c =
14512 *static_cast<const gles2::cmds::PathParameterfCHROMIUM*>(cmd_data);
14513 if (!features().chromium_path_rendering) {
14514 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14515 "function not available");
14516 return error::kNoError;
14518 GLuint service_id = 0;
14519 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14520 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14521 "invalid path name");
14522 return error::kNoError;
14525 GLenum pname = static_cast<GLenum>(c.pname);
14526 GLfloat value = static_cast<GLfloat>(c.value);
14527 bool hasValueError = false;
14529 switch (pname) {
14530 case GL_PATH_STROKE_WIDTH_CHROMIUM:
14531 case GL_PATH_MITER_LIMIT_CHROMIUM:
14532 hasValueError = std::isnan(value) || !std::isfinite(value) || value < 0;
14533 break;
14534 case GL_PATH_STROKE_BOUND_CHROMIUM:
14535 value = std::max(std::min(1.0f, value), 0.0f);
14536 break;
14537 case GL_PATH_END_CAPS_CHROMIUM:
14538 hasValueError = !validators_->path_parameter_cap_values.IsValid(
14539 static_cast<GLint>(value));
14540 break;
14541 case GL_PATH_JOIN_STYLE_CHROMIUM:
14542 hasValueError = !validators_->path_parameter_join_values.IsValid(
14543 static_cast<GLint>(value));
14544 break;
14545 default:
14546 DCHECK(!validators_->path_parameter.IsValid(pname));
14547 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, pname, "pname");
14548 return error::kNoError;
14550 DCHECK(validators_->path_parameter.IsValid(pname));
14552 if (hasValueError) {
14553 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "value not correct");
14554 return error::kNoError;
14557 glPathParameterfNV(service_id, pname, value);
14558 return error::kNoError;
14561 error::Error GLES2DecoderImpl::HandlePathParameteriCHROMIUM(
14562 uint32 immediate_data_size,
14563 const void* cmd_data) {
14564 static const char kFunctionName[] = "glPathParameteriCHROMIUM";
14565 const gles2::cmds::PathParameteriCHROMIUM& c =
14566 *static_cast<const gles2::cmds::PathParameteriCHROMIUM*>(cmd_data);
14567 if (!features().chromium_path_rendering) {
14568 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14569 "function not available");
14570 return error::kNoError;
14572 GLuint service_id = 0;
14573 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14574 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14575 "invalid path name");
14576 return error::kNoError;
14579 GLenum pname = static_cast<GLenum>(c.pname);
14580 GLint value = static_cast<GLint>(c.value);
14581 bool hasValueError = false;
14583 switch (pname) {
14584 case GL_PATH_STROKE_WIDTH_CHROMIUM:
14585 case GL_PATH_MITER_LIMIT_CHROMIUM:
14586 hasValueError = value < 0;
14587 break;
14588 case GL_PATH_STROKE_BOUND_CHROMIUM:
14589 value = std::max(std::min(1, value), 0);
14590 break;
14591 case GL_PATH_END_CAPS_CHROMIUM:
14592 hasValueError = !validators_->path_parameter_cap_values.IsValid(value);
14593 break;
14594 case GL_PATH_JOIN_STYLE_CHROMIUM:
14595 hasValueError = !validators_->path_parameter_join_values.IsValid(value);
14596 break;
14597 default:
14598 DCHECK(!validators_->path_parameter.IsValid(pname));
14599 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, pname, "pname");
14600 return error::kNoError;
14602 DCHECK(validators_->path_parameter.IsValid(pname));
14604 if (hasValueError) {
14605 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "value not correct");
14606 return error::kNoError;
14609 glPathParameteriNV(service_id, pname, value);
14610 return error::kNoError;
14613 error::Error GLES2DecoderImpl::HandleStencilFillPathCHROMIUM(
14614 uint32 immediate_data_size,
14615 const void* cmd_data) {
14616 static const char kFunctionName[] = "glStencilFillPathCHROMIUM";
14617 const gles2::cmds::StencilFillPathCHROMIUM& c =
14618 *static_cast<const gles2::cmds::StencilFillPathCHROMIUM*>(cmd_data);
14619 if (!features().chromium_path_rendering) {
14620 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14621 "function not available");
14622 return error::kNoError;
14624 GLenum fill_mode = static_cast<GLenum>(c.fillMode);
14625 if (!validators_->path_fill_mode.IsValid(fill_mode)) {
14626 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, fill_mode, "fillMode");
14627 return error::kNoError;
14629 GLuint mask = static_cast<GLuint>(c.mask);
14630 if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
14631 fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
14632 GLES2Util::IsNPOT(mask + 1)) {
14633 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
14634 "mask + 1 is not power of two");
14635 return error::kNoError;
14637 GLuint service_id = 0;
14638 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14639 // "If /path/ does not name an existing path object, the command does
14640 // nothing (and no error is generated)."
14641 // This holds for other rendering functions, too.
14642 return error::kNoError;
14644 ApplyDirtyState();
14645 glStencilFillPathNV(service_id, fill_mode, mask);
14646 return error::kNoError;
14649 error::Error GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM(
14650 uint32 immediate_data_size,
14651 const void* cmd_data) {
14652 static const char kFunctionName[] = "glStencilStrokePathCHROMIUM";
14653 const gles2::cmds::StencilStrokePathCHROMIUM& c =
14654 *static_cast<const gles2::cmds::StencilStrokePathCHROMIUM*>(cmd_data);
14655 if (!features().chromium_path_rendering) {
14656 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14657 "function not available");
14658 return error::kNoError;
14660 GLuint service_id = 0;
14661 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14662 return error::kNoError;
14664 GLint reference = static_cast<GLint>(c.reference);
14665 GLuint mask = static_cast<GLuint>(c.mask);
14666 ApplyDirtyState();
14667 glStencilStrokePathNV(service_id, reference, mask);
14668 return error::kNoError;
14671 error::Error GLES2DecoderImpl::HandleCoverFillPathCHROMIUM(
14672 uint32 immediate_data_size,
14673 const void* cmd_data) {
14674 static const char kFunctionName[] = "glCoverFillPathCHROMIUM";
14675 const gles2::cmds::CoverFillPathCHROMIUM& c =
14676 *static_cast<const gles2::cmds::CoverFillPathCHROMIUM*>(cmd_data);
14677 if (!features().chromium_path_rendering) {
14678 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14679 "function not available");
14680 return error::kNoError;
14682 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14683 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14684 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14685 return error::kNoError;
14687 GLuint service_id = 0;
14688 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14689 return error::kNoError;
14691 ApplyDirtyState();
14692 glCoverFillPathNV(service_id, cover_mode);
14693 return error::kNoError;
14696 error::Error GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM(
14697 uint32 immediate_data_size,
14698 const void* cmd_data) {
14699 static const char kFunctionName[] = "glCoverStrokePathCHROMIUM";
14700 const gles2::cmds::CoverStrokePathCHROMIUM& c =
14701 *static_cast<const gles2::cmds::CoverStrokePathCHROMIUM*>(cmd_data);
14702 if (!features().chromium_path_rendering) {
14703 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14704 "function not available");
14705 return error::kNoError;
14707 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14708 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14709 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14710 return error::kNoError;
14712 GLuint service_id = 0;
14713 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14714 return error::kNoError;
14716 ApplyDirtyState();
14717 glCoverStrokePathNV(service_id, cover_mode);
14718 return error::kNoError;
14721 error::Error GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM(
14722 uint32 immediate_data_size,
14723 const void* cmd_data) {
14724 static const char kFunctionName[] = "glStencilThenCoverFillPathCHROMIUM";
14725 const gles2::cmds::StencilThenCoverFillPathCHROMIUM& c =
14726 *static_cast<const gles2::cmds::StencilThenCoverFillPathCHROMIUM*>(
14727 cmd_data);
14728 if (!features().chromium_path_rendering) {
14729 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14730 "function not available");
14731 return error::kNoError;
14733 GLenum fill_mode = static_cast<GLenum>(c.fillMode);
14734 if (!validators_->path_fill_mode.IsValid(fill_mode)) {
14735 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, fill_mode, "fillMode");
14736 return error::kNoError;
14738 GLuint mask = static_cast<GLuint>(c.mask);
14739 if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
14740 fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
14741 GLES2Util::IsNPOT(mask + 1)) {
14742 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
14743 "mask + 1 is not power of two");
14744 return error::kNoError;
14746 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14747 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14748 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14749 return error::kNoError;
14751 GLuint service_id = 0;
14752 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14753 return error::kNoError;
14755 ApplyDirtyState();
14756 glStencilThenCoverFillPathNV(service_id, fill_mode, mask, cover_mode);
14757 return error::kNoError;
14760 error::Error GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM(
14761 uint32 immediate_data_size,
14762 const void* cmd_data) {
14763 static const char kFunctionName[] = "glStencilThenCoverStrokePathCHROMIUM";
14764 const gles2::cmds::StencilThenCoverStrokePathCHROMIUM& c =
14765 *static_cast<const gles2::cmds::StencilThenCoverStrokePathCHROMIUM*>(
14766 cmd_data);
14767 if (!features().chromium_path_rendering) {
14768 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14769 "function not available");
14770 return error::kNoError;
14772 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14773 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14774 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14775 return error::kNoError;
14777 GLuint service_id = 0;
14778 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14779 return error::kNoError;
14781 GLint reference = static_cast<GLint>(c.reference);
14782 GLuint mask = static_cast<GLuint>(c.mask);
14783 ApplyDirtyState();
14784 glStencilThenCoverStrokePathNV(service_id, reference, mask, cover_mode);
14785 return error::kNoError;
14788 // Include the auto-generated part of this file. We split this because it means
14789 // we can easily edit the non-auto generated parts right here in this file
14790 // instead of having to edit some template or the code generator.
14791 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
14793 } // namespace gles2
14794 } // namespace gpu