Add CHROMIUM_ycbcr_422_image extension.
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_decoder.cc
blob74f3401b497a4995a3d0e38a40c4bc21374d0a47
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.image_ycbcr_422 =
3202 feature_info_->feature_flags().chromium_image_ycbcr_422;
3203 caps.max_copy_texture_chromium_size =
3204 feature_info_->workarounds().max_copy_texture_chromium_size;
3205 caps.render_buffer_format_bgra8888 =
3206 feature_info_->feature_flags().ext_render_buffer_format_bgra8888;
3207 caps.occlusion_query_boolean =
3208 feature_info_->feature_flags().occlusion_query_boolean;
3209 caps.timer_queries =
3210 query_manager_->GPUTimingAvailable();
3211 return caps;
3214 void GLES2DecoderImpl::UpdateCapabilities() {
3215 util_.set_num_compressed_texture_formats(
3216 validators_->compressed_texture_format.GetValues().size());
3217 util_.set_num_shader_binary_formats(
3218 validators_->shader_binary_format.GetValues().size());
3221 bool GLES2DecoderImpl::InitializeShaderTranslator() {
3222 TRACE_EVENT0("gpu", "GLES2DecoderImpl::InitializeShaderTranslator");
3224 if (!use_shader_translator_) {
3225 return true;
3227 ShBuiltInResources resources;
3228 ShInitBuiltInResources(&resources);
3229 resources.MaxVertexAttribs = group_->max_vertex_attribs();
3230 resources.MaxVertexUniformVectors =
3231 group_->max_vertex_uniform_vectors();
3232 resources.MaxVaryingVectors = group_->max_varying_vectors();
3233 resources.MaxVertexTextureImageUnits =
3234 group_->max_vertex_texture_image_units();
3235 resources.MaxCombinedTextureImageUnits = group_->max_texture_units();
3236 resources.MaxTextureImageUnits = group_->max_texture_image_units();
3237 resources.MaxFragmentUniformVectors =
3238 group_->max_fragment_uniform_vectors();
3239 resources.MaxDrawBuffers = group_->max_draw_buffers();
3240 resources.MaxExpressionComplexity = 256;
3241 resources.MaxCallStackDepth = 256;
3243 GLint range[2] = { 0, 0 };
3244 GLint precision = 0;
3245 GetShaderPrecisionFormatImpl(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
3246 range, &precision);
3247 resources.FragmentPrecisionHigh =
3248 PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
3250 if (IsWebGLContext()) {
3251 resources.OES_standard_derivatives = derivatives_explicitly_enabled_;
3252 resources.EXT_frag_depth = frag_depth_explicitly_enabled_;
3253 resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
3254 if (!draw_buffers_explicitly_enabled_)
3255 resources.MaxDrawBuffers = 1;
3256 resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
3257 resources.NV_draw_buffers =
3258 draw_buffers_explicitly_enabled_ && features().nv_draw_buffers;
3259 } else {
3260 resources.OES_standard_derivatives =
3261 features().oes_standard_derivatives ? 1 : 0;
3262 resources.ARB_texture_rectangle =
3263 features().arb_texture_rectangle ? 1 : 0;
3264 resources.OES_EGL_image_external =
3265 features().oes_egl_image_external ? 1 : 0;
3266 resources.EXT_draw_buffers =
3267 features().ext_draw_buffers ? 1 : 0;
3268 resources.EXT_frag_depth =
3269 features().ext_frag_depth ? 1 : 0;
3270 resources.EXT_shader_texture_lod =
3271 features().ext_shader_texture_lod ? 1 : 0;
3272 resources.NV_draw_buffers =
3273 features().nv_draw_buffers ? 1 : 0;
3276 ShShaderSpec shader_spec;
3277 if (IsWebGLContext()) {
3278 shader_spec = webgl_version_ == 2 ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC;
3279 } else {
3280 shader_spec = unsafe_es3_apis_enabled() ? SH_GLES3_SPEC : SH_GLES2_SPEC;
3283 if ((shader_spec == SH_WEBGL_SPEC || shader_spec == SH_WEBGL2_SPEC) &&
3284 features().enable_shader_name_hashing)
3285 resources.HashFunction = &CityHash64;
3286 else
3287 resources.HashFunction = NULL;
3289 int driver_bug_workarounds = 0;
3290 if (workarounds().needs_glsl_built_in_function_emulation)
3291 driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
3292 if (workarounds().init_gl_position_in_vertex_shader)
3293 driver_bug_workarounds |= SH_INIT_GL_POSITION;
3294 if (workarounds().unfold_short_circuit_as_ternary_operation)
3295 driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
3296 if (workarounds().init_varyings_without_static_use)
3297 driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
3298 if (workarounds().unroll_for_loop_with_sampler_array_index)
3299 driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
3300 if (workarounds().scalarize_vec_and_mat_constructor_args)
3301 driver_bug_workarounds |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
3302 if (workarounds().regenerate_struct_names)
3303 driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES;
3304 if (workarounds().remove_pow_with_constant_exponent)
3305 driver_bug_workarounds |= SH_REMOVE_POW_WITH_CONSTANT_EXPONENT;
3307 if (base::CommandLine::InitializedForCurrentProcess() &&
3308 base::CommandLine::ForCurrentProcess()->HasSwitch(
3309 switches::kEmulateShaderPrecision))
3310 resources.WEBGL_debug_shader_precision = true;
3312 ShShaderOutput shader_output_language =
3313 ShaderTranslator::GetShaderOutputLanguageForContext(
3314 feature_info_->gl_version_info());
3316 vertex_translator_ = shader_translator_cache()->GetTranslator(
3317 GL_VERTEX_SHADER, shader_spec, &resources, shader_output_language,
3318 static_cast<ShCompileOptions>(driver_bug_workarounds));
3319 if (!vertex_translator_.get()) {
3320 LOG(ERROR) << "Could not initialize vertex shader translator.";
3321 Destroy(true);
3322 return false;
3325 fragment_translator_ = shader_translator_cache()->GetTranslator(
3326 GL_FRAGMENT_SHADER, shader_spec, &resources, shader_output_language,
3327 static_cast<ShCompileOptions>(driver_bug_workarounds));
3328 if (!fragment_translator_.get()) {
3329 LOG(ERROR) << "Could not initialize fragment shader translator.";
3330 Destroy(true);
3331 return false;
3333 return true;
3336 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
3337 for (GLsizei ii = 0; ii < n; ++ii) {
3338 if (GetBuffer(client_ids[ii])) {
3339 return false;
3342 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3343 glGenBuffersARB(n, service_ids.get());
3344 for (GLsizei ii = 0; ii < n; ++ii) {
3345 CreateBuffer(client_ids[ii], service_ids[ii]);
3347 return true;
3350 bool GLES2DecoderImpl::GenFramebuffersHelper(
3351 GLsizei n, const GLuint* client_ids) {
3352 for (GLsizei ii = 0; ii < n; ++ii) {
3353 if (GetFramebuffer(client_ids[ii])) {
3354 return false;
3357 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3358 glGenFramebuffersEXT(n, service_ids.get());
3359 for (GLsizei ii = 0; ii < n; ++ii) {
3360 CreateFramebuffer(client_ids[ii], service_ids[ii]);
3362 return true;
3365 bool GLES2DecoderImpl::GenRenderbuffersHelper(
3366 GLsizei n, const GLuint* client_ids) {
3367 for (GLsizei ii = 0; ii < n; ++ii) {
3368 if (GetRenderbuffer(client_ids[ii])) {
3369 return false;
3372 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3373 glGenRenderbuffersEXT(n, service_ids.get());
3374 for (GLsizei ii = 0; ii < n; ++ii) {
3375 CreateRenderbuffer(client_ids[ii], service_ids[ii]);
3377 return true;
3380 bool GLES2DecoderImpl::GenValuebuffersCHROMIUMHelper(GLsizei n,
3381 const GLuint* client_ids) {
3382 for (GLsizei ii = 0; ii < n; ++ii) {
3383 if (GetValuebuffer(client_ids[ii])) {
3384 return false;
3387 for (GLsizei ii = 0; ii < n; ++ii) {
3388 CreateValuebuffer(client_ids[ii]);
3390 return true;
3393 bool GLES2DecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) {
3394 for (GLsizei ii = 0; ii < n; ++ii) {
3395 if (GetTexture(client_ids[ii])) {
3396 return false;
3399 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
3400 glGenTextures(n, service_ids.get());
3401 for (GLsizei ii = 0; ii < n; ++ii) {
3402 CreateTexture(client_ids[ii], service_ids[ii]);
3404 return true;
3407 bool GLES2DecoderImpl::GenPathsCHROMIUMHelper(GLuint first_client_id,
3408 GLsizei range) {
3409 GLuint last_client_id;
3410 if (!SafeAddUint32(first_client_id, range - 1, &last_client_id))
3411 return false;
3413 if (path_manager()->HasPathsInRange(first_client_id, last_client_id))
3414 return false;
3416 GLuint first_service_id = glGenPathsNV(range);
3417 if (first_service_id == 0) {
3418 // We have to fail the connection here, because client has already
3419 // succeeded in allocating the ids. This happens if we allocate
3420 // the whole path id space (two allocations of 0x7FFFFFFF paths, for
3421 // example).
3422 return false;
3424 // GenPathsNV does not wrap.
3425 DCHECK(first_service_id + range - 1 >= first_service_id);
3427 path_manager()->CreatePathRange(first_client_id, last_client_id,
3428 first_service_id);
3430 return true;
3433 bool GLES2DecoderImpl::DeletePathsCHROMIUMHelper(GLuint first_client_id,
3434 GLsizei range) {
3435 GLuint last_client_id;
3436 if (!SafeAddUint32(first_client_id, range - 1, &last_client_id))
3437 return false;
3439 path_manager()->RemovePaths(first_client_id, last_client_id);
3440 return true;
3443 void GLES2DecoderImpl::DeleteBuffersHelper(
3444 GLsizei n, const GLuint* client_ids) {
3445 for (GLsizei ii = 0; ii < n; ++ii) {
3446 Buffer* buffer = GetBuffer(client_ids[ii]);
3447 if (buffer && !buffer->IsDeleted()) {
3448 buffer->RemoveMappedRange();
3449 state_.RemoveBoundBuffer(buffer);
3450 RemoveBuffer(client_ids[ii]);
3455 void GLES2DecoderImpl::DeleteFramebuffersHelper(
3456 GLsizei n, const GLuint* client_ids) {
3457 bool supports_separate_framebuffer_binds =
3458 features().chromium_framebuffer_multisample;
3460 for (GLsizei ii = 0; ii < n; ++ii) {
3461 Framebuffer* framebuffer =
3462 GetFramebuffer(client_ids[ii]);
3463 if (framebuffer && !framebuffer->IsDeleted()) {
3464 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
3465 GLenum target = supports_separate_framebuffer_binds ?
3466 GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3468 // Unbind attachments on FBO before deletion.
3469 if (workarounds().unbind_attachments_on_bound_render_fbo_delete)
3470 framebuffer->DoUnbindGLAttachmentsForWorkaround(target);
3472 glBindFramebufferEXT(target, GetBackbufferServiceId());
3473 framebuffer_state_.bound_draw_framebuffer = NULL;
3474 framebuffer_state_.clear_state_dirty = true;
3476 if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
3477 framebuffer_state_.bound_read_framebuffer = NULL;
3478 GLenum target = supports_separate_framebuffer_binds ?
3479 GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
3480 glBindFramebufferEXT(target, GetBackbufferServiceId());
3482 OnFboChanged();
3483 RemoveFramebuffer(client_ids[ii]);
3488 void GLES2DecoderImpl::DeleteRenderbuffersHelper(
3489 GLsizei n, const GLuint* client_ids) {
3490 bool supports_separate_framebuffer_binds =
3491 features().chromium_framebuffer_multisample;
3492 for (GLsizei ii = 0; ii < n; ++ii) {
3493 Renderbuffer* renderbuffer =
3494 GetRenderbuffer(client_ids[ii]);
3495 if (renderbuffer && !renderbuffer->IsDeleted()) {
3496 if (state_.bound_renderbuffer.get() == renderbuffer) {
3497 state_.bound_renderbuffer = NULL;
3499 // Unbind from current framebuffers.
3500 if (supports_separate_framebuffer_binds) {
3501 if (framebuffer_state_.bound_read_framebuffer.get()) {
3502 framebuffer_state_.bound_read_framebuffer
3503 ->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
3505 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3506 framebuffer_state_.bound_draw_framebuffer
3507 ->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
3509 } else {
3510 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3511 framebuffer_state_.bound_draw_framebuffer
3512 ->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
3515 framebuffer_state_.clear_state_dirty = true;
3516 RemoveRenderbuffer(client_ids[ii]);
3521 void GLES2DecoderImpl::DeleteValuebuffersCHROMIUMHelper(
3522 GLsizei n,
3523 const GLuint* client_ids) {
3524 for (GLsizei ii = 0; ii < n; ++ii) {
3525 Valuebuffer* valuebuffer = GetValuebuffer(client_ids[ii]);
3526 if (valuebuffer) {
3527 if (state_.bound_valuebuffer.get() == valuebuffer) {
3528 state_.bound_valuebuffer = NULL;
3530 RemoveValuebuffer(client_ids[ii]);
3535 void GLES2DecoderImpl::DeleteTexturesHelper(
3536 GLsizei n, const GLuint* client_ids) {
3537 bool supports_separate_framebuffer_binds =
3538 features().chromium_framebuffer_multisample;
3539 for (GLsizei ii = 0; ii < n; ++ii) {
3540 TextureRef* texture_ref = GetTexture(client_ids[ii]);
3541 if (texture_ref) {
3542 Texture* texture = texture_ref->texture();
3543 if (texture->IsAttachedToFramebuffer()) {
3544 framebuffer_state_.clear_state_dirty = true;
3546 // Unbind texture_ref from texture_ref units.
3547 for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
3548 state_.texture_units[jj].Unbind(texture_ref);
3550 // Unbind from current framebuffers.
3551 if (supports_separate_framebuffer_binds) {
3552 if (framebuffer_state_.bound_read_framebuffer.get()) {
3553 framebuffer_state_.bound_read_framebuffer
3554 ->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
3556 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3557 framebuffer_state_.bound_draw_framebuffer
3558 ->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
3560 } else {
3561 if (framebuffer_state_.bound_draw_framebuffer.get()) {
3562 framebuffer_state_.bound_draw_framebuffer
3563 ->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
3566 #if defined(OS_MACOSX)
3567 GLuint service_id = texture->service_id();
3568 if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) {
3569 ReleaseIOSurfaceForTexture(service_id);
3571 #endif
3572 RemoveTexture(client_ids[ii]);
3577 // } // anonymous namespace
3579 bool GLES2DecoderImpl::MakeCurrent() {
3580 if (!context_.get())
3581 return false;
3583 if (WasContextLost()) {
3584 LOG(ERROR) << " GLES2DecoderImpl: Trying to make lost context current.";
3585 return false;
3588 if (!context_->MakeCurrent(surface_.get())) {
3589 LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
3590 MarkContextLost(error::kMakeCurrentFailed);
3591 group_->LoseContexts(error::kUnknown);
3592 return false;
3595 if (CheckResetStatus()) {
3596 LOG(ERROR)
3597 << " GLES2DecoderImpl: Context reset detected after MakeCurrent.";
3598 group_->LoseContexts(error::kUnknown);
3599 return false;
3602 ProcessFinishedAsyncTransfers();
3604 // Rebind the FBO if it was unbound by the context.
3605 if (workarounds().unbind_fbo_on_context_switch)
3606 RestoreFramebufferBindings();
3608 framebuffer_state_.clear_state_dirty = true;
3610 return true;
3613 void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
3614 ProcessPendingReadPixels(false);
3615 if (engine() && query_manager_.get())
3616 query_manager_->ProcessPendingTransferQueries();
3618 // TODO(epenner): Is there a better place to do this?
3619 // This needs to occur before we execute any batch of commands
3620 // from the client, as the client may have recieved an async
3621 // completion while issuing those commands.
3622 // "DidFlushStart" would be ideal if we had such a callback.
3623 async_pixel_transfer_manager_->BindCompletedAsyncTransfers();
3626 static void RebindCurrentFramebuffer(
3627 GLenum target,
3628 Framebuffer* framebuffer,
3629 GLuint back_buffer_service_id) {
3630 GLuint framebuffer_id = framebuffer ? framebuffer->service_id() : 0;
3632 if (framebuffer_id == 0) {
3633 framebuffer_id = back_buffer_service_id;
3636 glBindFramebufferEXT(target, framebuffer_id);
3639 void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
3640 framebuffer_state_.clear_state_dirty = true;
3642 if (!features().chromium_framebuffer_multisample) {
3643 RebindCurrentFramebuffer(
3644 GL_FRAMEBUFFER,
3645 framebuffer_state_.bound_draw_framebuffer.get(),
3646 GetBackbufferServiceId());
3647 } else {
3648 RebindCurrentFramebuffer(
3649 GL_READ_FRAMEBUFFER_EXT,
3650 framebuffer_state_.bound_read_framebuffer.get(),
3651 GetBackbufferServiceId());
3652 RebindCurrentFramebuffer(
3653 GL_DRAW_FRAMEBUFFER_EXT,
3654 framebuffer_state_.bound_draw_framebuffer.get(),
3655 GetBackbufferServiceId());
3657 OnFboChanged();
3660 bool GLES2DecoderImpl::CheckFramebufferValid(
3661 Framebuffer* framebuffer,
3662 GLenum target, const char* func_name) {
3663 if (!framebuffer) {
3664 if (surfaceless_)
3665 return false;
3666 if (backbuffer_needs_clear_bits_) {
3667 glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
3668 offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f);
3669 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3670 glClearStencil(0);
3671 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
3672 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
3673 glClearDepth(1.0f);
3674 state_.SetDeviceDepthMask(GL_TRUE);
3675 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
3676 bool reset_draw_buffer = false;
3677 if ((backbuffer_needs_clear_bits_ & GL_COLOR_BUFFER_BIT) != 0 &&
3678 back_buffer_draw_buffer_ == GL_NONE) {
3679 reset_draw_buffer = true;
3680 GLenum buf = GL_BACK;
3681 if (GetBackbufferServiceId() != 0) // emulated backbuffer
3682 buf = GL_COLOR_ATTACHMENT0;
3683 glDrawBuffersARB(1, &buf);
3685 glClear(backbuffer_needs_clear_bits_);
3686 if (reset_draw_buffer) {
3687 GLenum buf = GL_NONE;
3688 glDrawBuffersARB(1, &buf);
3690 backbuffer_needs_clear_bits_ = 0;
3691 RestoreClearState();
3693 return true;
3696 if (framebuffer_manager()->IsComplete(framebuffer)) {
3697 return true;
3700 GLenum completeness = framebuffer->IsPossiblyComplete();
3701 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
3702 LOCAL_SET_GL_ERROR(
3703 GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
3704 return false;
3707 // Are all the attachments cleared?
3708 if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
3709 texture_manager()->HaveUnclearedMips()) {
3710 if (!framebuffer->IsCleared()) {
3711 // Can we clear them?
3712 if (framebuffer->GetStatus(texture_manager(), target) !=
3713 GL_FRAMEBUFFER_COMPLETE) {
3714 LOCAL_SET_GL_ERROR(
3715 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3716 "framebuffer incomplete (clear)");
3717 return false;
3719 ClearUnclearedAttachments(target, framebuffer);
3723 if (!framebuffer_manager()->IsComplete(framebuffer)) {
3724 if (framebuffer->GetStatus(texture_manager(), target) !=
3725 GL_FRAMEBUFFER_COMPLETE) {
3726 LOCAL_SET_GL_ERROR(
3727 GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
3728 "framebuffer incomplete (check)");
3729 return false;
3731 framebuffer_manager()->MarkAsComplete(framebuffer);
3734 // NOTE: At this point we don't know if the framebuffer is complete but
3735 // we DO know that everything that needs to be cleared has been cleared.
3736 return true;
3739 bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
3740 if (!features().chromium_framebuffer_multisample) {
3741 bool valid = CheckFramebufferValid(
3742 framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
3743 func_name);
3745 if (valid)
3746 OnUseFramebuffer();
3748 return valid;
3750 return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
3751 GL_DRAW_FRAMEBUFFER_EXT,
3752 func_name) &&
3753 CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
3754 GL_READ_FRAMEBUFFER_EXT,
3755 func_name);
3758 bool GLES2DecoderImpl::CheckBoundReadFramebufferColorAttachment(
3759 const char* func_name) {
3760 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3761 framebuffer_state_.bound_read_framebuffer.get() :
3762 framebuffer_state_.bound_draw_framebuffer.get();
3763 if (!framebuffer)
3764 return true;
3765 if (framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL) {
3766 LOCAL_SET_GL_ERROR(
3767 GL_INVALID_OPERATION, func_name, "no color image attached");
3768 return false;
3770 return true;
3773 bool GLES2DecoderImpl::FormsTextureCopyingFeedbackLoop(
3774 TextureRef* texture, GLint level) {
3775 Framebuffer* framebuffer = features().chromium_framebuffer_multisample ?
3776 framebuffer_state_.bound_read_framebuffer.get() :
3777 framebuffer_state_.bound_draw_framebuffer.get();
3778 if (!framebuffer)
3779 return false;
3780 const Framebuffer::Attachment* attachment = framebuffer->GetAttachment(
3781 GL_COLOR_ATTACHMENT0);
3782 if (!attachment)
3783 return false;
3784 return attachment->FormsFeedbackLoop(texture, level);
3787 gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
3788 Framebuffer* framebuffer =
3789 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3790 if (framebuffer != NULL) {
3791 const Framebuffer::Attachment* attachment =
3792 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
3793 if (attachment) {
3794 return gfx::Size(attachment->width(), attachment->height());
3796 return gfx::Size(0, 0);
3797 } else if (offscreen_target_frame_buffer_.get()) {
3798 return offscreen_size_;
3799 } else {
3800 return surface_->GetSize();
3804 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
3805 Framebuffer* framebuffer =
3806 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3807 if (framebuffer) {
3808 return framebuffer->GetReadBufferTextureType();
3809 } else { // Back buffer.
3810 if (back_buffer_read_buffer_ == GL_NONE)
3811 return 0;
3812 return GL_UNSIGNED_BYTE;
3816 GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
3817 Framebuffer* framebuffer =
3818 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
3819 if (framebuffer) {
3820 return framebuffer->GetReadBufferInternalFormat();
3821 } else { // Back buffer.
3822 if (back_buffer_read_buffer_ == GL_NONE)
3823 return 0;
3824 if (offscreen_target_frame_buffer_.get()) {
3825 return offscreen_target_color_format_;
3827 return back_buffer_color_format_;
3831 void GLES2DecoderImpl::UpdateParentTextureInfo() {
3832 if (!offscreen_saved_color_texture_info_.get())
3833 return;
3834 GLenum target = offscreen_saved_color_texture_info_->texture()->target();
3835 glBindTexture(target, offscreen_saved_color_texture_info_->service_id());
3836 texture_manager()->SetLevelInfo(
3837 offscreen_saved_color_texture_info_.get(), GL_TEXTURE_2D,
3838 0, // level
3839 GL_RGBA, offscreen_size_.width(), offscreen_size_.height(),
3840 1, // depth
3841 0, // border
3842 GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(offscreen_size_));
3843 texture_manager()->SetParameteri(
3844 "UpdateParentTextureInfo",
3845 GetErrorState(),
3846 offscreen_saved_color_texture_info_.get(),
3847 GL_TEXTURE_MAG_FILTER,
3848 GL_LINEAR);
3849 texture_manager()->SetParameteri(
3850 "UpdateParentTextureInfo",
3851 GetErrorState(),
3852 offscreen_saved_color_texture_info_.get(),
3853 GL_TEXTURE_MIN_FILTER,
3854 GL_LINEAR);
3855 texture_manager()->SetParameteri(
3856 "UpdateParentTextureInfo",
3857 GetErrorState(),
3858 offscreen_saved_color_texture_info_.get(),
3859 GL_TEXTURE_WRAP_S,
3860 GL_CLAMP_TO_EDGE);
3861 texture_manager()->SetParameteri(
3862 "UpdateParentTextureInfo",
3863 GetErrorState(),
3864 offscreen_saved_color_texture_info_.get(),
3865 GL_TEXTURE_WRAP_T,
3866 GL_CLAMP_TO_EDGE);
3867 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
3868 &state_, target);
3869 glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
3872 void GLES2DecoderImpl::SetResizeCallback(
3873 const base::Callback<void(gfx::Size, float)>& callback) {
3874 resize_callback_ = callback;
3877 Logger* GLES2DecoderImpl::GetLogger() {
3878 return &logger_;
3881 void GLES2DecoderImpl::BeginDecoding() {
3882 gpu_tracer_->BeginDecoding();
3883 gpu_trace_commands_ = gpu_tracer_->IsTracing() && *gpu_decoder_category_;
3884 gpu_debug_commands_ = log_commands() || debug() || gpu_trace_commands_ ||
3885 (*cb_command_trace_category_ != 0);
3886 query_manager_->ProcessFrameBeginUpdates();
3889 void GLES2DecoderImpl::EndDecoding() {
3890 gpu_tracer_->EndDecoding();
3893 ErrorState* GLES2DecoderImpl::GetErrorState() {
3894 return state_.GetErrorState();
3897 void GLES2DecoderImpl::SetShaderCacheCallback(
3898 const ShaderCacheCallback& callback) {
3899 shader_cache_callback_ = callback;
3902 void GLES2DecoderImpl::SetWaitSyncPointCallback(
3903 const WaitSyncPointCallback& callback) {
3904 wait_sync_point_callback_ = callback;
3907 AsyncPixelTransferManager*
3908 GLES2DecoderImpl::GetAsyncPixelTransferManager() {
3909 return async_pixel_transfer_manager_.get();
3912 void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
3913 async_pixel_transfer_manager_.reset();
3916 void GLES2DecoderImpl::SetAsyncPixelTransferManagerForTest(
3917 AsyncPixelTransferManager* manager) {
3918 async_pixel_transfer_manager_ = make_scoped_ptr(manager);
3921 bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
3922 uint32* service_texture_id) {
3923 TextureRef* texture_ref = texture_manager()->GetTexture(client_texture_id);
3924 if (texture_ref) {
3925 *service_texture_id = texture_ref->service_id();
3926 return true;
3928 return false;
3931 uint32 GLES2DecoderImpl::GetTextureUploadCount() {
3932 return texture_state_.texture_upload_count +
3933 async_pixel_transfer_manager_->GetTextureUploadCount();
3936 base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
3937 return texture_state_.total_texture_upload_time +
3938 async_pixel_transfer_manager_->GetTotalTextureUploadTime();
3941 base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
3942 return total_processing_commands_time_;
3945 void GLES2DecoderImpl::AddProcessingCommandsTime(base::TimeDelta time) {
3946 total_processing_commands_time_ += time;
3949 void GLES2DecoderImpl::Destroy(bool have_context) {
3950 if (!initialized())
3951 return;
3953 DCHECK(!have_context || context_->IsCurrent(NULL));
3955 // Unbind everything.
3956 state_.vertex_attrib_manager = NULL;
3957 state_.default_vertex_attrib_manager = NULL;
3958 state_.texture_units.clear();
3959 state_.bound_array_buffer = NULL;
3960 state_.bound_copy_read_buffer = NULL;
3961 state_.bound_copy_write_buffer = NULL;
3962 state_.bound_pixel_pack_buffer = NULL;
3963 state_.bound_pixel_unpack_buffer = NULL;
3964 state_.bound_transform_feedback_buffer = NULL;
3965 state_.bound_uniform_buffer = NULL;
3966 framebuffer_state_.bound_read_framebuffer = NULL;
3967 framebuffer_state_.bound_draw_framebuffer = NULL;
3968 state_.bound_renderbuffer = NULL;
3969 state_.bound_valuebuffer = NULL;
3971 if (offscreen_saved_color_texture_info_.get()) {
3972 DCHECK(offscreen_target_color_texture_);
3973 DCHECK_EQ(offscreen_saved_color_texture_info_->service_id(),
3974 offscreen_saved_color_texture_->id());
3975 offscreen_saved_color_texture_->Invalidate();
3976 offscreen_saved_color_texture_info_ = NULL;
3978 if (have_context) {
3979 if (copy_texture_CHROMIUM_.get()) {
3980 copy_texture_CHROMIUM_->Destroy();
3981 copy_texture_CHROMIUM_.reset();
3984 clear_framebuffer_blit_.reset();
3986 if (state_.current_program.get()) {
3987 program_manager()->UnuseProgram(shader_manager(),
3988 state_.current_program.get());
3991 if (attrib_0_buffer_id_) {
3992 glDeleteBuffersARB(1, &attrib_0_buffer_id_);
3994 if (fixed_attrib_buffer_id_) {
3995 glDeleteBuffersARB(1, &fixed_attrib_buffer_id_);
3998 if (validation_texture_) {
3999 glDeleteTextures(1, &validation_texture_);
4000 glDeleteFramebuffersEXT(1, &validation_fbo_multisample_);
4001 glDeleteFramebuffersEXT(1, &validation_fbo_);
4004 if (offscreen_target_frame_buffer_.get())
4005 offscreen_target_frame_buffer_->Destroy();
4006 if (offscreen_target_color_texture_.get())
4007 offscreen_target_color_texture_->Destroy();
4008 if (offscreen_target_color_render_buffer_.get())
4009 offscreen_target_color_render_buffer_->Destroy();
4010 if (offscreen_target_depth_render_buffer_.get())
4011 offscreen_target_depth_render_buffer_->Destroy();
4012 if (offscreen_target_stencil_render_buffer_.get())
4013 offscreen_target_stencil_render_buffer_->Destroy();
4014 if (offscreen_saved_frame_buffer_.get())
4015 offscreen_saved_frame_buffer_->Destroy();
4016 if (offscreen_saved_color_texture_.get())
4017 offscreen_saved_color_texture_->Destroy();
4018 if (offscreen_resolved_frame_buffer_.get())
4019 offscreen_resolved_frame_buffer_->Destroy();
4020 if (offscreen_resolved_color_texture_.get())
4021 offscreen_resolved_color_texture_->Destroy();
4022 } else {
4023 if (offscreen_target_frame_buffer_.get())
4024 offscreen_target_frame_buffer_->Invalidate();
4025 if (offscreen_target_color_texture_.get())
4026 offscreen_target_color_texture_->Invalidate();
4027 if (offscreen_target_color_render_buffer_.get())
4028 offscreen_target_color_render_buffer_->Invalidate();
4029 if (offscreen_target_depth_render_buffer_.get())
4030 offscreen_target_depth_render_buffer_->Invalidate();
4031 if (offscreen_target_stencil_render_buffer_.get())
4032 offscreen_target_stencil_render_buffer_->Invalidate();
4033 if (offscreen_saved_frame_buffer_.get())
4034 offscreen_saved_frame_buffer_->Invalidate();
4035 if (offscreen_saved_color_texture_.get())
4036 offscreen_saved_color_texture_->Invalidate();
4037 if (offscreen_resolved_frame_buffer_.get())
4038 offscreen_resolved_frame_buffer_->Invalidate();
4039 if (offscreen_resolved_color_texture_.get())
4040 offscreen_resolved_color_texture_->Invalidate();
4043 // Current program must be cleared after calling ProgramManager::UnuseProgram.
4044 // Otherwise, we can leak objects. http://crbug.com/258772.
4045 // state_.current_program must be reset before group_ is reset because
4046 // the later deletes the ProgramManager object that referred by
4047 // state_.current_program object.
4048 state_.current_program = NULL;
4050 copy_texture_CHROMIUM_.reset();
4051 clear_framebuffer_blit_.reset();
4053 if (query_manager_.get()) {
4054 query_manager_->Destroy(have_context);
4055 query_manager_.reset();
4058 if (vertex_array_manager_ .get()) {
4059 vertex_array_manager_->Destroy(have_context);
4060 vertex_array_manager_.reset();
4063 if (image_manager_.get()) {
4064 image_manager_->Destroy(have_context);
4065 image_manager_.reset();
4068 offscreen_target_frame_buffer_.reset();
4069 offscreen_target_color_texture_.reset();
4070 offscreen_target_color_render_buffer_.reset();
4071 offscreen_target_depth_render_buffer_.reset();
4072 offscreen_target_stencil_render_buffer_.reset();
4073 offscreen_saved_frame_buffer_.reset();
4074 offscreen_saved_color_texture_.reset();
4075 offscreen_resolved_frame_buffer_.reset();
4076 offscreen_resolved_color_texture_.reset();
4078 // Need to release these before releasing |group_| which may own the
4079 // ShaderTranslatorCache.
4080 fragment_translator_ = NULL;
4081 vertex_translator_ = NULL;
4083 // Should destroy the transfer manager before the texture manager held
4084 // by the context group.
4085 async_pixel_transfer_manager_.reset();
4087 // Destroy the GPU Tracer which may own some in process GPU Timings.
4088 if (gpu_tracer_) {
4089 gpu_tracer_->Destroy(have_context);
4090 gpu_tracer_.reset();
4093 if (group_.get()) {
4094 framebuffer_manager()->RemoveObserver(this);
4095 group_->Destroy(this, have_context);
4096 group_ = NULL;
4099 if (context_.get()) {
4100 context_->ReleaseCurrent(NULL);
4101 context_ = NULL;
4104 #if defined(OS_MACOSX)
4105 for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin();
4106 it != texture_to_io_surface_map_.end(); ++it) {
4107 CFRelease(it->second);
4109 texture_to_io_surface_map_.clear();
4110 #endif
4113 void GLES2DecoderImpl::SetSurface(
4114 const scoped_refptr<gfx::GLSurface>& surface) {
4115 DCHECK(context_->IsCurrent(NULL));
4116 DCHECK(surface_.get());
4117 surface_ = surface;
4118 RestoreCurrentFramebufferBindings();
4121 void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
4122 if (!offscreen_saved_color_texture_.get()) {
4123 LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
4124 return;
4126 if (!offscreen_saved_color_texture_info_.get()) {
4127 GLuint service_id = offscreen_saved_color_texture_->id();
4128 offscreen_saved_color_texture_info_ = TextureRef::Create(
4129 texture_manager(), 0, service_id);
4130 texture_manager()->SetTarget(offscreen_saved_color_texture_info_.get(),
4131 GL_TEXTURE_2D);
4132 UpdateParentTextureInfo();
4134 mailbox_manager()->ProduceTexture(
4135 mailbox, offscreen_saved_color_texture_info_->texture());
4138 bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
4139 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4140 if (!is_offscreen) {
4141 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer called "
4142 << " with an onscreen framebuffer.";
4143 return false;
4146 if (offscreen_size_ == size)
4147 return true;
4149 offscreen_size_ = size;
4150 int w = offscreen_size_.width();
4151 int h = offscreen_size_.height();
4152 if (w < 0 || h < 0 || h >= (INT_MAX / 4) / (w ? w : 1)) {
4153 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4154 << "to allocate storage due to excessive dimensions.";
4155 return false;
4158 // Reallocate the offscreen target buffers.
4159 DCHECK(offscreen_target_color_format_);
4160 if (IsOffscreenBufferMultisampled()) {
4161 if (!offscreen_target_color_render_buffer_->AllocateStorage(
4162 feature_info_.get(),
4163 offscreen_size_,
4164 offscreen_target_color_format_,
4165 offscreen_target_samples_)) {
4166 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4167 << "to allocate storage for offscreen target color buffer.";
4168 return false;
4170 } else {
4171 if (!offscreen_target_color_texture_->AllocateStorage(
4172 offscreen_size_, offscreen_target_color_format_, false)) {
4173 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4174 << "to allocate storage for offscreen target color texture.";
4175 return false;
4178 if (offscreen_target_depth_format_ &&
4179 !offscreen_target_depth_render_buffer_->AllocateStorage(
4180 feature_info_.get(),
4181 offscreen_size_,
4182 offscreen_target_depth_format_,
4183 offscreen_target_samples_)) {
4184 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4185 << "to allocate storage for offscreen target depth buffer.";
4186 return false;
4188 if (offscreen_target_stencil_format_ &&
4189 !offscreen_target_stencil_render_buffer_->AllocateStorage(
4190 feature_info_.get(),
4191 offscreen_size_,
4192 offscreen_target_stencil_format_,
4193 offscreen_target_samples_)) {
4194 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4195 << "to allocate storage for offscreen target stencil buffer.";
4196 return false;
4199 // Attach the offscreen target buffers to the target frame buffer.
4200 if (IsOffscreenBufferMultisampled()) {
4201 offscreen_target_frame_buffer_->AttachRenderBuffer(
4202 GL_COLOR_ATTACHMENT0,
4203 offscreen_target_color_render_buffer_.get());
4204 } else {
4205 offscreen_target_frame_buffer_->AttachRenderTexture(
4206 offscreen_target_color_texture_.get());
4208 if (offscreen_target_depth_format_) {
4209 offscreen_target_frame_buffer_->AttachRenderBuffer(
4210 GL_DEPTH_ATTACHMENT,
4211 offscreen_target_depth_render_buffer_.get());
4213 const bool packed_depth_stencil =
4214 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4215 if (packed_depth_stencil) {
4216 offscreen_target_frame_buffer_->AttachRenderBuffer(
4217 GL_STENCIL_ATTACHMENT,
4218 offscreen_target_depth_render_buffer_.get());
4219 } else if (offscreen_target_stencil_format_) {
4220 offscreen_target_frame_buffer_->AttachRenderBuffer(
4221 GL_STENCIL_ATTACHMENT,
4222 offscreen_target_stencil_render_buffer_.get());
4225 if (offscreen_target_frame_buffer_->CheckStatus() !=
4226 GL_FRAMEBUFFER_COMPLETE) {
4227 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
4228 << "because offscreen FBO was incomplete.";
4229 return false;
4232 // Clear the target frame buffer.
4234 ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
4235 glClearColor(0, 0, 0, BackBufferHasAlpha() ? 0 : 1.f);
4236 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4237 glClearStencil(0);
4238 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
4239 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
4240 glClearDepth(0);
4241 state_.SetDeviceDepthMask(GL_TRUE);
4242 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
4243 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4244 RestoreClearState();
4247 // Destroy the offscreen resolved framebuffers.
4248 if (offscreen_resolved_frame_buffer_.get())
4249 offscreen_resolved_frame_buffer_->Destroy();
4250 if (offscreen_resolved_color_texture_.get())
4251 offscreen_resolved_color_texture_->Destroy();
4252 offscreen_resolved_color_texture_.reset();
4253 offscreen_resolved_frame_buffer_.reset();
4255 return true;
4258 error::Error GLES2DecoderImpl::HandleResizeCHROMIUM(uint32 immediate_data_size,
4259 const void* cmd_data) {
4260 const gles2::cmds::ResizeCHROMIUM& c =
4261 *static_cast<const gles2::cmds::ResizeCHROMIUM*>(cmd_data);
4262 if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws())
4263 return error::kDeferCommandUntilLater;
4265 GLuint width = static_cast<GLuint>(c.width);
4266 GLuint height = static_cast<GLuint>(c.height);
4267 GLfloat scale_factor = c.scale_factor;
4268 TRACE_EVENT2("gpu", "glResizeChromium", "width", width, "height", height);
4270 width = std::max(1U, width);
4271 height = std::max(1U, height);
4273 #if defined(OS_POSIX) && !defined(OS_MACOSX) && \
4274 !defined(UI_COMPOSITOR_IMAGE_TRANSPORT)
4275 // Make sure that we are done drawing to the back buffer before resizing.
4276 glFinish();
4277 #endif
4278 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
4279 if (is_offscreen) {
4280 if (!ResizeOffscreenFrameBuffer(gfx::Size(width, height))) {
4281 LOG(ERROR) << "GLES2DecoderImpl: Context lost because "
4282 << "ResizeOffscreenFrameBuffer failed.";
4283 return error::kLostContext;
4287 if (!resize_callback_.is_null()) {
4288 resize_callback_.Run(gfx::Size(width, height), scale_factor);
4289 DCHECK(context_->IsCurrent(surface_.get()));
4290 if (!context_->IsCurrent(surface_.get())) {
4291 LOG(ERROR) << "GLES2DecoderImpl: Context lost because context no longer "
4292 << "current after resize callback.";
4293 return error::kLostContext;
4297 return error::kNoError;
4300 const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
4301 if (command_id > kStartPoint && command_id < kNumCommands) {
4302 return gles2::GetCommandName(static_cast<CommandId>(command_id));
4304 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
4307 // Decode a command, and call the corresponding GL functions.
4308 // NOTE: DoCommand() is slower than calling DoCommands() on larger batches
4309 // of commands at once, and is now only used for tests that need to track
4310 // individual commands.
4311 error::Error GLES2DecoderImpl::DoCommand(unsigned int command,
4312 unsigned int arg_count,
4313 const void* cmd_data) {
4314 return DoCommands(1, cmd_data, arg_count + 1, 0);
4317 // Decode multiple commands, and call the corresponding GL functions.
4318 // NOTE: 'buffer' is a pointer to the command buffer. As such, it could be
4319 // changed by a (malicious) client at any time, so if validation has to happen,
4320 // it should operate on a copy of them.
4321 // NOTE: This is duplicating code from AsyncAPIInterface::DoCommands() in the
4322 // interest of performance in this critical execution loop.
4323 template <bool DebugImpl>
4324 error::Error GLES2DecoderImpl::DoCommandsImpl(unsigned int num_commands,
4325 const void* buffer,
4326 int num_entries,
4327 int* entries_processed) {
4328 commands_to_process_ = num_commands;
4329 error::Error result = error::kNoError;
4330 const CommandBufferEntry* cmd_data =
4331 static_cast<const CommandBufferEntry*>(buffer);
4332 int process_pos = 0;
4333 unsigned int command = 0;
4335 while (process_pos < num_entries && result == error::kNoError &&
4336 commands_to_process_--) {
4337 const unsigned int size = cmd_data->value_header.size;
4338 command = cmd_data->value_header.command;
4340 if (size == 0) {
4341 result = error::kInvalidSize;
4342 break;
4345 if (static_cast<int>(size) + process_pos > num_entries) {
4346 result = error::kOutOfBounds;
4347 break;
4350 if (DebugImpl) {
4351 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4352 GetCommandName(command));
4354 if (log_commands()) {
4355 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]"
4356 << "cmd: " << GetCommandName(command);
4360 const unsigned int arg_count = size - 1;
4361 unsigned int command_index = command - kStartPoint - 1;
4362 if (command_index < arraysize(command_info)) {
4363 const CommandInfo& info = command_info[command_index];
4364 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
4365 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
4366 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
4367 bool doing_gpu_trace = false;
4368 if (DebugImpl && gpu_trace_commands_) {
4369 if (CMD_FLAG_GET_TRACE_LEVEL(info.cmd_flags) <= gpu_trace_level_) {
4370 doing_gpu_trace = true;
4371 gpu_tracer_->Begin(TRACE_DISABLED_BY_DEFAULT("gpu_decoder"),
4372 GetCommandName(command),
4373 kTraceDecoder);
4377 uint32 immediate_data_size = (arg_count - info_arg_count) *
4378 sizeof(CommandBufferEntry); // NOLINT
4380 result = (this->*info.cmd_handler)(immediate_data_size, cmd_data);
4382 if (DebugImpl && doing_gpu_trace)
4383 gpu_tracer_->End(kTraceDecoder);
4385 if (DebugImpl && debug()) {
4386 GLenum error;
4387 while ((error = glGetError()) != GL_NO_ERROR) {
4388 LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] "
4389 << "GL ERROR: " << GLES2Util::GetStringEnum(error)
4390 << " : " << GetCommandName(command);
4391 LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver");
4394 } else {
4395 result = error::kInvalidArguments;
4397 } else {
4398 result = DoCommonCommand(command, arg_count, cmd_data);
4401 if (DebugImpl) {
4402 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("cb_command"),
4403 GetCommandName(command));
4406 if (result == error::kNoError &&
4407 current_decoder_error_ != error::kNoError) {
4408 result = current_decoder_error_;
4409 current_decoder_error_ = error::kNoError;
4412 if (result != error::kDeferCommandUntilLater) {
4413 process_pos += size;
4414 cmd_data += size;
4418 if (entries_processed)
4419 *entries_processed = process_pos;
4421 if (error::IsError(result)) {
4422 LOG(ERROR) << "Error: " << result << " for Command "
4423 << GetCommandName(command);
4426 return result;
4429 error::Error GLES2DecoderImpl::DoCommands(unsigned int num_commands,
4430 const void* buffer,
4431 int num_entries,
4432 int* entries_processed) {
4433 if (gpu_debug_commands_) {
4434 return DoCommandsImpl<true>(
4435 num_commands, buffer, num_entries, entries_processed);
4436 } else {
4437 return DoCommandsImpl<false>(
4438 num_commands, buffer, num_entries, entries_processed);
4442 void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
4443 buffer_manager()->RemoveBuffer(client_id);
4446 void GLES2DecoderImpl::DoFinish() {
4447 glFinish();
4448 ProcessPendingReadPixels(true);
4449 ProcessPendingQueries(true);
4452 void GLES2DecoderImpl::DoFlush() {
4453 glFlush();
4454 ProcessPendingQueries(false);
4457 void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
4458 GLuint texture_index = texture_unit - GL_TEXTURE0;
4459 if (texture_index >= state_.texture_units.size()) {
4460 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4461 "glActiveTexture", texture_unit, "texture_unit");
4462 return;
4464 state_.active_texture_unit = texture_index;
4465 glActiveTexture(texture_unit);
4468 void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
4469 Buffer* buffer = NULL;
4470 GLuint service_id = 0;
4471 if (client_id != 0) {
4472 buffer = GetBuffer(client_id);
4473 if (!buffer) {
4474 if (!group_->bind_generates_resource()) {
4475 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4476 "glBindBuffer",
4477 "id not generated by glGenBuffers");
4478 return;
4481 // It's a new id so make a buffer buffer for it.
4482 glGenBuffersARB(1, &service_id);
4483 CreateBuffer(client_id, service_id);
4484 buffer = GetBuffer(client_id);
4487 LogClientServiceForInfo(buffer, client_id, "glBindBuffer");
4488 if (buffer) {
4489 if (!buffer_manager()->SetTarget(buffer, target)) {
4490 LOCAL_SET_GL_ERROR(
4491 GL_INVALID_OPERATION,
4492 "glBindBuffer", "buffer bound to more than 1 target");
4493 return;
4495 service_id = buffer->service_id();
4497 state_.SetBoundBuffer(target, buffer);
4498 glBindBuffer(target, service_id);
4501 bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
4502 Framebuffer* framebuffer =
4503 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4504 if (framebuffer)
4505 return framebuffer->HasAlphaMRT();
4506 return BackBufferHasAlpha();
4509 bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
4510 Framebuffer* framebuffer =
4511 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4512 if (framebuffer) {
4513 return framebuffer->HasDepthAttachment();
4515 if (offscreen_target_frame_buffer_.get()) {
4516 return offscreen_target_depth_format_ != 0;
4518 return back_buffer_has_depth_;
4521 bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
4522 Framebuffer* framebuffer =
4523 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
4524 if (framebuffer) {
4525 return framebuffer->HasStencilAttachment();
4527 if (offscreen_target_frame_buffer_.get()) {
4528 return offscreen_target_stencil_format_ != 0 ||
4529 offscreen_target_depth_format_ == GL_DEPTH24_STENCIL8;
4531 return back_buffer_has_stencil_;
4534 void GLES2DecoderImpl::ApplyDirtyState() {
4535 if (framebuffer_state_.clear_state_dirty) {
4536 bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha();
4537 state_.SetDeviceColorMask(state_.color_mask_red,
4538 state_.color_mask_green,
4539 state_.color_mask_blue,
4540 state_.color_mask_alpha && have_alpha);
4542 bool have_depth = BoundFramebufferHasDepthAttachment();
4543 state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
4545 bool have_stencil = BoundFramebufferHasStencilAttachment();
4546 state_.SetDeviceStencilMaskSeparate(
4547 GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
4548 state_.SetDeviceStencilMaskSeparate(
4549 GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
4551 state_.SetDeviceCapabilityState(
4552 GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
4553 state_.SetDeviceCapabilityState(
4554 GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
4555 framebuffer_state_.clear_state_dirty = false;
4559 GLuint GLES2DecoderImpl::GetBackbufferServiceId() const {
4560 return (offscreen_target_frame_buffer_.get())
4561 ? offscreen_target_frame_buffer_->id()
4562 : (surface_.get() ? surface_->GetBackingFrameBufferObject() : 0);
4565 void GLES2DecoderImpl::RestoreState(const ContextState* prev_state) {
4566 TRACE_EVENT1("gpu", "GLES2DecoderImpl::RestoreState",
4567 "context", logger_.GetLogPrefix());
4568 // Restore the Framebuffer first because of bugs in Intel drivers.
4569 // Intel drivers incorrectly clip the viewport settings to
4570 // the size of the current framebuffer object.
4571 RestoreFramebufferBindings();
4572 state_.RestoreState(prev_state);
4575 void GLES2DecoderImpl::RestoreFramebufferBindings() const {
4576 GLuint service_id =
4577 framebuffer_state_.bound_draw_framebuffer.get()
4578 ? framebuffer_state_.bound_draw_framebuffer->service_id()
4579 : GetBackbufferServiceId();
4580 if (!features().chromium_framebuffer_multisample) {
4581 glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
4582 } else {
4583 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
4584 service_id = framebuffer_state_.bound_read_framebuffer.get()
4585 ? framebuffer_state_.bound_read_framebuffer->service_id()
4586 : GetBackbufferServiceId();
4587 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
4589 OnFboChanged();
4592 void GLES2DecoderImpl::RestoreRenderbufferBindings() {
4593 state_.RestoreRenderbufferBindings();
4596 void GLES2DecoderImpl::RestoreTextureState(unsigned service_id) const {
4597 Texture* texture = texture_manager()->GetTextureForServiceId(service_id);
4598 if (texture) {
4599 GLenum target = texture->target();
4600 glBindTexture(target, service_id);
4601 glTexParameteri(
4602 target, GL_TEXTURE_WRAP_S, texture->wrap_s());
4603 glTexParameteri(
4604 target, GL_TEXTURE_WRAP_T, texture->wrap_t());
4605 glTexParameteri(
4606 target, GL_TEXTURE_MIN_FILTER, texture->min_filter());
4607 glTexParameteri(
4608 target, GL_TEXTURE_MAG_FILTER, texture->mag_filter());
4609 RestoreTextureUnitBindings(state_.active_texture_unit);
4613 void GLES2DecoderImpl::ClearAllAttributes() const {
4614 // Must use native VAO 0, as RestoreAllAttributes can't fully restore
4615 // other VAOs.
4616 if (feature_info_->feature_flags().native_vertex_array_object)
4617 glBindVertexArrayOES(0);
4619 for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
4620 if (i != 0) // Never disable attribute 0
4621 glDisableVertexAttribArray(i);
4622 if (features().angle_instanced_arrays)
4623 glVertexAttribDivisorANGLE(i, 0);
4627 void GLES2DecoderImpl::RestoreAllAttributes() const {
4628 state_.RestoreVertexAttribs();
4631 void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
4632 state_.SetIgnoreCachedStateForTest(ignore);
4635 void GLES2DecoderImpl::OnFboChanged() const {
4636 if (workarounds().restore_scissor_on_fbo_change)
4637 state_.fbo_binding_for_scissor_workaround_dirty = true;
4639 if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer) {
4640 GLint bound_fbo_unsigned = -1;
4641 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &bound_fbo_unsigned);
4642 GLuint bound_fbo = static_cast<GLuint>(bound_fbo_unsigned);
4643 if (surface_ && surface_->GetBackingFrameBufferObject() == bound_fbo)
4644 surface_->NotifyWasBound();
4648 // Called after the FBO is checked for completeness.
4649 void GLES2DecoderImpl::OnUseFramebuffer() const {
4650 if (state_.fbo_binding_for_scissor_workaround_dirty) {
4651 state_.fbo_binding_for_scissor_workaround_dirty = false;
4652 // The driver forgets the correct scissor when modifying the FBO binding.
4653 glScissor(state_.scissor_x,
4654 state_.scissor_y,
4655 state_.scissor_width,
4656 state_.scissor_height);
4658 // crbug.com/222018 - Also on QualComm, the flush here avoids flicker,
4659 // it's unclear how this bug works.
4660 glFlush();
4664 void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
4665 Framebuffer* framebuffer = NULL;
4666 GLuint service_id = 0;
4667 if (client_id != 0) {
4668 framebuffer = GetFramebuffer(client_id);
4669 if (!framebuffer) {
4670 if (!group_->bind_generates_resource()) {
4671 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4672 "glBindFramebuffer",
4673 "id not generated by glGenFramebuffers");
4674 return;
4677 // It's a new id so make a framebuffer framebuffer for it.
4678 glGenFramebuffersEXT(1, &service_id);
4679 CreateFramebuffer(client_id, service_id);
4680 framebuffer = GetFramebuffer(client_id);
4681 } else {
4682 service_id = framebuffer->service_id();
4684 framebuffer->MarkAsValid();
4686 LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
4688 if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
4689 framebuffer_state_.bound_draw_framebuffer = framebuffer;
4692 // vmiura: This looks like dup code
4693 if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
4694 framebuffer_state_.bound_read_framebuffer = framebuffer;
4697 framebuffer_state_.clear_state_dirty = true;
4699 // If we are rendering to the backbuffer get the FBO id for any simulated
4700 // backbuffer.
4701 if (framebuffer == NULL) {
4702 service_id = GetBackbufferServiceId();
4705 glBindFramebufferEXT(target, service_id);
4706 OnFboChanged();
4709 void GLES2DecoderImpl::DoBindRenderbuffer(GLenum target, GLuint client_id) {
4710 Renderbuffer* renderbuffer = NULL;
4711 GLuint service_id = 0;
4712 if (client_id != 0) {
4713 renderbuffer = GetRenderbuffer(client_id);
4714 if (!renderbuffer) {
4715 if (!group_->bind_generates_resource()) {
4716 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4717 "glBindRenderbuffer",
4718 "id not generated by glGenRenderbuffers");
4719 return;
4722 // It's a new id so make a renderbuffer for it.
4723 glGenRenderbuffersEXT(1, &service_id);
4724 CreateRenderbuffer(client_id, service_id);
4725 renderbuffer = GetRenderbuffer(client_id);
4726 } else {
4727 service_id = renderbuffer->service_id();
4729 renderbuffer->MarkAsValid();
4731 LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
4732 state_.bound_renderbuffer = renderbuffer;
4733 state_.bound_renderbuffer_valid = true;
4734 glBindRenderbufferEXT(GL_RENDERBUFFER, service_id);
4737 void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
4738 TextureRef* texture_ref = NULL;
4739 GLuint service_id = 0;
4740 if (client_id != 0) {
4741 texture_ref = GetTexture(client_id);
4742 if (!texture_ref) {
4743 if (!group_->bind_generates_resource()) {
4744 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4745 "glBindTexture",
4746 "id not generated by glGenTextures");
4747 return;
4750 // It's a new id so make a texture texture for it.
4751 glGenTextures(1, &service_id);
4752 DCHECK_NE(0u, service_id);
4753 CreateTexture(client_id, service_id);
4754 texture_ref = GetTexture(client_id);
4756 } else {
4757 texture_ref = texture_manager()->GetDefaultTextureInfo(target);
4760 // Check the texture exists
4761 if (texture_ref) {
4762 Texture* texture = texture_ref->texture();
4763 // Check that we are not trying to bind it to a different target.
4764 if (texture->target() != 0 && texture->target() != target) {
4765 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
4766 "glBindTexture",
4767 "texture bound to more than 1 target.");
4768 return;
4770 LogClientServiceForInfo(texture, client_id, "glBindTexture");
4771 if (texture->target() == 0) {
4772 texture_manager()->SetTarget(texture_ref, target);
4774 glBindTexture(target, texture->service_id());
4775 } else {
4776 glBindTexture(target, 0);
4779 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
4780 unit.bind_target = target;
4781 switch (target) {
4782 case GL_TEXTURE_2D:
4783 unit.bound_texture_2d = texture_ref;
4784 break;
4785 case GL_TEXTURE_CUBE_MAP:
4786 unit.bound_texture_cube_map = texture_ref;
4787 break;
4788 case GL_TEXTURE_EXTERNAL_OES:
4789 unit.bound_texture_external_oes = texture_ref;
4790 break;
4791 case GL_TEXTURE_RECTANGLE_ARB:
4792 unit.bound_texture_rectangle_arb = texture_ref;
4793 break;
4794 case GL_TEXTURE_3D:
4795 unit.bound_texture_3d = texture_ref;
4796 break;
4797 case GL_TEXTURE_2D_ARRAY:
4798 unit.bound_texture_2d_array = texture_ref;
4799 break;
4800 default:
4801 NOTREACHED(); // Validation should prevent us getting here.
4802 break;
4806 void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
4807 if (state_.vertex_attrib_manager->Enable(index, false)) {
4808 if (index != 0 ||
4809 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
4810 glDisableVertexAttribArray(index);
4812 } else {
4813 LOCAL_SET_GL_ERROR(
4814 GL_INVALID_VALUE,
4815 "glDisableVertexAttribArray", "index out of range");
4819 void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
4820 GLsizei numAttachments,
4821 const GLenum* attachments) {
4822 if (workarounds().disable_discard_framebuffer)
4823 return;
4825 Framebuffer* framebuffer =
4826 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
4828 // Validates the attachments. If one of them fails
4829 // the whole command fails.
4830 for (GLsizei i = 0; i < numAttachments; ++i) {
4831 if ((framebuffer &&
4832 !validators_->attachment.IsValid(attachments[i])) ||
4833 (!framebuffer &&
4834 !validators_->backbuffer_attachment.IsValid(attachments[i]))) {
4835 LOCAL_SET_GL_ERROR_INVALID_ENUM(
4836 "glDiscardFramebufferEXT", attachments[i], "attachments");
4837 return;
4841 // Marks each one of them as not cleared
4842 for (GLsizei i = 0; i < numAttachments; ++i) {
4843 if (framebuffer) {
4844 framebuffer->MarkAttachmentAsCleared(renderbuffer_manager(),
4845 texture_manager(),
4846 attachments[i],
4847 false);
4848 } else {
4849 switch (attachments[i]) {
4850 case GL_COLOR_EXT:
4851 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
4852 break;
4853 case GL_DEPTH_EXT:
4854 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
4855 case GL_STENCIL_EXT:
4856 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
4857 break;
4858 default:
4859 NOTREACHED();
4860 break;
4865 // If the default framebuffer is bound but we are still rendering to an
4866 // FBO, translate attachment names that refer to default framebuffer
4867 // channels to corresponding framebuffer attachments.
4868 scoped_ptr<GLenum[]> translated_attachments(new GLenum[numAttachments]);
4869 for (GLsizei i = 0; i < numAttachments; ++i) {
4870 GLenum attachment = attachments[i];
4871 if (!framebuffer && GetBackbufferServiceId()) {
4872 switch (attachment) {
4873 case GL_COLOR_EXT:
4874 attachment = GL_COLOR_ATTACHMENT0;
4875 break;
4876 case GL_DEPTH_EXT:
4877 attachment = GL_DEPTH_ATTACHMENT;
4878 break;
4879 case GL_STENCIL_EXT:
4880 attachment = GL_STENCIL_ATTACHMENT;
4881 break;
4882 default:
4883 NOTREACHED();
4884 return;
4887 translated_attachments[i] = attachment;
4890 ScopedRenderTo do_render(framebuffer);
4891 if (feature_info_->gl_version_info().is_es3) {
4892 glInvalidateFramebuffer(
4893 target, numAttachments, translated_attachments.get());
4894 } else {
4895 glDiscardFramebufferEXT(
4896 target, numAttachments, translated_attachments.get());
4900 void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
4901 if (state_.vertex_attrib_manager->Enable(index, true)) {
4902 glEnableVertexAttribArray(index);
4903 } else {
4904 LOCAL_SET_GL_ERROR(
4905 GL_INVALID_VALUE, "glEnableVertexAttribArray", "index out of range");
4909 void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
4910 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
4911 &state_, target);
4912 if (!texture_ref ||
4913 !texture_manager()->CanGenerateMipmaps(texture_ref)) {
4914 LOCAL_SET_GL_ERROR(
4915 GL_INVALID_OPERATION, "glGenerateMipmap", "Can not generate mips");
4916 return;
4919 if (target == GL_TEXTURE_CUBE_MAP) {
4920 for (int i = 0; i < 6; ++i) {
4921 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4922 if (!texture_manager()->ClearTextureLevel(this, texture_ref, face, 0)) {
4923 LOCAL_SET_GL_ERROR(
4924 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4925 return;
4928 } else {
4929 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, 0)) {
4930 LOCAL_SET_GL_ERROR(
4931 GL_OUT_OF_MEMORY, "glGenerateMipmap", "dimensions too big");
4932 return;
4936 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glGenerateMipmap");
4937 // Workaround for Mac driver bug. In the large scheme of things setting
4938 // glTexParamter twice for glGenerateMipmap is probably not a lage performance
4939 // hit so there's probably no need to make this conditional. The bug appears
4940 // to be that if the filtering mode is set to something that doesn't require
4941 // mipmaps for rendering, or is never set to something other than the default,
4942 // then glGenerateMipmap misbehaves.
4943 if (workarounds().set_texture_filter_before_generating_mipmap) {
4944 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4946 glGenerateMipmapEXT(target);
4947 if (workarounds().set_texture_filter_before_generating_mipmap) {
4948 glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
4949 texture_ref->texture()->min_filter());
4951 GLenum error = LOCAL_PEEK_GL_ERROR("glGenerateMipmap");
4952 if (error == GL_NO_ERROR) {
4953 texture_manager()->MarkMipmapsGenerated(texture_ref);
4957 bool GLES2DecoderImpl::GetHelper(
4958 GLenum pname, GLint* params, GLsizei* num_written) {
4959 DCHECK(num_written);
4960 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
4961 switch (pname) {
4962 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
4963 *num_written = 1;
4964 // Return the GL implementation's preferred format and (see below type)
4965 // if we have the GL extension that exposes this. This allows the GPU
4966 // client to use the implementation's preferred format for glReadPixels
4967 // for optimisation.
4969 // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
4970 // case when requested on integer/floating point buffers but which is
4971 // acceptable on GLES2 and with the GL_OES_read_format extension.
4973 // Therefore if an error occurs we swallow the error and use the
4974 // internal implementation.
4975 if (params) {
4976 if (context_->HasExtension("GL_OES_read_format")) {
4977 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4978 GetErrorState());
4979 glGetIntegerv(pname, params);
4980 if (glGetError() == GL_NO_ERROR)
4981 return true;
4983 *params = GLES2Util::GetPreferredGLReadPixelsFormat(
4984 GetBoundReadFrameBufferInternalFormat());
4986 return true;
4987 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
4988 *num_written = 1;
4989 if (params) {
4990 if (context_->HasExtension("GL_OES_read_format")) {
4991 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
4992 GetErrorState());
4993 glGetIntegerv(pname, params);
4994 if (glGetError() == GL_NO_ERROR)
4995 return true;
4997 *params = GLES2Util::GetPreferredGLReadPixelsType(
4998 GetBoundReadFrameBufferInternalFormat(),
4999 GetBoundReadFrameBufferTextureType());
5001 return true;
5002 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
5003 *num_written = 1;
5004 if (params) {
5005 *params = group_->max_fragment_uniform_vectors();
5007 return true;
5008 case GL_MAX_VARYING_VECTORS:
5009 *num_written = 1;
5010 if (params) {
5011 *params = group_->max_varying_vectors();
5013 return true;
5014 case GL_MAX_VERTEX_UNIFORM_VECTORS:
5015 *num_written = 1;
5016 if (params) {
5017 *params = group_->max_vertex_uniform_vectors();
5019 return true;
5022 if (unsafe_es3_apis_enabled()) {
5023 switch (pname) {
5024 case GL_MAX_VARYING_COMPONENTS: {
5025 if (feature_info_->gl_version_info().is_es) {
5026 // We can just delegate this query to the driver.
5027 return false;
5030 // GL_MAX_VARYING_COMPONENTS is deprecated in the desktop
5031 // OpenGL core profile, so for simplicity, just compute it
5032 // from GL_MAX_VARYING_VECTORS on non-OpenGL ES
5033 // configurations.
5034 GLint max_varying_vectors = 0;
5035 glGetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors);
5036 *num_written = 1;
5037 if (params) {
5038 *params = max_varying_vectors * 4;
5040 return true;
5042 case GL_READ_BUFFER:
5043 *num_written = 1;
5044 if (params) {
5045 Framebuffer* framebuffer =
5046 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
5047 GLenum read_buffer;
5048 if (framebuffer) {
5049 read_buffer = framebuffer->read_buffer();
5050 } else {
5051 read_buffer = back_buffer_read_buffer_;
5053 *params = static_cast<GLint>(read_buffer);
5055 return true;
5058 switch (pname) {
5059 case GL_MAX_VIEWPORT_DIMS:
5060 if (offscreen_target_frame_buffer_.get()) {
5061 *num_written = 2;
5062 if (params) {
5063 params[0] = renderbuffer_manager()->max_renderbuffer_size();
5064 params[1] = renderbuffer_manager()->max_renderbuffer_size();
5066 return true;
5068 return false;
5069 case GL_MAX_SAMPLES:
5070 *num_written = 1;
5071 if (params) {
5072 params[0] = renderbuffer_manager()->max_samples();
5074 return true;
5075 case GL_MAX_RENDERBUFFER_SIZE:
5076 *num_written = 1;
5077 if (params) {
5078 params[0] = renderbuffer_manager()->max_renderbuffer_size();
5080 return true;
5081 case GL_MAX_TEXTURE_SIZE:
5082 *num_written = 1;
5083 if (params) {
5084 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D);
5086 return true;
5087 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
5088 *num_written = 1;
5089 if (params) {
5090 params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_CUBE_MAP);
5092 return true;
5093 case GL_MAX_COLOR_ATTACHMENTS_EXT:
5094 *num_written = 1;
5095 if (params) {
5096 params[0] = group_->max_color_attachments();
5098 return true;
5099 case GL_MAX_DRAW_BUFFERS_ARB:
5100 *num_written = 1;
5101 if (params) {
5102 params[0] = group_->max_draw_buffers();
5104 return true;
5105 case GL_ALPHA_BITS:
5106 *num_written = 1;
5107 if (params) {
5108 GLint v = 0;
5109 Framebuffer* framebuffer =
5110 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5111 if (framebuffer) {
5112 if (framebuffer->HasAlphaMRT() &&
5113 framebuffer->HasSameInternalFormatsMRT()) {
5114 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5115 glGetFramebufferAttachmentParameterivEXT(
5116 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5117 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &v);
5118 } else {
5119 glGetIntegerv(GL_ALPHA_BITS, &v);
5122 } else {
5123 v = (BackBufferHasAlpha() ? 8 : 0);
5125 params[0] = v;
5127 return true;
5128 case GL_DEPTH_BITS:
5129 *num_written = 1;
5130 if (params) {
5131 GLint v = 0;
5132 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5133 Framebuffer* framebuffer =
5134 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5135 if (framebuffer) {
5136 glGetFramebufferAttachmentParameterivEXT(
5137 GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
5138 GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &v);
5139 } else {
5140 v = (back_buffer_has_depth_ ? 24 : 0);
5142 } else {
5143 glGetIntegerv(GL_DEPTH_BITS, &v);
5145 params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
5147 return true;
5148 case GL_RED_BITS:
5149 case GL_GREEN_BITS:
5150 case GL_BLUE_BITS:
5151 *num_written = 1;
5152 if (params) {
5153 GLint v = 0;
5154 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5155 Framebuffer* framebuffer =
5156 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5157 if (framebuffer) {
5158 GLenum framebuffer_enum = 0;
5159 switch (pname) {
5160 case GL_RED_BITS:
5161 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
5162 break;
5163 case GL_GREEN_BITS:
5164 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
5165 break;
5166 case GL_BLUE_BITS:
5167 framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
5168 break;
5170 glGetFramebufferAttachmentParameterivEXT(
5171 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, framebuffer_enum, &v);
5172 } else {
5173 v = 8;
5175 } else {
5176 glGetIntegerv(pname, &v);
5178 params[0] = v;
5180 return true;
5181 case GL_STENCIL_BITS:
5182 *num_written = 1;
5183 if (params) {
5184 GLint v = 0;
5185 if (feature_info_->gl_version_info().is_desktop_core_profile) {
5186 Framebuffer* framebuffer =
5187 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5188 if (framebuffer) {
5189 glGetFramebufferAttachmentParameterivEXT(
5190 GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
5191 GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &v);
5192 } else {
5193 v = (back_buffer_has_stencil_ ? 8 : 0);
5195 } else {
5196 glGetIntegerv(GL_STENCIL_BITS, &v);
5198 params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
5200 return true;
5201 case GL_COMPRESSED_TEXTURE_FORMATS:
5202 *num_written = validators_->compressed_texture_format.GetValues().size();
5203 if (params) {
5204 for (GLint ii = 0; ii < *num_written; ++ii) {
5205 params[ii] = validators_->compressed_texture_format.GetValues()[ii];
5208 return true;
5209 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
5210 *num_written = 1;
5211 if (params) {
5212 *params = validators_->compressed_texture_format.GetValues().size();
5214 return true;
5215 case GL_NUM_SHADER_BINARY_FORMATS:
5216 *num_written = 1;
5217 if (params) {
5218 *params = validators_->shader_binary_format.GetValues().size();
5220 return true;
5221 case GL_SHADER_BINARY_FORMATS:
5222 *num_written = validators_->shader_binary_format.GetValues().size();
5223 if (params) {
5224 for (GLint ii = 0; ii < *num_written; ++ii) {
5225 params[ii] = validators_->shader_binary_format.GetValues()[ii];
5228 return true;
5229 case GL_SHADER_COMPILER:
5230 *num_written = 1;
5231 if (params) {
5232 *params = GL_TRUE;
5234 return true;
5235 case GL_ARRAY_BUFFER_BINDING:
5236 *num_written = 1;
5237 if (params) {
5238 *params = GetClientId(
5239 buffer_manager(), state_.bound_array_buffer.get());
5241 return true;
5242 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
5243 *num_written = 1;
5244 if (params) {
5245 *params = GetClientId(
5246 buffer_manager(),
5247 state_.vertex_attrib_manager->element_array_buffer());
5249 return true;
5250 case GL_COPY_READ_BUFFER_BINDING:
5251 *num_written = 1;
5252 if (params) {
5253 *params = GetClientId(
5254 buffer_manager(), state_.bound_copy_read_buffer.get());
5256 return true;
5257 case GL_COPY_WRITE_BUFFER_BINDING:
5258 *num_written = 1;
5259 if (params) {
5260 *params = GetClientId(
5261 buffer_manager(), state_.bound_copy_write_buffer.get());
5263 return true;
5264 case GL_PIXEL_PACK_BUFFER_BINDING:
5265 *num_written = 1;
5266 if (params) {
5267 *params = GetClientId(
5268 buffer_manager(), state_.bound_pixel_pack_buffer.get());
5270 return true;
5271 case GL_PIXEL_UNPACK_BUFFER_BINDING:
5272 *num_written = 1;
5273 if (params) {
5274 *params = GetClientId(
5275 buffer_manager(), state_.bound_pixel_unpack_buffer.get());
5277 return true;
5278 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
5279 *num_written = 1;
5280 if (params) {
5281 *params = GetClientId(
5282 buffer_manager(), state_.bound_transform_feedback_buffer.get());
5284 return true;
5285 case GL_UNIFORM_BUFFER_BINDING:
5286 *num_written = 1;
5287 if (params) {
5288 *params = GetClientId(
5289 buffer_manager(), state_.bound_uniform_buffer.get());
5291 return true;
5292 case GL_FRAMEBUFFER_BINDING:
5293 // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
5294 *num_written = 1;
5295 if (params) {
5296 *params = GetClientId(
5297 framebuffer_manager(),
5298 GetFramebufferInfoForTarget(GL_FRAMEBUFFER));
5300 return true;
5301 case GL_READ_FRAMEBUFFER_BINDING_EXT:
5302 *num_written = 1;
5303 if (params) {
5304 *params = GetClientId(
5305 framebuffer_manager(),
5306 GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT));
5308 return true;
5309 case GL_RENDERBUFFER_BINDING:
5310 *num_written = 1;
5311 if (params) {
5312 Renderbuffer* renderbuffer =
5313 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5314 if (renderbuffer) {
5315 *params = renderbuffer->client_id();
5316 } else {
5317 *params = 0;
5320 return true;
5321 case GL_CURRENT_PROGRAM:
5322 *num_written = 1;
5323 if (params) {
5324 *params = GetClientId(program_manager(), state_.current_program.get());
5326 return true;
5327 case GL_VERTEX_ARRAY_BINDING_OES:
5328 *num_written = 1;
5329 if (params) {
5330 if (state_.vertex_attrib_manager.get() !=
5331 state_.default_vertex_attrib_manager.get()) {
5332 GLuint client_id = 0;
5333 vertex_array_manager_->GetClientId(
5334 state_.vertex_attrib_manager->service_id(), &client_id);
5335 *params = client_id;
5336 } else {
5337 *params = 0;
5340 return true;
5341 case GL_TEXTURE_BINDING_2D:
5342 *num_written = 1;
5343 if (params) {
5344 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5345 if (unit.bound_texture_2d.get()) {
5346 *params = unit.bound_texture_2d->client_id();
5347 } else {
5348 *params = 0;
5351 return true;
5352 case GL_TEXTURE_BINDING_CUBE_MAP:
5353 *num_written = 1;
5354 if (params) {
5355 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5356 if (unit.bound_texture_cube_map.get()) {
5357 *params = unit.bound_texture_cube_map->client_id();
5358 } else {
5359 *params = 0;
5362 return true;
5363 case GL_TEXTURE_BINDING_EXTERNAL_OES:
5364 *num_written = 1;
5365 if (params) {
5366 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5367 if (unit.bound_texture_external_oes.get()) {
5368 *params = unit.bound_texture_external_oes->client_id();
5369 } else {
5370 *params = 0;
5373 return true;
5374 case GL_TEXTURE_BINDING_RECTANGLE_ARB:
5375 *num_written = 1;
5376 if (params) {
5377 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
5378 if (unit.bound_texture_rectangle_arb.get()) {
5379 *params = unit.bound_texture_rectangle_arb->client_id();
5380 } else {
5381 *params = 0;
5384 return true;
5385 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
5386 *num_written = 1;
5387 if (params) {
5388 params[0] = group_->bind_generates_resource() ? 1 : 0;
5390 return true;
5391 default:
5392 if (pname >= GL_DRAW_BUFFER0_ARB &&
5393 pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
5394 *num_written = 1;
5395 if (params) {
5396 Framebuffer* framebuffer =
5397 GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
5398 if (framebuffer) {
5399 params[0] = framebuffer->GetDrawBuffer(pname);
5400 } else { // backbuffer
5401 if (pname == GL_DRAW_BUFFER0_ARB)
5402 params[0] = back_buffer_draw_buffer_;
5403 else
5404 params[0] = GL_NONE;
5407 return true;
5409 *num_written = util_.GLGetNumValuesReturned(pname);
5410 return false;
5414 bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet(
5415 GLenum pname, GLsizei* num_values) {
5416 if (state_.GetStateAsGLint(pname, NULL, num_values)) {
5417 return true;
5419 return GetHelper(pname, NULL, num_values);
5422 GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) {
5423 if (GL_MAX_SAMPLES == pname &&
5424 features().use_img_for_multisampled_render_to_texture) {
5425 return GL_MAX_SAMPLES_IMG;
5427 return pname;
5430 void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) {
5431 DCHECK(params);
5432 GLsizei num_written = 0;
5433 if (GetNumValuesReturnedForGLGet(pname, &num_written)) {
5434 scoped_ptr<GLint[]> values(new GLint[num_written]);
5435 if (!state_.GetStateAsGLint(pname, values.get(), &num_written)) {
5436 GetHelper(pname, values.get(), &num_written);
5438 for (GLsizei ii = 0; ii < num_written; ++ii) {
5439 params[ii] = static_cast<GLboolean>(values[ii]);
5441 } else {
5442 pname = AdjustGetPname(pname);
5443 glGetBooleanv(pname, params);
5447 void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) {
5448 DCHECK(params);
5449 GLsizei num_written = 0;
5450 if (!state_.GetStateAsGLfloat(pname, params, &num_written)) {
5451 if (GetHelper(pname, NULL, &num_written)) {
5452 scoped_ptr<GLint[]> values(new GLint[num_written]);
5453 GetHelper(pname, values.get(), &num_written);
5454 for (GLsizei ii = 0; ii < num_written; ++ii) {
5455 params[ii] = static_cast<GLfloat>(values[ii]);
5457 } else {
5458 pname = AdjustGetPname(pname);
5459 glGetFloatv(pname, params);
5464 void GLES2DecoderImpl::DoGetInteger64v(GLenum pname, GLint64* params) {
5465 DCHECK(params);
5466 if (unsafe_es3_apis_enabled()) {
5467 switch (pname) {
5468 case GL_MAX_ELEMENT_INDEX: {
5469 if (feature_info_->gl_version_info().IsAtLeastGLES(3, 0) ||
5470 feature_info_->gl_version_info().IsAtLeastGL(4, 3)) {
5471 glGetInteger64v(GL_MAX_ELEMENT_INDEX, params);
5472 } else {
5473 // Assume that desktop GL implementations can generally support
5474 // 32-bit indices.
5475 if (params) {
5476 *params = std::numeric_limits<unsigned int>::max();
5479 return;
5483 pname = AdjustGetPname(pname);
5484 glGetInteger64v(pname, params);
5487 void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) {
5488 DCHECK(params);
5489 GLsizei num_written;
5490 if (!state_.GetStateAsGLint(pname, params, &num_written) &&
5491 !GetHelper(pname, params, &num_written)) {
5492 pname = AdjustGetPname(pname);
5493 glGetIntegerv(pname, params);
5497 void GLES2DecoderImpl::DoGetProgramiv(
5498 GLuint program_id, GLenum pname, GLint* params) {
5499 Program* program = GetProgramInfoNotShader(program_id, "glGetProgramiv");
5500 if (!program) {
5501 return;
5503 program->GetProgramiv(pname, params);
5506 void GLES2DecoderImpl::DoGetBufferParameteri64v(
5507 GLenum target, GLenum pname, GLint64* params) {
5508 // Just delegate it. Some validation is actually done before this.
5509 buffer_manager()->ValidateAndDoGetBufferParameteri64v(
5510 &state_, target, pname, params);
5513 void GLES2DecoderImpl::DoGetBufferParameteriv(
5514 GLenum target, GLenum pname, GLint* params) {
5515 // Just delegate it. Some validation is actually done before this.
5516 buffer_manager()->ValidateAndDoGetBufferParameteriv(
5517 &state_, target, pname, params);
5520 void GLES2DecoderImpl::DoBindAttribLocation(
5521 GLuint program_id, GLuint index, const char* name) {
5522 if (!StringIsValidForGLES(name)) {
5523 LOCAL_SET_GL_ERROR(
5524 GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character");
5525 return;
5527 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5528 LOCAL_SET_GL_ERROR(
5529 GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix");
5530 return;
5532 if (index >= group_->max_vertex_attribs()) {
5533 LOCAL_SET_GL_ERROR(
5534 GL_INVALID_VALUE, "glBindAttribLocation", "index out of range");
5535 return;
5537 Program* program = GetProgramInfoNotShader(
5538 program_id, "glBindAttribLocation");
5539 if (!program) {
5540 return;
5542 // At this point, the program's shaders may not be translated yet,
5543 // therefore, we may not find the hashed attribute name.
5544 // glBindAttribLocation call with original name is useless.
5545 // So instead, we should simply cache the binding, and then call
5546 // Program::ExecuteBindAttribLocationCalls() right before link.
5547 program->SetAttribLocationBinding(name, static_cast<GLint>(index));
5548 // TODO(zmo): Get rid of the following glBindAttribLocation call.
5549 glBindAttribLocation(program->service_id(), index, name);
5552 error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
5553 uint32 immediate_data_size,
5554 const void* cmd_data) {
5555 const gles2::cmds::BindAttribLocationBucket& c =
5556 *static_cast<const gles2::cmds::BindAttribLocationBucket*>(cmd_data);
5557 GLuint program = static_cast<GLuint>(c.program);
5558 GLuint index = static_cast<GLuint>(c.index);
5559 Bucket* bucket = GetBucket(c.name_bucket_id);
5560 if (!bucket || bucket->size() == 0) {
5561 return error::kInvalidArguments;
5563 std::string name_str;
5564 if (!bucket->GetAsString(&name_str)) {
5565 return error::kInvalidArguments;
5567 DoBindAttribLocation(program, index, name_str.c_str());
5568 return error::kNoError;
5571 void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
5572 GLuint program_id, GLint location, const char* name) {
5573 if (!StringIsValidForGLES(name)) {
5574 LOCAL_SET_GL_ERROR(
5575 GL_INVALID_VALUE,
5576 "glBindUniformLocationCHROMIUM", "Invalid character");
5577 return;
5579 if (ProgramManager::IsInvalidPrefix(name, strlen(name))) {
5580 LOCAL_SET_GL_ERROR(
5581 GL_INVALID_OPERATION,
5582 "glBindUniformLocationCHROMIUM", "reserved prefix");
5583 return;
5585 if (location < 0 || static_cast<uint32>(location) >=
5586 (group_->max_fragment_uniform_vectors() +
5587 group_->max_vertex_uniform_vectors()) * 4) {
5588 LOCAL_SET_GL_ERROR(
5589 GL_INVALID_VALUE,
5590 "glBindUniformLocationCHROMIUM", "location out of range");
5591 return;
5593 Program* program = GetProgramInfoNotShader(
5594 program_id, "glBindUniformLocationCHROMIUM");
5595 if (!program) {
5596 return;
5598 if (!program->SetUniformLocationBinding(name, location)) {
5599 LOCAL_SET_GL_ERROR(
5600 GL_INVALID_VALUE,
5601 "glBindUniformLocationCHROMIUM", "location out of range");
5605 error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
5606 uint32 immediate_data_size,
5607 const void* cmd_data) {
5608 const gles2::cmds::BindUniformLocationCHROMIUMBucket& c =
5609 *static_cast<const gles2::cmds::BindUniformLocationCHROMIUMBucket*>(
5610 cmd_data);
5611 GLuint program = static_cast<GLuint>(c.program);
5612 GLint location = static_cast<GLint>(c.location);
5613 Bucket* bucket = GetBucket(c.name_bucket_id);
5614 if (!bucket || bucket->size() == 0) {
5615 return error::kInvalidArguments;
5617 std::string name_str;
5618 if (!bucket->GetAsString(&name_str)) {
5619 return error::kInvalidArguments;
5621 DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
5622 return error::kNoError;
5625 error::Error GLES2DecoderImpl::HandleDeleteShader(uint32 immediate_data_size,
5626 const void* cmd_data) {
5627 const gles2::cmds::DeleteShader& c =
5628 *static_cast<const gles2::cmds::DeleteShader*>(cmd_data);
5629 GLuint client_id = c.shader;
5630 if (client_id) {
5631 Shader* shader = GetShader(client_id);
5632 if (shader) {
5633 if (!shader->IsDeleted()) {
5634 shader_manager()->Delete(shader);
5636 } else {
5637 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glDeleteShader", "unknown shader");
5640 return error::kNoError;
5643 error::Error GLES2DecoderImpl::HandleDeleteProgram(uint32 immediate_data_size,
5644 const void* cmd_data) {
5645 const gles2::cmds::DeleteProgram& c =
5646 *static_cast<const gles2::cmds::DeleteProgram*>(cmd_data);
5647 GLuint client_id = c.program;
5648 if (client_id) {
5649 Program* program = GetProgram(client_id);
5650 if (program) {
5651 if (!program->IsDeleted()) {
5652 program_manager()->MarkAsDeleted(shader_manager(), program);
5654 } else {
5655 LOCAL_SET_GL_ERROR(
5656 GL_INVALID_VALUE, "glDeleteProgram", "unknown program");
5659 return error::kNoError;
5662 error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) {
5663 DCHECK(!ShouldDeferDraws());
5664 if (CheckBoundFramebuffersValid("glClear")) {
5665 ApplyDirtyState();
5666 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
5667 if (workarounds().gl_clear_broken) {
5668 ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::ClearWorkaround",
5669 GetErrorState());
5670 if (!BoundFramebufferHasDepthAttachment())
5671 mask &= ~GL_DEPTH_BUFFER_BIT;
5672 if (!BoundFramebufferHasStencilAttachment())
5673 mask &= ~GL_STENCIL_BUFFER_BIT;
5674 clear_framebuffer_blit_->ClearFramebuffer(
5675 this, GetBoundReadFrameBufferSize(), mask, state_.color_clear_red,
5676 state_.color_clear_green, state_.color_clear_blue,
5677 state_.color_clear_alpha, state_.depth_clear, state_.stencil_clear);
5678 return error::kNoError;
5680 glClear(mask);
5682 return error::kNoError;
5685 void GLES2DecoderImpl::DoFramebufferRenderbuffer(
5686 GLenum target, GLenum attachment, GLenum renderbuffertarget,
5687 GLuint client_renderbuffer_id) {
5688 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5689 if (!framebuffer) {
5690 LOCAL_SET_GL_ERROR(
5691 GL_INVALID_OPERATION,
5692 "glFramebufferRenderbuffer", "no framebuffer bound");
5693 return;
5695 GLuint service_id = 0;
5696 Renderbuffer* renderbuffer = NULL;
5697 if (client_renderbuffer_id) {
5698 renderbuffer = GetRenderbuffer(client_renderbuffer_id);
5699 if (!renderbuffer) {
5700 LOCAL_SET_GL_ERROR(
5701 GL_INVALID_OPERATION,
5702 "glFramebufferRenderbuffer", "unknown renderbuffer");
5703 return;
5705 service_id = renderbuffer->service_id();
5707 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferRenderbuffer");
5708 glFramebufferRenderbufferEXT(
5709 target, attachment, renderbuffertarget, service_id);
5710 GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferRenderbuffer");
5711 if (error == GL_NO_ERROR) {
5712 framebuffer->AttachRenderbuffer(attachment, renderbuffer);
5714 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5715 framebuffer_state_.clear_state_dirty = true;
5717 OnFboChanged();
5720 void GLES2DecoderImpl::DoDisable(GLenum cap) {
5721 if (SetCapabilityState(cap, false)) {
5722 glDisable(cap);
5726 void GLES2DecoderImpl::DoEnable(GLenum cap) {
5727 if (SetCapabilityState(cap, true)) {
5728 glEnable(cap);
5732 void GLES2DecoderImpl::DoDepthRangef(GLclampf znear, GLclampf zfar) {
5733 state_.z_near = std::min(1.0f, std::max(0.0f, znear));
5734 state_.z_far = std::min(1.0f, std::max(0.0f, zfar));
5735 glDepthRange(znear, zfar);
5738 void GLES2DecoderImpl::DoSampleCoverage(GLclampf value, GLboolean invert) {
5739 state_.sample_coverage_value = std::min(1.0f, std::max(0.0f, value));
5740 state_.sample_coverage_invert = (invert != 0);
5741 glSampleCoverage(state_.sample_coverage_value, invert);
5744 // Assumes framebuffer is complete.
5745 void GLES2DecoderImpl::ClearUnclearedAttachments(
5746 GLenum target, Framebuffer* framebuffer) {
5747 if (target == GL_READ_FRAMEBUFFER_EXT) {
5748 // bind this to the DRAW point, clear then bind back to READ
5749 // TODO(gman): I don't think there is any guarantee that an FBO that
5750 // is complete on the READ attachment will be complete as a DRAW
5751 // attachment.
5752 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
5753 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, framebuffer->service_id());
5755 GLbitfield clear_bits = 0;
5756 if (framebuffer->HasUnclearedColorAttachments()) {
5757 // We should always use alpha == 0 here, because 1) some draw buffers may
5758 // have alpha and some may not; 2) we won't have the same situation as the
5759 // back buffer where alpha channel exists but is not requested.
5760 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
5761 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5762 clear_bits |= GL_COLOR_BUFFER_BIT;
5763 if (feature_info_->feature_flags().ext_draw_buffers)
5764 framebuffer->PrepareDrawBuffersForClear();
5767 if (framebuffer->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT) ||
5768 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5769 glClearStencil(0);
5770 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
5771 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
5772 clear_bits |= GL_STENCIL_BUFFER_BIT;
5775 if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
5776 framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
5777 glClearDepth(1.0f);
5778 state_.SetDeviceDepthMask(GL_TRUE);
5779 clear_bits |= GL_DEPTH_BUFFER_BIT;
5782 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
5783 glClear(clear_bits);
5785 if ((clear_bits & GL_COLOR_BUFFER_BIT) != 0 &&
5786 feature_info_->feature_flags().ext_draw_buffers)
5787 framebuffer->RestoreDrawBuffersAfterClear();
5789 framebuffer_manager()->MarkAttachmentsAsCleared(
5790 framebuffer, renderbuffer_manager(), texture_manager());
5792 RestoreClearState();
5794 if (target == GL_READ_FRAMEBUFFER_EXT) {
5795 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, framebuffer->service_id());
5796 Framebuffer* draw_framebuffer =
5797 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
5798 GLuint service_id = draw_framebuffer ? draw_framebuffer->service_id() :
5799 GetBackbufferServiceId();
5800 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, service_id);
5804 void GLES2DecoderImpl::RestoreClearState() {
5805 framebuffer_state_.clear_state_dirty = true;
5806 glClearColor(
5807 state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
5808 state_.color_clear_alpha);
5809 glClearStencil(state_.stencil_clear);
5810 glClearDepth(state_.depth_clear);
5811 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
5812 state_.enable_flags.scissor_test);
5813 glScissor(state_.scissor_x, state_.scissor_y, state_.scissor_width,
5814 state_.scissor_height);
5817 GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
5818 Framebuffer* framebuffer =
5819 GetFramebufferInfoForTarget(target);
5820 if (!framebuffer) {
5821 return GL_FRAMEBUFFER_COMPLETE;
5823 GLenum completeness = framebuffer->IsPossiblyComplete();
5824 if (completeness != GL_FRAMEBUFFER_COMPLETE) {
5825 return completeness;
5827 return framebuffer->GetStatus(texture_manager(), target);
5830 void GLES2DecoderImpl::DoFramebufferTexture2D(
5831 GLenum target, GLenum attachment, GLenum textarget,
5832 GLuint client_texture_id, GLint level) {
5833 DoFramebufferTexture2DCommon(
5834 "glFramebufferTexture2D", target, attachment,
5835 textarget, client_texture_id, level, 0);
5838 void GLES2DecoderImpl::DoFramebufferTexture2DMultisample(
5839 GLenum target, GLenum attachment, GLenum textarget,
5840 GLuint client_texture_id, GLint level, GLsizei samples) {
5841 DoFramebufferTexture2DCommon(
5842 "glFramebufferTexture2DMultisample", target, attachment,
5843 textarget, client_texture_id, level, samples);
5846 void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
5847 const char* name, GLenum target, GLenum attachment, GLenum textarget,
5848 GLuint client_texture_id, GLint level, GLsizei samples) {
5849 if (samples > renderbuffer_manager()->max_samples()) {
5850 LOCAL_SET_GL_ERROR(
5851 GL_INVALID_VALUE,
5852 "glFramebufferTexture2DMultisample", "samples too large");
5853 return;
5855 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5856 if (!framebuffer) {
5857 LOCAL_SET_GL_ERROR(
5858 GL_INVALID_OPERATION,
5859 name, "no framebuffer bound.");
5860 return;
5862 GLuint service_id = 0;
5863 TextureRef* texture_ref = NULL;
5864 if (client_texture_id) {
5865 texture_ref = GetTexture(client_texture_id);
5866 if (!texture_ref) {
5867 LOCAL_SET_GL_ERROR(
5868 GL_INVALID_OPERATION,
5869 name, "unknown texture_ref");
5870 return;
5872 service_id = texture_ref->service_id();
5875 if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
5876 LOCAL_SET_GL_ERROR(
5877 GL_INVALID_VALUE,
5878 name, "level out of range");
5879 return;
5882 if (texture_ref)
5883 DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
5885 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
5886 if (0 == samples) {
5887 glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
5888 } else {
5889 if (features().use_img_for_multisampled_render_to_texture) {
5890 glFramebufferTexture2DMultisampleIMG(target, attachment, textarget,
5891 service_id, level, samples);
5892 } else {
5893 glFramebufferTexture2DMultisampleEXT(target, attachment, textarget,
5894 service_id, level, samples);
5897 GLenum error = LOCAL_PEEK_GL_ERROR(name);
5898 if (error == GL_NO_ERROR) {
5899 framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
5900 samples);
5902 if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
5903 framebuffer_state_.clear_state_dirty = true;
5906 if (texture_ref)
5907 DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
5909 OnFboChanged();
5912 void GLES2DecoderImpl::DoFramebufferTextureLayer(
5913 GLenum target, GLenum attachment, GLuint client_texture_id,
5914 GLint level, GLint layer) {
5915 // TODO(zmo): Unsafe ES3 API, missing states update.
5916 GLuint service_id = 0;
5917 TextureRef* texture_ref = NULL;
5918 if (client_texture_id) {
5919 texture_ref = GetTexture(client_texture_id);
5920 if (!texture_ref) {
5921 LOCAL_SET_GL_ERROR(
5922 GL_INVALID_OPERATION,
5923 "glFramebufferTextureLayer", "unknown texture_ref");
5924 return;
5926 service_id = texture_ref->service_id();
5928 glFramebufferTextureLayer(target, attachment, service_id, level, layer);
5931 void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
5932 GLenum target, GLenum attachment, GLenum pname, GLint* params) {
5933 Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
5934 if (!framebuffer) {
5935 LOCAL_SET_GL_ERROR(
5936 GL_INVALID_OPERATION,
5937 "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
5938 return;
5940 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
5941 const Framebuffer::Attachment* attachment_object =
5942 framebuffer->GetAttachment(attachment);
5943 *params = attachment_object ? attachment_object->object_name() : 0;
5944 } else {
5945 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT &&
5946 features().use_img_for_multisampled_render_to_texture) {
5947 pname = GL_TEXTURE_SAMPLES_IMG;
5949 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
5953 void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
5954 GLenum target, GLenum pname, GLint* params) {
5955 Renderbuffer* renderbuffer =
5956 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
5957 if (!renderbuffer) {
5958 LOCAL_SET_GL_ERROR(
5959 GL_INVALID_OPERATION,
5960 "glGetRenderbufferParameteriv", "no renderbuffer bound");
5961 return;
5964 EnsureRenderbufferBound();
5965 switch (pname) {
5966 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5967 *params = renderbuffer->internal_format();
5968 break;
5969 case GL_RENDERBUFFER_WIDTH:
5970 *params = renderbuffer->width();
5971 break;
5972 case GL_RENDERBUFFER_HEIGHT:
5973 *params = renderbuffer->height();
5974 break;
5975 case GL_RENDERBUFFER_SAMPLES_EXT:
5976 if (features().use_img_for_multisampled_render_to_texture) {
5977 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG,
5978 params);
5979 } else {
5980 glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT,
5981 params);
5983 default:
5984 glGetRenderbufferParameterivEXT(target, pname, params);
5985 break;
5989 void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
5990 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
5991 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5992 GLbitfield mask, GLenum filter) {
5993 DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
5995 if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
5996 return;
5999 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
6000 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
6001 BlitFramebufferHelper(
6002 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6003 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
6004 state_.enable_flags.scissor_test);
6007 void GLES2DecoderImpl::EnsureRenderbufferBound() {
6008 if (!state_.bound_renderbuffer_valid) {
6009 state_.bound_renderbuffer_valid = true;
6010 glBindRenderbufferEXT(GL_RENDERBUFFER,
6011 state_.bound_renderbuffer.get()
6012 ? state_.bound_renderbuffer->service_id()
6013 : 0);
6017 void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
6018 const FeatureInfo* feature_info,
6019 GLenum target,
6020 GLsizei samples,
6021 GLenum internal_format,
6022 GLsizei width,
6023 GLsizei height) {
6024 // TODO(sievers): This could be resolved at the GL binding level, but the
6025 // binding process is currently a bit too 'brute force'.
6026 if (feature_info->gl_version_info().is_angle) {
6027 glRenderbufferStorageMultisampleANGLE(
6028 target, samples, internal_format, width, height);
6029 } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
6030 glRenderbufferStorageMultisample(
6031 target, samples, internal_format, width, height);
6032 } else {
6033 glRenderbufferStorageMultisampleEXT(
6034 target, samples, internal_format, width, height);
6038 void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
6039 GLint srcY0,
6040 GLint srcX1,
6041 GLint srcY1,
6042 GLint dstX0,
6043 GLint dstY0,
6044 GLint dstX1,
6045 GLint dstY1,
6046 GLbitfield mask,
6047 GLenum filter) {
6048 // TODO(sievers): This could be resolved at the GL binding level, but the
6049 // binding process is currently a bit too 'brute force'.
6050 if (feature_info_->gl_version_info().is_angle) {
6051 glBlitFramebufferANGLE(
6052 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6053 } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
6054 glBlitFramebuffer(
6055 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6056 } else {
6057 glBlitFramebufferEXT(
6058 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6062 bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
6063 GLsizei samples,
6064 GLenum internalformat,
6065 GLsizei width,
6066 GLsizei height) {
6067 if (samples > renderbuffer_manager()->max_samples()) {
6068 LOCAL_SET_GL_ERROR(
6069 GL_INVALID_VALUE,
6070 "glRenderbufferStorageMultisample", "samples too large");
6071 return false;
6074 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6075 height > renderbuffer_manager()->max_renderbuffer_size()) {
6076 LOCAL_SET_GL_ERROR(
6077 GL_INVALID_VALUE,
6078 "glRenderbufferStorageMultisample", "dimensions too large");
6079 return false;
6082 uint32 estimated_size = 0;
6083 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6084 width, height, samples, internalformat, &estimated_size)) {
6085 LOCAL_SET_GL_ERROR(
6086 GL_OUT_OF_MEMORY,
6087 "glRenderbufferStorageMultisample", "dimensions too large");
6088 return false;
6091 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6092 LOCAL_SET_GL_ERROR(
6093 GL_OUT_OF_MEMORY,
6094 "glRenderbufferStorageMultisample", "out of memory");
6095 return false;
6098 return true;
6101 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
6102 GLenum target, GLsizei samples, GLenum internalformat,
6103 GLsizei width, GLsizei height) {
6104 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6105 if (!renderbuffer) {
6106 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
6107 "glRenderbufferStorageMultisampleCHROMIUM",
6108 "no renderbuffer bound");
6109 return;
6112 if (!ValidateRenderbufferStorageMultisample(
6113 samples, internalformat, width, height)) {
6114 return;
6117 EnsureRenderbufferBound();
6118 GLenum impl_format =
6119 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6120 internalformat);
6121 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
6122 "glRenderbufferStorageMultisampleCHROMIUM");
6123 RenderbufferStorageMultisampleHelper(
6124 feature_info_.get(), target, samples, impl_format, width, height);
6125 GLenum error =
6126 LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
6127 if (error == GL_NO_ERROR) {
6128 if (workarounds().validate_multisample_buffer_allocation) {
6129 if (!VerifyMultisampleRenderbufferIntegrity(
6130 renderbuffer->service_id(), impl_format)) {
6131 LOCAL_SET_GL_ERROR(
6132 GL_OUT_OF_MEMORY,
6133 "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
6134 return;
6138 // TODO(gman): If renderbuffers tracked which framebuffers they were
6139 // attached to we could just mark those framebuffers as not complete.
6140 framebuffer_manager()->IncFramebufferStateChangeCount();
6141 renderbuffer_manager()->SetInfo(
6142 renderbuffer, samples, internalformat, width, height);
6146 // This is the handler for multisampled_render_to_texture extensions.
6147 void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
6148 GLenum target, GLsizei samples, GLenum internalformat,
6149 GLsizei width, GLsizei height) {
6150 Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6151 if (!renderbuffer) {
6152 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
6153 "glRenderbufferStorageMultisampleEXT",
6154 "no renderbuffer bound");
6155 return;
6158 if (!ValidateRenderbufferStorageMultisample(
6159 samples, internalformat, width, height)) {
6160 return;
6163 EnsureRenderbufferBound();
6164 GLenum impl_format =
6165 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6166 internalformat);
6167 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
6168 if (features().use_img_for_multisampled_render_to_texture) {
6169 glRenderbufferStorageMultisampleIMG(
6170 target, samples, impl_format, width, height);
6171 } else {
6172 glRenderbufferStorageMultisampleEXT(
6173 target, samples, impl_format, width, height);
6175 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
6176 if (error == GL_NO_ERROR) {
6177 // TODO(gman): If renderbuffers tracked which framebuffers they were
6178 // attached to we could just mark those framebuffers as not complete.
6179 framebuffer_manager()->IncFramebufferStateChangeCount();
6180 renderbuffer_manager()->SetInfo(
6181 renderbuffer, samples, internalformat, width, height);
6185 // This function validates the allocation of a multisampled renderbuffer
6186 // by clearing it to a key color, blitting the contents to a texture, and
6187 // reading back the color to ensure it matches the key.
6188 bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
6189 GLuint renderbuffer, GLenum format) {
6191 // Only validate color buffers.
6192 // These formats have been selected because they are very common or are known
6193 // to be used by the WebGL backbuffer. If problems are observed with other
6194 // color formats they can be added here.
6195 switch (format) {
6196 case GL_RGB:
6197 case GL_RGB8:
6198 case GL_RGBA:
6199 case GL_RGBA8:
6200 break;
6201 default:
6202 return true;
6205 GLint draw_framebuffer, read_framebuffer;
6207 // Cache framebuffer and texture bindings.
6208 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
6209 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
6211 if (!validation_texture_) {
6212 GLint bound_texture;
6213 glGetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
6215 // Create additional resources needed for the verification.
6216 glGenTextures(1, &validation_texture_);
6217 glGenFramebuffersEXT(1, &validation_fbo_multisample_);
6218 glGenFramebuffersEXT(1, &validation_fbo_);
6220 // Texture only needs to be 1x1.
6221 glBindTexture(GL_TEXTURE_2D, validation_texture_);
6222 // TODO(erikchen): When Chrome on Mac is linked against an OSX 10.9+ SDK, a
6223 // multisample will fail if the color format of the source and destination
6224 // do not match. Here, we assume that the source is GL_RGBA, and make the
6225 // destination GL_RGBA. http://crbug.com/484203
6226 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
6227 GL_UNSIGNED_BYTE, NULL);
6229 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6230 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6231 GL_TEXTURE_2D, validation_texture_, 0);
6233 glBindTexture(GL_TEXTURE_2D, bound_texture);
6236 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6237 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6238 GL_RENDERBUFFER, renderbuffer);
6240 // Cache current state and reset it to the values we require.
6241 GLboolean scissor_enabled = false;
6242 glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
6243 if (scissor_enabled)
6244 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
6246 GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
6247 glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
6248 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6250 GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
6251 glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
6252 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
6254 // Clear the buffer to the desired key color.
6255 glClear(GL_COLOR_BUFFER_BIT);
6257 // Blit from the multisample buffer to a standard texture.
6258 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
6259 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
6261 BlitFramebufferHelper(
6262 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
6264 // Read a pixel from the buffer.
6265 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
6267 unsigned char pixel[3] = {0, 0, 0};
6268 glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel);
6270 // Detach the renderbuffer.
6271 glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_multisample_);
6272 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6273 GL_RENDERBUFFER, 0);
6275 // Restore cached state.
6276 if (scissor_enabled)
6277 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
6279 state_.SetDeviceColorMask(
6280 color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
6281 glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
6282 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
6283 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
6285 // Return true if the pixel matched the desired key color.
6286 return (pixel[0] == 0xFF &&
6287 pixel[1] == 0x00 &&
6288 pixel[2] == 0xFF);
6291 void GLES2DecoderImpl::DoRenderbufferStorage(
6292 GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
6293 Renderbuffer* renderbuffer =
6294 GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
6295 if (!renderbuffer) {
6296 LOCAL_SET_GL_ERROR(
6297 GL_INVALID_OPERATION,
6298 "glRenderbufferStorage", "no renderbuffer bound");
6299 return;
6302 if (width > renderbuffer_manager()->max_renderbuffer_size() ||
6303 height > renderbuffer_manager()->max_renderbuffer_size()) {
6304 LOCAL_SET_GL_ERROR(
6305 GL_INVALID_VALUE, "glRenderbufferStorage", "dimensions too large");
6306 return;
6309 uint32 estimated_size = 0;
6310 if (!renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
6311 width, height, 1, internalformat, &estimated_size)) {
6312 LOCAL_SET_GL_ERROR(
6313 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "dimensions too large");
6314 return;
6317 if (!EnsureGPUMemoryAvailable(estimated_size)) {
6318 LOCAL_SET_GL_ERROR(
6319 GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory");
6320 return;
6323 EnsureRenderbufferBound();
6324 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorage");
6325 glRenderbufferStorageEXT(
6326 target,
6327 renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
6328 internalformat),
6329 width,
6330 height);
6331 GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorage");
6332 if (error == GL_NO_ERROR) {
6333 // TODO(gman): If tetxures tracked which framebuffers they were attached to
6334 // we could just mark those framebuffers as not complete.
6335 framebuffer_manager()->IncFramebufferStateChangeCount();
6336 renderbuffer_manager()->SetInfo(
6337 renderbuffer, 1, internalformat, width, height);
6341 void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
6342 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoLinkProgram");
6343 SCOPED_UMA_HISTOGRAM_TIMER("GPU.DoLinkProgramTime");
6344 Program* program = GetProgramInfoNotShader(
6345 program_id, "glLinkProgram");
6346 if (!program) {
6347 return;
6350 LogClientServiceForInfo(program, program_id, "glLinkProgram");
6351 if (program->Link(shader_manager(),
6352 workarounds().count_all_in_varyings_packing ?
6353 Program::kCountAll : Program::kCountOnlyStaticallyUsed,
6354 shader_cache_callback_)) {
6355 if (program == state_.current_program.get()) {
6356 if (workarounds().use_current_program_after_successful_link)
6357 glUseProgram(program->service_id());
6358 if (workarounds().clear_uniforms_before_first_program_use)
6359 program_manager()->ClearUniforms(program);
6363 // LinkProgram can be very slow. Exit command processing to allow for
6364 // context preemption and GPU watchdog checks.
6365 ExitCommandProcessingEarly();
6368 void GLES2DecoderImpl::DoReadBuffer(GLenum src) {
6369 switch (src) {
6370 case GL_NONE:
6371 case GL_BACK:
6372 break;
6373 default:
6375 GLenum upper_limit = static_cast<GLenum>(
6376 group_->max_color_attachments() + GL_COLOR_ATTACHMENT0);
6377 if (src < GL_COLOR_ATTACHMENT0 || src >= upper_limit) {
6378 LOCAL_SET_GL_ERROR(
6379 GL_INVALID_ENUM, "glReadBuffer", "invalid enum for src");
6380 return;
6383 break;
6386 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
6387 if (framebuffer) {
6388 if (src == GL_BACK) {
6389 LOCAL_SET_GL_ERROR(
6390 GL_INVALID_ENUM, "glReadBuffer",
6391 "invalid src for a named framebuffer");
6392 return;
6394 framebuffer->set_read_buffer(src);
6395 } else {
6396 if (src != GL_NONE && src != GL_BACK) {
6397 LOCAL_SET_GL_ERROR(
6398 GL_INVALID_ENUM, "glReadBuffer",
6399 "invalid src for the default framebuffer");
6400 return;
6402 back_buffer_read_buffer_ = src;
6403 if (GetBackbufferServiceId() && src == GL_BACK)
6404 src = GL_COLOR_ATTACHMENT0;
6406 glReadBuffer(src);
6409 void GLES2DecoderImpl::DoSamplerParameterfv(
6410 GLuint sampler, GLenum pname, const GLfloat* params) {
6411 DCHECK(params);
6412 glSamplerParameterf(sampler, pname, params[0]);
6415 void GLES2DecoderImpl::DoSamplerParameteriv(
6416 GLuint sampler, GLenum pname, const GLint* params) {
6417 DCHECK(params);
6418 glSamplerParameteri(sampler, pname, params[0]);
6421 void GLES2DecoderImpl::DoTexParameterf(
6422 GLenum target, GLenum pname, GLfloat param) {
6423 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6424 &state_, target);
6425 if (!texture) {
6426 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
6427 return;
6430 texture_manager()->SetParameterf(
6431 "glTexParameterf", GetErrorState(), texture, pname, param);
6434 void GLES2DecoderImpl::DoTexParameteri(
6435 GLenum target, GLenum pname, GLint param) {
6436 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6437 &state_, target);
6438 if (!texture) {
6439 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
6440 return;
6443 texture_manager()->SetParameteri(
6444 "glTexParameteri", GetErrorState(), texture, pname, param);
6447 void GLES2DecoderImpl::DoTexParameterfv(
6448 GLenum target, GLenum pname, const GLfloat* params) {
6449 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6450 &state_, target);
6451 if (!texture) {
6452 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
6453 return;
6456 texture_manager()->SetParameterf(
6457 "glTexParameterfv", GetErrorState(), texture, pname, *params);
6460 void GLES2DecoderImpl::DoTexParameteriv(
6461 GLenum target, GLenum pname, const GLint* params) {
6462 TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
6463 &state_, target);
6464 if (!texture) {
6465 LOCAL_SET_GL_ERROR(
6466 GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
6467 return;
6470 texture_manager()->SetParameteri(
6471 "glTexParameteriv", GetErrorState(), texture, pname, *params);
6474 bool GLES2DecoderImpl::CheckCurrentValuebuffer(const char* function_name) {
6475 if (!state_.bound_valuebuffer.get()) {
6476 // There is no valuebuffer bound
6477 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6478 "no valuebuffer in use");
6479 return false;
6481 return true;
6484 bool GLES2DecoderImpl::CheckCurrentValuebufferForSubscription(
6485 GLenum subscription,
6486 const char* function_name) {
6487 if (!CheckCurrentValuebuffer(function_name)) {
6488 return false;
6490 if (!state_.bound_valuebuffer.get()->IsSubscribed(subscription)) {
6491 // The valuebuffer is not subscribed to the target
6492 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6493 "valuebuffer is not subscribed");
6494 return false;
6496 return true;
6499 bool GLES2DecoderImpl::CheckSubscriptionTarget(GLint location,
6500 GLenum subscription,
6501 const char* function_name) {
6502 if (!CheckCurrentProgramForUniform(location, function_name)) {
6503 return false;
6505 GLint real_location = -1;
6506 GLint array_index = -1;
6507 const Program::UniformInfo* info =
6508 state_.current_program->GetUniformInfoByFakeLocation(
6509 location, &real_location, &array_index);
6510 if (!info) {
6511 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "unknown location");
6512 return false;
6514 if ((ValuebufferManager::ApiTypeForSubscriptionTarget(subscription) &
6515 info->accepts_api_type) == 0) {
6516 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6517 "wrong type for subscription");
6518 return false;
6520 return true;
6523 bool GLES2DecoderImpl::CheckCurrentProgram(const char* function_name) {
6524 if (!state_.current_program.get()) {
6525 // The program does not exist.
6526 LOCAL_SET_GL_ERROR(
6527 GL_INVALID_OPERATION, function_name, "no program in use");
6528 return false;
6530 if (!state_.current_program->InUse()) {
6531 LOCAL_SET_GL_ERROR(
6532 GL_INVALID_OPERATION, function_name, "program not linked");
6533 return false;
6535 return true;
6538 bool GLES2DecoderImpl::CheckCurrentProgramForUniform(
6539 GLint location, const char* function_name) {
6540 if (!CheckCurrentProgram(function_name)) {
6541 return false;
6543 return location != -1;
6546 bool GLES2DecoderImpl::CheckDrawingFeedbackLoops() {
6547 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
6548 if (!framebuffer)
6549 return false;
6550 const Framebuffer::Attachment* attachment =
6551 framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
6552 if (!attachment)
6553 return false;
6555 DCHECK(state_.current_program.get());
6556 const Program::SamplerIndices& sampler_indices =
6557 state_.current_program->sampler_indices();
6558 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6559 const Program::UniformInfo* uniform_info =
6560 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6561 DCHECK(uniform_info);
6562 if (uniform_info->type != GL_SAMPLER_2D)
6563 continue;
6564 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6565 GLuint texture_unit_index = uniform_info->texture_units[jj];
6566 if (texture_unit_index >= state_.texture_units.size())
6567 continue;
6568 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6569 TextureRef* texture_ref =
6570 texture_unit.GetInfoForSamplerType(GL_SAMPLER_2D).get();
6571 if (attachment->IsTexture(texture_ref))
6572 return true;
6575 return false;
6578 bool GLES2DecoderImpl::CheckUniformForApiType(
6579 const Program::UniformInfo* info,
6580 const char* function_name,
6581 Program::UniformApiType api_type) {
6582 DCHECK(info);
6583 if ((api_type & info->accepts_api_type) == 0) {
6584 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
6585 "wrong uniform function for type");
6586 return false;
6588 return true;
6591 bool GLES2DecoderImpl::PrepForSetUniformByLocation(
6592 GLint fake_location,
6593 const char* function_name,
6594 Program::UniformApiType api_type,
6595 GLint* real_location,
6596 GLenum* type,
6597 GLsizei* count) {
6598 DCHECK(type);
6599 DCHECK(count);
6600 DCHECK(real_location);
6602 if (!CheckCurrentProgramForUniform(fake_location, function_name)) {
6603 return false;
6605 GLint array_index = -1;
6606 const Program::UniformInfo* info =
6607 state_.current_program->GetUniformInfoByFakeLocation(
6608 fake_location, real_location, &array_index);
6609 if (!info) {
6610 LOCAL_SET_GL_ERROR(
6611 GL_INVALID_OPERATION, function_name, "unknown location");
6612 return false;
6614 if (!CheckUniformForApiType(info, function_name, api_type)) {
6615 return false;
6617 if (*count > 1 && !info->is_array) {
6618 LOCAL_SET_GL_ERROR(
6619 GL_INVALID_OPERATION, function_name, "count > 1 for non-array");
6620 return false;
6622 *count = std::min(info->size - array_index, *count);
6623 if (*count <= 0) {
6624 return false;
6626 *type = info->type;
6627 return true;
6630 void GLES2DecoderImpl::DoUniform1i(GLint fake_location, GLint v0) {
6631 GLenum type = 0;
6632 GLsizei count = 1;
6633 GLint real_location = -1;
6634 if (!PrepForSetUniformByLocation(fake_location,
6635 "glUniform1i",
6636 Program::kUniform1i,
6637 &real_location,
6638 &type,
6639 &count)) {
6640 return;
6642 if (!state_.current_program->SetSamplers(
6643 state_.texture_units.size(), fake_location, 1, &v0)) {
6644 LOCAL_SET_GL_ERROR(
6645 GL_INVALID_VALUE, "glUniform1i", "texture unit out of range");
6646 return;
6648 glUniform1i(real_location, v0);
6651 void GLES2DecoderImpl::DoUniform1iv(
6652 GLint fake_location, GLsizei count, const GLint *value) {
6653 GLenum type = 0;
6654 GLint real_location = -1;
6655 if (!PrepForSetUniformByLocation(fake_location,
6656 "glUniform1iv",
6657 Program::kUniform1i,
6658 &real_location,
6659 &type,
6660 &count)) {
6661 return;
6663 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_2D_RECT_ARB ||
6664 type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES) {
6665 if (!state_.current_program->SetSamplers(
6666 state_.texture_units.size(), fake_location, count, value)) {
6667 LOCAL_SET_GL_ERROR(
6668 GL_INVALID_VALUE, "glUniform1iv", "texture unit out of range");
6669 return;
6672 glUniform1iv(real_location, count, value);
6675 void GLES2DecoderImpl::DoUniform1fv(
6676 GLint fake_location, GLsizei count, const GLfloat* value) {
6677 GLenum type = 0;
6678 GLint real_location = -1;
6679 if (!PrepForSetUniformByLocation(fake_location,
6680 "glUniform1fv",
6681 Program::kUniform1f,
6682 &real_location,
6683 &type,
6684 &count)) {
6685 return;
6687 if (type == GL_BOOL) {
6688 scoped_ptr<GLint[]> temp(new GLint[count]);
6689 for (GLsizei ii = 0; ii < count; ++ii) {
6690 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6692 DoUniform1iv(real_location, count, temp.get());
6693 } else {
6694 glUniform1fv(real_location, count, value);
6698 void GLES2DecoderImpl::DoUniform2fv(
6699 GLint fake_location, GLsizei count, const GLfloat* value) {
6700 GLenum type = 0;
6701 GLint real_location = -1;
6702 if (!PrepForSetUniformByLocation(fake_location,
6703 "glUniform2fv",
6704 Program::kUniform2f,
6705 &real_location,
6706 &type,
6707 &count)) {
6708 return;
6710 if (type == GL_BOOL_VEC2) {
6711 GLsizei num_values = count * 2;
6712 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6713 for (GLsizei ii = 0; ii < num_values; ++ii) {
6714 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6716 glUniform2iv(real_location, count, temp.get());
6717 } else {
6718 glUniform2fv(real_location, count, value);
6722 void GLES2DecoderImpl::DoUniform3fv(
6723 GLint fake_location, GLsizei count, const GLfloat* value) {
6724 GLenum type = 0;
6725 GLint real_location = -1;
6726 if (!PrepForSetUniformByLocation(fake_location,
6727 "glUniform3fv",
6728 Program::kUniform3f,
6729 &real_location,
6730 &type,
6731 &count)) {
6732 return;
6734 if (type == GL_BOOL_VEC3) {
6735 GLsizei num_values = count * 3;
6736 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6737 for (GLsizei ii = 0; ii < num_values; ++ii) {
6738 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6740 glUniform3iv(real_location, count, temp.get());
6741 } else {
6742 glUniform3fv(real_location, count, value);
6746 void GLES2DecoderImpl::DoUniform4fv(
6747 GLint fake_location, GLsizei count, const GLfloat* value) {
6748 GLenum type = 0;
6749 GLint real_location = -1;
6750 if (!PrepForSetUniformByLocation(fake_location,
6751 "glUniform4fv",
6752 Program::kUniform4f,
6753 &real_location,
6754 &type,
6755 &count)) {
6756 return;
6758 if (type == GL_BOOL_VEC4) {
6759 GLsizei num_values = count * 4;
6760 scoped_ptr<GLint[]> temp(new GLint[num_values]);
6761 for (GLsizei ii = 0; ii < num_values; ++ii) {
6762 temp[ii] = static_cast<GLint>(value[ii] != 0.0f);
6764 glUniform4iv(real_location, count, temp.get());
6765 } else {
6766 glUniform4fv(real_location, count, value);
6770 void GLES2DecoderImpl::DoUniform2iv(
6771 GLint fake_location, GLsizei count, const GLint* value) {
6772 GLenum type = 0;
6773 GLint real_location = -1;
6774 if (!PrepForSetUniformByLocation(fake_location,
6775 "glUniform2iv",
6776 Program::kUniform2i,
6777 &real_location,
6778 &type,
6779 &count)) {
6780 return;
6782 glUniform2iv(real_location, count, value);
6785 void GLES2DecoderImpl::DoUniform3iv(
6786 GLint fake_location, GLsizei count, const GLint* value) {
6787 GLenum type = 0;
6788 GLint real_location = -1;
6789 if (!PrepForSetUniformByLocation(fake_location,
6790 "glUniform3iv",
6791 Program::kUniform3i,
6792 &real_location,
6793 &type,
6794 &count)) {
6795 return;
6797 glUniform3iv(real_location, count, value);
6800 void GLES2DecoderImpl::DoUniform4iv(
6801 GLint fake_location, GLsizei count, const GLint* value) {
6802 GLenum type = 0;
6803 GLint real_location = -1;
6804 if (!PrepForSetUniformByLocation(fake_location,
6805 "glUniform4iv",
6806 Program::kUniform4i,
6807 &real_location,
6808 &type,
6809 &count)) {
6810 return;
6812 glUniform4iv(real_location, count, value);
6815 void GLES2DecoderImpl::DoUniformMatrix2fv(
6816 GLint fake_location, GLsizei count, GLboolean transpose,
6817 const GLfloat* value) {
6818 GLenum type = 0;
6819 GLint real_location = -1;
6820 if (!PrepForSetUniformByLocation(fake_location,
6821 "glUniformMatrix2fv",
6822 Program::kUniformMatrix2f,
6823 &real_location,
6824 &type,
6825 &count)) {
6826 return;
6828 glUniformMatrix2fv(real_location, count, transpose, value);
6831 void GLES2DecoderImpl::DoUniformMatrix3fv(
6832 GLint fake_location, GLsizei count, GLboolean transpose,
6833 const GLfloat* value) {
6834 GLenum type = 0;
6835 GLint real_location = -1;
6836 if (!PrepForSetUniformByLocation(fake_location,
6837 "glUniformMatrix3fv",
6838 Program::kUniformMatrix3f,
6839 &real_location,
6840 &type,
6841 &count)) {
6842 return;
6844 glUniformMatrix3fv(real_location, count, transpose, value);
6847 void GLES2DecoderImpl::DoUniformMatrix4fv(
6848 GLint fake_location, GLsizei count, GLboolean transpose,
6849 const GLfloat* value) {
6850 GLenum type = 0;
6851 GLint real_location = -1;
6852 if (!PrepForSetUniformByLocation(fake_location,
6853 "glUniformMatrix4fv",
6854 Program::kUniformMatrix4f,
6855 &real_location,
6856 &type,
6857 &count)) {
6858 return;
6860 glUniformMatrix4fv(real_location, count, transpose, value);
6863 void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
6864 GLuint service_id = 0;
6865 Program* program = NULL;
6866 if (program_id) {
6867 program = GetProgramInfoNotShader(program_id, "glUseProgram");
6868 if (!program) {
6869 return;
6871 if (!program->IsValid()) {
6872 // Program was not linked successfully. (ie, glLinkProgram)
6873 LOCAL_SET_GL_ERROR(
6874 GL_INVALID_OPERATION, "glUseProgram", "program not linked");
6875 return;
6877 service_id = program->service_id();
6879 if (state_.current_program.get()) {
6880 program_manager()->UnuseProgram(shader_manager(),
6881 state_.current_program.get());
6883 state_.current_program = program;
6884 LogClientServiceMapping("glUseProgram", program_id, service_id);
6885 glUseProgram(service_id);
6886 if (state_.current_program.get()) {
6887 program_manager()->UseProgram(state_.current_program.get());
6888 if (workarounds().clear_uniforms_before_first_program_use)
6889 program_manager()->ClearUniforms(program);
6893 void GLES2DecoderImpl::RenderWarning(
6894 const char* filename, int line, const std::string& msg) {
6895 logger_.LogMessage(filename, line, std::string("RENDER WARNING: ") + msg);
6898 void GLES2DecoderImpl::PerformanceWarning(
6899 const char* filename, int line, const std::string& msg) {
6900 logger_.LogMessage(filename, line,
6901 std::string("PERFORMANCE WARNING: ") + msg);
6904 void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
6905 Texture* texture, GLenum textarget) {
6906 // Image is already in use if texture is attached to a framebuffer.
6907 if (texture && !texture->IsAttachedToFramebuffer()) {
6908 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6909 if (image) {
6910 ScopedGLErrorSuppressor suppressor(
6911 "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
6912 GetErrorState());
6913 glBindTexture(textarget, texture->service_id());
6914 image->WillUseTexImage();
6915 RestoreCurrentTextureBindings(&state_, textarget);
6920 void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
6921 Texture* texture, GLenum textarget) {
6922 // Image is still in use if texture is attached to a framebuffer.
6923 if (texture && !texture->IsAttachedToFramebuffer()) {
6924 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6925 if (image) {
6926 ScopedGLErrorSuppressor suppressor(
6927 "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
6928 GetErrorState());
6929 glBindTexture(textarget, texture->service_id());
6930 image->DidUseTexImage();
6931 RestoreCurrentTextureBindings(&state_, textarget);
6936 bool GLES2DecoderImpl::PrepareTexturesForRender() {
6937 DCHECK(state_.current_program.get());
6938 if (!texture_manager()->HaveUnrenderableTextures() &&
6939 !texture_manager()->HaveImages()) {
6940 return true;
6943 bool textures_set = false;
6944 const Program::SamplerIndices& sampler_indices =
6945 state_.current_program->sampler_indices();
6946 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
6947 const Program::UniformInfo* uniform_info =
6948 state_.current_program->GetUniformInfo(sampler_indices[ii]);
6949 DCHECK(uniform_info);
6950 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
6951 GLuint texture_unit_index = uniform_info->texture_units[jj];
6952 if (texture_unit_index < state_.texture_units.size()) {
6953 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
6954 TextureRef* texture_ref =
6955 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
6956 GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
6957 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
6958 textures_set = true;
6959 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6960 glBindTexture(
6961 textarget,
6962 texture_manager()->black_texture_id(uniform_info->type));
6963 if (!texture_ref) {
6964 LOCAL_RENDER_WARNING(
6965 std::string("there is no texture bound to the unit ") +
6966 base::IntToString(texture_unit_index));
6967 } else {
6968 LOCAL_RENDER_WARNING(
6969 std::string("texture bound to texture unit ") +
6970 base::IntToString(texture_unit_index) +
6971 " is not renderable. It maybe non-power-of-2 and have"
6972 " incompatible texture filtering.");
6974 continue;
6977 if (textarget != GL_TEXTURE_CUBE_MAP) {
6978 Texture* texture = texture_ref->texture();
6979 gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
6980 if (image && !texture->IsAttachedToFramebuffer()) {
6981 ScopedGLErrorSuppressor suppressor(
6982 "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
6983 textures_set = true;
6984 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
6985 image->WillUseTexImage();
6986 continue;
6990 // else: should this be an error?
6993 return !textures_set;
6996 void GLES2DecoderImpl::RestoreStateForTextures() {
6997 DCHECK(state_.current_program.get());
6998 const Program::SamplerIndices& sampler_indices =
6999 state_.current_program->sampler_indices();
7000 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
7001 const Program::UniformInfo* uniform_info =
7002 state_.current_program->GetUniformInfo(sampler_indices[ii]);
7003 DCHECK(uniform_info);
7004 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
7005 GLuint texture_unit_index = uniform_info->texture_units[jj];
7006 if (texture_unit_index < state_.texture_units.size()) {
7007 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
7008 TextureRef* texture_ref =
7009 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
7010 if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
7011 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
7012 // Get the texture_ref info that was previously bound here.
7013 texture_ref = texture_unit.bind_target == GL_TEXTURE_2D
7014 ? texture_unit.bound_texture_2d.get()
7015 : texture_unit.bound_texture_cube_map.get();
7016 glBindTexture(texture_unit.bind_target,
7017 texture_ref ? texture_ref->service_id() : 0);
7018 continue;
7021 if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
7022 Texture* texture = texture_ref->texture();
7023 gfx::GLImage* image =
7024 texture->GetLevelImage(texture_unit.bind_target, 0);
7025 if (image && !texture->IsAttachedToFramebuffer()) {
7026 ScopedGLErrorSuppressor suppressor(
7027 "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
7028 glActiveTexture(GL_TEXTURE0 + texture_unit_index);
7029 image->DidUseTexImage();
7030 continue;
7036 // Set the active texture back to whatever the user had it as.
7037 glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
7040 bool GLES2DecoderImpl::ClearUnclearedTextures() {
7041 // Only check if there are some uncleared textures.
7042 if (!texture_manager()->HaveUnsafeTextures()) {
7043 return true;
7046 // 1: Check all textures we are about to render with.
7047 if (state_.current_program.get()) {
7048 const Program::SamplerIndices& sampler_indices =
7049 state_.current_program->sampler_indices();
7050 for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
7051 const Program::UniformInfo* uniform_info =
7052 state_.current_program->GetUniformInfo(sampler_indices[ii]);
7053 DCHECK(uniform_info);
7054 for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
7055 GLuint texture_unit_index = uniform_info->texture_units[jj];
7056 if (texture_unit_index < state_.texture_units.size()) {
7057 TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
7058 TextureRef* texture_ref =
7059 texture_unit.GetInfoForSamplerType(uniform_info->type).get();
7060 if (texture_ref && !texture_ref->texture()->SafeToRenderFrom()) {
7061 if (!texture_manager()->ClearRenderableLevels(this, texture_ref)) {
7062 return false;
7069 return true;
7072 bool GLES2DecoderImpl::IsDrawValid(
7073 const char* function_name, GLuint max_vertex_accessed, bool instanced,
7074 GLsizei primcount) {
7075 DCHECK(instanced || primcount == 1);
7077 // NOTE: We specifically do not check current_program->IsValid() because
7078 // it could never be invalid since glUseProgram would have failed. While
7079 // glLinkProgram could later mark the program as invalid the previous
7080 // valid program will still function if it is still the current program.
7081 if (!state_.current_program.get()) {
7082 // The program does not exist.
7083 // But GL says no ERROR.
7084 LOCAL_RENDER_WARNING("Drawing with no current shader program.");
7085 return false;
7088 if (CheckDrawingFeedbackLoops()) {
7089 LOCAL_SET_GL_ERROR(
7090 GL_INVALID_OPERATION, function_name,
7091 "Source and destination textures of the draw are the same.");
7092 return false;
7095 return state_.vertex_attrib_manager
7096 ->ValidateBindings(function_name,
7097 this,
7098 feature_info_.get(),
7099 state_.current_program.get(),
7100 max_vertex_accessed,
7101 instanced,
7102 primcount);
7105 bool GLES2DecoderImpl::SimulateAttrib0(
7106 const char* function_name, GLuint max_vertex_accessed, bool* simulated) {
7107 DCHECK(simulated);
7108 *simulated = false;
7110 if (feature_info_->gl_version_info().BehavesLikeGLES())
7111 return true;
7113 const VertexAttrib* attrib =
7114 state_.vertex_attrib_manager->GetVertexAttrib(0);
7115 // If it's enabled or it's not used then we don't need to do anything.
7116 bool attrib_0_used =
7117 state_.current_program->GetAttribInfoByLocation(0) != NULL;
7118 if (attrib->enabled() && attrib_0_used) {
7119 return true;
7122 // Make a buffer with a single repeated vec4 value enough to
7123 // simulate the constant value that is supposed to be here.
7124 // This is required to emulate GLES2 on GL.
7125 GLuint num_vertices = max_vertex_accessed + 1;
7126 uint32 size_needed = 0;
7128 if (num_vertices == 0 ||
7129 !SafeMultiplyUint32(num_vertices, sizeof(Vec4f), &size_needed) ||
7130 size_needed > 0x7FFFFFFFU) {
7131 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7132 return false;
7135 LOCAL_PERFORMANCE_WARNING(
7136 "Attribute 0 is disabled. This has signficant performance penalty");
7138 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
7139 glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
7141 bool new_buffer = static_cast<GLsizei>(size_needed) > attrib_0_size_;
7142 if (new_buffer) {
7143 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
7144 GLenum error = glGetError();
7145 if (error != GL_NO_ERROR) {
7146 LOCAL_SET_GL_ERROR(
7147 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7148 return false;
7152 const Vec4& value = state_.attrib_values[0];
7153 if (new_buffer ||
7154 (attrib_0_used &&
7155 (!attrib_0_buffer_matches_value_ || !value.Equal(attrib_0_value_)))){
7156 // TODO(zmo): This is not 100% correct because we might lose data when
7157 // casting to float type, but it is a corner case and once we migrate to
7158 // core profiles on desktop GL, it is no longer relevant.
7159 Vec4f fvalue(value);
7160 std::vector<Vec4f> temp(num_vertices, fvalue);
7161 glBufferSubData(GL_ARRAY_BUFFER, 0, size_needed, &temp[0].v[0]);
7162 attrib_0_buffer_matches_value_ = true;
7163 attrib_0_value_ = value;
7164 attrib_0_size_ = size_needed;
7167 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
7169 if (attrib->divisor())
7170 glVertexAttribDivisorANGLE(0, 0);
7172 *simulated = true;
7173 return true;
7176 void GLES2DecoderImpl::RestoreStateForAttrib(
7177 GLuint attrib_index, bool restore_array_binding) {
7178 const VertexAttrib* attrib =
7179 state_.vertex_attrib_manager->GetVertexAttrib(attrib_index);
7180 if (restore_array_binding) {
7181 const void* ptr = reinterpret_cast<const void*>(attrib->offset());
7182 Buffer* buffer = attrib->buffer();
7183 glBindBuffer(GL_ARRAY_BUFFER, buffer ? buffer->service_id() : 0);
7184 glVertexAttribPointer(
7185 attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
7186 attrib->gl_stride(), ptr);
7188 if (attrib->divisor())
7189 glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
7190 glBindBuffer(
7191 GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
7192 state_.bound_array_buffer->service_id() : 0);
7194 // Never touch vertex attribute 0's state (in particular, never
7195 // disable it) when running on desktop GL because it will never be
7196 // re-enabled.
7197 if (attrib_index != 0 ||
7198 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
7199 if (attrib->enabled()) {
7200 glEnableVertexAttribArray(attrib_index);
7201 } else {
7202 glDisableVertexAttribArray(attrib_index);
7207 bool GLES2DecoderImpl::SimulateFixedAttribs(
7208 const char* function_name,
7209 GLuint max_vertex_accessed, bool* simulated, GLsizei primcount) {
7210 DCHECK(simulated);
7211 *simulated = false;
7212 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
7213 return true;
7215 if (!state_.vertex_attrib_manager->HaveFixedAttribs()) {
7216 return true;
7219 LOCAL_PERFORMANCE_WARNING(
7220 "GL_FIXED attributes have a signficant performance penalty");
7222 // NOTE: we could be smart and try to check if a buffer is used
7223 // twice in 2 different attribs, find the overlapping parts and therefore
7224 // duplicate the minimum amount of data but this whole code path is not meant
7225 // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
7226 // tests so we just add to the buffer attrib used.
7228 GLuint elements_needed = 0;
7229 const VertexAttribManager::VertexAttribList& enabled_attribs =
7230 state_.vertex_attrib_manager->GetEnabledVertexAttribs();
7231 for (VertexAttribManager::VertexAttribList::const_iterator it =
7232 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7233 const VertexAttrib* attrib = *it;
7234 const Program::VertexAttrib* attrib_info =
7235 state_.current_program->GetAttribInfoByLocation(attrib->index());
7236 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7237 max_vertex_accessed);
7238 GLuint num_vertices = max_accessed + 1;
7239 if (num_vertices == 0) {
7240 LOCAL_SET_GL_ERROR(
7241 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7242 return false;
7244 if (attrib_info &&
7245 attrib->CanAccess(max_accessed) &&
7246 attrib->type() == GL_FIXED) {
7247 uint32 elements_used = 0;
7248 if (!SafeMultiplyUint32(num_vertices, attrib->size(), &elements_used) ||
7249 !SafeAddUint32(elements_needed, elements_used, &elements_needed)) {
7250 LOCAL_SET_GL_ERROR(
7251 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7252 return false;
7257 const uint32 kSizeOfFloat = sizeof(float); // NOLINT
7258 uint32 size_needed = 0;
7259 if (!SafeMultiplyUint32(elements_needed, kSizeOfFloat, &size_needed) ||
7260 size_needed > 0x7FFFFFFFU) {
7261 LOCAL_SET_GL_ERROR(
7262 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7263 return false;
7266 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
7268 glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
7269 if (static_cast<GLsizei>(size_needed) > fixed_attrib_buffer_size_) {
7270 glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
7271 GLenum error = glGetError();
7272 if (error != GL_NO_ERROR) {
7273 LOCAL_SET_GL_ERROR(
7274 GL_OUT_OF_MEMORY, function_name, "simulating GL_FIXED attribs");
7275 return false;
7279 // Copy the elements and convert to float
7280 GLintptr offset = 0;
7281 for (VertexAttribManager::VertexAttribList::const_iterator it =
7282 enabled_attribs.begin(); it != enabled_attribs.end(); ++it) {
7283 const VertexAttrib* attrib = *it;
7284 const Program::VertexAttrib* attrib_info =
7285 state_.current_program->GetAttribInfoByLocation(attrib->index());
7286 GLuint max_accessed = attrib->MaxVertexAccessed(primcount,
7287 max_vertex_accessed);
7288 GLuint num_vertices = max_accessed + 1;
7289 if (num_vertices == 0) {
7290 LOCAL_SET_GL_ERROR(
7291 GL_OUT_OF_MEMORY, function_name, "Simulating attrib 0");
7292 return false;
7294 if (attrib_info &&
7295 attrib->CanAccess(max_accessed) &&
7296 attrib->type() == GL_FIXED) {
7297 int num_elements = attrib->size() * num_vertices;
7298 const int src_size = num_elements * sizeof(int32);
7299 const int dst_size = num_elements * sizeof(float);
7300 scoped_ptr<float[]> data(new float[num_elements]);
7301 const int32* src = reinterpret_cast<const int32 *>(
7302 attrib->buffer()->GetRange(attrib->offset(), src_size));
7303 const int32* end = src + num_elements;
7304 float* dst = data.get();
7305 while (src != end) {
7306 *dst++ = static_cast<float>(*src++) / 65536.0f;
7308 glBufferSubData(GL_ARRAY_BUFFER, offset, dst_size, data.get());
7309 glVertexAttribPointer(
7310 attrib->index(), attrib->size(), GL_FLOAT, false, 0,
7311 reinterpret_cast<GLvoid*>(offset));
7312 offset += dst_size;
7315 *simulated = true;
7316 return true;
7319 void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
7320 // There's no need to call glVertexAttribPointer because we shadow all the
7321 // settings and passing GL_FIXED to it will not work.
7322 glBindBuffer(
7323 GL_ARRAY_BUFFER,
7324 state_.bound_array_buffer.get() ? state_.bound_array_buffer->service_id()
7325 : 0);
7328 error::Error GLES2DecoderImpl::DoDrawArrays(
7329 const char* function_name,
7330 bool instanced,
7331 GLenum mode,
7332 GLint first,
7333 GLsizei count,
7334 GLsizei primcount) {
7335 error::Error error = WillAccessBoundFramebufferForDraw();
7336 if (error != error::kNoError)
7337 return error;
7338 if (!validators_->draw_mode.IsValid(mode)) {
7339 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7340 return error::kNoError;
7342 if (count < 0) {
7343 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7344 return error::kNoError;
7346 if (primcount < 0) {
7347 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7348 return error::kNoError;
7350 if (!CheckBoundFramebuffersValid(function_name)) {
7351 return error::kNoError;
7353 // We have to check this here because the prototype for glDrawArrays
7354 // is GLint not GLsizei.
7355 if (first < 0) {
7356 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "first < 0");
7357 return error::kNoError;
7360 if (count == 0 || primcount == 0) {
7361 LOCAL_RENDER_WARNING("Render count or primcount is 0.");
7362 return error::kNoError;
7365 GLuint max_vertex_accessed = first + count - 1;
7366 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7367 if (!ClearUnclearedTextures()) {
7368 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7369 return error::kNoError;
7371 bool simulated_attrib_0 = false;
7372 if (!SimulateAttrib0(
7373 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7374 return error::kNoError;
7376 bool simulated_fixed_attribs = false;
7377 if (SimulateFixedAttribs(
7378 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7379 primcount)) {
7380 bool textures_set = !PrepareTexturesForRender();
7381 ApplyDirtyState();
7382 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7383 if (!instanced) {
7384 glDrawArrays(mode, first, count);
7385 } else {
7386 glDrawArraysInstancedANGLE(mode, first, count, primcount);
7388 if (textures_set) {
7389 RestoreStateForTextures();
7391 if (simulated_fixed_attribs) {
7392 RestoreStateForSimulatedFixedAttribs();
7395 if (simulated_attrib_0) {
7396 // We don't have to restore attrib 0 generic data at the end of this
7397 // function even if it is simulated. This is because we will simulate
7398 // it in each draw call, and attrib 0 generic data queries use cached
7399 // values instead of passing down to the underlying driver.
7400 RestoreStateForAttrib(0, false);
7403 return error::kNoError;
7406 error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size,
7407 const void* cmd_data) {
7408 // TODO(zmo): crbug.com/481184
7409 // On Desktop GL with versions lower than 4.3, we need to emulate
7410 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7411 const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data);
7412 return DoDrawArrays("glDrawArrays",
7413 false,
7414 static_cast<GLenum>(c.mode),
7415 static_cast<GLint>(c.first),
7416 static_cast<GLsizei>(c.count),
7420 error::Error GLES2DecoderImpl::HandleDrawArraysInstancedANGLE(
7421 uint32 immediate_data_size,
7422 const void* cmd_data) {
7423 const gles2::cmds::DrawArraysInstancedANGLE& c =
7424 *static_cast<const gles2::cmds::DrawArraysInstancedANGLE*>(cmd_data);
7425 if (!features().angle_instanced_arrays) {
7426 LOCAL_SET_GL_ERROR(
7427 GL_INVALID_OPERATION,
7428 "glDrawArraysInstancedANGLE", "function not available");
7429 return error::kNoError;
7431 return DoDrawArrays("glDrawArraysIntancedANGLE",
7432 true,
7433 static_cast<GLenum>(c.mode),
7434 static_cast<GLint>(c.first),
7435 static_cast<GLsizei>(c.count),
7436 static_cast<GLsizei>(c.primcount));
7439 error::Error GLES2DecoderImpl::DoDrawElements(
7440 const char* function_name,
7441 bool instanced,
7442 GLenum mode,
7443 GLsizei count,
7444 GLenum type,
7445 int32 offset,
7446 GLsizei primcount) {
7447 error::Error error = WillAccessBoundFramebufferForDraw();
7448 if (error != error::kNoError)
7449 return error;
7450 if (!state_.vertex_attrib_manager->element_array_buffer()) {
7451 LOCAL_SET_GL_ERROR(
7452 GL_INVALID_OPERATION, function_name, "No element array buffer bound");
7453 return error::kNoError;
7456 if (count < 0) {
7457 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "count < 0");
7458 return error::kNoError;
7460 if (offset < 0) {
7461 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "offset < 0");
7462 return error::kNoError;
7464 if (!validators_->draw_mode.IsValid(mode)) {
7465 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
7466 return error::kNoError;
7468 if (!validators_->index_type.IsValid(type)) {
7469 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
7470 return error::kNoError;
7472 if (primcount < 0) {
7473 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "primcount < 0");
7474 return error::kNoError;
7477 if (!CheckBoundFramebuffersValid(function_name)) {
7478 return error::kNoError;
7481 if (count == 0 || primcount == 0) {
7482 return error::kNoError;
7485 GLuint max_vertex_accessed;
7486 Buffer* element_array_buffer =
7487 state_.vertex_attrib_manager->element_array_buffer();
7489 if (!element_array_buffer->GetMaxValueForRange(
7490 offset, count, type, &max_vertex_accessed)) {
7491 LOCAL_SET_GL_ERROR(
7492 GL_INVALID_OPERATION, function_name, "range out of bounds for buffer");
7493 return error::kNoError;
7496 if (IsDrawValid(function_name, max_vertex_accessed, instanced, primcount)) {
7497 if (!ClearUnclearedTextures()) {
7498 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "out of memory");
7499 return error::kNoError;
7501 bool simulated_attrib_0 = false;
7502 if (!SimulateAttrib0(
7503 function_name, max_vertex_accessed, &simulated_attrib_0)) {
7504 return error::kNoError;
7506 bool simulated_fixed_attribs = false;
7507 if (SimulateFixedAttribs(
7508 function_name, max_vertex_accessed, &simulated_fixed_attribs,
7509 primcount)) {
7510 bool textures_set = !PrepareTexturesForRender();
7511 ApplyDirtyState();
7512 // TODO(gman): Refactor to hide these details in BufferManager or
7513 // VertexAttribManager.
7514 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
7515 bool used_client_side_array = false;
7516 if (element_array_buffer->IsClientSideArray()) {
7517 used_client_side_array = true;
7518 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
7519 indices = element_array_buffer->GetRange(offset, 0);
7522 ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get());
7523 if (!instanced) {
7524 glDrawElements(mode, count, type, indices);
7525 } else {
7526 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
7529 if (used_client_side_array) {
7530 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
7531 element_array_buffer->service_id());
7534 if (textures_set) {
7535 RestoreStateForTextures();
7537 if (simulated_fixed_attribs) {
7538 RestoreStateForSimulatedFixedAttribs();
7541 if (simulated_attrib_0) {
7542 // We don't have to restore attrib 0 generic data at the end of this
7543 // function even if it is simulated. This is because we will simulate
7544 // it in each draw call, and attrib 0 generic data queries use cached
7545 // values instead of passing down to the underlying driver.
7546 RestoreStateForAttrib(0, false);
7549 return error::kNoError;
7552 error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size,
7553 const void* cmd_data) {
7554 // TODO(zmo): crbug.com/481184
7555 // On Desktop GL with versions lower than 4.3, we need to emulate
7556 // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex().
7557 const gles2::cmds::DrawElements& c =
7558 *static_cast<const gles2::cmds::DrawElements*>(cmd_data);
7559 return DoDrawElements("glDrawElements",
7560 false,
7561 static_cast<GLenum>(c.mode),
7562 static_cast<GLsizei>(c.count),
7563 static_cast<GLenum>(c.type),
7564 static_cast<int32>(c.index_offset),
7568 error::Error GLES2DecoderImpl::HandleDrawElementsInstancedANGLE(
7569 uint32 immediate_data_size,
7570 const void* cmd_data) {
7571 const gles2::cmds::DrawElementsInstancedANGLE& c =
7572 *static_cast<const gles2::cmds::DrawElementsInstancedANGLE*>(cmd_data);
7573 if (!features().angle_instanced_arrays) {
7574 LOCAL_SET_GL_ERROR(
7575 GL_INVALID_OPERATION,
7576 "glDrawElementsInstancedANGLE", "function not available");
7577 return error::kNoError;
7579 return DoDrawElements("glDrawElementsInstancedANGLE",
7580 true,
7581 static_cast<GLenum>(c.mode),
7582 static_cast<GLsizei>(c.count),
7583 static_cast<GLenum>(c.type),
7584 static_cast<int32>(c.index_offset),
7585 static_cast<GLsizei>(c.primcount));
7588 GLuint GLES2DecoderImpl::DoGetMaxValueInBufferCHROMIUM(
7589 GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
7590 GLuint max_vertex_accessed = 0;
7591 Buffer* buffer = GetBuffer(buffer_id);
7592 if (!buffer) {
7593 // TODO(gman): Should this be a GL error or a command buffer error?
7594 LOCAL_SET_GL_ERROR(
7595 GL_INVALID_VALUE, "GetMaxValueInBufferCHROMIUM", "unknown buffer");
7596 } else {
7597 if (!buffer->GetMaxValueForRange(
7598 offset, count, type, &max_vertex_accessed)) {
7599 // TODO(gman): Should this be a GL error or a command buffer error?
7600 LOCAL_SET_GL_ERROR(
7601 GL_INVALID_OPERATION,
7602 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer");
7605 return max_vertex_accessed;
7608 void GLES2DecoderImpl::DoShaderSource(
7609 GLuint client_id, GLsizei count, const char** data, const GLint* length) {
7610 std::string str;
7611 for (GLsizei ii = 0; ii < count; ++ii) {
7612 if (length && length[ii] > 0)
7613 str.append(data[ii], length[ii]);
7614 else
7615 str.append(data[ii]);
7617 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
7618 if (!shader) {
7619 return;
7621 // Note: We don't actually call glShaderSource here. We wait until
7622 // we actually compile the shader.
7623 shader->set_source(str);
7626 void GLES2DecoderImpl::DoTransformFeedbackVaryings(
7627 GLuint client_program_id, GLsizei count, const char* const* varyings,
7628 GLenum buffer_mode) {
7629 Program* program = GetProgramInfoNotShader(
7630 client_program_id, "glTransformFeedbackVaryings");
7631 if (!program) {
7632 return;
7634 program->TransformFeedbackVaryings(count, varyings, buffer_mode);
7635 glTransformFeedbackVaryings(
7636 program->service_id(), count, varyings, buffer_mode);
7639 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
7640 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader");
7641 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader");
7642 if (!shader) {
7643 return;
7646 scoped_refptr<ShaderTranslatorInterface> translator;
7647 if (use_shader_translator_) {
7648 translator = shader->shader_type() == GL_VERTEX_SHADER ?
7649 vertex_translator_ : fragment_translator_;
7652 const Shader::TranslatedShaderSourceType source_type =
7653 feature_info_->feature_flags().angle_translated_shader_source ?
7654 Shader::kANGLE : Shader::kGL;
7655 shader->RequestCompile(translator, source_type);
7658 void GLES2DecoderImpl::DoGetShaderiv(
7659 GLuint shader_id, GLenum pname, GLint* params) {
7660 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderiv");
7661 if (!shader) {
7662 return;
7665 // Compile now for statuses that require it.
7666 switch (pname) {
7667 case GL_COMPILE_STATUS:
7668 case GL_INFO_LOG_LENGTH:
7669 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7670 shader->DoCompile();
7671 break;
7673 default:
7674 break;
7677 switch (pname) {
7678 case GL_SHADER_SOURCE_LENGTH:
7679 *params = shader->source().size();
7680 if (*params)
7681 ++(*params);
7682 return;
7683 case GL_COMPILE_STATUS:
7684 *params = compile_shader_always_succeeds_ ? true : shader->valid();
7685 return;
7686 case GL_INFO_LOG_LENGTH:
7687 *params = shader->log_info().size();
7688 if (*params)
7689 ++(*params);
7690 return;
7691 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7692 *params = shader->translated_source().size();
7693 if (*params)
7694 ++(*params);
7695 return;
7696 default:
7697 break;
7699 glGetShaderiv(shader->service_id(), pname, params);
7702 error::Error GLES2DecoderImpl::HandleGetShaderSource(uint32 immediate_data_size,
7703 const void* cmd_data) {
7704 const gles2::cmds::GetShaderSource& c =
7705 *static_cast<const gles2::cmds::GetShaderSource*>(cmd_data);
7706 GLuint shader_id = c.shader;
7707 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7708 Bucket* bucket = CreateBucket(bucket_id);
7709 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderSource");
7710 if (!shader || shader->source().empty()) {
7711 bucket->SetSize(0);
7712 return error::kNoError;
7714 bucket->SetFromString(shader->source().c_str());
7715 return error::kNoError;
7718 error::Error GLES2DecoderImpl::HandleGetTranslatedShaderSourceANGLE(
7719 uint32 immediate_data_size,
7720 const void* cmd_data) {
7721 const gles2::cmds::GetTranslatedShaderSourceANGLE& c =
7722 *static_cast<const gles2::cmds::GetTranslatedShaderSourceANGLE*>(
7723 cmd_data);
7724 GLuint shader_id = c.shader;
7725 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7726 Bucket* bucket = CreateBucket(bucket_id);
7727 Shader* shader = GetShaderInfoNotProgram(
7728 shader_id, "glGetTranslatedShaderSourceANGLE");
7729 if (!shader) {
7730 bucket->SetSize(0);
7731 return error::kNoError;
7734 // Make sure translator has been utilized in compile.
7735 shader->DoCompile();
7737 bucket->SetFromString(shader->translated_source().c_str());
7738 return error::kNoError;
7741 error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
7742 uint32 immediate_data_size,
7743 const void* cmd_data) {
7744 const gles2::cmds::GetProgramInfoLog& c =
7745 *static_cast<const gles2::cmds::GetProgramInfoLog*>(cmd_data);
7746 GLuint program_id = c.program;
7747 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7748 Bucket* bucket = CreateBucket(bucket_id);
7749 Program* program = GetProgramInfoNotShader(
7750 program_id, "glGetProgramInfoLog");
7751 if (!program || !program->log_info()) {
7752 bucket->SetFromString("");
7753 return error::kNoError;
7755 bucket->SetFromString(program->log_info()->c_str());
7756 return error::kNoError;
7759 error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
7760 uint32 immediate_data_size,
7761 const void* cmd_data) {
7762 const gles2::cmds::GetShaderInfoLog& c =
7763 *static_cast<const gles2::cmds::GetShaderInfoLog*>(cmd_data);
7764 GLuint shader_id = c.shader;
7765 uint32 bucket_id = static_cast<uint32>(c.bucket_id);
7766 Bucket* bucket = CreateBucket(bucket_id);
7767 Shader* shader = GetShaderInfoNotProgram(shader_id, "glGetShaderInfoLog");
7768 if (!shader) {
7769 bucket->SetFromString("");
7770 return error::kNoError;
7773 // Shader must be compiled in order to get the info log.
7774 shader->DoCompile();
7776 bucket->SetFromString(shader->log_info().c_str());
7777 return error::kNoError;
7780 bool GLES2DecoderImpl::DoIsEnabled(GLenum cap) {
7781 return state_.GetEnabled(cap);
7784 bool GLES2DecoderImpl::DoIsBuffer(GLuint client_id) {
7785 const Buffer* buffer = GetBuffer(client_id);
7786 return buffer && buffer->IsValid() && !buffer->IsDeleted();
7789 bool GLES2DecoderImpl::DoIsFramebuffer(GLuint client_id) {
7790 const Framebuffer* framebuffer =
7791 GetFramebuffer(client_id);
7792 return framebuffer && framebuffer->IsValid() && !framebuffer->IsDeleted();
7795 bool GLES2DecoderImpl::DoIsProgram(GLuint client_id) {
7796 // IsProgram is true for programs as soon as they are created, until they are
7797 // deleted and no longer in use.
7798 const Program* program = GetProgram(client_id);
7799 return program != NULL && !program->IsDeleted();
7802 bool GLES2DecoderImpl::DoIsRenderbuffer(GLuint client_id) {
7803 const Renderbuffer* renderbuffer =
7804 GetRenderbuffer(client_id);
7805 return renderbuffer && renderbuffer->IsValid() && !renderbuffer->IsDeleted();
7808 bool GLES2DecoderImpl::DoIsShader(GLuint client_id) {
7809 // IsShader is true for shaders as soon as they are created, until they
7810 // are deleted and not attached to any programs.
7811 const Shader* shader = GetShader(client_id);
7812 return shader != NULL && !shader->IsDeleted();
7815 bool GLES2DecoderImpl::DoIsTexture(GLuint client_id) {
7816 const TextureRef* texture_ref = GetTexture(client_id);
7817 return texture_ref && texture_ref->texture()->IsValid();
7820 void GLES2DecoderImpl::DoAttachShader(
7821 GLuint program_client_id, GLint shader_client_id) {
7822 Program* program = GetProgramInfoNotShader(
7823 program_client_id, "glAttachShader");
7824 if (!program) {
7825 return;
7827 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glAttachShader");
7828 if (!shader) {
7829 return;
7831 if (!program->AttachShader(shader_manager(), shader)) {
7832 LOCAL_SET_GL_ERROR(
7833 GL_INVALID_OPERATION,
7834 "glAttachShader",
7835 "can not attach more than one shader of the same type.");
7836 return;
7838 glAttachShader(program->service_id(), shader->service_id());
7841 void GLES2DecoderImpl::DoDetachShader(
7842 GLuint program_client_id, GLint shader_client_id) {
7843 Program* program = GetProgramInfoNotShader(
7844 program_client_id, "glDetachShader");
7845 if (!program) {
7846 return;
7848 Shader* shader = GetShaderInfoNotProgram(shader_client_id, "glDetachShader");
7849 if (!shader) {
7850 return;
7852 if (!program->DetachShader(shader_manager(), shader)) {
7853 LOCAL_SET_GL_ERROR(
7854 GL_INVALID_OPERATION,
7855 "glDetachShader", "shader not attached to program");
7856 return;
7858 glDetachShader(program->service_id(), shader->service_id());
7861 void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
7862 Program* program = GetProgramInfoNotShader(
7863 program_client_id, "glValidateProgram");
7864 if (!program) {
7865 return;
7867 program->Validate();
7870 void GLES2DecoderImpl::GetVertexAttribHelper(
7871 const VertexAttrib* attrib, GLenum pname, GLint* params) {
7872 switch (pname) {
7873 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
7875 Buffer* buffer = attrib->buffer();
7876 if (buffer && !buffer->IsDeleted()) {
7877 GLuint client_id;
7878 buffer_manager()->GetClientId(buffer->service_id(), &client_id);
7879 *params = client_id;
7881 break;
7883 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
7884 *params = attrib->enabled();
7885 break;
7886 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
7887 *params = attrib->size();
7888 break;
7889 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
7890 *params = attrib->gl_stride();
7891 break;
7892 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7893 *params = attrib->type();
7894 break;
7895 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7896 *params = attrib->normalized();
7897 break;
7898 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
7899 *params = attrib->divisor();
7900 break;
7901 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
7902 *params = attrib->integer();
7903 break;
7904 default:
7905 NOTREACHED();
7906 break;
7910 void GLES2DecoderImpl::DoGetTexParameterfv(
7911 GLenum target, GLenum pname, GLfloat* params) {
7912 InitTextureMaxAnisotropyIfNeeded(target, pname);
7913 glGetTexParameterfv(target, pname, params);
7916 void GLES2DecoderImpl::DoGetTexParameteriv(
7917 GLenum target, GLenum pname, GLint* params) {
7918 InitTextureMaxAnisotropyIfNeeded(target, pname);
7919 glGetTexParameteriv(target, pname, params);
7922 void GLES2DecoderImpl::InitTextureMaxAnisotropyIfNeeded(
7923 GLenum target, GLenum pname) {
7924 if (!workarounds().init_texture_max_anisotropy)
7925 return;
7926 if (pname != GL_TEXTURE_MAX_ANISOTROPY_EXT ||
7927 !validators_->texture_parameter.IsValid(pname)) {
7928 return;
7931 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
7932 &state_, target);
7933 if (!texture_ref) {
7934 LOCAL_SET_GL_ERROR(
7935 GL_INVALID_OPERATION,
7936 "glGetTexParamter{fi}v", "unknown texture for target");
7937 return;
7939 Texture* texture = texture_ref->texture();
7940 texture->InitTextureMaxAnisotropyIfNeeded(target);
7943 template <typename T>
7944 void GLES2DecoderImpl::DoGetVertexAttribImpl(
7945 GLuint index, GLenum pname, T* params) {
7946 VertexAttrib* attrib = state_.vertex_attrib_manager->GetVertexAttrib(index);
7947 if (!attrib) {
7948 LOCAL_SET_GL_ERROR(
7949 GL_INVALID_VALUE, "glGetVertexAttrib", "index out of range");
7950 return;
7952 switch (pname) {
7953 case GL_CURRENT_VERTEX_ATTRIB:
7954 state_.attrib_values[index].GetValues(params);
7955 break;
7956 default: {
7957 GLint value = 0;
7958 GetVertexAttribHelper(attrib, pname, &value);
7959 *params = static_cast<T>(value);
7960 break;
7965 void GLES2DecoderImpl::DoGetVertexAttribfv(
7966 GLuint index, GLenum pname, GLfloat* params) {
7967 DoGetVertexAttribImpl<GLfloat>(index, pname, params);
7970 void GLES2DecoderImpl::DoGetVertexAttribiv(
7971 GLuint index, GLenum pname, GLint* params) {
7972 DoGetVertexAttribImpl<GLint>(index, pname, params);
7975 void GLES2DecoderImpl::DoGetVertexAttribIiv(
7976 GLuint index, GLenum pname, GLint* params) {
7977 DoGetVertexAttribImpl<GLint>(index, pname, params);
7980 void GLES2DecoderImpl::DoGetVertexAttribIuiv(
7981 GLuint index, GLenum pname, GLuint* params) {
7982 DoGetVertexAttribImpl<GLuint>(index, pname, params);
7985 template <typename T>
7986 bool GLES2DecoderImpl::SetVertexAttribValue(
7987 const char* function_name, GLuint index, const T* value) {
7988 if (index >= state_.attrib_values.size()) {
7989 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "index out of range");
7990 return false;
7992 state_.attrib_values[index].SetValues(value);
7993 return true;
7996 void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
7997 GLfloat v[4] = { v0, 0.0f, 0.0f, 1.0f, };
7998 if (SetVertexAttribValue("glVertexAttrib1f", index, v)) {
7999 glVertexAttrib1f(index, v0);
8003 void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
8004 GLfloat v[4] = { v0, v1, 0.0f, 1.0f, };
8005 if (SetVertexAttribValue("glVertexAttrib2f", index, v)) {
8006 glVertexAttrib2f(index, v0, v1);
8010 void GLES2DecoderImpl::DoVertexAttrib3f(
8011 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
8012 GLfloat v[4] = { v0, v1, v2, 1.0f, };
8013 if (SetVertexAttribValue("glVertexAttrib3f", index, v)) {
8014 glVertexAttrib3f(index, v0, v1, v2);
8018 void GLES2DecoderImpl::DoVertexAttrib4f(
8019 GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
8020 GLfloat v[4] = { v0, v1, v2, v3, };
8021 if (SetVertexAttribValue("glVertexAttrib4f", index, v)) {
8022 glVertexAttrib4f(index, v0, v1, v2, v3);
8026 void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
8027 GLfloat t[4] = { v[0], 0.0f, 0.0f, 1.0f, };
8028 if (SetVertexAttribValue("glVertexAttrib1fv", index, t)) {
8029 glVertexAttrib1fv(index, v);
8033 void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
8034 GLfloat t[4] = { v[0], v[1], 0.0f, 1.0f, };
8035 if (SetVertexAttribValue("glVertexAttrib2fv", index, t)) {
8036 glVertexAttrib2fv(index, v);
8040 void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
8041 GLfloat t[4] = { v[0], v[1], v[2], 1.0f, };
8042 if (SetVertexAttribValue("glVertexAttrib3fv", index, t)) {
8043 glVertexAttrib3fv(index, v);
8047 void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
8048 if (SetVertexAttribValue("glVertexAttrib4fv", index, v)) {
8049 glVertexAttrib4fv(index, v);
8053 void GLES2DecoderImpl::DoVertexAttribI4i(
8054 GLuint index, GLint v0, GLint v1, GLint v2, GLint v3) {
8055 GLint v[4] = { v0, v1, v2, v3 };
8056 if (SetVertexAttribValue("glVertexAttribI4i", index, v)) {
8057 glVertexAttribI4i(index, v0, v1, v2, v3);
8061 void GLES2DecoderImpl::DoVertexAttribI4iv(GLuint index, const GLint* v) {
8062 if (SetVertexAttribValue("glVertexAttribI4iv", index, v)) {
8063 glVertexAttribI4iv(index, v);
8067 void GLES2DecoderImpl::DoVertexAttribI4ui(
8068 GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
8069 GLuint v[4] = { v0, v1, v2, v3 };
8070 if (SetVertexAttribValue("glVertexAttribI4ui", index, v)) {
8071 glVertexAttribI4ui(index, v0, v1, v2, v3);
8075 void GLES2DecoderImpl::DoVertexAttribI4uiv(GLuint index, const GLuint* v) {
8076 if (SetVertexAttribValue("glVertexAttribI4uiv", index, v)) {
8077 glVertexAttribI4uiv(index, v);
8081 error::Error GLES2DecoderImpl::HandleVertexAttribIPointer(
8082 uint32 immediate_data_size,
8083 const void* cmd_data) {
8084 if (!unsafe_es3_apis_enabled())
8085 return error::kUnknownCommand;
8086 const gles2::cmds::VertexAttribIPointer& c =
8087 *static_cast<const gles2::cmds::VertexAttribIPointer*>(cmd_data);
8089 if (!state_.bound_array_buffer.get() ||
8090 state_.bound_array_buffer->IsDeleted()) {
8091 if (state_.vertex_attrib_manager.get() ==
8092 state_.default_vertex_attrib_manager.get()) {
8093 LOCAL_SET_GL_ERROR(
8094 GL_INVALID_VALUE, "glVertexAttribIPointer", "no array buffer bound");
8095 return error::kNoError;
8096 } else if (c.offset != 0) {
8097 LOCAL_SET_GL_ERROR(
8098 GL_INVALID_VALUE,
8099 "glVertexAttribIPointer", "client side arrays are not allowed");
8100 return error::kNoError;
8104 GLuint indx = c.indx;
8105 GLint size = c.size;
8106 GLenum type = c.type;
8107 GLsizei stride = c.stride;
8108 GLsizei offset = c.offset;
8109 const void* ptr = reinterpret_cast<const void*>(offset);
8110 if (!validators_->vertex_attrib_i_type.IsValid(type)) {
8111 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type, "type");
8112 return error::kNoError;
8114 if (!validators_->vertex_attrib_size.IsValid(size)) {
8115 LOCAL_SET_GL_ERROR(
8116 GL_INVALID_VALUE, "glVertexAttribIPointer", "size GL_INVALID_VALUE");
8117 return error::kNoError;
8119 if (indx >= group_->max_vertex_attribs()) {
8120 LOCAL_SET_GL_ERROR(
8121 GL_INVALID_VALUE, "glVertexAttribIPointer", "index out of range");
8122 return error::kNoError;
8124 if (stride < 0) {
8125 LOCAL_SET_GL_ERROR(
8126 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride < 0");
8127 return error::kNoError;
8129 if (stride > 255) {
8130 LOCAL_SET_GL_ERROR(
8131 GL_INVALID_VALUE, "glVertexAttribIPointer", "stride > 255");
8132 return error::kNoError;
8134 if (offset < 0) {
8135 LOCAL_SET_GL_ERROR(
8136 GL_INVALID_VALUE, "glVertexAttribIPointer", "offset < 0");
8137 return error::kNoError;
8139 GLsizei component_size =
8140 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
8141 // component_size must be a power of two to use & as optimized modulo.
8142 DCHECK(GLES2Util::IsPOT(component_size));
8143 if (offset & (component_size - 1)) {
8144 LOCAL_SET_GL_ERROR(
8145 GL_INVALID_OPERATION,
8146 "glVertexAttribIPointer", "offset not valid for type");
8147 return error::kNoError;
8149 if (stride & (component_size - 1)) {
8150 LOCAL_SET_GL_ERROR(
8151 GL_INVALID_OPERATION,
8152 "glVertexAttribIPointer", "stride not valid for type");
8153 return error::kNoError;
8155 state_.vertex_attrib_manager
8156 ->SetAttribInfo(indx,
8157 state_.bound_array_buffer.get(),
8158 size,
8159 type,
8160 GL_FALSE,
8161 stride,
8162 stride != 0 ? stride : component_size * size,
8163 offset,
8164 GL_TRUE);
8165 glVertexAttribIPointer(indx, size, type, stride, ptr);
8166 return error::kNoError;
8169 error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
8170 uint32 immediate_data_size,
8171 const void* cmd_data) {
8172 const gles2::cmds::VertexAttribPointer& c =
8173 *static_cast<const gles2::cmds::VertexAttribPointer*>(cmd_data);
8175 if (!state_.bound_array_buffer.get() ||
8176 state_.bound_array_buffer->IsDeleted()) {
8177 if (state_.vertex_attrib_manager.get() ==
8178 state_.default_vertex_attrib_manager.get()) {
8179 LOCAL_SET_GL_ERROR(
8180 GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
8181 return error::kNoError;
8182 } else if (c.offset != 0) {
8183 LOCAL_SET_GL_ERROR(
8184 GL_INVALID_VALUE,
8185 "glVertexAttribPointer", "client side arrays are not allowed");
8186 return error::kNoError;
8190 GLuint indx = c.indx;
8191 GLint size = c.size;
8192 GLenum type = c.type;
8193 GLboolean normalized = static_cast<GLboolean>(c.normalized);
8194 GLsizei stride = c.stride;
8195 GLsizei offset = c.offset;
8196 const void* ptr = reinterpret_cast<const void*>(offset);
8197 if (!validators_->vertex_attrib_type.IsValid(type)) {
8198 LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribPointer", type, "type");
8199 return error::kNoError;
8201 if (!validators_->vertex_attrib_size.IsValid(size)) {
8202 LOCAL_SET_GL_ERROR(
8203 GL_INVALID_VALUE, "glVertexAttribPointer", "size GL_INVALID_VALUE");
8204 return error::kNoError;
8206 if (indx >= group_->max_vertex_attribs()) {
8207 LOCAL_SET_GL_ERROR(
8208 GL_INVALID_VALUE, "glVertexAttribPointer", "index out of range");
8209 return error::kNoError;
8211 if (stride < 0) {
8212 LOCAL_SET_GL_ERROR(
8213 GL_INVALID_VALUE, "glVertexAttribPointer", "stride < 0");
8214 return error::kNoError;
8216 if (stride > 255) {
8217 LOCAL_SET_GL_ERROR(
8218 GL_INVALID_VALUE, "glVertexAttribPointer", "stride > 255");
8219 return error::kNoError;
8221 if (offset < 0) {
8222 LOCAL_SET_GL_ERROR(
8223 GL_INVALID_VALUE, "glVertexAttribPointer", "offset < 0");
8224 return error::kNoError;
8226 GLsizei component_size =
8227 GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
8228 // component_size must be a power of two to use & as optimized modulo.
8229 DCHECK(GLES2Util::IsPOT(component_size));
8230 if (offset & (component_size - 1)) {
8231 LOCAL_SET_GL_ERROR(
8232 GL_INVALID_OPERATION,
8233 "glVertexAttribPointer", "offset not valid for type");
8234 return error::kNoError;
8236 if (stride & (component_size - 1)) {
8237 LOCAL_SET_GL_ERROR(
8238 GL_INVALID_OPERATION,
8239 "glVertexAttribPointer", "stride not valid for type");
8240 return error::kNoError;
8242 state_.vertex_attrib_manager
8243 ->SetAttribInfo(indx,
8244 state_.bound_array_buffer.get(),
8245 size,
8246 type,
8247 normalized,
8248 stride,
8249 stride != 0 ? stride : component_size * size,
8250 offset,
8251 GL_FALSE);
8252 // We support GL_FIXED natively on EGL/GLES2 implementations
8253 if (type != GL_FIXED || feature_info_->gl_version_info().is_es) {
8254 glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
8256 return error::kNoError;
8259 void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width,
8260 GLsizei height) {
8261 state_.viewport_x = x;
8262 state_.viewport_y = y;
8263 state_.viewport_width = std::min(width, viewport_max_width_);
8264 state_.viewport_height = std::min(height, viewport_max_height_);
8265 glViewport(x, y, width, height);
8268 error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
8269 uint32 immediate_data_size,
8270 const void* cmd_data) {
8271 const gles2::cmds::VertexAttribDivisorANGLE& c =
8272 *static_cast<const gles2::cmds::VertexAttribDivisorANGLE*>(cmd_data);
8273 if (!features().angle_instanced_arrays) {
8274 LOCAL_SET_GL_ERROR(
8275 GL_INVALID_OPERATION,
8276 "glVertexAttribDivisorANGLE", "function not available");
8277 return error::kNoError;
8279 GLuint index = c.index;
8280 GLuint divisor = c.divisor;
8281 if (index >= group_->max_vertex_attribs()) {
8282 LOCAL_SET_GL_ERROR(
8283 GL_INVALID_VALUE,
8284 "glVertexAttribDivisorANGLE", "index out of range");
8285 return error::kNoError;
8288 state_.vertex_attrib_manager->SetDivisor(
8289 index,
8290 divisor);
8291 glVertexAttribDivisorANGLE(index, divisor);
8292 return error::kNoError;
8295 template <typename pixel_data_type>
8296 static void WriteAlphaData(
8297 void* pixels, uint32 row_count, uint32 channel_count,
8298 uint32 alpha_channel_index, uint32 unpadded_row_size,
8299 uint32 padded_row_size, pixel_data_type alpha_value) {
8300 DCHECK_GT(channel_count, 0U);
8301 DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
8302 uint32 unpadded_row_size_in_elements =
8303 unpadded_row_size / sizeof(pixel_data_type);
8304 DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
8305 uint32 padded_row_size_in_elements =
8306 padded_row_size / sizeof(pixel_data_type);
8307 pixel_data_type* dst =
8308 static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
8309 for (uint32 yy = 0; yy < row_count; ++yy) {
8310 pixel_data_type* end = dst + unpadded_row_size_in_elements;
8311 for (pixel_data_type* d = dst; d < end; d += channel_count) {
8312 *d = alpha_value;
8314 dst += padded_row_size_in_elements;
8318 void GLES2DecoderImpl::FinishReadPixels(
8319 const cmds::ReadPixels& c,
8320 GLuint buffer) {
8321 TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
8322 GLsizei width = c.width;
8323 GLsizei height = c.height;
8324 GLenum format = c.format;
8325 GLenum type = c.type;
8326 typedef cmds::ReadPixels::Result Result;
8327 uint32 pixels_size;
8328 Result* result = NULL;
8329 if (c.result_shm_id != 0) {
8330 result = GetSharedMemoryAs<Result*>(
8331 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8332 if (!result) {
8333 if (buffer != 0) {
8334 glDeleteBuffersARB(1, &buffer);
8336 return;
8339 GLES2Util::ComputeImageDataSizes(
8340 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8341 NULL, NULL);
8342 void* pixels = GetSharedMemoryAs<void*>(
8343 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8344 if (!pixels) {
8345 if (buffer != 0) {
8346 glDeleteBuffersARB(1, &buffer);
8348 return;
8351 if (buffer != 0) {
8352 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8353 void* data;
8354 if (features().map_buffer_range) {
8355 data = glMapBufferRange(
8356 GL_PIXEL_PACK_BUFFER_ARB, 0, pixels_size, GL_MAP_READ_BIT);
8357 } else {
8358 data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
8360 if (!data) {
8361 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glMapBuffer",
8362 "Unable to map memory for readback.");
8363 return;
8365 memcpy(pixels, data, pixels_size);
8366 // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
8367 // have to restore the state.
8368 glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
8369 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8370 glDeleteBuffersARB(1, &buffer);
8373 if (result != NULL) {
8374 *result = true;
8377 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
8378 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
8379 if ((channels_exist & 0x0008) == 0 &&
8380 workarounds().clear_alpha_in_readpixels) {
8381 // Set the alpha to 255 because some drivers are buggy in this regard.
8382 uint32 temp_size;
8384 uint32 unpadded_row_size;
8385 uint32 padded_row_size;
8386 if (!GLES2Util::ComputeImageDataSizes(
8387 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8388 &unpadded_row_size, &padded_row_size)) {
8389 return;
8392 uint32 channel_count = 0;
8393 uint32 alpha_channel = 0;
8394 switch (format) {
8395 case GL_RGBA:
8396 case GL_BGRA_EXT:
8397 channel_count = 4;
8398 alpha_channel = 3;
8399 break;
8400 case GL_ALPHA:
8401 channel_count = 1;
8402 alpha_channel = 0;
8403 break;
8406 if (channel_count > 0) {
8407 switch (type) {
8408 case GL_UNSIGNED_BYTE:
8409 WriteAlphaData<uint8>(
8410 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8411 padded_row_size, 0xFF);
8412 break;
8413 case GL_FLOAT:
8414 WriteAlphaData<float>(
8415 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8416 padded_row_size, 1.0f);
8417 break;
8418 case GL_HALF_FLOAT:
8419 WriteAlphaData<uint16>(
8420 pixels, height, channel_count, alpha_channel, unpadded_row_size,
8421 padded_row_size, 0x3C00);
8422 break;
8428 error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size,
8429 const void* cmd_data) {
8430 const gles2::cmds::ReadPixels& c =
8431 *static_cast<const gles2::cmds::ReadPixels*>(cmd_data);
8432 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
8433 error::Error fbo_error = WillAccessBoundFramebufferForRead();
8434 if (fbo_error != error::kNoError)
8435 return fbo_error;
8436 GLint x = c.x;
8437 GLint y = c.y;
8438 GLsizei width = c.width;
8439 GLsizei height = c.height;
8440 GLenum format = c.format;
8441 GLenum type = c.type;
8442 GLboolean async = static_cast<GLboolean>(c.async);
8443 if (width < 0 || height < 0) {
8444 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
8445 return error::kNoError;
8447 typedef cmds::ReadPixels::Result Result;
8448 uint32 pixels_size;
8449 if (!GLES2Util::ComputeImageDataSizes(
8450 width, height, 1, format, type, state_.pack_alignment, &pixels_size,
8451 NULL, NULL)) {
8452 return error::kOutOfBounds;
8454 void* pixels = GetSharedMemoryAs<void*>(
8455 c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
8456 if (!pixels) {
8457 return error::kOutOfBounds;
8459 Result* result = NULL;
8460 if (c.result_shm_id != 0) {
8461 result = GetSharedMemoryAs<Result*>(
8462 c.result_shm_id, c.result_shm_offset, sizeof(*result));
8463 if (!result) {
8464 return error::kOutOfBounds;
8468 if (!validators_->read_pixel_format.IsValid(format)) {
8469 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
8470 return error::kNoError;
8472 if (!validators_->read_pixel_type.IsValid(type)) {
8473 LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
8474 return error::kNoError;
8477 GLenum src_internal_format = GetBoundReadFrameBufferInternalFormat();
8478 if (src_internal_format == 0) {
8479 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels",
8480 "no valid read buffer source");
8481 return error::kNoError;
8483 std::vector<GLenum> accepted_formats;
8484 std::vector<GLenum> accepted_types;
8485 switch (src_internal_format) {
8486 case GL_RGB10_A2UI:
8487 accepted_formats.push_back(GL_RGBA);
8488 accepted_types.push_back(GL_UNSIGNED_INT_2_10_10_10_REV);
8489 case GL_R8UI:
8490 case GL_R16UI:
8491 case GL_R32UI:
8492 case GL_RG8UI:
8493 case GL_RG16UI:
8494 case GL_RG32UI:
8495 // All the RGB_INTEGER formats are not renderable.
8496 case GL_RGBA8UI:
8497 case GL_RGBA16UI:
8498 case GL_RGBA32UI:
8499 accepted_formats.push_back(GL_RGBA_INTEGER);
8500 accepted_types.push_back(GL_UNSIGNED_INT);
8501 break;
8502 case GL_R8I:
8503 case GL_R16I:
8504 case GL_R32I:
8505 case GL_RG8I:
8506 case GL_RG16I:
8507 case GL_RG32I:
8508 case GL_RGBA8I:
8509 case GL_RGBA16I:
8510 case GL_RGBA32I:
8511 accepted_formats.push_back(GL_RGBA_INTEGER);
8512 accepted_types.push_back(GL_INT);
8513 break;
8514 default:
8515 accepted_formats.push_back(GL_RGBA);
8517 GLenum src_type = GetBoundReadFrameBufferTextureType();
8518 switch (src_type) {
8519 case GL_HALF_FLOAT:
8520 case GL_HALF_FLOAT_OES:
8521 case GL_FLOAT:
8522 case GL_UNSIGNED_INT_10F_11F_11F_REV:
8523 accepted_types.push_back(GL_FLOAT);
8524 break;
8525 default:
8526 accepted_types.push_back(GL_UNSIGNED_BYTE);
8527 break;
8530 break;
8532 if (!IsWebGLContext()) {
8533 accepted_formats.push_back(GL_BGRA_EXT);
8534 accepted_types.push_back(GL_UNSIGNED_BYTE);
8536 DCHECK_EQ(accepted_formats.size(), accepted_types.size());
8537 bool format_type_acceptable = false;
8538 for (size_t ii = 0; ii < accepted_formats.size(); ++ii) {
8539 if (format == accepted_formats[ii] && type == accepted_types[ii]) {
8540 format_type_acceptable = true;
8541 break;
8544 if (!format_type_acceptable) {
8545 // format and type are acceptable enums but not guaranteed to be supported
8546 // for this framebuffer. Have to ask gl if they are valid.
8547 GLint preferred_format = 0;
8548 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
8549 GLint preferred_type = 0;
8550 DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
8551 if (format == static_cast<GLenum>(preferred_format) &&
8552 type == static_cast<GLenum>(preferred_type)) {
8553 format_type_acceptable = true;
8556 if (!format_type_acceptable) {
8557 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glReadPixels",
8558 "format and type incompatible with the current read framebuffer");
8559 return error::kNoError;
8561 if (width == 0 || height == 0) {
8562 return error::kNoError;
8565 // Get the size of the current fbo or backbuffer.
8566 gfx::Size max_size = GetBoundReadFrameBufferSize();
8568 int32 max_x;
8569 int32 max_y;
8570 if (!SafeAddInt32(x, width, &max_x) || !SafeAddInt32(y, height, &max_y)) {
8571 LOCAL_SET_GL_ERROR(
8572 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8573 return error::kNoError;
8576 if (!CheckBoundFramebuffersValid("glReadPixels")) {
8577 return error::kNoError;
8580 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
8582 ScopedResolvedFrameBufferBinder binder(this, false, true);
8584 if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
8585 // The user requested an out of range area. Get the results 1 line
8586 // at a time.
8587 uint32 temp_size;
8588 uint32 unpadded_row_size;
8589 uint32 padded_row_size;
8590 if (!GLES2Util::ComputeImageDataSizes(
8591 width, 2, 1, format, type, state_.pack_alignment, &temp_size,
8592 &unpadded_row_size, &padded_row_size)) {
8593 LOCAL_SET_GL_ERROR(
8594 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8595 return error::kNoError;
8598 GLint dest_x_offset = std::max(-x, 0);
8599 uint32 dest_row_offset;
8600 if (!GLES2Util::ComputeImageDataSizes(
8601 dest_x_offset, 1, 1, format, type, state_.pack_alignment,
8602 &dest_row_offset, NULL, NULL)) {
8603 LOCAL_SET_GL_ERROR(
8604 GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
8605 return error::kNoError;
8608 // Copy each row into the larger dest rect.
8609 int8* dst = static_cast<int8*>(pixels);
8610 GLint read_x = std::max(0, x);
8611 GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
8612 GLint read_width = read_end_x - read_x;
8613 for (GLint yy = 0; yy < height; ++yy) {
8614 GLint ry = y + yy;
8616 // Clear the row.
8617 memset(dst, 0, unpadded_row_size);
8619 // If the row is in range, copy it.
8620 if (ry >= 0 && ry < max_size.height() && read_width > 0) {
8621 glReadPixels(
8622 read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
8624 dst += padded_row_size;
8626 } else {
8627 if (async && features().use_async_readpixels) {
8628 GLuint buffer = 0;
8629 glGenBuffersARB(1, &buffer);
8630 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
8631 // For ANGLE client version 2, GL_STREAM_READ is not available.
8632 const GLenum usage_hint = feature_info_->gl_version_info().is_angle ?
8633 GL_STATIC_DRAW : GL_STREAM_READ;
8634 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, usage_hint);
8635 GLenum error = glGetError();
8636 if (error == GL_NO_ERROR) {
8637 glReadPixels(x, y, width, height, format, type, 0);
8638 pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
8639 new FenceCallback()));
8640 WaitForReadPixels(base::Bind(
8641 &GLES2DecoderImpl::FinishReadPixels,
8642 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
8643 <GLES2DecoderImpl>(this),
8644 c, buffer));
8645 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8646 return error::kNoError;
8647 } else {
8648 // On error, unbind pack buffer and fall through to sync readpixels
8649 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
8650 glDeleteBuffersARB(1, &buffer);
8653 glReadPixels(x, y, width, height, format, type, pixels);
8655 GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
8656 if (error == GL_NO_ERROR) {
8657 if (result != NULL) {
8658 *result = true;
8660 FinishReadPixels(c, 0);
8663 return error::kNoError;
8666 error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size,
8667 const void* cmd_data) {
8668 const gles2::cmds::PixelStorei& c =
8669 *static_cast<const gles2::cmds::PixelStorei*>(cmd_data);
8670 GLenum pname = c.pname;
8671 GLenum param = c.param;
8672 if (!validators_->pixel_store.IsValid(pname)) {
8673 LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname");
8674 return error::kNoError;
8676 switch (pname) {
8677 case GL_PACK_ALIGNMENT:
8678 case GL_UNPACK_ALIGNMENT:
8679 if (!validators_->pixel_store_alignment.IsValid(param)) {
8680 LOCAL_SET_GL_ERROR(
8681 GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
8682 return error::kNoError;
8684 break;
8685 default:
8686 break;
8688 glPixelStorei(pname, param);
8689 switch (pname) {
8690 case GL_PACK_ALIGNMENT:
8691 state_.pack_alignment = param;
8692 break;
8693 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
8694 state_.pack_reverse_row_order = (param != 0);
8695 break;
8696 case GL_UNPACK_ALIGNMENT:
8697 state_.unpack_alignment = param;
8698 break;
8699 default:
8700 // Validation should have prevented us from getting here.
8701 NOTREACHED();
8702 break;
8704 return error::kNoError;
8707 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
8708 uint32 immediate_data_size,
8709 const void* cmd_data) {
8710 const gles2::cmds::PostSubBufferCHROMIUM& c =
8711 *static_cast<const gles2::cmds::PostSubBufferCHROMIUM*>(cmd_data);
8712 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
8714 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
8716 if (!supports_post_sub_buffer_) {
8717 LOCAL_SET_GL_ERROR(
8718 GL_INVALID_OPERATION,
8719 "glPostSubBufferCHROMIUM", "command not supported by surface");
8720 return error::kNoError;
8722 bool is_tracing;
8723 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
8724 &is_tracing);
8725 if (is_tracing) {
8726 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
8727 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
8728 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
8729 is_offscreen ? offscreen_size_ : surface_->GetSize());
8731 if (surface_->PostSubBuffer(c.x, c.y, c.width, c.height) !=
8732 gfx::SwapResult::SWAP_FAILED) {
8733 return error::kNoError;
8734 } else {
8735 LOG(ERROR) << "Context lost because PostSubBuffer failed.";
8736 return error::kLostContext;
8740 error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
8741 uint32 immediate_data_size,
8742 const void* cmd_data) {
8743 const gles2::cmds::ScheduleOverlayPlaneCHROMIUM& c =
8744 *static_cast<const gles2::cmds::ScheduleOverlayPlaneCHROMIUM*>(cmd_data);
8745 TextureRef* ref = texture_manager()->GetTexture(c.overlay_texture_id);
8746 if (!ref) {
8747 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8748 "glScheduleOverlayPlaneCHROMIUM",
8749 "unknown texture");
8750 return error::kNoError;
8752 gfx::GLImage* image =
8753 ref->texture()->GetLevelImage(ref->texture()->target(), 0);
8754 if (!image) {
8755 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
8756 "glScheduleOverlayPlaneCHROMIUM",
8757 "unsupported texture format");
8758 return error::kNoError;
8760 gfx::OverlayTransform transform = GetGFXOverlayTransform(c.plane_transform);
8761 if (transform == gfx::OVERLAY_TRANSFORM_INVALID) {
8762 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM,
8763 "glScheduleOverlayPlaneCHROMIUM",
8764 "invalid transform enum");
8765 return error::kNoError;
8767 if (!surface_->ScheduleOverlayPlane(
8768 c.plane_z_order,
8769 transform,
8770 image,
8771 gfx::Rect(c.bounds_x, c.bounds_y, c.bounds_width, c.bounds_height),
8772 gfx::RectF(c.uv_x, c.uv_y, c.uv_width, c.uv_height))) {
8773 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8774 "glScheduleOverlayPlaneCHROMIUM",
8775 "failed to schedule overlay");
8777 return error::kNoError;
8780 error::Error GLES2DecoderImpl::GetAttribLocationHelper(
8781 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8782 const std::string& name_str) {
8783 if (!StringIsValidForGLES(name_str.c_str())) {
8784 LOCAL_SET_GL_ERROR(
8785 GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character");
8786 return error::kNoError;
8788 Program* program = GetProgramInfoNotShader(
8789 client_id, "glGetAttribLocation");
8790 if (!program) {
8791 return error::kNoError;
8793 if (!program->IsValid()) {
8794 LOCAL_SET_GL_ERROR(
8795 GL_INVALID_OPERATION, "glGetAttribLocation", "program not linked");
8796 return error::kNoError;
8798 GLint* location = GetSharedMemoryAs<GLint*>(
8799 location_shm_id, location_shm_offset, sizeof(GLint));
8800 if (!location) {
8801 return error::kOutOfBounds;
8803 // Require the client to init this incase the context is lost and we are no
8804 // longer executing commands.
8805 if (*location != -1) {
8806 return error::kGenericError;
8808 *location = program->GetAttribLocation(name_str);
8809 return error::kNoError;
8812 error::Error GLES2DecoderImpl::HandleGetAttribLocation(
8813 uint32 immediate_data_size,
8814 const void* cmd_data) {
8815 const gles2::cmds::GetAttribLocation& c =
8816 *static_cast<const gles2::cmds::GetAttribLocation*>(cmd_data);
8817 Bucket* bucket = GetBucket(c.name_bucket_id);
8818 if (!bucket) {
8819 return error::kInvalidArguments;
8821 std::string name_str;
8822 if (!bucket->GetAsString(&name_str)) {
8823 return error::kInvalidArguments;
8825 return GetAttribLocationHelper(
8826 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8829 error::Error GLES2DecoderImpl::GetUniformLocationHelper(
8830 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8831 const std::string& name_str) {
8832 if (!StringIsValidForGLES(name_str.c_str())) {
8833 LOCAL_SET_GL_ERROR(
8834 GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character");
8835 return error::kNoError;
8837 Program* program = GetProgramInfoNotShader(
8838 client_id, "glGetUniformLocation");
8839 if (!program) {
8840 return error::kNoError;
8842 if (!program->IsValid()) {
8843 LOCAL_SET_GL_ERROR(
8844 GL_INVALID_OPERATION, "glGetUniformLocation", "program not linked");
8845 return error::kNoError;
8847 GLint* location = GetSharedMemoryAs<GLint*>(
8848 location_shm_id, location_shm_offset, sizeof(GLint));
8849 if (!location) {
8850 return error::kOutOfBounds;
8852 // Require the client to init this incase the context is lost an we are no
8853 // longer executing commands.
8854 if (*location != -1) {
8855 return error::kGenericError;
8857 *location = program->GetUniformFakeLocation(name_str);
8858 return error::kNoError;
8861 error::Error GLES2DecoderImpl::HandleGetUniformLocation(
8862 uint32 immediate_data_size,
8863 const void* cmd_data) {
8864 const gles2::cmds::GetUniformLocation& c =
8865 *static_cast<const gles2::cmds::GetUniformLocation*>(cmd_data);
8866 Bucket* bucket = GetBucket(c.name_bucket_id);
8867 if (!bucket) {
8868 return error::kInvalidArguments;
8870 std::string name_str;
8871 if (!bucket->GetAsString(&name_str)) {
8872 return error::kInvalidArguments;
8874 return GetUniformLocationHelper(
8875 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8878 error::Error GLES2DecoderImpl::HandleGetUniformIndices(
8879 uint32 immediate_data_size,
8880 const void* cmd_data) {
8881 if (!unsafe_es3_apis_enabled())
8882 return error::kUnknownCommand;
8883 const gles2::cmds::GetUniformIndices& c =
8884 *static_cast<const gles2::cmds::GetUniformIndices*>(cmd_data);
8885 Bucket* bucket = GetBucket(c.names_bucket_id);
8886 if (!bucket) {
8887 return error::kInvalidArguments;
8889 GLsizei count = 0;
8890 std::vector<char*> names;
8891 std::vector<GLint> len;
8892 if (!bucket->GetAsStrings(&count, &names, &len) || count <= 0) {
8893 return error::kInvalidArguments;
8895 typedef cmds::GetUniformIndices::Result Result;
8896 Result* result = GetSharedMemoryAs<Result*>(
8897 c.indices_shm_id, c.indices_shm_offset,
8898 Result::ComputeSize(static_cast<size_t>(count)));
8899 GLuint* indices = result ? result->GetData() : NULL;
8900 if (indices == NULL) {
8901 return error::kOutOfBounds;
8903 // Check that the client initialized the result.
8904 if (result->size != 0) {
8905 return error::kInvalidArguments;
8907 Program* program = GetProgramInfoNotShader(c.program, "glGetUniformIndices");
8908 if (!program) {
8909 return error::kNoError;
8911 GLuint service_id = program->service_id();
8912 GLint link_status = GL_FALSE;
8913 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
8914 if (link_status != GL_TRUE) {
8915 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
8916 "glGetUniformIndices", "program not linked");
8917 return error::kNoError;
8919 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
8920 glGetUniformIndices(service_id, count, &names[0], indices);
8921 GLenum error = glGetError();
8922 if (error == GL_NO_ERROR) {
8923 result->SetNumResults(count);
8924 } else {
8925 LOCAL_SET_GL_ERROR(error, "GetUniformIndices", "");
8927 return error::kNoError;
8930 error::Error GLES2DecoderImpl::GetFragDataLocationHelper(
8931 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
8932 const std::string& name_str) {
8933 GLint* location = GetSharedMemoryAs<GLint*>(
8934 location_shm_id, location_shm_offset, sizeof(GLint));
8935 if (!location) {
8936 return error::kOutOfBounds;
8938 // Require the client to init this incase the context is lost and we are no
8939 // longer executing commands.
8940 if (*location != -1) {
8941 return error::kGenericError;
8943 Program* program = GetProgramInfoNotShader(
8944 client_id, "glGetFragDataLocation");
8945 if (!program) {
8946 return error::kNoError;
8948 *location = glGetFragDataLocation(program->service_id(), name_str.c_str());
8949 return error::kNoError;
8952 error::Error GLES2DecoderImpl::HandleGetFragDataLocation(
8953 uint32 immediate_data_size,
8954 const void* cmd_data) {
8955 if (!unsafe_es3_apis_enabled())
8956 return error::kUnknownCommand;
8957 const gles2::cmds::GetFragDataLocation& c =
8958 *static_cast<const gles2::cmds::GetFragDataLocation*>(cmd_data);
8959 Bucket* bucket = GetBucket(c.name_bucket_id);
8960 if (!bucket) {
8961 return error::kInvalidArguments;
8963 std::string name_str;
8964 if (!bucket->GetAsString(&name_str)) {
8965 return error::kInvalidArguments;
8967 return GetFragDataLocationHelper(
8968 c.program, c.location_shm_id, c.location_shm_offset, name_str);
8971 error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex(
8972 uint32 immediate_data_size, const void* cmd_data) {
8973 if (!unsafe_es3_apis_enabled())
8974 return error::kUnknownCommand;
8975 const gles2::cmds::GetUniformBlockIndex& c =
8976 *static_cast<const gles2::cmds::GetUniformBlockIndex*>(cmd_data);
8977 Bucket* bucket = GetBucket(c.name_bucket_id);
8978 if (!bucket) {
8979 return error::kInvalidArguments;
8981 std::string name_str;
8982 if (!bucket->GetAsString(&name_str)) {
8983 return error::kInvalidArguments;
8985 GLuint* index = GetSharedMemoryAs<GLuint*>(
8986 c.index_shm_id, c.index_shm_offset, sizeof(GLuint));
8987 if (!index) {
8988 return error::kOutOfBounds;
8990 // Require the client to init this in case the context is lost and we are no
8991 // longer executing commands.
8992 if (*index != GL_INVALID_INDEX) {
8993 return error::kGenericError;
8995 Program* program = GetProgramInfoNotShader(
8996 c.program, "glGetUniformBlockIndex");
8997 if (!program) {
8998 return error::kNoError;
9000 *index = glGetUniformBlockIndex(program->service_id(), name_str.c_str());
9001 return error::kNoError;
9004 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size,
9005 const void* cmd_data) {
9006 const gles2::cmds::GetString& c =
9007 *static_cast<const gles2::cmds::GetString*>(cmd_data);
9008 GLenum name = static_cast<GLenum>(c.name);
9009 if (!validators_->string_type.IsValid(name)) {
9010 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name");
9011 return error::kNoError;
9014 const char* str = nullptr;
9015 std::string extensions;
9016 switch (name) {
9017 case GL_VERSION:
9018 if (unsafe_es3_apis_enabled())
9019 str = "OpenGL ES 3.0 Chromium";
9020 else
9021 str = "OpenGL ES 2.0 Chromium";
9022 break;
9023 case GL_SHADING_LANGUAGE_VERSION:
9024 if (unsafe_es3_apis_enabled())
9025 str = "OpenGL ES GLSL ES 3.0 Chromium";
9026 else
9027 str = "OpenGL ES GLSL ES 1.0 Chromium";
9028 break;
9029 case GL_RENDERER:
9030 case GL_VENDOR:
9031 // Return the unmasked VENDOR/RENDERER string for WebGL contexts.
9032 // They are used by WEBGL_debug_renderer_info.
9033 if (!IsWebGLContext())
9034 str = "Chromium";
9035 else
9036 str = reinterpret_cast<const char*>(glGetString(name));
9037 break;
9038 case GL_EXTENSIONS:
9040 // For WebGL contexts, strip out the OES derivatives and
9041 // EXT frag depth extensions if they have not been enabled.
9042 if (IsWebGLContext()) {
9043 extensions = feature_info_->extensions();
9044 if (!derivatives_explicitly_enabled_) {
9045 size_t offset = extensions.find(kOESDerivativeExtension);
9046 if (std::string::npos != offset) {
9047 extensions.replace(offset, arraysize(kOESDerivativeExtension),
9048 std::string());
9051 if (!frag_depth_explicitly_enabled_) {
9052 size_t offset = extensions.find(kEXTFragDepthExtension);
9053 if (std::string::npos != offset) {
9054 extensions.replace(offset, arraysize(kEXTFragDepthExtension),
9055 std::string());
9058 if (!draw_buffers_explicitly_enabled_) {
9059 size_t offset = extensions.find(kEXTDrawBuffersExtension);
9060 if (std::string::npos != offset) {
9061 extensions.replace(offset, arraysize(kEXTDrawBuffersExtension),
9062 std::string());
9065 if (!shader_texture_lod_explicitly_enabled_) {
9066 size_t offset = extensions.find(kEXTShaderTextureLodExtension);
9067 if (std::string::npos != offset) {
9068 extensions.replace(offset,
9069 arraysize(kEXTShaderTextureLodExtension),
9070 std::string());
9073 } else {
9074 extensions = feature_info_->extensions().c_str();
9076 if (supports_post_sub_buffer_)
9077 extensions += " GL_CHROMIUM_post_sub_buffer";
9078 str = extensions.c_str();
9080 break;
9081 default:
9082 str = reinterpret_cast<const char*>(glGetString(name));
9083 break;
9085 Bucket* bucket = CreateBucket(c.bucket_id);
9086 bucket->SetFromString(str);
9087 return error::kNoError;
9090 error::Error GLES2DecoderImpl::HandleBufferData(uint32 immediate_data_size,
9091 const void* cmd_data) {
9092 const gles2::cmds::BufferData& c =
9093 *static_cast<const gles2::cmds::BufferData*>(cmd_data);
9094 GLenum target = static_cast<GLenum>(c.target);
9095 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
9096 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9097 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9098 GLenum usage = static_cast<GLenum>(c.usage);
9099 const void* data = NULL;
9100 if (data_shm_id != 0 || data_shm_offset != 0) {
9101 data = GetSharedMemoryAs<const void*>(data_shm_id, data_shm_offset, size);
9102 if (!data) {
9103 return error::kOutOfBounds;
9106 buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
9107 return error::kNoError;
9110 void GLES2DecoderImpl::DoBufferSubData(
9111 GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
9112 // Just delegate it. Some validation is actually done before this.
9113 buffer_manager()->ValidateAndDoBufferSubData(
9114 &state_, target, offset, size, data);
9117 bool GLES2DecoderImpl::ClearLevel(Texture* texture,
9118 unsigned target,
9119 int level,
9120 unsigned format,
9121 unsigned type,
9122 int xoffset,
9123 int yoffset,
9124 int width,
9125 int height) {
9126 uint32 channels = GLES2Util::GetChannelsForFormat(format);
9127 if ((feature_info_->feature_flags().angle_depth_texture ||
9128 feature_info_->IsES3Enabled())
9129 && (channels & GLES2Util::kDepth) != 0) {
9130 // It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
9131 // on depth formats.
9132 GLuint fb = 0;
9133 glGenFramebuffersEXT(1, &fb);
9134 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb);
9136 bool have_stencil = (channels & GLES2Util::kStencil) != 0;
9137 GLenum attachment = have_stencil ? GL_DEPTH_STENCIL_ATTACHMENT :
9138 GL_DEPTH_ATTACHMENT;
9140 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, attachment, target,
9141 texture->service_id(), level);
9142 // ANGLE promises a depth only attachment ok.
9143 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT) !=
9144 GL_FRAMEBUFFER_COMPLETE) {
9145 return false;
9147 glClearStencil(0);
9148 state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask);
9149 state_.SetDeviceStencilMaskSeparate(GL_BACK, kDefaultStencilMask);
9150 glClearDepth(1.0f);
9151 state_.SetDeviceDepthMask(GL_TRUE);
9152 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
9153 glScissor(xoffset, yoffset, width, height);
9154 glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
9156 RestoreClearState();
9158 glDeleteFramebuffersEXT(1, &fb);
9159 Framebuffer* framebuffer =
9160 GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT);
9161 GLuint fb_service_id =
9162 framebuffer ? framebuffer->service_id() : GetBackbufferServiceId();
9163 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fb_service_id);
9164 return true;
9167 static const uint32 kMaxZeroSize = 1024 * 1024 * 4;
9169 uint32 size;
9170 uint32 padded_row_size;
9171 if (!GLES2Util::ComputeImageDataSizes(
9172 width, height, 1, format, type, state_.unpack_alignment, &size,
9173 NULL, &padded_row_size)) {
9174 return false;
9177 TRACE_EVENT1("gpu", "GLES2DecoderImpl::ClearLevel", "size", size);
9179 int tile_height;
9181 if (size > kMaxZeroSize) {
9182 if (kMaxZeroSize < padded_row_size) {
9183 // That'd be an awfully large texture.
9184 return false;
9186 // We should never have a large total size with a zero row size.
9187 DCHECK_GT(padded_row_size, 0U);
9188 tile_height = kMaxZeroSize / padded_row_size;
9189 if (!GLES2Util::ComputeImageDataSizes(
9190 width, tile_height, 1, format, type, state_.unpack_alignment, &size,
9191 NULL, NULL)) {
9192 return false;
9194 } else {
9195 tile_height = height;
9198 // Assumes the size has already been checked.
9199 scoped_ptr<char[]> zero(new char[size]);
9200 memset(zero.get(), 0, size);
9201 glBindTexture(texture->target(), texture->service_id());
9203 GLint y = 0;
9204 while (y < height) {
9205 GLint h = y + tile_height > height ? height - y : tile_height;
9206 glTexSubImage2D(target, level, xoffset, yoffset + y, width, h, format, type,
9207 zero.get());
9208 y += tile_height;
9210 TextureRef* bound_texture =
9211 texture_manager()->GetTextureInfoForTarget(&state_, texture->target());
9212 glBindTexture(texture->target(),
9213 bound_texture ? bound_texture->service_id() : 0);
9214 return true;
9217 namespace {
9219 const int kS3TCBlockWidth = 4;
9220 const int kS3TCBlockHeight = 4;
9221 const int kS3TCDXT1BlockSize = 8;
9222 const int kS3TCDXT3AndDXT5BlockSize = 16;
9223 const int kEACAndETC2BlockSize = 4;
9225 bool IsValidDXTSize(GLint level, GLsizei size) {
9226 return (size == 1) ||
9227 (size == 2) || !(size % kS3TCBlockWidth);
9230 bool IsValidPVRTCSize(GLint level, GLsizei size) {
9231 return GLES2Util::IsPOT(size);
9234 } // anonymous namespace.
9236 bool GLES2DecoderImpl::GetCompressedTexSizeInBytes(
9237 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
9238 GLenum format, GLsizei* size_in_bytes) {
9239 base::CheckedNumeric<GLsizei> bytes_required(0);
9241 switch (format) {
9242 case GL_ATC_RGB_AMD:
9243 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9244 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9245 case GL_ETC1_RGB8_OES:
9246 bytes_required =
9247 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9248 bytes_required *=
9249 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9250 bytes_required *= kS3TCDXT1BlockSize;
9251 break;
9252 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9253 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9254 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9255 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9256 bytes_required =
9257 (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
9258 bytes_required *=
9259 (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
9260 bytes_required *= kS3TCDXT3AndDXT5BlockSize;
9261 break;
9262 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9263 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9264 bytes_required = std::max(width, 8);
9265 bytes_required *= std::max(height, 8);
9266 bytes_required *= 4;
9267 bytes_required += 7;
9268 bytes_required /= 8;
9269 break;
9270 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9271 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9272 bytes_required = std::max(width, 16);
9273 bytes_required *= std::max(height, 8);
9274 bytes_required *= 2;
9275 bytes_required += 7;
9276 bytes_required /= 8;
9277 break;
9279 // ES3 formats.
9280 case GL_COMPRESSED_R11_EAC:
9281 case GL_COMPRESSED_SIGNED_R11_EAC:
9282 case GL_COMPRESSED_RGB8_ETC2:
9283 case GL_COMPRESSED_SRGB8_ETC2:
9284 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9285 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9286 bytes_required =
9287 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9288 bytes_required *=
9289 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9290 bytes_required *= 8;
9291 bytes_required *= depth;
9292 break;
9293 case GL_COMPRESSED_RG11_EAC:
9294 case GL_COMPRESSED_SIGNED_RG11_EAC:
9295 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9296 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9297 bytes_required =
9298 (width + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9299 bytes_required *=
9300 (height + kEACAndETC2BlockSize - 1) / kEACAndETC2BlockSize;
9301 bytes_required *= 16;
9302 bytes_required *= depth;
9303 break;
9304 default:
9305 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
9306 return false;
9309 if (!bytes_required.IsValid()) {
9310 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "invalid size");
9311 return false;
9314 *size_in_bytes = bytes_required.ValueOrDefault(0);
9315 return true;
9318 bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
9319 const char* function_name, GLsizei width, GLsizei height, GLsizei depth,
9320 GLenum format, GLsizei size) {
9321 GLsizei bytes_required = 0;
9322 if (!GetCompressedTexSizeInBytes(
9323 function_name, width, height, depth, format, &bytes_required)) {
9324 return false;
9327 if (size != bytes_required) {
9328 LOCAL_SET_GL_ERROR(
9329 GL_INVALID_VALUE, function_name, "size is not correct for dimensions");
9330 return false;
9333 return true;
9336 bool GLES2DecoderImpl::ValidateCompressedTexDimensions(
9337 const char* function_name, GLenum target, GLint level,
9338 GLsizei width, GLsizei height, GLsizei depth, GLenum format) {
9339 switch (format) {
9340 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9341 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9342 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9343 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
9344 DCHECK_EQ(1, depth); // 2D formats.
9345 if (!IsValidDXTSize(level, width) || !IsValidDXTSize(level, height)) {
9346 LOCAL_SET_GL_ERROR(
9347 GL_INVALID_OPERATION, function_name,
9348 "width or height invalid for level");
9349 return false;
9351 return true;
9352 case GL_ATC_RGB_AMD:
9353 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9354 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
9355 case GL_ETC1_RGB8_OES:
9356 DCHECK_EQ(1, depth); // 2D formats.
9357 if (width <= 0 || height <= 0) {
9358 LOCAL_SET_GL_ERROR(
9359 GL_INVALID_OPERATION, function_name,
9360 "width or height invalid for level");
9361 return false;
9363 return true;
9364 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9365 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9366 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9367 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
9368 DCHECK_EQ(1, depth); // 2D formats.
9369 if (!IsValidPVRTCSize(level, width) ||
9370 !IsValidPVRTCSize(level, height)) {
9371 LOCAL_SET_GL_ERROR(
9372 GL_INVALID_OPERATION, function_name,
9373 "width or height invalid for level");
9374 return false;
9376 return true;
9378 // ES3 formats.
9379 case GL_COMPRESSED_R11_EAC:
9380 case GL_COMPRESSED_SIGNED_R11_EAC:
9381 case GL_COMPRESSED_RG11_EAC:
9382 case GL_COMPRESSED_SIGNED_RG11_EAC:
9383 case GL_COMPRESSED_RGB8_ETC2:
9384 case GL_COMPRESSED_SRGB8_ETC2:
9385 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9386 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9387 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9388 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9389 if (width <= 0 || height <= 0 || depth <= 0) {
9390 LOCAL_SET_GL_ERROR(
9391 GL_INVALID_OPERATION, function_name,
9392 "width, height, or depth invalid");
9393 return false;
9395 if (target == GL_TEXTURE_3D) {
9396 LOCAL_SET_GL_ERROR(
9397 GL_INVALID_OPERATION, function_name,
9398 "target invalid for format");
9399 return false;
9401 return true;
9402 default:
9403 return false;
9407 bool GLES2DecoderImpl::ValidateCompressedTexSubDimensions(
9408 const char* function_name,
9409 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9410 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9411 Texture* texture) {
9412 if (xoffset < 0 || yoffset < 0 || zoffset < 0) {
9413 LOCAL_SET_GL_ERROR(
9414 GL_INVALID_VALUE, function_name, "x/y/z offset < 0");
9415 return false;
9418 switch (format) {
9419 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
9420 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
9421 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
9422 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
9423 const int kBlockWidth = 4;
9424 const int kBlockHeight = 4;
9425 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
9426 LOCAL_SET_GL_ERROR(
9427 GL_INVALID_OPERATION, function_name,
9428 "xoffset or yoffset not multiple of 4");
9429 return false;
9431 GLsizei tex_width = 0;
9432 GLsizei tex_height = 0;
9433 if (!texture->GetLevelSize(target, level,
9434 &tex_width, &tex_height, nullptr) ||
9435 width - xoffset > tex_width ||
9436 height - yoffset > tex_height) {
9437 LOCAL_SET_GL_ERROR(
9438 GL_INVALID_OPERATION, function_name, "dimensions out of range");
9439 return false;
9441 return ValidateCompressedTexDimensions(
9442 function_name, target, level, width, height, 1, format);
9444 case GL_ATC_RGB_AMD:
9445 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
9446 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
9447 LOCAL_SET_GL_ERROR(
9448 GL_INVALID_OPERATION, function_name,
9449 "not supported for ATC textures");
9450 return false;
9452 case GL_ETC1_RGB8_OES: {
9453 LOCAL_SET_GL_ERROR(
9454 GL_INVALID_OPERATION, function_name,
9455 "not supported for ECT1_RGB8_OES textures");
9456 return false;
9458 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
9459 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
9460 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
9461 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
9462 if ((xoffset != 0) || (yoffset != 0)) {
9463 LOCAL_SET_GL_ERROR(
9464 GL_INVALID_OPERATION, function_name,
9465 "xoffset and yoffset must be zero");
9466 return false;
9468 GLsizei tex_width = 0;
9469 GLsizei tex_height = 0;
9470 if (!texture->GetLevelSize(target, level,
9471 &tex_width, &tex_height, nullptr) ||
9472 width != tex_width ||
9473 height != tex_height) {
9474 LOCAL_SET_GL_ERROR(
9475 GL_INVALID_OPERATION, function_name,
9476 "dimensions must match existing texture level dimensions");
9477 return false;
9479 return ValidateCompressedTexDimensions(
9480 function_name, target, level, width, height, 1, format);
9483 // ES3 formats
9484 case GL_COMPRESSED_R11_EAC:
9485 case GL_COMPRESSED_SIGNED_R11_EAC:
9486 case GL_COMPRESSED_RG11_EAC:
9487 case GL_COMPRESSED_SIGNED_RG11_EAC:
9488 case GL_COMPRESSED_RGB8_ETC2:
9489 case GL_COMPRESSED_SRGB8_ETC2:
9490 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9491 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
9492 case GL_COMPRESSED_RGBA8_ETC2_EAC:
9493 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
9495 const int kBlockSize = 4;
9496 GLsizei tex_width, tex_height;
9497 if (target == GL_TEXTURE_3D ||
9498 !texture->GetLevelSize(target, level,
9499 &tex_width, &tex_height, nullptr) ||
9500 (xoffset % kBlockSize) || (yoffset % kBlockSize) ||
9501 ((width % kBlockSize) && xoffset + width != tex_width) ||
9502 ((height % kBlockSize) && yoffset + height != tex_height)) {
9503 LOCAL_SET_GL_ERROR(
9504 GL_INVALID_OPERATION, function_name,
9505 "dimensions must match existing texture level dimensions");
9506 return false;
9508 return true;
9510 default:
9511 return false;
9515 error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
9516 GLenum target,
9517 GLint level,
9518 GLenum internal_format,
9519 GLsizei width,
9520 GLsizei height,
9521 GLint border,
9522 GLsizei image_size,
9523 const void* data) {
9524 if (!validators_->texture_target.IsValid(target)) {
9525 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9526 "glCompressedTexImage2D", target, "target");
9527 return error::kNoError;
9529 if (!validators_->compressed_texture_format.IsValid(
9530 internal_format)) {
9531 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9532 "glCompressedTexImage2D", internal_format, "internal_format");
9533 return error::kNoError;
9535 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
9536 border != 0) {
9537 LOCAL_SET_GL_ERROR(
9538 GL_INVALID_VALUE,
9539 "glCompressedTexImage2D", "dimensions out of range");
9540 return error::kNoError;
9542 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9543 &state_, target);
9544 if (!texture_ref) {
9545 LOCAL_SET_GL_ERROR(
9546 GL_INVALID_VALUE,
9547 "glCompressedTexImage2D", "unknown texture target");
9548 return error::kNoError;
9550 Texture* texture = texture_ref->texture();
9551 if (texture->IsImmutable()) {
9552 LOCAL_SET_GL_ERROR(
9553 GL_INVALID_OPERATION,
9554 "glCompressedTexImage2D", "texture is immutable");
9555 return error::kNoError;
9558 if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target, level,
9559 width, height, 1, internal_format) ||
9560 !ValidateCompressedTexFuncData("glCompressedTexImage2D", width, height,
9561 1, internal_format, image_size)) {
9562 return error::kNoError;
9565 if (!EnsureGPUMemoryAvailable(image_size)) {
9566 LOCAL_SET_GL_ERROR(
9567 GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory");
9568 return error::kNoError;
9571 if (texture->IsAttachedToFramebuffer()) {
9572 framebuffer_state_.clear_state_dirty = true;
9575 scoped_ptr<int8[]> zero;
9576 if (!data) {
9577 zero.reset(new int8[image_size]);
9578 memset(zero.get(), 0, image_size);
9579 data = zero.get();
9581 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D");
9582 glCompressedTexImage2D(
9583 target, level, internal_format, width, height, border, image_size, data);
9584 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D");
9585 if (error == GL_NO_ERROR) {
9586 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
9587 width, height, 1, border, 0, 0,
9588 gfx::Rect(width, height));
9591 // This may be a slow command. Exit command processing to allow for
9592 // context preemption and GPU watchdog checks.
9593 ExitCommandProcessingEarly();
9594 return error::kNoError;
9597 error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
9598 uint32 immediate_data_size,
9599 const void* cmd_data) {
9600 const gles2::cmds::CompressedTexImage2D& c =
9601 *static_cast<const gles2::cmds::CompressedTexImage2D*>(cmd_data);
9602 GLenum target = static_cast<GLenum>(c.target);
9603 GLint level = static_cast<GLint>(c.level);
9604 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9605 GLsizei width = static_cast<GLsizei>(c.width);
9606 GLsizei height = static_cast<GLsizei>(c.height);
9607 GLint border = static_cast<GLint>(c.border);
9608 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9609 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9610 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9611 const void* data = NULL;
9612 if (data_shm_id != 0 || data_shm_offset != 0) {
9613 data = GetSharedMemoryAs<const void*>(
9614 data_shm_id, data_shm_offset, image_size);
9615 if (!data) {
9616 return error::kOutOfBounds;
9619 return DoCompressedTexImage2D(
9620 target, level, internal_format, width, height, border, image_size, data);
9623 error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
9624 uint32 immediate_data_size,
9625 const void* cmd_data) {
9626 const gles2::cmds::CompressedTexImage2DBucket& c =
9627 *static_cast<const gles2::cmds::CompressedTexImage2DBucket*>(cmd_data);
9628 GLenum target = static_cast<GLenum>(c.target);
9629 GLint level = static_cast<GLint>(c.level);
9630 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9631 GLsizei width = static_cast<GLsizei>(c.width);
9632 GLsizei height = static_cast<GLsizei>(c.height);
9633 GLint border = static_cast<GLint>(c.border);
9634 Bucket* bucket = GetBucket(c.bucket_id);
9635 if (!bucket) {
9636 return error::kInvalidArguments;
9638 uint32 data_size = bucket->size();
9639 GLsizei imageSize = data_size;
9640 const void* data = bucket->GetData(0, data_size);
9641 if (!data) {
9642 return error::kInvalidArguments;
9644 return DoCompressedTexImage2D(
9645 target, level, internal_format, width, height, border,
9646 imageSize, data);
9649 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
9650 uint32 immediate_data_size,
9651 const void* cmd_data) {
9652 const gles2::cmds::CompressedTexSubImage2DBucket& c =
9653 *static_cast<const gles2::cmds::CompressedTexSubImage2DBucket*>(cmd_data);
9654 GLenum target = static_cast<GLenum>(c.target);
9655 GLint level = static_cast<GLint>(c.level);
9656 GLint xoffset = static_cast<GLint>(c.xoffset);
9657 GLint yoffset = static_cast<GLint>(c.yoffset);
9658 GLsizei width = static_cast<GLsizei>(c.width);
9659 GLsizei height = static_cast<GLsizei>(c.height);
9660 GLenum format = static_cast<GLenum>(c.format);
9661 Bucket* bucket = GetBucket(c.bucket_id);
9662 if (!bucket) {
9663 return error::kInvalidArguments;
9665 uint32 data_size = bucket->size();
9666 GLsizei imageSize = data_size;
9667 const void* data = bucket->GetData(0, data_size);
9668 if (!data) {
9669 return error::kInvalidArguments;
9671 if (!validators_->texture_target.IsValid(target)) {
9672 LOCAL_SET_GL_ERROR(
9673 GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
9674 return error::kNoError;
9676 if (!validators_->compressed_texture_format.IsValid(format)) {
9677 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9678 "glCompressedTexSubImage2D", format, "format");
9679 return error::kNoError;
9681 if (width < 0) {
9682 LOCAL_SET_GL_ERROR(
9683 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "width < 0");
9684 return error::kNoError;
9686 if (height < 0) {
9687 LOCAL_SET_GL_ERROR(
9688 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "height < 0");
9689 return error::kNoError;
9691 if (imageSize < 0) {
9692 LOCAL_SET_GL_ERROR(
9693 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "imageSize < 0");
9694 return error::kNoError;
9696 DoCompressedTexSubImage2D(
9697 target, level, xoffset, yoffset, width, height, format, imageSize, data);
9698 return error::kNoError;
9701 error::Error GLES2DecoderImpl::DoCompressedTexImage3D(
9702 GLenum target,
9703 GLint level,
9704 GLenum internal_format,
9705 GLsizei width,
9706 GLsizei height,
9707 GLsizei depth,
9708 GLint border,
9709 GLsizei image_size,
9710 const void* data) {
9711 if (!validators_->texture_3_d_target.IsValid(target)) {
9712 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9713 "glCompressedTexImage3D", target, "target");
9714 return error::kNoError;
9716 if (!validators_->compressed_texture_format.IsValid(
9717 internal_format)) {
9718 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9719 "glCompressedTexImage3D", internal_format, "internal_format");
9720 return error::kNoError;
9722 if (!texture_manager()->ValidForTarget(target, level, width, height, depth) ||
9723 border != 0) {
9724 LOCAL_SET_GL_ERROR(
9725 GL_INVALID_VALUE,
9726 "glCompressedTexImage3D", "dimensions out of range");
9727 return error::kNoError;
9729 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9730 &state_, target);
9731 if (!texture_ref) {
9732 LOCAL_SET_GL_ERROR(
9733 GL_INVALID_VALUE,
9734 "glCompressedTexImage3D", "unknown texture target");
9735 return error::kNoError;
9737 Texture* texture = texture_ref->texture();
9738 if (texture->IsImmutable()) {
9739 LOCAL_SET_GL_ERROR(
9740 GL_INVALID_OPERATION,
9741 "glCompressedTexImage3D", "texture is immutable");
9742 return error::kNoError;
9745 if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target, level,
9746 width, height, depth, internal_format) ||
9747 !ValidateCompressedTexFuncData("glCompressedTexImage3D", width, height,
9748 depth, internal_format, image_size)) {
9749 return error::kNoError;
9752 if (!EnsureGPUMemoryAvailable(image_size)) {
9753 LOCAL_SET_GL_ERROR(
9754 GL_OUT_OF_MEMORY, "glCompressedTexImage3D", "out of memory");
9755 return error::kNoError;
9758 if (texture->IsAttachedToFramebuffer()) {
9759 framebuffer_state_.clear_state_dirty = true;
9762 scoped_ptr<int8[]> zero;
9763 if (!data) {
9764 zero.reset(new int8[image_size]);
9765 memset(zero.get(), 0, image_size);
9766 data = zero.get();
9768 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D");
9769 glCompressedTexImage3D(target, level, internal_format, width, height, depth,
9770 border, image_size, data);
9771 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D");
9772 if (error == GL_NO_ERROR) {
9773 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
9774 width, height, depth, border, 0, 0,
9775 gfx::Rect(width, height));
9778 // This may be a slow command. Exit command processing to allow for
9779 // context preemption and GPU watchdog checks.
9780 ExitCommandProcessingEarly();
9781 return error::kNoError;
9784 error::Error GLES2DecoderImpl::HandleCompressedTexImage3D(
9785 uint32 immediate_data_size, const void* cmd_data) {
9786 if (!unsafe_es3_apis_enabled())
9787 return error::kUnknownCommand;
9789 const gles2::cmds::CompressedTexImage3D& c =
9790 *static_cast<const gles2::cmds::CompressedTexImage3D*>(cmd_data);
9791 GLenum target = static_cast<GLenum>(c.target);
9792 GLint level = static_cast<GLint>(c.level);
9793 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9794 GLsizei width = static_cast<GLsizei>(c.width);
9795 GLsizei height = static_cast<GLsizei>(c.height);
9796 GLsizei depth = static_cast<GLsizei>(c.depth);
9797 GLint border = static_cast<GLint>(c.border);
9798 GLsizei image_size = static_cast<GLsizei>(c.imageSize);
9799 uint32 data_shm_id = static_cast<uint32>(c.data_shm_id);
9800 uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset);
9801 const void* data = NULL;
9802 if (data_shm_id != 0 || data_shm_offset != 0) {
9803 data = GetSharedMemoryAs<const void*>(
9804 data_shm_id, data_shm_offset, image_size);
9805 if (!data) {
9806 return error::kOutOfBounds;
9809 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9810 depth, border, image_size, data);
9813 error::Error GLES2DecoderImpl::HandleCompressedTexImage3DBucket(
9814 uint32 immediate_data_size, const void* cmd_data) {
9815 if (!unsafe_es3_apis_enabled())
9816 return error::kUnknownCommand;
9818 const gles2::cmds::CompressedTexImage3DBucket& c =
9819 *static_cast<const gles2::cmds::CompressedTexImage3DBucket*>(cmd_data);
9820 GLenum target = static_cast<GLenum>(c.target);
9821 GLint level = static_cast<GLint>(c.level);
9822 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9823 GLsizei width = static_cast<GLsizei>(c.width);
9824 GLsizei height = static_cast<GLsizei>(c.height);
9825 GLsizei depth = static_cast<GLsizei>(c.depth);
9826 GLint border = static_cast<GLint>(c.border);
9827 Bucket* bucket = GetBucket(c.bucket_id);
9828 if (!bucket) {
9829 return error::kInvalidArguments;
9831 uint32 data_size = bucket->size();
9832 GLsizei imageSize = data_size;
9833 const void* data = bucket->GetData(0, data_size);
9834 if (!data) {
9835 return error::kInvalidArguments;
9837 return DoCompressedTexImage3D(target, level, internal_format, width, height,
9838 depth, border, imageSize, data);
9841 void GLES2DecoderImpl::DoCompressedTexSubImage3D(
9842 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
9843 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
9844 GLsizei image_size, const void* data) {
9845 if (!validators_->texture_3_d_target.IsValid(target)) {
9846 LOCAL_SET_GL_ERROR(
9847 GL_INVALID_ENUM, "glCompressedTexSubImage3D", "target");
9848 return;
9850 if (!validators_->compressed_texture_format.IsValid(format)) {
9851 LOCAL_SET_GL_ERROR_INVALID_ENUM(
9852 "glCompressedTexSubImage3D", format, "format");
9853 return;
9855 if (width < 0 || height < 0 || depth < 0) {
9856 LOCAL_SET_GL_ERROR(
9857 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "size < 0");
9858 return;
9860 if (image_size < 0) {
9861 LOCAL_SET_GL_ERROR(
9862 GL_INVALID_VALUE, "glCompressedTexSubImage3D", "imageSize < 0");
9863 return;
9865 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
9866 &state_, target);
9867 if (!texture_ref) {
9868 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9869 "unknown texture for target");
9870 return;
9872 Texture* texture = texture_ref->texture();
9873 GLenum type = 0, internal_format = 0;
9874 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
9875 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9876 "level does not exist");
9877 return;
9879 if (internal_format != format) {
9880 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCompressedTexSubImage3D",
9881 "format does not match internal format");
9882 return;
9884 if (!texture->ValidForTexture(target, level, xoffset, yoffset, zoffset,
9885 width, height, depth, type)) {
9886 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedTexSubImage3D",
9887 "bad dimensions");
9888 return;
9890 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D",
9891 width, height, depth, format,
9892 image_size) ||
9893 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D",
9894 target, level, xoffset, yoffset,
9895 zoffset, width, height, depth,
9896 format, texture)) {
9897 return;
9900 // Note: There is no need to deal with texture cleared tracking here
9901 // because the validation above means you can only get here if the level
9902 // is already a matching compressed format and in that case
9903 // CompressedTexImage3D already cleared the texture.
9904 glCompressedTexSubImage3D(
9905 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
9906 image_size, data);
9908 // This may be a slow command. Exit command processing to allow for
9909 // context preemption and GPU watchdog checks.
9910 ExitCommandProcessingEarly();
9913 error::Error GLES2DecoderImpl::HandleCompressedTexSubImage3DBucket(
9914 uint32 immediate_data_size, const void* cmd_data) {
9915 if (!unsafe_es3_apis_enabled())
9916 return error::kUnknownCommand;
9917 const gles2::cmds::CompressedTexSubImage3DBucket& c =
9918 *static_cast<const gles2::cmds::CompressedTexSubImage3DBucket*>(cmd_data);
9919 GLenum target = static_cast<GLenum>(c.target);
9920 GLint level = static_cast<GLint>(c.level);
9921 GLint xoffset = static_cast<GLint>(c.xoffset);
9922 GLint yoffset = static_cast<GLint>(c.yoffset);
9923 GLint zoffset = static_cast<GLint>(c.zoffset);
9924 GLsizei width = static_cast<GLsizei>(c.width);
9925 GLsizei height = static_cast<GLsizei>(c.height);
9926 GLsizei depth = static_cast<GLsizei>(c.depth);
9927 GLenum format = static_cast<GLenum>(c.format);
9928 Bucket* bucket = GetBucket(c.bucket_id);
9929 if (!bucket) {
9930 return error::kInvalidArguments;
9932 uint32 data_size = bucket->size();
9933 GLsizei image_size = data_size;
9934 const void* data = bucket->GetData(0, data_size);
9935 if (!data) {
9936 return error::kInvalidArguments;
9938 DoCompressedTexSubImage3D(
9939 target, level, xoffset, yoffset, zoffset, width, height, depth, format,
9940 image_size, data);
9941 return error::kNoError;
9944 error::Error GLES2DecoderImpl::HandleTexImage2D(uint32 immediate_data_size,
9945 const void* cmd_data) {
9946 const gles2::cmds::TexImage2D& c =
9947 *static_cast<const gles2::cmds::TexImage2D*>(cmd_data);
9948 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage2D",
9949 "width", c.width, "height", c.height);
9950 // Set as failed for now, but if it successed, this will be set to not failed.
9951 texture_state_.tex_image_failed = true;
9952 GLenum target = static_cast<GLenum>(c.target);
9953 GLint level = static_cast<GLint>(c.level);
9954 // TODO(kloveless): Change TexImage2D command to use unsigned integer
9955 // for internalformat.
9956 GLenum internal_format = static_cast<GLenum>(c.internalformat);
9957 GLsizei width = static_cast<GLsizei>(c.width);
9958 GLsizei height = static_cast<GLsizei>(c.height);
9959 GLint border = static_cast<GLint>(c.border);
9960 GLenum format = static_cast<GLenum>(c.format);
9961 GLenum type = static_cast<GLenum>(c.type);
9962 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
9963 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
9964 uint32 pixels_size;
9965 if (!GLES2Util::ComputeImageDataSizes(
9966 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
9967 NULL, NULL)) {
9968 return error::kOutOfBounds;
9970 const void* pixels = NULL;
9971 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
9972 pixels = GetSharedMemoryAs<const void*>(
9973 pixels_shm_id, pixels_shm_offset, pixels_size);
9974 if (!pixels) {
9975 return error::kOutOfBounds;
9979 // For testing only. Allows us to stress the ability to respond to OOM errors.
9980 if (workarounds().simulate_out_of_memory_on_large_textures &&
9981 (width * height >= 4096 * 4096)) {
9982 LOCAL_SET_GL_ERROR(
9983 GL_OUT_OF_MEMORY,
9984 "glTexImage2D", "synthetic out of memory");
9985 return error::kNoError;
9988 TextureManager::DoTexImageArguments args = {
9989 target, level, internal_format, width, height, 1, border, format, type,
9990 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
9991 texture_manager()->ValidateAndDoTexImage(
9992 &texture_state_, &state_, &framebuffer_state_, "glTexImage2D", args);
9994 // This may be a slow command. Exit command processing to allow for
9995 // context preemption and GPU watchdog checks.
9996 ExitCommandProcessingEarly();
9997 return error::kNoError;
10000 error::Error GLES2DecoderImpl::HandleTexImage3D(uint32 immediate_data_size,
10001 const void* cmd_data) {
10002 if (!unsafe_es3_apis_enabled())
10003 return error::kUnknownCommand;
10005 const gles2::cmds::TexImage3D& c =
10006 *static_cast<const gles2::cmds::TexImage3D*>(cmd_data);
10007 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexImage3D",
10008 "widthXheight", c.width * c.height, "depth", c.depth);
10009 // Set as failed for now, but if it successed, this will be set to not failed.
10010 texture_state_.tex_image_failed = true;
10011 GLenum target = static_cast<GLenum>(c.target);
10012 GLint level = static_cast<GLint>(c.level);
10013 GLenum internal_format = static_cast<GLenum>(c.internalformat);
10014 GLsizei width = static_cast<GLsizei>(c.width);
10015 GLsizei height = static_cast<GLsizei>(c.height);
10016 GLsizei depth = static_cast<GLsizei>(c.depth);
10017 GLint border = static_cast<GLint>(c.border);
10018 GLenum format = static_cast<GLenum>(c.format);
10019 GLenum type = static_cast<GLenum>(c.type);
10020 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
10021 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
10022 uint32 pixels_size;
10023 if (!GLES2Util::ComputeImageDataSizes(
10024 width, height, depth, format, type, state_.unpack_alignment, &pixels_size,
10025 NULL, NULL)) {
10026 return error::kOutOfBounds;
10028 const void* pixels = NULL;
10029 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
10030 pixels = GetSharedMemoryAs<const void*>(
10031 pixels_shm_id, pixels_shm_offset, pixels_size);
10032 if (!pixels) {
10033 return error::kOutOfBounds;
10037 // For testing only. Allows us to stress the ability to respond to OOM errors.
10038 if (workarounds().simulate_out_of_memory_on_large_textures &&
10039 (width * height * depth >= 4096 * 4096)) {
10040 LOCAL_SET_GL_ERROR(
10041 GL_OUT_OF_MEMORY,
10042 "glTexImage3D", "synthetic out of memory");
10043 return error::kNoError;
10046 TextureManager::DoTexImageArguments args = {
10047 target, level, internal_format, width, height, depth, border, format, type,
10048 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage3D };
10049 texture_manager()->ValidateAndDoTexImage(
10050 &texture_state_, &state_, &framebuffer_state_, "glTexImage3D", args);
10052 // This may be a slow command. Exit command processing to allow for
10053 // context preemption and GPU watchdog checks.
10054 ExitCommandProcessingEarly();
10055 return error::kNoError;
10058 void GLES2DecoderImpl::DoCompressedTexSubImage2D(
10059 GLenum target,
10060 GLint level,
10061 GLint xoffset,
10062 GLint yoffset,
10063 GLsizei width,
10064 GLsizei height,
10065 GLenum format,
10066 GLsizei image_size,
10067 const void * data) {
10068 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10069 &state_, target);
10070 if (!texture_ref) {
10071 LOCAL_SET_GL_ERROR(
10072 GL_INVALID_OPERATION,
10073 "glCompressedTexSubImage2D", "unknown texture for target");
10074 return;
10076 Texture* texture = texture_ref->texture();
10077 GLenum type = 0;
10078 GLenum internal_format = 0;
10079 if (!texture->GetLevelType(target, level, &type, &internal_format)) {
10080 LOCAL_SET_GL_ERROR(
10081 GL_INVALID_OPERATION,
10082 "glCompressedTexSubImage2D", "level does not exist.");
10083 return;
10085 if (internal_format != format) {
10086 LOCAL_SET_GL_ERROR(
10087 GL_INVALID_OPERATION,
10088 "glCompressedTexSubImage2D", "format does not match internal format.");
10089 return;
10091 if (!texture->ValidForTexture(target, level, xoffset, yoffset, 0, width,
10092 height, 1, type)) {
10093 LOCAL_SET_GL_ERROR(
10094 GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
10095 return;
10098 if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D",
10099 width, height, 1, format, image_size) ||
10100 !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D",
10101 target, level, xoffset, yoffset, 0,
10102 width, height, 1, format, texture)) {
10103 return;
10107 // Note: There is no need to deal with texture cleared tracking here
10108 // because the validation above means you can only get here if the level
10109 // is already a matching compressed format and in that case
10110 // CompressedTexImage2D already cleared the texture.
10111 glCompressedTexSubImage2D(
10112 target, level, xoffset, yoffset, width, height, format, image_size, data);
10114 // This may be a slow command. Exit command processing to allow for
10115 // context preemption and GPU watchdog checks.
10116 ExitCommandProcessingEarly();
10119 static void Clip(
10120 GLint start, GLint range, GLint sourceRange,
10121 GLint* out_start, GLint* out_range) {
10122 DCHECK(out_start);
10123 DCHECK(out_range);
10124 if (start < 0) {
10125 range += start;
10126 start = 0;
10128 GLint end = start + range;
10129 if (end > sourceRange) {
10130 range -= end - sourceRange;
10132 *out_start = start;
10133 *out_range = range;
10136 void GLES2DecoderImpl::DoCopyTexImage2D(
10137 GLenum target,
10138 GLint level,
10139 GLenum internal_format,
10140 GLint x,
10141 GLint y,
10142 GLsizei width,
10143 GLsizei height,
10144 GLint border) {
10145 DCHECK(!ShouldDeferReads());
10146 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10147 &state_, target);
10148 if (!texture_ref) {
10149 LOCAL_SET_GL_ERROR(
10150 GL_INVALID_OPERATION,
10151 "glCopyTexImage2D", "unknown texture for target");
10152 return;
10154 Texture* texture = texture_ref->texture();
10155 if (texture->IsImmutable()) {
10156 LOCAL_SET_GL_ERROR(
10157 GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
10158 return;
10160 if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
10161 border != 0) {
10162 LOCAL_SET_GL_ERROR(
10163 GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
10164 return;
10166 if (!texture_manager()->ValidateFormatAndTypeCombination(
10167 state_.GetErrorState(), "glCopyTexImage2D", internal_format,
10168 GL_UNSIGNED_BYTE)) {
10169 return;
10172 // Check we have compatible formats.
10173 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
10174 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
10175 uint32 channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
10177 if ((channels_needed & channels_exist) != channels_needed) {
10178 LOCAL_SET_GL_ERROR(
10179 GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
10180 return;
10183 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10184 LOCAL_SET_GL_ERROR(
10185 GL_INVALID_OPERATION,
10186 "glCopyTexImage2D", "can not be used with depth or stencil textures");
10187 return;
10190 uint32 estimated_size = 0;
10191 if (!GLES2Util::ComputeImageDataSizes(
10192 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
10193 state_.unpack_alignment, &estimated_size, NULL, NULL)) {
10194 LOCAL_SET_GL_ERROR(
10195 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
10196 return;
10199 if (!EnsureGPUMemoryAvailable(estimated_size)) {
10200 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
10201 return;
10204 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexImage2D")) {
10205 return;
10208 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
10209 LOCAL_SET_GL_ERROR(
10210 GL_INVALID_OPERATION,
10211 "glCopyTexImage2D", "source and destination textures are the same");
10212 return;
10215 if (!CheckBoundFramebuffersValid("glCopyTexImage2D")) {
10216 return;
10219 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
10220 ScopedResolvedFrameBufferBinder binder(this, false, true);
10221 gfx::Size size = GetBoundReadFrameBufferSize();
10223 if (texture->IsAttachedToFramebuffer()) {
10224 framebuffer_state_.clear_state_dirty = true;
10227 // Clip to size to source dimensions
10228 GLint copyX = 0;
10229 GLint copyY = 0;
10230 GLint copyWidth = 0;
10231 GLint copyHeight = 0;
10232 Clip(x, width, size.width(), &copyX, &copyWidth);
10233 Clip(y, height, size.height(), &copyY, &copyHeight);
10235 if (copyX != x ||
10236 copyY != y ||
10237 copyWidth != width ||
10238 copyHeight != height) {
10239 // some part was clipped so clear the rect.
10240 uint32 pixels_size = 0;
10241 if (!GLES2Util::ComputeImageDataSizes(
10242 width, height, 1, internal_format, GL_UNSIGNED_BYTE,
10243 state_.unpack_alignment, &pixels_size, NULL, NULL)) {
10244 LOCAL_SET_GL_ERROR(
10245 GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
10246 return;
10248 scoped_ptr<char[]> zero(new char[pixels_size]);
10249 memset(zero.get(), 0, pixels_size);
10250 ScopedModifyPixels modify(texture_ref);
10251 glTexImage2D(target, level, internal_format, width, height, border,
10252 internal_format, GL_UNSIGNED_BYTE, zero.get());
10253 if (copyHeight > 0 && copyWidth > 0) {
10254 GLint dx = copyX - x;
10255 GLint dy = copyY - y;
10256 GLint destX = dx;
10257 GLint destY = dy;
10258 glCopyTexSubImage2D(target, level,
10259 destX, destY, copyX, copyY,
10260 copyWidth, copyHeight);
10262 } else {
10263 ScopedModifyPixels modify(texture_ref);
10264 glCopyTexImage2D(target, level, internal_format,
10265 copyX, copyY, copyWidth, copyHeight, border);
10267 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
10268 if (error == GL_NO_ERROR) {
10269 texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
10270 width, height, 1, border, internal_format,
10271 GL_UNSIGNED_BYTE, gfx::Rect(width, height));
10274 // This may be a slow command. Exit command processing to allow for
10275 // context preemption and GPU watchdog checks.
10276 ExitCommandProcessingEarly();
10279 void GLES2DecoderImpl::DoCopyTexSubImage2D(
10280 GLenum target,
10281 GLint level,
10282 GLint xoffset,
10283 GLint yoffset,
10284 GLint x,
10285 GLint y,
10286 GLsizei width,
10287 GLsizei height) {
10288 DCHECK(!ShouldDeferReads());
10289 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10290 &state_, target);
10291 if (!texture_ref) {
10292 LOCAL_SET_GL_ERROR(
10293 GL_INVALID_OPERATION,
10294 "glCopyTexSubImage2D", "unknown texture for target");
10295 return;
10297 Texture* texture = texture_ref->texture();
10298 GLenum type = 0;
10299 GLenum format = 0;
10300 if (!texture->GetLevelType(target, level, &type, &format) ||
10301 !texture->ValidForTexture(
10302 target, level, xoffset, yoffset, 0, width, height, 1, type)) {
10303 LOCAL_SET_GL_ERROR(
10304 GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
10305 return;
10307 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10308 LOCAL_SET_GL_ERROR(
10309 GL_INVALID_OPERATION,
10310 "glCopyTexSubImage2D", "async upload pending for texture");
10311 return;
10314 // Check we have compatible formats.
10315 GLenum read_format = GetBoundReadFrameBufferInternalFormat();
10316 uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
10317 uint32 channels_needed = GLES2Util::GetChannelsForFormat(format);
10319 if (!channels_needed ||
10320 (channels_needed & channels_exist) != channels_needed) {
10321 LOCAL_SET_GL_ERROR(
10322 GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
10323 return;
10326 if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
10327 LOCAL_SET_GL_ERROR(
10328 GL_INVALID_OPERATION,
10329 "glCopySubImage2D", "can not be used with depth or stencil textures");
10330 return;
10333 if (!CheckBoundReadFramebufferColorAttachment("glCopyTexSubImage2D")) {
10334 return;
10337 if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
10338 LOCAL_SET_GL_ERROR(
10339 GL_INVALID_OPERATION,
10340 "glCopyTexSubImage2D", "source and destination textures are the same");
10341 return;
10344 if (!CheckBoundFramebuffersValid("glCopyTexSubImage2D")) {
10345 return;
10348 ScopedResolvedFrameBufferBinder binder(this, false, true);
10349 gfx::Size size = GetBoundReadFrameBufferSize();
10350 GLint copyX = 0;
10351 GLint copyY = 0;
10352 GLint copyWidth = 0;
10353 GLint copyHeight = 0;
10354 Clip(x, width, size.width(), &copyX, &copyWidth);
10355 Clip(y, height, size.height(), &copyY, &copyHeight);
10357 if (xoffset != 0 || yoffset != 0 || width != size.width() ||
10358 height != size.height()) {
10359 gfx::Rect cleared_rect;
10360 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
10361 gfx::Rect(xoffset, yoffset, width, height),
10362 &cleared_rect)) {
10363 DCHECK_GE(cleared_rect.size().GetArea(),
10364 texture->GetLevelClearedRect(target, level).size().GetArea());
10365 texture_manager()->SetLevelClearedRect(texture_ref, target, level,
10366 cleared_rect);
10367 } else {
10368 // Otherwise clear part of texture level that is not already cleared.
10369 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
10370 level)) {
10371 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D",
10372 "dimensions too big");
10373 return;
10376 } else {
10377 // Write all pixels in below.
10378 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10381 if (copyX != x ||
10382 copyY != y ||
10383 copyWidth != width ||
10384 copyHeight != height) {
10385 // some part was clipped so clear the sub rect.
10386 uint32 pixels_size = 0;
10387 if (!GLES2Util::ComputeImageDataSizes(
10388 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
10389 NULL, NULL)) {
10390 LOCAL_SET_GL_ERROR(
10391 GL_INVALID_VALUE, "glCopyTexSubImage2D", "dimensions too large");
10392 return;
10394 scoped_ptr<char[]> zero(new char[pixels_size]);
10395 memset(zero.get(), 0, pixels_size);
10396 ScopedModifyPixels modify(texture_ref);
10397 glTexSubImage2D(
10398 target, level, xoffset, yoffset, width, height,
10399 format, type, zero.get());
10402 if (copyHeight > 0 && copyWidth > 0) {
10403 GLint dx = copyX - x;
10404 GLint dy = copyY - y;
10405 GLint destX = xoffset + dx;
10406 GLint destY = yoffset + dy;
10407 ScopedModifyPixels modify(texture_ref);
10408 glCopyTexSubImage2D(target, level,
10409 destX, destY, copyX, copyY,
10410 copyWidth, copyHeight);
10413 // This may be a slow command. Exit command processing to allow for
10414 // context preemption and GPU watchdog checks.
10415 ExitCommandProcessingEarly();
10418 bool GLES2DecoderImpl::ValidateTexSubImage2D(
10419 error::Error* error,
10420 const char* function_name,
10421 GLenum target,
10422 GLint level,
10423 GLint xoffset,
10424 GLint yoffset,
10425 GLsizei width,
10426 GLsizei height,
10427 GLenum format,
10428 GLenum type,
10429 const void * data) {
10430 (*error) = error::kNoError;
10431 if (!validators_->texture_target.IsValid(target)) {
10432 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
10433 return false;
10435 if (width < 0) {
10436 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
10437 return false;
10439 if (height < 0) {
10440 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
10441 return false;
10443 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10444 &state_, target);
10445 if (!texture_ref) {
10446 LOCAL_SET_GL_ERROR(
10447 GL_INVALID_OPERATION,
10448 function_name, "unknown texture for target");
10449 return false;
10451 Texture* texture = texture_ref->texture();
10452 GLenum current_type = 0;
10453 GLenum internal_format = 0;
10454 if (!texture->GetLevelType(target, level, &current_type, &internal_format)) {
10455 LOCAL_SET_GL_ERROR(
10456 GL_INVALID_OPERATION, function_name, "level does not exist.");
10457 return false;
10459 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
10460 function_name, format, type, internal_format, level)) {
10461 return false;
10463 if (type != current_type) {
10464 LOCAL_SET_GL_ERROR(
10465 GL_INVALID_OPERATION,
10466 function_name, "type does not match type of texture.");
10467 return false;
10469 if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
10470 LOCAL_SET_GL_ERROR(
10471 GL_INVALID_OPERATION,
10472 function_name, "async upload pending for texture");
10473 return false;
10475 if (!texture->ValidForTexture(
10476 target, level, xoffset, yoffset, 0, width, height, 1, type)) {
10477 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
10478 return false;
10480 if ((GLES2Util::GetChannelsForFormat(format) &
10481 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0
10482 && !feature_info_->IsES3Enabled()) {
10483 LOCAL_SET_GL_ERROR(
10484 GL_INVALID_OPERATION,
10485 function_name, "can not supply data for depth or stencil textures");
10486 return false;
10488 if (data == NULL) {
10489 (*error) = error::kOutOfBounds;
10490 return false;
10492 return true;
10495 error::Error GLES2DecoderImpl::DoTexSubImage2D(
10496 GLenum target,
10497 GLint level,
10498 GLint xoffset,
10499 GLint yoffset,
10500 GLsizei width,
10501 GLsizei height,
10502 GLenum format,
10503 GLenum type,
10504 const void * data) {
10505 error::Error error = error::kNoError;
10506 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level,
10507 xoffset, yoffset, width, height, format, type, data)) {
10508 return error;
10510 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10511 &state_, target);
10512 Texture* texture = texture_ref->texture();
10513 GLsizei tex_width = 0;
10514 GLsizei tex_height = 0;
10515 bool ok = texture->GetLevelSize(
10516 target, level, &tex_width, &tex_height, nullptr);
10517 DCHECK(ok);
10518 if (xoffset != 0 || yoffset != 0 ||
10519 width != tex_width || height != tex_height) {
10520 gfx::Rect cleared_rect;
10521 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
10522 gfx::Rect(xoffset, yoffset, width, height),
10523 &cleared_rect)) {
10524 DCHECK_GE(cleared_rect.size().GetArea(),
10525 texture->GetLevelClearedRect(target, level).size().GetArea());
10526 texture_manager()->SetLevelClearedRect(texture_ref, target, level,
10527 cleared_rect);
10528 } else {
10529 // Otherwise clear part of texture level that is not already cleared.
10530 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
10531 level)) {
10532 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexSubImage2D",
10533 "dimensions too big");
10534 return error::kNoError;
10537 ScopedTextureUploadTimer timer(&texture_state_);
10538 glTexSubImage2D(
10539 target, level, xoffset, yoffset, width, height, format, type, data);
10540 return error::kNoError;
10543 if (!texture_state_.texsubimage_faster_than_teximage &&
10544 !texture->IsImmutable() &&
10545 !texture->HasImages()) {
10546 ScopedTextureUploadTimer timer(&texture_state_);
10547 GLenum internal_format;
10548 GLenum tex_type;
10549 texture->GetLevelType(target, level, &tex_type, &internal_format);
10550 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
10551 // to look it up.
10552 glTexImage2D(
10553 target, level, internal_format, width, height, 0, format, type, data);
10554 } else {
10555 ScopedTextureUploadTimer timer(&texture_state_);
10556 glTexSubImage2D(
10557 target, level, xoffset, yoffset, width, height, format, type, data);
10559 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10561 // This may be a slow command. Exit command processing to allow for
10562 // context preemption and GPU watchdog checks.
10563 ExitCommandProcessingEarly();
10564 return error::kNoError;
10567 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size,
10568 const void* cmd_data) {
10569 const gles2::cmds::TexSubImage2D& c =
10570 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data);
10571 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D",
10572 "width", c.width, "height", c.height);
10573 GLboolean internal = static_cast<GLboolean>(c.internal);
10574 if (internal == GL_TRUE && texture_state_.tex_image_failed)
10575 return error::kNoError;
10577 GLenum target = static_cast<GLenum>(c.target);
10578 GLint level = static_cast<GLint>(c.level);
10579 GLint xoffset = static_cast<GLint>(c.xoffset);
10580 GLint yoffset = static_cast<GLint>(c.yoffset);
10581 GLsizei width = static_cast<GLsizei>(c.width);
10582 GLsizei height = static_cast<GLsizei>(c.height);
10583 GLenum format = static_cast<GLenum>(c.format);
10584 GLenum type = static_cast<GLenum>(c.type);
10585 uint32 data_size;
10586 if (!GLES2Util::ComputeImageDataSizes(
10587 width, height, 1, format, type, state_.unpack_alignment, &data_size,
10588 NULL, NULL)) {
10589 return error::kOutOfBounds;
10591 const void* pixels = GetSharedMemoryAs<const void*>(
10592 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10593 return DoTexSubImage2D(
10594 target, level, xoffset, yoffset, width, height, format, type, pixels);
10597 error::Error GLES2DecoderImpl::DoTexSubImage3D(
10598 GLenum target,
10599 GLint level,
10600 GLint xoffset,
10601 GLint yoffset,
10602 GLint zoffset,
10603 GLsizei width,
10604 GLsizei height,
10605 GLsizei depth,
10606 GLenum format,
10607 GLenum type,
10608 const void * data) {
10609 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
10610 &state_, target);
10611 if (!texture_ref) {
10612 LOCAL_SET_GL_ERROR(
10613 GL_INVALID_ENUM, "glTexSubImage3D", "invalid target");
10616 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexSubImage3D");
10617 ScopedTextureUploadTimer timer(&texture_state_);
10618 glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
10619 depth, format, type, data);
10620 GLenum error = LOCAL_PEEK_GL_ERROR("glTexSubImage3D");
10621 if (error == GL_NO_ERROR) {
10622 // TODO(zmo): This is not 100% correct because only part of the level
10623 // image is cleared.
10624 texture_manager()->SetLevelCleared(texture_ref, target, level, true);
10627 // This may be a slow command. Exit command processing to allow for
10628 // context preemption and GPU watchdog checks.
10629 ExitCommandProcessingEarly();
10630 return error::kNoError;
10633 error::Error GLES2DecoderImpl::HandleTexSubImage3D(uint32 immediate_data_size,
10634 const void* cmd_data) {
10635 if (!unsafe_es3_apis_enabled())
10636 return error::kUnknownCommand;
10638 const gles2::cmds::TexSubImage3D& c =
10639 *static_cast<const gles2::cmds::TexSubImage3D*>(cmd_data);
10640 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage3D",
10641 "widthXheight", c.width * c.height, "depth", c.depth);
10642 GLboolean internal = static_cast<GLboolean>(c.internal);
10643 if (internal == GL_TRUE && texture_state_.tex_image_failed)
10644 return error::kNoError;
10646 GLenum target = static_cast<GLenum>(c.target);
10647 GLint level = static_cast<GLint>(c.level);
10648 GLint xoffset = static_cast<GLint>(c.xoffset);
10649 GLint yoffset = static_cast<GLint>(c.yoffset);
10650 GLint zoffset = static_cast<GLint>(c.zoffset);
10651 GLsizei width = static_cast<GLsizei>(c.width);
10652 GLsizei height = static_cast<GLsizei>(c.height);
10653 GLsizei depth = static_cast<GLsizei>(c.depth);
10654 GLenum format = static_cast<GLenum>(c.format);
10655 GLenum type = static_cast<GLenum>(c.type);
10656 uint32 data_size;
10657 if (!GLES2Util::ComputeImageDataSizes(
10658 width, height, depth, format, type, state_.unpack_alignment, &data_size,
10659 NULL, NULL)) {
10660 return error::kOutOfBounds;
10662 const void* pixels = GetSharedMemoryAs<const void*>(
10663 c.pixels_shm_id, c.pixels_shm_offset, data_size);
10664 return DoTexSubImage3D(target, level, xoffset, yoffset, zoffset, width,
10665 height, depth, format, type, pixels);
10668 error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
10669 uint32 immediate_data_size,
10670 const void* cmd_data) {
10671 const gles2::cmds::GetVertexAttribPointerv& c =
10672 *static_cast<const gles2::cmds::GetVertexAttribPointerv*>(cmd_data);
10673 GLuint index = static_cast<GLuint>(c.index);
10674 GLenum pname = static_cast<GLenum>(c.pname);
10675 typedef cmds::GetVertexAttribPointerv::Result Result;
10676 Result* result = GetSharedMemoryAs<Result*>(
10677 c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1));
10678 if (!result) {
10679 return error::kOutOfBounds;
10681 // Check that the client initialized the result.
10682 if (result->size != 0) {
10683 return error::kInvalidArguments;
10685 if (!validators_->vertex_pointer.IsValid(pname)) {
10686 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10687 "glGetVertexAttribPointerv", pname, "pname");
10688 return error::kNoError;
10690 if (index >= group_->max_vertex_attribs()) {
10691 LOCAL_SET_GL_ERROR(
10692 GL_INVALID_VALUE, "glGetVertexAttribPointerv", "index out of range.");
10693 return error::kNoError;
10695 result->SetNumResults(1);
10696 *result->GetData() =
10697 state_.vertex_attrib_manager->GetVertexAttrib(index)->offset();
10698 return error::kNoError;
10701 template <class T>
10702 bool GLES2DecoderImpl::GetUniformSetup(GLuint program_id,
10703 GLint fake_location,
10704 uint32 shm_id,
10705 uint32 shm_offset,
10706 error::Error* error,
10707 GLint* real_location,
10708 GLuint* service_id,
10709 SizedResult<T>** result_pointer,
10710 GLenum* result_type,
10711 GLsizei* result_size) {
10712 DCHECK(error);
10713 DCHECK(service_id);
10714 DCHECK(result_pointer);
10715 DCHECK(result_type);
10716 DCHECK(result_size);
10717 DCHECK(real_location);
10718 *error = error::kNoError;
10719 // Make sure we have enough room for the result on failure.
10720 SizedResult<T>* result;
10721 result = GetSharedMemoryAs<SizedResult<T>*>(
10722 shm_id, shm_offset, SizedResult<T>::ComputeSize(0));
10723 if (!result) {
10724 *error = error::kOutOfBounds;
10725 return false;
10727 *result_pointer = result;
10728 // Set the result size to 0 so the client does not have to check for success.
10729 result->SetNumResults(0);
10730 Program* program = GetProgramInfoNotShader(program_id, "glGetUniform");
10731 if (!program) {
10732 return false;
10734 if (!program->IsValid()) {
10735 // Program was not linked successfully. (ie, glLinkProgram)
10736 LOCAL_SET_GL_ERROR(
10737 GL_INVALID_OPERATION, "glGetUniform", "program not linked");
10738 return false;
10740 *service_id = program->service_id();
10741 GLint array_index = -1;
10742 const Program::UniformInfo* uniform_info =
10743 program->GetUniformInfoByFakeLocation(
10744 fake_location, real_location, &array_index);
10745 if (!uniform_info) {
10746 // No such location.
10747 LOCAL_SET_GL_ERROR(
10748 GL_INVALID_OPERATION, "glGetUniform", "unknown location");
10749 return false;
10751 GLenum type = uniform_info->type;
10752 uint32 num_elements = GLES2Util::GetElementCountForUniformType(type);
10753 if (num_elements == 0) {
10754 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glGetUniform", "unknown type");
10755 return false;
10757 result = GetSharedMemoryAs<SizedResult<T>*>(
10758 shm_id, shm_offset, SizedResult<T>::ComputeSize(num_elements));
10759 if (!result) {
10760 *error = error::kOutOfBounds;
10761 return false;
10763 result->SetNumResults(num_elements);
10764 *result_size = num_elements * sizeof(T);
10765 *result_type = type;
10766 return true;
10769 error::Error GLES2DecoderImpl::HandleGetUniformiv(uint32 immediate_data_size,
10770 const void* cmd_data) {
10771 const gles2::cmds::GetUniformiv& c =
10772 *static_cast<const gles2::cmds::GetUniformiv*>(cmd_data);
10773 GLuint program = c.program;
10774 GLint fake_location = c.location;
10775 GLuint service_id;
10776 GLenum result_type;
10777 GLsizei result_size;
10778 GLint real_location = -1;
10779 Error error;
10780 cmds::GetUniformiv::Result* result;
10781 if (GetUniformSetup<GLint>(program, fake_location, c.params_shm_id,
10782 c.params_shm_offset, &error, &real_location,
10783 &service_id, &result, &result_type,
10784 &result_size)) {
10785 glGetUniformiv(
10786 service_id, real_location, result->GetData());
10788 return error;
10791 error::Error GLES2DecoderImpl::HandleGetUniformuiv(uint32 immediate_data_size,
10792 const void* cmd_data) {
10793 if (!unsafe_es3_apis_enabled())
10794 return error::kUnknownCommand;
10796 const gles2::cmds::GetUniformuiv& c =
10797 *static_cast<const gles2::cmds::GetUniformuiv*>(cmd_data);
10798 GLuint program = c.program;
10799 GLint fake_location = c.location;
10800 GLuint service_id;
10801 GLenum result_type;
10802 GLsizei result_size;
10803 GLint real_location = -1;
10804 Error error;
10805 cmds::GetUniformuiv::Result* result;
10806 if (GetUniformSetup<GLuint>(program, fake_location, c.params_shm_id,
10807 c.params_shm_offset, &error, &real_location,
10808 &service_id, &result, &result_type,
10809 &result_size)) {
10810 glGetUniformuiv(
10811 service_id, real_location, result->GetData());
10813 return error;
10816 error::Error GLES2DecoderImpl::HandleGetUniformfv(uint32 immediate_data_size,
10817 const void* cmd_data) {
10818 const gles2::cmds::GetUniformfv& c =
10819 *static_cast<const gles2::cmds::GetUniformfv*>(cmd_data);
10820 GLuint program = c.program;
10821 GLint fake_location = c.location;
10822 GLuint service_id;
10823 GLint real_location = -1;
10824 Error error;
10825 cmds::GetUniformfv::Result* result;
10826 GLenum result_type;
10827 GLsizei result_size;
10828 if (GetUniformSetup<GLfloat>(program, fake_location, c.params_shm_id,
10829 c.params_shm_offset, &error, &real_location,
10830 &service_id, &result, &result_type,
10831 &result_size)) {
10832 if (result_type == GL_BOOL || result_type == GL_BOOL_VEC2 ||
10833 result_type == GL_BOOL_VEC3 || result_type == GL_BOOL_VEC4) {
10834 GLsizei num_values = result_size / sizeof(GLfloat);
10835 scoped_ptr<GLint[]> temp(new GLint[num_values]);
10836 glGetUniformiv(service_id, real_location, temp.get());
10837 GLfloat* dst = result->GetData();
10838 for (GLsizei ii = 0; ii < num_values; ++ii) {
10839 dst[ii] = (temp[ii] != 0);
10841 } else {
10842 glGetUniformfv(service_id, real_location, result->GetData());
10845 return error;
10848 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
10849 uint32 immediate_data_size,
10850 const void* cmd_data) {
10851 const gles2::cmds::GetShaderPrecisionFormat& c =
10852 *static_cast<const gles2::cmds::GetShaderPrecisionFormat*>(cmd_data);
10853 GLenum shader_type = static_cast<GLenum>(c.shadertype);
10854 GLenum precision_type = static_cast<GLenum>(c.precisiontype);
10855 typedef cmds::GetShaderPrecisionFormat::Result Result;
10856 Result* result = GetSharedMemoryAs<Result*>(
10857 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10858 if (!result) {
10859 return error::kOutOfBounds;
10861 // Check that the client initialized the result.
10862 if (result->success != 0) {
10863 return error::kInvalidArguments;
10865 if (!validators_->shader_type.IsValid(shader_type)) {
10866 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10867 "glGetShaderPrecisionFormat", shader_type, "shader_type");
10868 return error::kNoError;
10870 if (!validators_->shader_precision.IsValid(precision_type)) {
10871 LOCAL_SET_GL_ERROR_INVALID_ENUM(
10872 "glGetShaderPrecisionFormat", precision_type, "precision_type");
10873 return error::kNoError;
10876 result->success = 1; // true
10878 GLint range[2] = { 0, 0 };
10879 GLint precision = 0;
10880 GetShaderPrecisionFormatImpl(shader_type, precision_type, range, &precision);
10882 result->min_range = range[0];
10883 result->max_range = range[1];
10884 result->precision = precision;
10886 return error::kNoError;
10889 error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
10890 uint32 immediate_data_size,
10891 const void* cmd_data) {
10892 const gles2::cmds::GetAttachedShaders& c =
10893 *static_cast<const gles2::cmds::GetAttachedShaders*>(cmd_data);
10894 uint32 result_size = c.result_size;
10895 GLuint program_id = static_cast<GLuint>(c.program);
10896 Program* program = GetProgramInfoNotShader(
10897 program_id, "glGetAttachedShaders");
10898 if (!program) {
10899 return error::kNoError;
10901 typedef cmds::GetAttachedShaders::Result Result;
10902 uint32 max_count = Result::ComputeMaxResults(result_size);
10903 Result* result = GetSharedMemoryAs<Result*>(
10904 c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count));
10905 if (!result) {
10906 return error::kOutOfBounds;
10908 // Check that the client initialized the result.
10909 if (result->size != 0) {
10910 return error::kInvalidArguments;
10912 GLsizei count = 0;
10913 glGetAttachedShaders(
10914 program->service_id(), max_count, &count, result->GetData());
10915 for (GLsizei ii = 0; ii < count; ++ii) {
10916 if (!shader_manager()->GetClientId(result->GetData()[ii],
10917 &result->GetData()[ii])) {
10918 NOTREACHED();
10919 return error::kGenericError;
10922 result->SetNumResults(count);
10923 return error::kNoError;
10926 error::Error GLES2DecoderImpl::HandleGetActiveUniform(
10927 uint32 immediate_data_size,
10928 const void* cmd_data) {
10929 const gles2::cmds::GetActiveUniform& c =
10930 *static_cast<const gles2::cmds::GetActiveUniform*>(cmd_data);
10931 GLuint program_id = c.program;
10932 GLuint index = c.index;
10933 uint32 name_bucket_id = c.name_bucket_id;
10934 typedef cmds::GetActiveUniform::Result Result;
10935 Result* result = GetSharedMemoryAs<Result*>(
10936 c.result_shm_id, c.result_shm_offset, sizeof(*result));
10937 if (!result) {
10938 return error::kOutOfBounds;
10940 // Check that the client initialized the result.
10941 if (result->success != 0) {
10942 return error::kInvalidArguments;
10944 Program* program = GetProgramInfoNotShader(
10945 program_id, "glGetActiveUniform");
10946 if (!program) {
10947 return error::kNoError;
10949 const Program::UniformInfo* uniform_info =
10950 program->GetUniformInfo(index);
10951 if (!uniform_info) {
10952 LOCAL_SET_GL_ERROR(
10953 GL_INVALID_VALUE, "glGetActiveUniform", "index out of range");
10954 return error::kNoError;
10956 result->success = 1; // true.
10957 result->size = uniform_info->size;
10958 result->type = uniform_info->type;
10959 Bucket* bucket = CreateBucket(name_bucket_id);
10960 bucket->SetFromString(uniform_info->name.c_str());
10961 return error::kNoError;
10964 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
10965 uint32 immediate_data_size, const void* cmd_data) {
10966 if (!unsafe_es3_apis_enabled())
10967 return error::kUnknownCommand;
10968 const gles2::cmds::GetActiveUniformBlockiv& c =
10969 *static_cast<const gles2::cmds::GetActiveUniformBlockiv*>(cmd_data);
10970 GLuint program_id = c.program;
10971 GLuint index = static_cast<GLuint>(c.index);
10972 GLenum pname = static_cast<GLenum>(c.pname);
10973 Program* program = GetProgramInfoNotShader(
10974 program_id, "glGetActiveUniformBlockiv");
10975 if (!program) {
10976 return error::kNoError;
10978 GLuint service_id = program->service_id();
10979 GLint link_status = GL_FALSE;
10980 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
10981 if (link_status != GL_TRUE) {
10982 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
10983 "glGetActiveActiveUniformBlockiv", "program not linked");
10984 return error::kNoError;
10986 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
10987 GLsizei num_values = 1;
10988 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
10989 GLint num = 0;
10990 glGetActiveUniformBlockiv(
10991 service_id, index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &num);
10992 GLenum error = glGetError();
10993 if (error != GL_NO_ERROR) {
10994 // Assume this will the same error if calling with pname.
10995 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
10996 return error::kNoError;
10998 num_values = static_cast<GLsizei>(num);
11000 typedef cmds::GetActiveUniformBlockiv::Result Result;
11001 Result* result = GetSharedMemoryAs<Result*>(
11002 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
11003 GLint* params = result ? result->GetData() : NULL;
11004 if (params == NULL) {
11005 return error::kOutOfBounds;
11007 // Check that the client initialized the result.
11008 if (result->size != 0) {
11009 return error::kInvalidArguments;
11011 glGetActiveUniformBlockiv(service_id, index, pname, params);
11012 GLenum error = glGetError();
11013 if (error == GL_NO_ERROR) {
11014 result->SetNumResults(num_values);
11015 } else {
11016 LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
11018 return error::kNoError;
11021 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName(
11022 uint32 immediate_data_size, const void* cmd_data) {
11023 if (!unsafe_es3_apis_enabled())
11024 return error::kUnknownCommand;
11025 const gles2::cmds::GetActiveUniformBlockName& c =
11026 *static_cast<const gles2::cmds::GetActiveUniformBlockName*>(cmd_data);
11027 GLuint program_id = c.program;
11028 GLuint index = c.index;
11029 uint32 name_bucket_id = c.name_bucket_id;
11030 typedef cmds::GetActiveUniformBlockName::Result Result;
11031 Result* result = GetSharedMemoryAs<Result*>(
11032 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11033 if (!result) {
11034 return error::kOutOfBounds;
11036 // Check that the client initialized the result.
11037 if (*result != 0) {
11038 return error::kInvalidArguments;
11040 Program* program = GetProgramInfoNotShader(
11041 program_id, "glGetActiveUniformBlockName");
11042 if (!program) {
11043 return error::kNoError;
11045 GLuint service_id = program->service_id();
11046 GLint link_status = GL_FALSE;
11047 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11048 if (link_status != GL_TRUE) {
11049 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11050 "glGetActiveActiveUniformBlockName", "program not linked");
11051 return error::kNoError;
11053 GLint max_length = 0;
11054 glGetProgramiv(
11055 service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_length);
11056 // Increase one so &buffer[0] is always valid.
11057 GLsizei buf_size = static_cast<GLsizei>(max_length) + 1;
11058 std::vector<char> buffer(buf_size);
11059 GLsizei length = 0;
11060 glGetActiveUniformBlockName(
11061 service_id, index, buf_size, &length, &buffer[0]);
11062 if (length == 0) {
11063 *result = 0;
11064 return error::kNoError;
11066 *result = 1;
11067 Bucket* bucket = CreateBucket(name_bucket_id);
11068 DCHECK_GT(buf_size, length);
11069 DCHECK_EQ(0, buffer[length]);
11070 bucket->SetFromString(&buffer[0]);
11071 return error::kNoError;
11074 error::Error GLES2DecoderImpl::HandleGetActiveUniformsiv(
11075 uint32 immediate_data_size, const void* cmd_data) {
11076 if (!unsafe_es3_apis_enabled())
11077 return error::kUnknownCommand;
11078 const gles2::cmds::GetActiveUniformsiv& c =
11079 *static_cast<const gles2::cmds::GetActiveUniformsiv*>(cmd_data);
11080 GLuint program_id = c.program;
11081 GLenum pname = static_cast<GLenum>(c.pname);
11082 Bucket* bucket = GetBucket(c.indices_bucket_id);
11083 if (!bucket) {
11084 return error::kInvalidArguments;
11086 GLsizei count = static_cast<GLsizei>(bucket->size() / sizeof(GLuint));
11087 const GLuint* indices = bucket->GetDataAs<const GLuint*>(0, bucket->size());
11088 typedef cmds::GetActiveUniformsiv::Result Result;
11089 Result* result = GetSharedMemoryAs<Result*>(
11090 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(count));
11091 GLint* params = result ? result->GetData() : NULL;
11092 if (params == NULL) {
11093 return error::kOutOfBounds;
11095 // Check that the client initialized the result.
11096 if (result->size != 0) {
11097 return error::kInvalidArguments;
11099 Program* program = GetProgramInfoNotShader(
11100 program_id, "glGetActiveUniformsiv");
11101 if (!program) {
11102 return error::kNoError;
11104 GLuint service_id = program->service_id();
11105 GLint link_status = GL_FALSE;
11106 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11107 if (link_status != GL_TRUE) {
11108 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11109 "glGetActiveUniformsiv", "program not linked");
11110 return error::kNoError;
11112 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
11113 glGetActiveUniformsiv(service_id, count, indices, pname, params);
11114 GLenum error = glGetError();
11115 if (error == GL_NO_ERROR) {
11116 result->SetNumResults(count);
11117 } else {
11118 LOCAL_SET_GL_ERROR(error, "GetActiveUniformsiv", "");
11120 return error::kNoError;
11123 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
11124 const void* cmd_data) {
11125 const gles2::cmds::GetActiveAttrib& c =
11126 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data);
11127 GLuint program_id = c.program;
11128 GLuint index = c.index;
11129 uint32 name_bucket_id = c.name_bucket_id;
11130 typedef cmds::GetActiveAttrib::Result Result;
11131 Result* result = GetSharedMemoryAs<Result*>(
11132 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11133 if (!result) {
11134 return error::kOutOfBounds;
11136 // Check that the client initialized the result.
11137 if (result->success != 0) {
11138 return error::kInvalidArguments;
11140 Program* program = GetProgramInfoNotShader(
11141 program_id, "glGetActiveAttrib");
11142 if (!program) {
11143 return error::kNoError;
11145 const Program::VertexAttrib* attrib_info =
11146 program->GetAttribInfo(index);
11147 if (!attrib_info) {
11148 LOCAL_SET_GL_ERROR(
11149 GL_INVALID_VALUE, "glGetActiveAttrib", "index out of range");
11150 return error::kNoError;
11152 result->success = 1; // true.
11153 result->size = attrib_info->size;
11154 result->type = attrib_info->type;
11155 Bucket* bucket = CreateBucket(name_bucket_id);
11156 bucket->SetFromString(attrib_info->name.c_str());
11157 return error::kNoError;
11160 error::Error GLES2DecoderImpl::HandleShaderBinary(uint32 immediate_data_size,
11161 const void* cmd_data) {
11162 #if 1 // No binary shader support.
11163 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glShaderBinary", "not supported");
11164 return error::kNoError;
11165 #else
11166 GLsizei n = static_cast<GLsizei>(c.n);
11167 if (n < 0) {
11168 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "n < 0");
11169 return error::kNoError;
11171 GLsizei length = static_cast<GLsizei>(c.length);
11172 if (length < 0) {
11173 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "length < 0");
11174 return error::kNoError;
11176 uint32 data_size;
11177 if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) {
11178 return error::kOutOfBounds;
11180 const GLuint* shaders = GetSharedMemoryAs<const GLuint*>(
11181 c.shaders_shm_id, c.shaders_shm_offset, data_size);
11182 GLenum binaryformat = static_cast<GLenum>(c.binaryformat);
11183 const void* binary = GetSharedMemoryAs<const void*>(
11184 c.binary_shm_id, c.binary_shm_offset, length);
11185 if (shaders == NULL || binary == NULL) {
11186 return error::kOutOfBounds;
11188 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
11189 for (GLsizei ii = 0; ii < n; ++ii) {
11190 Shader* shader = GetShader(shaders[ii]);
11191 if (!shader) {
11192 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glShaderBinary", "unknown shader");
11193 return error::kNoError;
11195 service_ids[ii] = shader->service_id();
11197 // TODO(gman): call glShaderBinary
11198 return error::kNoError;
11199 #endif
11202 void GLES2DecoderImpl::DoSwapBuffers() {
11203 bool is_offscreen = !!offscreen_target_frame_buffer_.get();
11205 int this_frame_number = frame_number_++;
11206 // TRACE_EVENT for gpu tests:
11207 TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffersLatency",
11208 TRACE_EVENT_SCOPE_THREAD,
11209 "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
11210 "width", (is_offscreen ? offscreen_size_.width() :
11211 surface_->GetSize().width()));
11212 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoSwapBuffers",
11213 "offscreen", is_offscreen,
11214 "frame", this_frame_number);
11216 TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
11219 ScopedGPUTrace scoped_gpu_trace(gpu_tracer_.get(), kTraceDecoder,
11220 "GLES2Decoder", "SwapBuffer");
11222 bool is_tracing;
11223 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
11224 &is_tracing);
11225 if (is_tracing) {
11226 ScopedFrameBufferBinder binder(this, GetBackbufferServiceId());
11227 gpu_state_tracer_->TakeSnapshotWithCurrentFramebuffer(
11228 is_offscreen ? offscreen_size_ : surface_->GetSize());
11231 // If offscreen then don't actually SwapBuffers to the display. Just copy
11232 // the rendered frame to another frame buffer.
11233 if (is_offscreen) {
11234 TRACE_EVENT2("gpu", "Offscreen",
11235 "width", offscreen_size_.width(), "height", offscreen_size_.height());
11236 if (offscreen_size_ != offscreen_saved_color_texture_->size()) {
11237 // Workaround for NVIDIA driver bug on OS X; crbug.com/89557,
11238 // crbug.com/94163. TODO(kbr): figure out reproduction so Apple will
11239 // fix this.
11240 if (workarounds().needs_offscreen_buffer_workaround) {
11241 offscreen_saved_frame_buffer_->Create();
11242 glFinish();
11245 // Allocate the offscreen saved color texture.
11246 DCHECK(offscreen_saved_color_format_);
11247 offscreen_saved_color_texture_->AllocateStorage(
11248 offscreen_size_, offscreen_saved_color_format_, false);
11250 offscreen_saved_frame_buffer_->AttachRenderTexture(
11251 offscreen_saved_color_texture_.get());
11252 if (offscreen_size_.width() != 0 && offscreen_size_.height() != 0) {
11253 if (offscreen_saved_frame_buffer_->CheckStatus() !=
11254 GL_FRAMEBUFFER_COMPLETE) {
11255 LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
11256 << "because offscreen saved FBO was incomplete.";
11257 MarkContextLost(error::kUnknown);
11258 group_->LoseContexts(error::kUnknown);
11259 return;
11262 // Clear the offscreen color texture.
11263 // TODO(piman): Is this still necessary?
11265 ScopedFrameBufferBinder binder(this,
11266 offscreen_saved_frame_buffer_->id());
11267 glClearColor(0, 0, 0, 0);
11268 state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
11269 state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
11270 glClear(GL_COLOR_BUFFER_BIT);
11271 RestoreClearState();
11275 UpdateParentTextureInfo();
11278 if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
11279 return;
11280 ScopedGLErrorSuppressor suppressor(
11281 "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
11283 if (IsOffscreenBufferMultisampled()) {
11284 // For multisampled buffers, resolve the frame buffer.
11285 ScopedResolvedFrameBufferBinder binder(this, true, false);
11286 } else {
11287 ScopedFrameBufferBinder binder(this,
11288 offscreen_target_frame_buffer_->id());
11290 if (offscreen_target_buffer_preserved_) {
11291 // Copy the target frame buffer to the saved offscreen texture.
11292 offscreen_saved_color_texture_->Copy(
11293 offscreen_saved_color_texture_->size(),
11294 offscreen_saved_color_format_);
11295 } else {
11296 // Flip the textures in the parent context via the texture manager.
11297 if (!!offscreen_saved_color_texture_info_.get())
11298 offscreen_saved_color_texture_info_->texture()->
11299 SetServiceId(offscreen_target_color_texture_->id());
11301 offscreen_saved_color_texture_.swap(offscreen_target_color_texture_);
11302 offscreen_target_frame_buffer_->AttachRenderTexture(
11303 offscreen_target_color_texture_.get());
11306 // Ensure the side effects of the copy are visible to the parent
11307 // context. There is no need to do this for ANGLE because it uses a
11308 // single D3D device for all contexts.
11309 if (!feature_info_->gl_version_info().is_angle)
11310 glFlush();
11312 } else {
11313 if (surface_->SwapBuffers() == gfx::SwapResult::SWAP_FAILED) {
11314 LOG(ERROR) << "Context lost because SwapBuffers failed.";
11315 if (!CheckResetStatus()) {
11316 MarkContextLost(error::kUnknown);
11317 group_->LoseContexts(error::kUnknown);
11322 // This may be a slow command. Exit command processing to allow for
11323 // context preemption and GPU watchdog checks.
11324 ExitCommandProcessingEarly();
11327 void GLES2DecoderImpl::DoSwapInterval(int interval) {
11328 context_->SetSwapInterval(interval);
11331 error::Error GLES2DecoderImpl::HandleEnableFeatureCHROMIUM(
11332 uint32 immediate_data_size,
11333 const void* cmd_data) {
11334 const gles2::cmds::EnableFeatureCHROMIUM& c =
11335 *static_cast<const gles2::cmds::EnableFeatureCHROMIUM*>(cmd_data);
11336 Bucket* bucket = GetBucket(c.bucket_id);
11337 if (!bucket || bucket->size() == 0) {
11338 return error::kInvalidArguments;
11340 typedef cmds::EnableFeatureCHROMIUM::Result Result;
11341 Result* result = GetSharedMemoryAs<Result*>(
11342 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11343 if (!result) {
11344 return error::kOutOfBounds;
11346 // Check that the client initialized the result.
11347 if (*result != 0) {
11348 return error::kInvalidArguments;
11350 std::string feature_str;
11351 if (!bucket->GetAsString(&feature_str)) {
11352 return error::kInvalidArguments;
11355 // TODO(gman): make this some kind of table to function pointer thingy.
11356 if (feature_str.compare("pepper3d_allow_buffers_on_multiple_targets") == 0) {
11357 buffer_manager()->set_allow_buffers_on_multiple_targets(true);
11358 } else if (feature_str.compare("pepper3d_support_fixed_attribs") == 0) {
11359 buffer_manager()->set_allow_fixed_attribs(true);
11360 // TODO(gman): decide how to remove the need for this const_cast.
11361 // I could make validators_ non const but that seems bad as this is the only
11362 // place it is needed. I could make some special friend class of validators
11363 // just to allow this to set them. That seems silly. I could refactor this
11364 // code to use the extension mechanism or the initialization attributes to
11365 // turn this feature on. Given that the only real point of this is to make
11366 // the conformance tests pass and given that there is lots of real work that
11367 // needs to be done it seems like refactoring for one to one of those
11368 // methods is a very low priority.
11369 const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
11370 } else {
11371 return error::kNoError;
11374 *result = 1; // true.
11375 return error::kNoError;
11378 error::Error GLES2DecoderImpl::HandleGetRequestableExtensionsCHROMIUM(
11379 uint32 immediate_data_size,
11380 const void* cmd_data) {
11381 const gles2::cmds::GetRequestableExtensionsCHROMIUM& c =
11382 *static_cast<const gles2::cmds::GetRequestableExtensionsCHROMIUM*>(
11383 cmd_data);
11384 Bucket* bucket = CreateBucket(c.bucket_id);
11385 scoped_refptr<FeatureInfo> info(new FeatureInfo());
11386 info->Initialize(disallowed_features_);
11387 bucket->SetFromString(info->extensions().c_str());
11388 return error::kNoError;
11391 error::Error GLES2DecoderImpl::HandleRequestExtensionCHROMIUM(
11392 uint32 immediate_data_size,
11393 const void* cmd_data) {
11394 const gles2::cmds::RequestExtensionCHROMIUM& c =
11395 *static_cast<const gles2::cmds::RequestExtensionCHROMIUM*>(cmd_data);
11396 Bucket* bucket = GetBucket(c.bucket_id);
11397 if (!bucket || bucket->size() == 0) {
11398 return error::kInvalidArguments;
11400 std::string feature_str;
11401 if (!bucket->GetAsString(&feature_str)) {
11402 return error::kInvalidArguments;
11405 bool desire_standard_derivatives = false;
11406 bool desire_frag_depth = false;
11407 bool desire_draw_buffers = false;
11408 bool desire_shader_texture_lod = false;
11409 if (IsWebGLContext()) {
11410 desire_standard_derivatives =
11411 feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
11412 desire_frag_depth =
11413 feature_str.find("GL_EXT_frag_depth") != std::string::npos;
11414 desire_draw_buffers =
11415 feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
11416 desire_shader_texture_lod =
11417 feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
11420 if (desire_standard_derivatives != derivatives_explicitly_enabled_ ||
11421 desire_frag_depth != frag_depth_explicitly_enabled_ ||
11422 desire_draw_buffers != draw_buffers_explicitly_enabled_ ||
11423 desire_shader_texture_lod != shader_texture_lod_explicitly_enabled_) {
11424 derivatives_explicitly_enabled_ |= desire_standard_derivatives;
11425 frag_depth_explicitly_enabled_ |= desire_frag_depth;
11426 draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
11427 shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
11428 InitializeShaderTranslator();
11431 UpdateCapabilities();
11433 return error::kNoError;
11436 error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM(
11437 uint32 immediate_data_size,
11438 const void* cmd_data) {
11439 const gles2::cmds::GetProgramInfoCHROMIUM& c =
11440 *static_cast<const gles2::cmds::GetProgramInfoCHROMIUM*>(cmd_data);
11441 GLuint program_id = static_cast<GLuint>(c.program);
11442 uint32 bucket_id = c.bucket_id;
11443 Bucket* bucket = CreateBucket(bucket_id);
11444 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail.
11445 Program* program = NULL;
11446 program = GetProgram(program_id);
11447 if (!program || !program->IsValid()) {
11448 return error::kNoError;
11450 program->GetProgramInfo(program_manager(), bucket);
11451 return error::kNoError;
11454 error::Error GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM(
11455 uint32 immediate_data_size, const void* cmd_data) {
11456 if (!unsafe_es3_apis_enabled())
11457 return error::kUnknownCommand;
11458 const gles2::cmds::GetUniformBlocksCHROMIUM& c =
11459 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM*>(cmd_data);
11460 GLuint program_id = static_cast<GLuint>(c.program);
11461 uint32 bucket_id = c.bucket_id;
11462 Bucket* bucket = CreateBucket(bucket_id);
11463 bucket->SetSize(sizeof(UniformBlocksHeader)); // in case we fail.
11464 Program* program = NULL;
11465 program = GetProgram(program_id);
11466 if (!program || !program->IsValid()) {
11467 return error::kNoError;
11469 program->GetUniformBlocks(bucket);
11470 return error::kNoError;
11473 error::Error GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
11474 uint32 immediate_data_size, const void* cmd_data) {
11475 if (!unsafe_es3_apis_enabled())
11476 return error::kUnknownCommand;
11477 const gles2::cmds::GetUniformsES3CHROMIUM& c =
11478 *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM*>(cmd_data);
11479 GLuint program_id = static_cast<GLuint>(c.program);
11480 uint32 bucket_id = c.bucket_id;
11481 Bucket* bucket = CreateBucket(bucket_id);
11482 bucket->SetSize(sizeof(UniformsES3Header)); // in case we fail.
11483 Program* program = NULL;
11484 program = GetProgram(program_id);
11485 if (!program || !program->IsValid()) {
11486 return error::kNoError;
11488 program->GetUniformsES3(bucket);
11489 return error::kNoError;
11492 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
11493 uint32 immediate_data_size,
11494 const void* cmd_data) {
11495 if (!unsafe_es3_apis_enabled())
11496 return error::kUnknownCommand;
11497 const gles2::cmds::GetTransformFeedbackVarying& c =
11498 *static_cast<const gles2::cmds::GetTransformFeedbackVarying*>(cmd_data);
11499 GLuint program_id = c.program;
11500 GLuint index = c.index;
11501 uint32 name_bucket_id = c.name_bucket_id;
11502 typedef cmds::GetTransformFeedbackVarying::Result Result;
11503 Result* result = GetSharedMemoryAs<Result*>(
11504 c.result_shm_id, c.result_shm_offset, sizeof(*result));
11505 if (!result) {
11506 return error::kOutOfBounds;
11508 // Check that the client initialized the result.
11509 if (result->success != 0) {
11510 return error::kInvalidArguments;
11512 Program* program = GetProgramInfoNotShader(
11513 program_id, "glGetTransformFeedbackVarying");
11514 if (!program) {
11515 return error::kNoError;
11517 GLuint service_id = program->service_id();
11518 GLint link_status = GL_FALSE;
11519 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
11520 if (link_status != GL_TRUE) {
11521 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11522 "glGetTransformFeedbackVarying", "program not linked");
11523 return error::kNoError;
11525 GLint max_length = 0;
11526 glGetProgramiv(
11527 service_id, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_length);
11528 max_length = std::max(1, max_length);
11529 std::vector<char> buffer(max_length);
11530 GLsizei length = 0;
11531 GLsizei size = 0;
11532 GLenum type = 0;
11533 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
11534 glGetTransformFeedbackVarying(
11535 service_id, index, max_length, &length, &size, &type, &buffer[0]);
11536 GLenum error = glGetError();
11537 if (error != GL_NO_ERROR) {
11538 LOCAL_SET_GL_ERROR(error, "glGetTransformFeedbackVarying", "");
11539 return error::kNoError;
11541 result->success = 1; // true.
11542 result->size = static_cast<int32_t>(size);
11543 result->type = static_cast<uint32_t>(type);
11544 Bucket* bucket = CreateBucket(name_bucket_id);
11545 DCHECK(length >= 0 && length < max_length);
11546 buffer[length] = '\0'; // Just to be safe.
11547 bucket->SetFromString(&buffer[0]);
11548 return error::kNoError;
11551 error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
11552 uint32 immediate_data_size, const void* cmd_data) {
11553 if (!unsafe_es3_apis_enabled())
11554 return error::kUnknownCommand;
11555 const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM& c =
11556 *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM*>(
11557 cmd_data);
11558 GLuint program_id = static_cast<GLuint>(c.program);
11559 uint32 bucket_id = c.bucket_id;
11560 Bucket* bucket = CreateBucket(bucket_id);
11561 bucket->SetSize(sizeof(TransformFeedbackVaryingsHeader)); // in case we fail.
11562 Program* program = NULL;
11563 program = GetProgram(program_id);
11564 if (!program || !program->IsValid()) {
11565 return error::kNoError;
11567 program->GetTransformFeedbackVaryings(bucket);
11568 return error::kNoError;
11571 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
11572 return context_lost_reason_;
11575 error::ContextLostReason GLES2DecoderImpl::GetContextLostReasonFromResetStatus(
11576 GLenum reset_status) const {
11577 switch (reset_status) {
11578 case GL_NO_ERROR:
11579 // TODO(kbr): improve the precision of the error code in this case.
11580 // Consider delegating to context for error code if MakeCurrent fails.
11581 return error::kUnknown;
11582 case GL_GUILTY_CONTEXT_RESET_ARB:
11583 return error::kGuilty;
11584 case GL_INNOCENT_CONTEXT_RESET_ARB:
11585 return error::kInnocent;
11586 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11587 return error::kUnknown;
11590 NOTREACHED();
11591 return error::kUnknown;
11594 bool GLES2DecoderImpl::WasContextLost() const {
11595 return context_was_lost_;
11598 bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const {
11599 return WasContextLost() && reset_by_robustness_extension_;
11602 void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason) {
11603 // Only lose the context once.
11604 if (WasContextLost())
11605 return;
11607 // Don't make GL calls in here, the context might not be current.
11608 context_lost_reason_ = reason;
11609 current_decoder_error_ = error::kLostContext;
11610 context_was_lost_ = true;
11613 bool GLES2DecoderImpl::CheckResetStatus() {
11614 DCHECK(!WasContextLost());
11615 DCHECK(context_->IsCurrent(NULL));
11617 if (IsRobustnessSupported()) {
11618 // If the reason for the call was a GL error, we can try to determine the
11619 // reset status more accurately.
11620 GLenum driver_status = glGetGraphicsResetStatusARB();
11621 if (driver_status == GL_NO_ERROR)
11622 return false;
11624 LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen")
11625 << " context lost via ARB/EXT_robustness. Reset status = "
11626 << GLES2Util::GetStringEnum(driver_status);
11628 // Don't pretend we know which client was responsible.
11629 if (workarounds().use_virtualized_gl_contexts)
11630 driver_status = GL_UNKNOWN_CONTEXT_RESET_ARB;
11632 switch (driver_status) {
11633 case GL_GUILTY_CONTEXT_RESET_ARB:
11634 MarkContextLost(error::kGuilty);
11635 break;
11636 case GL_INNOCENT_CONTEXT_RESET_ARB:
11637 MarkContextLost(error::kInnocent);
11638 break;
11639 case GL_UNKNOWN_CONTEXT_RESET_ARB:
11640 MarkContextLost(error::kUnknown);
11641 break;
11642 default:
11643 NOTREACHED();
11644 return false;
11646 reset_by_robustness_extension_ = true;
11647 return true;
11649 return false;
11652 error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM(
11653 uint32 immediate_data_size,
11654 const void* cmd_data) {
11655 return error::kUnknownCommand;
11658 error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
11659 uint32 immediate_data_size,
11660 const void* cmd_data) {
11661 const gles2::cmds::WaitSyncPointCHROMIUM& c =
11662 *static_cast<const gles2::cmds::WaitSyncPointCHROMIUM*>(cmd_data);
11663 uint32 sync_point = c.sync_point;
11664 if (wait_sync_point_callback_.is_null())
11665 return error::kNoError;
11667 return wait_sync_point_callback_.Run(sync_point) ?
11668 error::kNoError : error::kDeferCommandUntilLater;
11671 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
11672 uint32 immediate_data_size,
11673 const void* cmd_data) {
11674 if (surface_->DeferDraws())
11675 return error::kDeferCommandUntilLater;
11676 if (!surface_->SetBackbufferAllocation(false))
11677 return error::kLostContext;
11678 backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
11679 backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
11680 backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
11681 return error::kNoError;
11684 bool GLES2DecoderImpl::GenQueriesEXTHelper(
11685 GLsizei n, const GLuint* client_ids) {
11686 for (GLsizei ii = 0; ii < n; ++ii) {
11687 if (query_manager_->GetQuery(client_ids[ii])) {
11688 return false;
11691 query_manager_->GenQueries(n, client_ids);
11692 return true;
11695 void GLES2DecoderImpl::DeleteQueriesEXTHelper(
11696 GLsizei n, const GLuint* client_ids) {
11697 for (GLsizei ii = 0; ii < n; ++ii) {
11698 query_manager_->RemoveQuery(client_ids[ii]);
11702 bool GLES2DecoderImpl::ProcessPendingQueries(bool did_finish) {
11703 if (query_manager_.get() == NULL) {
11704 return false;
11706 if (!query_manager_->ProcessPendingQueries(did_finish)) {
11707 current_decoder_error_ = error::kOutOfBounds;
11709 return query_manager_->HavePendingQueries();
11712 // Note that if there are no pending readpixels right now,
11713 // this function will call the callback immediately.
11714 void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
11715 if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
11716 pending_readpixel_fences_.back()->callbacks.push_back(callback);
11717 } else {
11718 callback.Run();
11722 void GLES2DecoderImpl::ProcessPendingReadPixels(bool did_finish) {
11723 // Note: |did_finish| guarantees that the GPU has passed the fence but
11724 // we cannot assume that GLFence::HasCompleted() will return true yet as
11725 // that's not guaranteed by all GLFence implementations.
11726 while (!pending_readpixel_fences_.empty() &&
11727 (did_finish ||
11728 pending_readpixel_fences_.front()->fence->HasCompleted())) {
11729 std::vector<base::Closure> callbacks =
11730 pending_readpixel_fences_.front()->callbacks;
11731 pending_readpixel_fences_.pop();
11732 for (size_t i = 0; i < callbacks.size(); i++) {
11733 callbacks[i].Run();
11738 bool GLES2DecoderImpl::HasMoreIdleWork() {
11739 return !pending_readpixel_fences_.empty() ||
11740 async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers() ||
11741 gpu_tracer_->HasTracesToProcess();
11744 void GLES2DecoderImpl::PerformIdleWork() {
11745 gpu_tracer_->ProcessTraces();
11746 ProcessPendingReadPixels(false);
11747 if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
11748 return;
11749 async_pixel_transfer_manager_->ProcessMorePendingTransfers();
11750 ProcessFinishedAsyncTransfers();
11753 error::Error GLES2DecoderImpl::HandleBeginQueryEXT(uint32 immediate_data_size,
11754 const void* cmd_data) {
11755 const gles2::cmds::BeginQueryEXT& c =
11756 *static_cast<const gles2::cmds::BeginQueryEXT*>(cmd_data);
11757 GLenum target = static_cast<GLenum>(c.target);
11758 GLuint client_id = static_cast<GLuint>(c.id);
11759 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11760 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11762 switch (target) {
11763 case GL_COMMANDS_ISSUED_CHROMIUM:
11764 case GL_LATENCY_QUERY_CHROMIUM:
11765 case GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM:
11766 case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
11767 case GL_GET_ERROR_QUERY_CHROMIUM:
11768 break;
11769 case GL_COMMANDS_COMPLETED_CHROMIUM:
11770 if (!features().chromium_sync_query) {
11771 LOCAL_SET_GL_ERROR(
11772 GL_INVALID_OPERATION, "glBeginQueryEXT",
11773 "not enabled for commands completed queries");
11774 return error::kNoError;
11776 break;
11777 case GL_SAMPLES_PASSED:
11778 case GL_ANY_SAMPLES_PASSED:
11779 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
11780 if (!features().occlusion_query_boolean) {
11781 LOCAL_SET_GL_ERROR(
11782 GL_INVALID_OPERATION, "glBeginQueryEXT",
11783 "not enabled for occlusion queries");
11784 return error::kNoError;
11786 break;
11787 case GL_TIME_ELAPSED:
11788 if (!query_manager_->GPUTimingAvailable()) {
11789 LOCAL_SET_GL_ERROR(
11790 GL_INVALID_OPERATION, "glBeginQueryEXT",
11791 "not enabled for timing queries");
11792 return error::kNoError;
11794 break;
11795 default:
11796 LOCAL_SET_GL_ERROR(
11797 GL_INVALID_ENUM, "glBeginQueryEXT",
11798 "unknown query target");
11799 return error::kNoError;
11802 if (query_manager_->GetActiveQuery(target)) {
11803 LOCAL_SET_GL_ERROR(
11804 GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");
11805 return error::kNoError;
11808 if (client_id == 0) {
11809 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginQueryEXT", "id is 0");
11810 return error::kNoError;
11813 QueryManager::Query* query = query_manager_->GetQuery(client_id);
11814 if (!query) {
11815 if (!query_manager_->IsValidQuery(client_id)) {
11816 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11817 "glBeginQueryEXT",
11818 "id not made by glGenQueriesEXT");
11819 return error::kNoError;
11821 query = query_manager_->CreateQuery(
11822 target, client_id, sync_shm_id, sync_shm_offset);
11825 if (query->target() != target) {
11826 LOCAL_SET_GL_ERROR(
11827 GL_INVALID_OPERATION, "glBeginQueryEXT", "target does not match");
11828 return error::kNoError;
11829 } else if (query->shm_id() != sync_shm_id ||
11830 query->shm_offset() != sync_shm_offset) {
11831 DLOG(ERROR) << "Shared memory used by query not the same as before";
11832 return error::kInvalidArguments;
11835 if (!query_manager_->BeginQuery(query)) {
11836 return error::kOutOfBounds;
11839 return error::kNoError;
11842 error::Error GLES2DecoderImpl::HandleEndQueryEXT(uint32 immediate_data_size,
11843 const void* cmd_data) {
11844 const gles2::cmds::EndQueryEXT& c =
11845 *static_cast<const gles2::cmds::EndQueryEXT*>(cmd_data);
11846 GLenum target = static_cast<GLenum>(c.target);
11847 uint32 submit_count = static_cast<GLuint>(c.submit_count);
11849 QueryManager::Query* query = query_manager_->GetActiveQuery(target);
11850 if (!query) {
11851 LOCAL_SET_GL_ERROR(
11852 GL_INVALID_OPERATION, "glEndQueryEXT", "No active query");
11853 return error::kNoError;
11856 if (!query_manager_->EndQuery(query, submit_count)) {
11857 return error::kOutOfBounds;
11860 query_manager_->ProcessPendingTransferQueries();
11862 return error::kNoError;
11865 error::Error GLES2DecoderImpl::HandleQueryCounterEXT(uint32 immediate_data_size,
11866 const void* cmd_data) {
11867 const gles2::cmds::QueryCounterEXT& c =
11868 *static_cast<const gles2::cmds::QueryCounterEXT*>(cmd_data);
11869 GLuint client_id = static_cast<GLuint>(c.id);
11870 GLenum target = static_cast<GLenum>(c.target);
11871 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11872 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11873 uint32 submit_count = static_cast<GLuint>(c.submit_count);
11875 switch (target) {
11876 case GL_TIMESTAMP:
11877 if (!query_manager_->GPUTimingAvailable()) {
11878 LOCAL_SET_GL_ERROR(
11879 GL_INVALID_OPERATION, "glQueryCounterEXT",
11880 "not enabled for timing queries");
11881 return error::kNoError;
11883 break;
11884 default:
11885 LOCAL_SET_GL_ERROR(
11886 GL_INVALID_ENUM, "glQueryCounterEXT",
11887 "unknown query target");
11888 return error::kNoError;
11891 QueryManager::Query* query = query_manager_->GetQuery(client_id);
11892 if (!query) {
11893 if (!query_manager_->IsValidQuery(client_id)) {
11894 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
11895 "glQueryCounterEXT",
11896 "id not made by glGenQueriesEXT");
11897 return error::kNoError;
11899 query = query_manager_->CreateQuery(
11900 target, client_id, sync_shm_id, sync_shm_offset);
11902 if (!query_manager_->QueryCounter(query, submit_count)) {
11903 return error::kOutOfBounds;
11906 return error::kNoError;
11909 error::Error GLES2DecoderImpl::HandleSetDisjointValueSyncCHROMIUM(
11910 uint32 immediate_data_size, const void* cmd_data) {
11911 const gles2::cmds::SetDisjointValueSyncCHROMIUM& c =
11912 *static_cast<const gles2::cmds::SetDisjointValueSyncCHROMIUM*>(cmd_data);
11913 int32 sync_shm_id = static_cast<int32>(c.sync_data_shm_id);
11914 uint32 sync_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
11916 query_manager_->SetDisjointSync(sync_shm_id, sync_shm_offset);
11917 return error::kNoError;
11920 bool GLES2DecoderImpl::GenVertexArraysOESHelper(
11921 GLsizei n, const GLuint* client_ids) {
11922 for (GLsizei ii = 0; ii < n; ++ii) {
11923 if (GetVertexAttribManager(client_ids[ii])) {
11924 return false;
11928 if (!features().native_vertex_array_object) {
11929 // Emulated VAO
11930 for (GLsizei ii = 0; ii < n; ++ii) {
11931 CreateVertexAttribManager(client_ids[ii], 0, true);
11933 } else {
11934 scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
11936 glGenVertexArraysOES(n, service_ids.get());
11937 for (GLsizei ii = 0; ii < n; ++ii) {
11938 CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
11942 return true;
11945 void GLES2DecoderImpl::DeleteVertexArraysOESHelper(
11946 GLsizei n, const GLuint* client_ids) {
11947 for (GLsizei ii = 0; ii < n; ++ii) {
11948 VertexAttribManager* vao =
11949 GetVertexAttribManager(client_ids[ii]);
11950 if (vao && !vao->IsDeleted()) {
11951 if (state_.vertex_attrib_manager.get() == vao) {
11952 DoBindVertexArrayOES(0);
11954 RemoveVertexAttribManager(client_ids[ii]);
11959 void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
11960 VertexAttribManager* vao = NULL;
11961 if (client_id != 0) {
11962 vao = GetVertexAttribManager(client_id);
11963 if (!vao) {
11964 // Unlike most Bind* methods, the spec explicitly states that VertexArray
11965 // only allows names that have been previously generated. As such, we do
11966 // not generate new names here.
11967 LOCAL_SET_GL_ERROR(
11968 GL_INVALID_OPERATION,
11969 "glBindVertexArrayOES", "bad vertex array id.");
11970 current_decoder_error_ = error::kNoError;
11971 return;
11973 } else {
11974 vao = state_.default_vertex_attrib_manager.get();
11977 // Only set the VAO state if it's changed
11978 if (state_.vertex_attrib_manager.get() != vao) {
11979 state_.vertex_attrib_manager = vao;
11980 if (!features().native_vertex_array_object) {
11981 EmulateVertexArrayState();
11982 } else {
11983 GLuint service_id = vao->service_id();
11984 glBindVertexArrayOES(service_id);
11989 // Used when OES_vertex_array_object isn't natively supported
11990 void GLES2DecoderImpl::EmulateVertexArrayState() {
11991 // Setup the Vertex attribute state
11992 for (uint32 vv = 0; vv < group_->max_vertex_attribs(); ++vv) {
11993 RestoreStateForAttrib(vv, true);
11996 // Setup the element buffer
11997 Buffer* element_array_buffer =
11998 state_.vertex_attrib_manager->element_array_buffer();
11999 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
12000 element_array_buffer ? element_array_buffer->service_id() : 0);
12003 bool GLES2DecoderImpl::DoIsVertexArrayOES(GLuint client_id) {
12004 const VertexAttribManager* vao =
12005 GetVertexAttribManager(client_id);
12006 return vao && vao->IsValid() && !vao->IsDeleted();
12009 bool GLES2DecoderImpl::DoIsPathCHROMIUM(GLuint client_id) {
12010 GLuint service_id = 0;
12011 return path_manager()->GetPath(client_id, &service_id) &&
12012 glIsPathNV(service_id) == GL_TRUE;
12015 #if defined(OS_MACOSX)
12016 void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) {
12017 TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find(
12018 texture_id);
12019 if (it != texture_to_io_surface_map_.end()) {
12020 // Found a previous IOSurface bound to this texture; release it.
12021 IOSurfaceRef surface = it->second;
12022 CFRelease(surface);
12023 texture_to_io_surface_map_.erase(it);
12026 #endif
12028 void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
12029 GLenum target, GLsizei width, GLsizei height,
12030 GLuint io_surface_id, GLuint plane) {
12031 #if defined(OS_MACOSX)
12032 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
12033 LOCAL_SET_GL_ERROR(
12034 GL_INVALID_OPERATION,
12035 "glTexImageIOSurface2DCHROMIUM", "only supported on desktop GL.");
12036 return;
12039 if (target != GL_TEXTURE_RECTANGLE_ARB) {
12040 // This might be supported in the future, and if we could require
12041 // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we
12042 // could delete a lot of code. For now, perform strict validation so we
12043 // know what's going on.
12044 LOCAL_SET_GL_ERROR(
12045 GL_INVALID_OPERATION,
12046 "glTexImageIOSurface2DCHROMIUM",
12047 "requires TEXTURE_RECTANGLE_ARB target");
12048 return;
12051 // Default target might be conceptually valid, but disallow it to avoid
12052 // accidents.
12053 TextureRef* texture_ref =
12054 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
12055 if (!texture_ref) {
12056 LOCAL_SET_GL_ERROR(
12057 GL_INVALID_OPERATION,
12058 "glTexImageIOSurface2DCHROMIUM", "no rectangle texture bound");
12059 return;
12062 // Look up the new IOSurface. Note that because of asynchrony
12063 // between processes this might fail; during live resizing the
12064 // plugin process might allocate and release an IOSurface before
12065 // this process gets a chance to look it up. Hold on to any old
12066 // IOSurface in this case.
12067 IOSurfaceRef surface = IOSurfaceLookup(io_surface_id);
12068 if (!surface) {
12069 LOCAL_SET_GL_ERROR(
12070 GL_INVALID_OPERATION,
12071 "glTexImageIOSurface2DCHROMIUM", "no IOSurface with the given ID");
12072 return;
12075 // Release any IOSurface previously bound to this texture.
12076 ReleaseIOSurfaceForTexture(texture_ref->service_id());
12078 // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails.
12079 texture_to_io_surface_map_.insert(
12080 std::make_pair(texture_ref->service_id(), surface));
12082 CGLContextObj context =
12083 static_cast<CGLContextObj>(context_->GetHandle());
12085 CGLError err = CGLTexImageIOSurface2D(
12086 context,
12087 target,
12088 GL_RGBA,
12089 width,
12090 height,
12091 GL_BGRA,
12092 GL_UNSIGNED_INT_8_8_8_8_REV,
12093 surface,
12094 plane);
12096 if (err != kCGLNoError) {
12097 LOCAL_SET_GL_ERROR(
12098 GL_INVALID_OPERATION,
12099 "glTexImageIOSurface2DCHROMIUM", "error in CGLTexImageIOSurface2D");
12100 return;
12103 texture_manager()->SetLevelInfo(
12104 texture_ref, target, 0, GL_RGBA, width, height, 1, 0, GL_BGRA,
12105 GL_UNSIGNED_INT_8_8_8_8_REV, gfx::Rect(width, height));
12107 #else
12108 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12109 "glTexImageIOSurface2DCHROMIUM", "not supported.");
12110 #endif
12113 static GLenum ExtractFormatFromStorageFormat(GLenum internalformat) {
12114 switch (internalformat) {
12115 case GL_R8:
12116 case GL_R8_SNORM:
12117 case GL_R16F:
12118 case GL_R32F:
12119 return GL_RED;
12120 case GL_R8UI:
12121 case GL_R8I:
12122 case GL_R16UI:
12123 case GL_R16I:
12124 case GL_R32UI:
12125 case GL_R32I:
12126 return GL_RED_INTEGER;
12127 case GL_RG8:
12128 case GL_RG8_SNORM:
12129 case GL_RG16F:
12130 case GL_RG32F:
12131 return GL_RG;
12132 case GL_RG8UI:
12133 case GL_RG8I:
12134 case GL_RG16UI:
12135 case GL_RG16I:
12136 case GL_RG32UI:
12137 case GL_RG32I:
12138 return GL_RG_INTEGER;
12139 case GL_ATC_RGB_AMD:
12140 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
12141 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
12142 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
12143 case GL_ETC1_RGB8_OES:
12144 case GL_RGB8:
12145 case GL_R11F_G11F_B10F:
12146 case GL_RGB565:
12147 case GL_RGB8_SNORM:
12148 case GL_RGB9_E5:
12149 case GL_RGB16F:
12150 case GL_RGB32F:
12151 return GL_RGB;
12152 case GL_RGB8UI:
12153 case GL_RGB8I:
12154 case GL_RGB16UI:
12155 case GL_RGB16I:
12156 case GL_RGB32UI:
12157 case GL_RGB32I:
12158 return GL_RGB_INTEGER;
12159 case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
12160 case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
12161 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
12162 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
12163 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
12164 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
12165 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
12166 case GL_RGBA8:
12167 case GL_SRGB8_ALPHA8:
12168 case GL_RGBA8_SNORM:
12169 case GL_RGBA4:
12170 case GL_RGB5_A1:
12171 case GL_RGB10_A2:
12172 case GL_RGBA16F:
12173 case GL_RGBA32F:
12174 return GL_RGBA;
12175 case GL_RGBA8UI:
12176 case GL_RGBA8I:
12177 case GL_RGB10_A2UI:
12178 case GL_RGBA16UI:
12179 case GL_RGBA16I:
12180 case GL_RGBA32UI:
12181 case GL_RGBA32I:
12182 return GL_RGBA_INTEGER;
12183 case GL_DEPTH_COMPONENT16:
12184 case GL_DEPTH_COMPONENT24:
12185 case GL_DEPTH_COMPONENT32F:
12186 return GL_DEPTH_COMPONENT;
12187 case GL_DEPTH24_STENCIL8:
12188 case GL_DEPTH32F_STENCIL8:
12189 return GL_DEPTH_STENCIL;
12190 case GL_LUMINANCE8_ALPHA8_EXT:
12191 return GL_LUMINANCE_ALPHA;
12192 case GL_LUMINANCE8_EXT:
12193 return GL_LUMINANCE;
12194 case GL_ALPHA8_EXT:
12195 return GL_ALPHA;
12196 case GL_ALPHA32F_EXT:
12197 return GL_ALPHA;
12198 case GL_LUMINANCE32F_EXT:
12199 return GL_LUMINANCE;
12200 case GL_LUMINANCE_ALPHA32F_EXT:
12201 return GL_LUMINANCE_ALPHA;
12202 case GL_ALPHA16F_EXT:
12203 return GL_ALPHA;
12204 case GL_LUMINANCE16F_EXT:
12205 return GL_LUMINANCE;
12206 case GL_LUMINANCE_ALPHA16F_EXT:
12207 return GL_LUMINANCE_ALPHA;
12208 case GL_BGRA8_EXT:
12209 return GL_BGRA_EXT;
12210 default:
12211 return GL_NONE;
12215 bool GLES2DecoderImpl::ValidateCopyTextureCHROMIUM(
12216 const char* function_name,
12217 GLenum target,
12218 TextureRef* source_texture_ref,
12219 TextureRef* dest_texture_ref,
12220 GLenum dest_internal_format) {
12221 if (!source_texture_ref || !dest_texture_ref) {
12222 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
12223 return false;
12226 if (GL_TEXTURE_2D != target) {
12227 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12228 "invalid texture target");
12229 return false;
12232 Texture* source_texture = source_texture_ref->texture();
12233 Texture* dest_texture = dest_texture_ref->texture();
12234 if (source_texture == dest_texture) {
12235 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12236 "source and destination textures are the same");
12237 return false;
12240 if (dest_texture->target() != GL_TEXTURE_2D ||
12241 (source_texture->target() != GL_TEXTURE_2D &&
12242 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
12243 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
12244 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12245 "invalid texture target binding");
12246 return false;
12249 GLenum source_type = 0;
12250 GLenum source_internal_format = 0;
12251 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12252 &source_internal_format);
12254 // The destination format should be GL_RGB, or GL_RGBA. GL_ALPHA,
12255 // GL_LUMINANCE, and GL_LUMINANCE_ALPHA are not supported because they are not
12256 // renderable on some platforms.
12257 bool valid_dest_format = dest_internal_format == GL_RGB ||
12258 dest_internal_format == GL_RGBA ||
12259 dest_internal_format == GL_BGRA_EXT;
12260 bool valid_source_format =
12261 source_internal_format == GL_R8 || source_internal_format == GL_ALPHA ||
12262 source_internal_format == GL_RGB || source_internal_format == GL_RGBA ||
12263 source_internal_format == GL_LUMINANCE ||
12264 source_internal_format == GL_LUMINANCE_ALPHA ||
12265 source_internal_format == GL_BGRA_EXT;
12266 if (!valid_source_format || !valid_dest_format) {
12267 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12268 "invalid internal format");
12269 return false;
12271 return true;
12274 bool GLES2DecoderImpl::ValidateCompressedCopyTextureCHROMIUM(
12275 const char* function_name,
12276 GLenum target,
12277 TextureRef* source_texture_ref,
12278 TextureRef* dest_texture_ref) {
12279 if (!source_texture_ref || !dest_texture_ref) {
12280 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "unknown texture id");
12281 return false;
12284 if (GL_TEXTURE_2D != target) {
12285 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12286 "invalid texture target");
12287 return false;
12290 Texture* source_texture = source_texture_ref->texture();
12291 Texture* dest_texture = dest_texture_ref->texture();
12292 if (source_texture == dest_texture) {
12293 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12294 "source and destination textures are the same");
12295 return false;
12298 if (dest_texture->target() != GL_TEXTURE_2D ||
12299 (source_texture->target() != GL_TEXTURE_2D &&
12300 source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
12301 source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
12302 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
12303 "invalid texture target binding");
12304 return false;
12307 GLenum source_type = 0;
12308 GLenum source_internal_format = 0;
12309 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12310 &source_internal_format);
12312 bool valid_format =
12313 source_internal_format == GL_ATC_RGB_AMD ||
12314 source_internal_format == GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD ||
12315 source_internal_format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
12316 source_internal_format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ||
12317 source_internal_format == GL_ETC1_RGB8_OES;
12319 if (!valid_format) {
12320 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
12321 "invalid internal format");
12322 return false;
12325 return true;
12328 void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
12329 GLenum target,
12330 GLuint source_id,
12331 GLuint dest_id,
12332 GLenum internal_format,
12333 GLenum dest_type,
12334 GLboolean unpack_flip_y,
12335 GLboolean unpack_premultiply_alpha,
12336 GLboolean unpack_unmultiply_alpha) {
12337 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
12339 TextureRef* source_texture_ref = GetTexture(source_id);
12340 TextureRef* dest_texture_ref = GetTexture(dest_id);
12341 Texture* source_texture = source_texture_ref->texture();
12342 Texture* dest_texture = dest_texture_ref->texture();
12343 int source_width = 0;
12344 int source_height = 0;
12345 gfx::GLImage* image =
12346 source_texture->GetLevelImage(source_texture->target(), 0);
12347 if (image) {
12348 gfx::Size size = image->GetSize();
12349 source_width = size.width();
12350 source_height = size.height();
12351 if (source_width <= 0 || source_height <= 0) {
12352 LOCAL_SET_GL_ERROR(
12353 GL_INVALID_VALUE,
12354 "glCopyTextureChromium", "invalid image size");
12355 return;
12357 } else {
12358 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12359 &source_width, &source_height, nullptr)) {
12360 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
12361 "glCopyTextureChromium",
12362 "source texture has no level 0");
12363 return;
12366 // Check that this type of texture is allowed.
12367 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12368 source_width, source_height, 1)) {
12369 LOCAL_SET_GL_ERROR(
12370 GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
12371 return;
12375 GLenum source_type = 0;
12376 GLenum source_internal_format = 0;
12377 source_texture->GetLevelType(
12378 source_texture->target(), 0, &source_type, &source_internal_format);
12380 if (dest_texture->IsImmutable()) {
12381 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyTextureCHROMIUM",
12382 "texture is immutable");
12383 return;
12386 if (!ValidateCopyTextureCHROMIUM("glCopyTextureCHROMIUM", target,
12387 source_texture_ref, dest_texture_ref,
12388 internal_format)) {
12389 return;
12392 // Clear the source texture if necessary.
12393 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12394 source_texture->target(), 0)) {
12395 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM",
12396 "dimensions too big");
12397 return;
12400 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12401 // needed because it takes 10s of milliseconds to initialize.
12402 if (!copy_texture_CHROMIUM_.get()) {
12403 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12404 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12405 copy_texture_CHROMIUM_->Initialize(this);
12406 RestoreCurrentFramebufferBindings();
12407 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
12408 return;
12411 GLenum dest_type_previous = dest_type;
12412 GLenum dest_internal_format = internal_format;
12413 int dest_width = 0;
12414 int dest_height = 0;
12415 bool dest_level_defined = dest_texture->GetLevelSize(
12416 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12418 if (dest_level_defined) {
12419 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type_previous,
12420 &dest_internal_format);
12423 // Resize the destination texture to the dimensions of the source texture.
12424 if (!dest_level_defined || dest_width != source_width ||
12425 dest_height != source_height ||
12426 dest_internal_format != internal_format ||
12427 dest_type_previous != dest_type) {
12428 // Ensure that the glTexImage2D succeeds.
12429 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12430 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12431 glTexImage2D(GL_TEXTURE_2D, 0, internal_format, source_width, source_height,
12432 0, internal_format, dest_type, NULL);
12433 GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
12434 if (error != GL_NO_ERROR) {
12435 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12436 return;
12439 texture_manager()->SetLevelInfo(
12440 dest_texture_ref, GL_TEXTURE_2D, 0, internal_format, source_width,
12441 source_height, 1, 0, internal_format, dest_type,
12442 gfx::Rect(source_width, source_height));
12443 } else {
12444 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12445 true);
12448 ScopedModifyPixels modify(dest_texture_ref);
12450 // Try using GLImage::CopyTexSubImage when possible.
12451 bool unpack_premultiply_alpha_change =
12452 (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0;
12453 if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) {
12454 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12455 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0),
12456 gfx::Rect(0, 0, source_width, source_height))) {
12457 return;
12461 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12463 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12464 // before presenting.
12465 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
12466 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12467 // instead of using kIdentityMatrix crbug.com/226218.
12468 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
12469 this, source_texture->target(), source_texture->service_id(),
12470 dest_texture->service_id(), source_width, source_height,
12471 unpack_flip_y == GL_TRUE,
12472 unpack_premultiply_alpha == GL_TRUE,
12473 unpack_unmultiply_alpha == GL_TRUE,
12474 kIdentityMatrix);
12475 } else {
12476 copy_texture_CHROMIUM_->DoCopyTexture(
12477 this, source_texture->target(), source_texture->service_id(),
12478 source_internal_format, dest_texture->service_id(), internal_format,
12479 source_width, source_height,
12480 unpack_flip_y == GL_TRUE,
12481 unpack_premultiply_alpha == GL_TRUE,
12482 unpack_unmultiply_alpha == GL_TRUE);
12485 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12488 void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(
12489 GLenum target,
12490 GLuint source_id,
12491 GLuint dest_id,
12492 GLint xoffset,
12493 GLint yoffset,
12494 GLint x,
12495 GLint y,
12496 GLsizei width,
12497 GLsizei height,
12498 GLboolean unpack_flip_y,
12499 GLboolean unpack_premultiply_alpha,
12500 GLboolean unpack_unmultiply_alpha) {
12501 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopySubTextureCHROMIUM");
12503 TextureRef* source_texture_ref = GetTexture(source_id);
12504 TextureRef* dest_texture_ref = GetTexture(dest_id);
12505 Texture* source_texture = source_texture_ref->texture();
12506 Texture* dest_texture = dest_texture_ref->texture();
12507 int source_width = 0;
12508 int source_height = 0;
12509 gfx::GLImage* image =
12510 source_texture->GetLevelImage(source_texture->target(), 0);
12511 if (image) {
12512 gfx::Size size = image->GetSize();
12513 source_width = size.width();
12514 source_height = size.height();
12515 if (source_width <= 0 || source_height <= 0) {
12516 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12517 "invalid image size");
12518 return;
12520 } else {
12521 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12522 &source_width, &source_height, nullptr)) {
12523 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12524 "source texture has no level 0");
12525 return;
12528 // Check that this type of texture is allowed.
12529 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12530 source_width, source_height, 1)) {
12531 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12532 "source texture bad dimensions");
12533 return;
12537 GLenum source_type = 0;
12538 GLenum source_internal_format = 0;
12539 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12540 &source_internal_format);
12541 if (!source_texture->ValidForTexture(source_texture->target(), 0, x, y, 0,
12542 width, height, 1, source_type)) {
12543 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12544 "source texture bad dimensions.");
12545 return;
12548 GLenum dest_type = 0;
12549 GLenum dest_internal_format = 0;
12550 bool dest_level_defined = dest_texture->GetLevelType(
12551 dest_texture->target(), 0, &dest_type, &dest_internal_format);
12552 if (!dest_level_defined) {
12553 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopySubTextureCHROMIUM",
12554 "destination texture is not defined");
12555 return;
12557 if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
12558 yoffset, 0, width, height, 1, dest_type)) {
12559 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTextureCHROMIUM",
12560 "destination texture bad dimensions.");
12561 return;
12564 if (!ValidateCopyTextureCHROMIUM("glCopySubTextureCHROMIUM", target,
12565 source_texture_ref, dest_texture_ref,
12566 dest_internal_format)) {
12567 return;
12570 // Clear the source texture if necessary.
12571 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12572 source_texture->target(), 0)) {
12573 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
12574 "source texture dimensions too big");
12575 return;
12578 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12579 // needed because it takes 10s of milliseconds to initialize.
12580 if (!copy_texture_CHROMIUM_.get()) {
12581 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTextureCHROMIUM");
12582 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12583 copy_texture_CHROMIUM_->Initialize(this);
12584 RestoreCurrentFramebufferBindings();
12585 if (LOCAL_PEEK_GL_ERROR("glCopySubTextureCHROMIUM") != GL_NO_ERROR)
12586 return;
12589 int dest_width = 0;
12590 int dest_height = 0;
12591 bool ok = dest_texture->GetLevelSize(
12592 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12593 DCHECK(ok);
12594 if (xoffset != 0 || yoffset != 0 || width != dest_width ||
12595 height != dest_height) {
12596 gfx::Rect cleared_rect;
12597 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0),
12598 gfx::Rect(xoffset, yoffset, width, height),
12599 &cleared_rect)) {
12600 DCHECK_GE(cleared_rect.size().GetArea(),
12601 dest_texture->GetLevelClearedRect(target, 0).size().GetArea());
12602 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0,
12603 cleared_rect);
12604 } else {
12605 // Otherwise clear part of texture level that is not already cleared.
12606 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
12607 0)) {
12608 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM",
12609 "destination texture dimensions too big");
12610 return;
12613 } else {
12614 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12615 true);
12618 ScopedModifyPixels modify(dest_texture_ref);
12620 // Try using GLImage::CopyTexSubImage when possible.
12621 bool unpack_premultiply_alpha_change =
12622 (unpack_premultiply_alpha ^ unpack_unmultiply_alpha) != 0;
12623 if (image && !unpack_flip_y && !unpack_premultiply_alpha_change) {
12624 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
12625 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset),
12626 gfx::Rect(x, y, width, height))) {
12627 return;
12631 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12633 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
12634 // crbug.com/226218.
12635 copy_texture_CHROMIUM_->DoCopySubTexture(
12636 this, source_texture->target(), source_texture->service_id(),
12637 source_internal_format, dest_texture->service_id(), dest_internal_format,
12638 xoffset, yoffset, x, y, width, height, dest_width, dest_height,
12639 source_width, source_height,
12640 unpack_flip_y == GL_TRUE,
12641 unpack_premultiply_alpha == GL_TRUE,
12642 unpack_unmultiply_alpha == GL_TRUE);
12644 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12647 void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLenum target,
12648 GLuint source_id,
12649 GLuint dest_id) {
12650 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM");
12652 TextureRef* source_texture_ref = GetTexture(source_id);
12653 TextureRef* dest_texture_ref = GetTexture(dest_id);
12654 Texture* source_texture = source_texture_ref->texture();
12655 Texture* dest_texture = dest_texture_ref->texture();
12656 int source_width = 0;
12657 int source_height = 0;
12658 gfx::GLImage* image =
12659 source_texture->GetLevelImage(source_texture->target(), 0);
12660 if (image) {
12661 gfx::Size size = image->GetSize();
12662 source_width = size.width();
12663 source_height = size.height();
12664 if (source_width <= 0 || source_height <= 0) {
12665 LOCAL_SET_GL_ERROR(
12666 GL_INVALID_VALUE,
12667 "glCompressedCopyTextureCHROMIUM", "invalid image size");
12668 return;
12670 } else {
12671 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12672 &source_width, &source_height, nullptr)) {
12673 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
12674 "glCompressedCopyTextureCHROMIUM",
12675 "source texture has no level 0");
12676 return;
12679 // Check that this type of texture is allowed.
12680 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12681 source_width, source_height, 1)) {
12682 LOCAL_SET_GL_ERROR(
12683 GL_INVALID_VALUE, "glCompressedCopyTextureCHROMIUM",
12684 "Bad dimensions");
12685 return;
12689 GLenum source_type = 0;
12690 GLenum source_internal_format = 0;
12691 source_texture->GetLevelType(
12692 source_texture->target(), 0, &source_type, &source_internal_format);
12694 if (dest_texture->IsImmutable()) {
12695 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12696 "glCompressedCopyTextureCHROMIUM",
12697 "texture is immutable");
12698 return;
12701 if (!ValidateCompressedCopyTextureCHROMIUM(
12702 "glCompressedCopyTextureCHROMIUM",
12703 target,
12704 source_texture_ref, dest_texture_ref)) {
12705 return;
12708 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12709 // needed because it takes 10s of milliseconds to initialize.
12710 if (!copy_texture_CHROMIUM_.get()) {
12711 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTextureCHROMIUM");
12712 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12713 copy_texture_CHROMIUM_->Initialize(this);
12714 RestoreCurrentFramebufferBindings();
12715 if (LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM") != GL_NO_ERROR)
12716 return;
12719 // Clear the source texture if necessary.
12720 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12721 source_texture->target(), 0)) {
12722 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCompressedCopyTextureCHROMIUM",
12723 "dimensions too big");
12724 return;
12727 ScopedTextureBinder binder(
12728 &state_, dest_texture->service_id(), GL_TEXTURE_2D);
12730 ScopedModifyPixels modify(dest_texture_ref);
12732 // Try using GLImage::CopyTexImage when possible.
12733 if (image) {
12734 GLenum dest_type = 0;
12735 GLenum dest_internal_format = 0;
12736 int dest_width = 0;
12737 int dest_height = 0;
12738 bool dest_level_defined = dest_texture->GetLevelSize(
12739 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12741 if (dest_level_defined) {
12742 dest_texture->GetLevelType(GL_TEXTURE_2D, 0, &dest_type,
12743 &dest_internal_format);
12746 // Resize the destination texture to the dimensions of the source texture.
12747 if (!dest_level_defined || dest_width != source_width ||
12748 dest_height != source_height ||
12749 dest_internal_format != source_internal_format) {
12750 GLsizei source_size = 0;
12752 bool did_get_size = GetCompressedTexSizeInBytes(
12753 "glCompressedCopyTextureCHROMIUM", source_width, source_height,
12754 1, source_internal_format, &source_size);
12755 DCHECK(did_get_size);
12757 // Ensure that the glCompressedTexImage2D succeeds.
12758 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12759 glCompressedTexImage2D(GL_TEXTURE_2D, 0, source_internal_format,
12760 source_width, source_height, 0, source_size,
12761 NULL);
12762 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12763 if (error != GL_NO_ERROR) {
12764 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12765 return;
12768 texture_manager()->SetLevelInfo(
12769 dest_texture_ref, GL_TEXTURE_2D, 0, source_internal_format,
12770 source_width, source_height, 1, 0, source_internal_format,
12771 source_type, gfx::Rect(source_width, source_height));
12772 } else {
12773 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12774 true);
12777 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(0, 0),
12778 gfx::Rect(0, 0, source_width, source_height))) {
12779 return;
12783 TRACE_EVENT0(
12784 "gpu",
12785 "GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM, fallback");
12787 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12789 // As a fallback, copy into a non-compressed GL_RGBA texture.
12790 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12791 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, source_width, source_height,
12792 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
12793 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopyTextureCHROMIUM");
12794 if (error != GL_NO_ERROR) {
12795 RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
12796 return;
12799 texture_manager()->SetLevelInfo(
12800 dest_texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, source_width,
12801 source_height, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
12802 gfx::Rect(source_width, source_height));
12804 // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
12805 // before presenting.
12806 if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
12807 // TODO(hkuang): get the StreamTexture transform matrix in GPU process
12808 // instead of using kIdentityMatrix crbug.com/226218.
12809 copy_texture_CHROMIUM_->DoCopyTextureWithTransform(
12810 this, source_texture->target(), source_texture->service_id(),
12811 dest_texture->service_id(), source_width, source_height,
12812 false, false, false, kIdentityMatrix);
12813 } else {
12814 copy_texture_CHROMIUM_->DoCopyTexture(
12815 this, source_texture->target(), source_texture->service_id(),
12816 source_internal_format, dest_texture->service_id(), GL_RGBA,
12817 source_width, source_height, false, false, false);
12820 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
12823 void GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM(GLenum target,
12824 GLuint source_id,
12825 GLuint dest_id,
12826 GLint xoffset,
12827 GLint yoffset,
12828 GLint x,
12829 GLint y,
12830 GLsizei width,
12831 GLsizei height) {
12832 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM");
12834 TextureRef* source_texture_ref = GetTexture(source_id);
12835 TextureRef* dest_texture_ref = GetTexture(dest_id);
12836 Texture* source_texture = source_texture_ref->texture();
12837 Texture* dest_texture = dest_texture_ref->texture();
12838 int source_width = 0;
12839 int source_height = 0;
12840 gfx::GLImage* image =
12841 source_texture->GetLevelImage(source_texture->target(), 0);
12842 if (image) {
12843 gfx::Size size = image->GetSize();
12844 source_width = size.width();
12845 source_height = size.height();
12846 if (source_width <= 0 || source_height <= 0) {
12847 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
12848 "invalid image size");
12849 return;
12851 } else {
12852 if (!source_texture->GetLevelSize(source_texture->target(), 0,
12853 &source_width, &source_height, nullptr)) {
12854 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
12855 "source texture has no level 0");
12856 return;
12859 // Check that this type of texture is allowed.
12860 if (!texture_manager()->ValidForTarget(source_texture->target(), 0,
12861 source_width, source_height, 1)) {
12862 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
12863 "source texture bad dimensions");
12864 return;
12868 GLenum source_type = 0;
12869 GLenum source_internal_format = 0;
12870 source_texture->GetLevelType(source_texture->target(), 0, &source_type,
12871 &source_internal_format);
12872 if (!source_texture->ValidForTexture(source_texture->target(), 0, x, y, 0,
12873 width, height, 1, source_type)) {
12874 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
12875 "source texture bad dimensions.");
12876 return;
12879 GLenum dest_type = 0;
12880 GLenum dest_internal_format = 0;
12881 bool dest_level_defined = dest_texture->GetLevelType(
12882 dest_texture->target(), 0, &dest_type, &dest_internal_format);
12883 if (!dest_level_defined) {
12884 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
12885 "glCompressedCopySubTextureCHROMIUM",
12886 "destination texture is not defined");
12887 return;
12889 if (!dest_texture->ValidForTexture(dest_texture->target(), 0, xoffset,
12890 yoffset, 0, width, height, 1, dest_type)) {
12891 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCompressedCopySubTextureCHROMIUM",
12892 "destination texture bad dimensions.");
12893 return;
12896 if (!ValidateCompressedCopyTextureCHROMIUM(
12897 "glCompressedCopySubTextureCHROMIUM", target, source_texture_ref,
12898 dest_texture_ref)) {
12899 return;
12902 if (!ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM",
12903 source_texture->target(), 0, x, y, 0,
12904 width, height, 1,
12905 source_internal_format,
12906 source_texture) ||
12907 !ValidateCompressedTexSubDimensions("glCompressedCopySubTextureCHROMIUM",
12908 dest_texture->target(), 0,
12909 xoffset, yoffset, 0, width, height, 1,
12910 dest_internal_format,
12911 dest_texture)) {
12912 return;
12915 // Defer initializing the CopyTextureCHROMIUMResourceManager until it is
12916 // needed because it takes 10s of milliseconds to initialize.
12917 if (!copy_texture_CHROMIUM_.get()) {
12918 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopySubTextureCHROMIUM");
12919 copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager());
12920 copy_texture_CHROMIUM_->Initialize(this);
12921 RestoreCurrentFramebufferBindings();
12922 if (LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM") !=
12923 GL_NO_ERROR) {
12924 return;
12928 // Clear the source texture if necessary.
12929 if (!texture_manager()->ClearTextureLevel(this, source_texture_ref,
12930 source_texture->target(), 0)) {
12931 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCompressedCopySubTextureCHROMIUM",
12932 "source texture dimensions too big");
12933 return;
12936 int dest_width = 0;
12937 int dest_height = 0;
12938 bool ok = dest_texture->GetLevelSize(
12939 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr);
12940 DCHECK(ok);
12941 if (xoffset != 0 || yoffset != 0 || width != dest_width ||
12942 height != dest_height) {
12943 gfx::Rect cleared_rect;
12944 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0),
12945 gfx::Rect(xoffset, yoffset, width, height),
12946 &cleared_rect)) {
12947 DCHECK_GE(cleared_rect.size().GetArea(),
12948 dest_texture->GetLevelClearedRect(target, 0).size().GetArea());
12949 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0,
12950 cleared_rect);
12951 } else {
12952 // Otherwise clear part of texture level that is not already cleared.
12953 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target,
12954 0)) {
12955 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY,
12956 "glCompressedCopySubTextureCHROMIUM",
12957 "destination texture dimensions too big");
12958 return;
12961 } else {
12962 texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0,
12963 true);
12966 ScopedTextureBinder binder(
12967 &state_, dest_texture->service_id(), GL_TEXTURE_2D);
12969 ScopedModifyPixels modify(dest_texture_ref);
12971 // Try using GLImage::CopyTexSubImage when possible.
12972 if (image) {
12973 if (image->CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(xoffset, yoffset),
12974 gfx::Rect(x, y, width, height))) {
12975 return;
12979 TRACE_EVENT0(
12980 "gpu",
12981 "GLES2DecoderImpl::DoCompressedCopySubTextureCHROMIUM, fallback");
12983 DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
12985 // As a fallback, copy into a non-compressed GL_RGBA texture.
12986 if (dest_internal_format != GL_RGBA) {
12987 // To preserve the contents of the original destination texture we must
12988 // first copy the original destination texture to a temporary storage, then
12989 // copy it back to the original destination texture.
12990 GLuint tmp_service_id;
12991 glGenTextures(1, &tmp_service_id);
12992 DCHECK_NE(0u, tmp_service_id);
12994 glBindTexture(GL_TEXTURE_2D, tmp_service_id);
12996 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
12997 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dest_width, dest_height, 0, GL_RGBA,
12998 GL_UNSIGNED_BYTE, NULL);
12999 GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM");
13000 if (error != GL_NO_ERROR)
13001 return;
13003 copy_texture_CHROMIUM_->DoCopyTexture(
13004 this, dest_texture->target(), dest_texture->service_id(),
13005 dest_internal_format, tmp_service_id, GL_RGBA,
13006 dest_width, dest_height, false, false, false);
13008 // Redefine destination texture to use RGBA.
13009 glBindTexture(GL_TEXTURE_2D, dest_texture->service_id());
13010 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedCopyTextureCHROMIUM");
13011 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dest_width, dest_height, 0, GL_RGBA,
13012 GL_UNSIGNED_BYTE, NULL);
13013 error = LOCAL_PEEK_GL_ERROR("glCompressedCopySubTextureCHROMIUM");
13014 if (error != GL_NO_ERROR)
13015 return;
13017 texture_manager()->SetLevelInfo(
13018 dest_texture_ref, GL_TEXTURE_2D, 0, GL_RGBA, dest_width, dest_height,
13019 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(dest_width, dest_height));
13021 copy_texture_CHROMIUM_->DoCopyTexture(
13022 this, GL_TEXTURE_2D, tmp_service_id, GL_RGBA,
13023 dest_texture->service_id(), GL_RGBA,
13024 dest_width, dest_height, false, false, false);
13026 glDeleteTextures(1, &tmp_service_id);
13029 // TODO(hkuang): get the StreamTexture transform matrix in GPU process.
13030 // crbug.com/226218.
13031 copy_texture_CHROMIUM_->DoCopySubTexture(
13032 this, source_texture->target(), source_texture->service_id(),
13033 source_internal_format, dest_texture->service_id(), GL_RGBA,
13034 xoffset, yoffset, x, y, width, height, dest_width, dest_height,
13035 source_width, source_height, false, false, false);
13037 DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
13040 static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
13041 switch (internalformat) {
13042 case GL_R8:
13043 return GL_UNSIGNED_BYTE;
13044 case GL_R8_SNORM:
13045 return GL_BYTE;
13046 case GL_R16F:
13047 return GL_HALF_FLOAT;
13048 case GL_R32F:
13049 return GL_FLOAT;
13050 case GL_R8UI:
13051 return GL_UNSIGNED_BYTE;
13052 case GL_R8I:
13053 return GL_BYTE;
13054 case GL_R16UI:
13055 return GL_UNSIGNED_SHORT;
13056 case GL_R16I:
13057 return GL_SHORT;
13058 case GL_R32UI:
13059 return GL_UNSIGNED_INT;
13060 case GL_R32I:
13061 return GL_INT;
13062 case GL_RG8:
13063 return GL_UNSIGNED_BYTE;
13064 case GL_RG8_SNORM:
13065 return GL_BYTE;
13066 case GL_RG16F:
13067 return GL_HALF_FLOAT;
13068 case GL_RG32F:
13069 return GL_FLOAT;
13070 case GL_RG8UI:
13071 return GL_UNSIGNED_BYTE;
13072 case GL_RG8I:
13073 return GL_BYTE;
13074 case GL_RG16UI:
13075 return GL_UNSIGNED_SHORT;
13076 case GL_RG16I:
13077 return GL_SHORT;
13078 case GL_RG32UI:
13079 return GL_UNSIGNED_INT;
13080 case GL_RG32I:
13081 return GL_INT;
13082 case GL_RGB8:
13083 case GL_SRGB8:
13084 return GL_UNSIGNED_BYTE;
13085 case GL_R11F_G11F_B10F:
13086 return GL_UNSIGNED_INT_10F_11F_11F_REV;
13087 case GL_RGB565:
13088 return GL_UNSIGNED_SHORT_5_6_5;
13089 case GL_RGB8_SNORM:
13090 return GL_BYTE;
13091 case GL_RGB9_E5:
13092 return GL_UNSIGNED_INT_5_9_9_9_REV;
13093 case GL_RGB16F:
13094 return GL_HALF_FLOAT;
13095 case GL_RGB32F:
13096 return GL_FLOAT;
13097 case GL_RGB8UI:
13098 return GL_UNSIGNED_BYTE;
13099 case GL_RGB8I:
13100 return GL_BYTE;
13101 case GL_RGB16UI:
13102 return GL_UNSIGNED_SHORT;
13103 case GL_RGB16I:
13104 return GL_SHORT;
13105 case GL_RGB32UI:
13106 return GL_UNSIGNED_INT;
13107 case GL_RGB32I:
13108 return GL_INT;
13109 case GL_RGBA8:
13110 return GL_UNSIGNED_BYTE;
13111 case GL_SRGB8_ALPHA8:
13112 return GL_UNSIGNED_BYTE;
13113 case GL_RGBA8_SNORM:
13114 return GL_BYTE;
13115 case GL_RGBA4:
13116 return GL_UNSIGNED_SHORT_4_4_4_4;
13117 case GL_RGB10_A2:
13118 return GL_UNSIGNED_INT_2_10_10_10_REV;
13119 case GL_RGB5_A1:
13120 return GL_UNSIGNED_SHORT_5_5_5_1;
13121 case GL_RGBA16F:
13122 return GL_HALF_FLOAT;
13123 case GL_RGBA32F:
13124 return GL_FLOAT;
13125 case GL_RGBA8UI:
13126 return GL_UNSIGNED_BYTE;
13127 case GL_RGBA8I:
13128 return GL_BYTE;
13129 case GL_RGB10_A2UI:
13130 return GL_UNSIGNED_INT_2_10_10_10_REV;
13131 case GL_RGBA16UI:
13132 return GL_UNSIGNED_SHORT;
13133 case GL_RGBA16I:
13134 return GL_SHORT;
13135 case GL_RGBA32I:
13136 return GL_INT;
13137 case GL_RGBA32UI:
13138 return GL_UNSIGNED_INT;
13139 case GL_DEPTH_COMPONENT16:
13140 return GL_UNSIGNED_SHORT;
13141 case GL_DEPTH_COMPONENT24:
13142 return GL_UNSIGNED_INT;
13143 case GL_DEPTH_COMPONENT32F:
13144 return GL_FLOAT;
13145 case GL_DEPTH24_STENCIL8:
13146 return GL_UNSIGNED_INT_24_8;
13147 case GL_DEPTH32F_STENCIL8:
13148 return GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
13149 case GL_LUMINANCE8_ALPHA8_EXT:
13150 return GL_UNSIGNED_BYTE;
13151 case GL_LUMINANCE8_EXT:
13152 return GL_UNSIGNED_BYTE;
13153 case GL_ALPHA8_EXT:
13154 return GL_UNSIGNED_BYTE;
13155 case GL_ALPHA32F_EXT:
13156 return GL_FLOAT;
13157 case GL_LUMINANCE32F_EXT:
13158 return GL_FLOAT;
13159 case GL_LUMINANCE_ALPHA32F_EXT:
13160 return GL_FLOAT;
13161 case GL_ALPHA16F_EXT:
13162 return GL_HALF_FLOAT_OES;
13163 case GL_LUMINANCE16F_EXT:
13164 return GL_HALF_FLOAT_OES;
13165 case GL_LUMINANCE_ALPHA16F_EXT:
13166 return GL_HALF_FLOAT_OES;
13167 case GL_BGRA8_EXT:
13168 return GL_UNSIGNED_BYTE;
13169 default:
13170 return GL_NONE;
13174 void GLES2DecoderImpl::DoTexStorage2DEXT(
13175 GLenum target,
13176 GLint levels,
13177 GLenum internal_format,
13178 GLsizei width,
13179 GLsizei height) {
13180 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
13181 "width", width, "height", height);
13182 if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
13183 TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
13184 LOCAL_SET_GL_ERROR(
13185 GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
13186 return;
13188 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13189 &state_, target);
13190 if (!texture_ref) {
13191 LOCAL_SET_GL_ERROR(
13192 GL_INVALID_OPERATION,
13193 "glTexStorage2DEXT", "unknown texture for target");
13194 return;
13196 Texture* texture = texture_ref->texture();
13197 if (texture->IsAttachedToFramebuffer()) {
13198 framebuffer_state_.clear_state_dirty = true;
13200 if (texture->IsImmutable()) {
13201 LOCAL_SET_GL_ERROR(
13202 GL_INVALID_OPERATION,
13203 "glTexStorage2DEXT", "texture is immutable");
13204 return;
13207 GLenum format = ExtractFormatFromStorageFormat(internal_format);
13208 GLenum type = ExtractTypeFromStorageFormat(internal_format);
13211 GLsizei level_width = width;
13212 GLsizei level_height = height;
13213 uint32 estimated_size = 0;
13214 for (int ii = 0; ii < levels; ++ii) {
13215 uint32 level_size = 0;
13216 if (!GLES2Util::ComputeImageDataSizes(
13217 level_width, level_height, 1, format, type, state_.unpack_alignment,
13218 &estimated_size, NULL, NULL) ||
13219 !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
13220 LOCAL_SET_GL_ERROR(
13221 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
13222 return;
13224 level_width = std::max(1, level_width >> 1);
13225 level_height = std::max(1, level_height >> 1);
13227 if (!EnsureGPUMemoryAvailable(estimated_size)) {
13228 LOCAL_SET_GL_ERROR(
13229 GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
13230 return;
13234 LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
13235 glTexStorage2DEXT(target, levels, internal_format, width, height);
13236 GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
13237 if (error == GL_NO_ERROR) {
13238 GLsizei level_width = width;
13239 GLsizei level_height = height;
13241 GLenum cur_format = feature_info_->IsES3Enabled() ?
13242 internal_format : format;
13243 for (int ii = 0; ii < levels; ++ii) {
13244 if (target == GL_TEXTURE_CUBE_MAP) {
13245 for (int jj = 0; jj < 6; ++jj) {
13246 GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + jj;
13247 texture_manager()->SetLevelInfo(texture_ref, face, ii, cur_format,
13248 level_width, level_height, 1, 0,
13249 format, type, gfx::Rect());
13251 } else {
13252 texture_manager()->SetLevelInfo(texture_ref, target, ii, cur_format,
13253 level_width, level_height, 1, 0,
13254 format, type, gfx::Rect());
13256 level_width = std::max(1, level_width >> 1);
13257 level_height = std::max(1, level_height >> 1);
13259 texture->SetImmutable(true);
13263 error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
13264 uint32 immediate_data_size,
13265 const void* cmd_data) {
13266 return error::kUnknownCommand;
13269 void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
13270 const GLbyte* data) {
13271 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
13272 "context", logger_.GetLogPrefix(),
13273 "mailbox[0]", static_cast<unsigned char>(data[0]));
13275 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13276 &state_, target);
13277 ProduceTextureRef("glProduceTextureCHROMIUM", texture_ref, target, data);
13280 void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
13281 GLenum target, const GLbyte* data) {
13282 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
13283 "context", logger_.GetLogPrefix(),
13284 "mailbox[0]", static_cast<unsigned char>(data[0]));
13286 ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
13287 target, data);
13290 void GLES2DecoderImpl::ProduceTextureRef(std::string func_name,
13291 TextureRef* texture_ref, GLenum target, const GLbyte* data) {
13292 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13293 DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
13294 "mailbox that was not generated by "
13295 "GenMailboxCHROMIUM.";
13297 if (!texture_ref) {
13298 LOCAL_SET_GL_ERROR(
13299 GL_INVALID_OPERATION, func_name.c_str(), "unknown texture for target");
13300 return;
13303 Texture* produced = texture_manager()->Produce(texture_ref);
13304 if (!produced) {
13305 LOCAL_SET_GL_ERROR(
13306 GL_INVALID_OPERATION, func_name.c_str(), "invalid texture");
13307 return;
13310 if (produced->target() != target) {
13311 LOCAL_SET_GL_ERROR(
13312 GL_INVALID_OPERATION, func_name.c_str(), "invalid target");
13313 return;
13316 group_->mailbox_manager()->ProduceTexture(mailbox, produced);
13319 void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
13320 const GLbyte* data) {
13321 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
13322 "context", logger_.GetLogPrefix(),
13323 "mailbox[0]", static_cast<unsigned char>(data[0]));
13324 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13325 DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
13326 "mailbox that was not generated by "
13327 "GenMailboxCHROMIUM.";
13329 scoped_refptr<TextureRef> texture_ref =
13330 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13331 if (!texture_ref.get()) {
13332 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13333 "glConsumeTextureCHROMIUM",
13334 "unknown texture for target");
13335 return;
13337 GLuint client_id = texture_ref->client_id();
13338 if (!client_id) {
13339 LOCAL_SET_GL_ERROR(
13340 GL_INVALID_OPERATION,
13341 "glConsumeTextureCHROMIUM", "unknown texture for target");
13342 return;
13344 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
13345 if (!texture) {
13346 LOCAL_SET_GL_ERROR(
13347 GL_INVALID_OPERATION,
13348 "glConsumeTextureCHROMIUM", "invalid mailbox name");
13349 return;
13351 if (texture->target() != target) {
13352 LOCAL_SET_GL_ERROR(
13353 GL_INVALID_OPERATION,
13354 "glConsumeTextureCHROMIUM", "invalid target");
13355 return;
13358 DeleteTexturesHelper(1, &client_id);
13359 texture_ref = texture_manager()->Consume(client_id, texture);
13360 glBindTexture(target, texture_ref->service_id());
13362 TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
13363 unit.bind_target = target;
13364 switch (target) {
13365 case GL_TEXTURE_2D:
13366 unit.bound_texture_2d = texture_ref;
13367 break;
13368 case GL_TEXTURE_CUBE_MAP:
13369 unit.bound_texture_cube_map = texture_ref;
13370 break;
13371 case GL_TEXTURE_EXTERNAL_OES:
13372 unit.bound_texture_external_oes = texture_ref;
13373 break;
13374 case GL_TEXTURE_RECTANGLE_ARB:
13375 unit.bound_texture_rectangle_arb = texture_ref;
13376 break;
13377 default:
13378 NOTREACHED(); // Validation should prevent us getting here.
13379 break;
13383 void GLES2DecoderImpl::EnsureTextureForClientId(
13384 GLenum target,
13385 GLuint client_id) {
13386 TextureRef* texture_ref = GetTexture(client_id);
13387 if (!texture_ref) {
13388 GLuint service_id;
13389 glGenTextures(1, &service_id);
13390 DCHECK_NE(0u, service_id);
13391 texture_ref = CreateTexture(client_id, service_id);
13392 texture_manager()->SetTarget(texture_ref, target);
13393 glBindTexture(target, service_id);
13394 RestoreCurrentTextureBindings(&state_, target);
13398 // If CreateAndConsumeTexture fails we still need to ensure that the client_id
13399 // provided is associated with a service_id/TextureRef for consistency, even if
13400 // the resulting texture is incomplete.
13401 error::Error GLES2DecoderImpl::HandleCreateAndConsumeTextureCHROMIUMImmediate(
13402 uint32_t immediate_data_size,
13403 const void* cmd_data) {
13404 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate& c =
13405 *static_cast<
13406 const gles2::cmds::CreateAndConsumeTextureCHROMIUMImmediate*>(
13407 cmd_data);
13408 GLenum target = static_cast<GLenum>(c.target);
13409 uint32_t data_size;
13410 if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
13411 return error::kOutOfBounds;
13413 if (data_size > immediate_data_size) {
13414 return error::kOutOfBounds;
13416 const GLbyte* mailbox =
13417 GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
13418 if (!validators_->texture_bind_target.IsValid(target)) {
13419 LOCAL_SET_GL_ERROR_INVALID_ENUM(
13420 "glCreateAndConsumeTextureCHROMIUM", target, "target");
13421 return error::kNoError;
13423 if (mailbox == NULL) {
13424 return error::kOutOfBounds;
13426 uint32_t client_id = c.client_id;
13427 DoCreateAndConsumeTextureCHROMIUM(target, mailbox, client_id);
13428 return error::kNoError;
13431 void GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM(GLenum target,
13432 const GLbyte* data, GLuint client_id) {
13433 TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoCreateAndConsumeTextureCHROMIUM",
13434 "context", logger_.GetLogPrefix(),
13435 "mailbox[0]", static_cast<unsigned char>(data[0]));
13436 const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
13437 DLOG_IF(ERROR, !mailbox.Verify()) << "CreateAndConsumeTextureCHROMIUM was "
13438 "passed a mailbox that was not "
13439 "generated by GenMailboxCHROMIUM.";
13441 TextureRef* texture_ref = GetTexture(client_id);
13442 if (texture_ref) {
13443 // No need to call EnsureTextureForClientId here, the client_id already has
13444 // an associated texture.
13445 LOCAL_SET_GL_ERROR(
13446 GL_INVALID_OPERATION,
13447 "glCreateAndConsumeTextureCHROMIUM", "client id already in use");
13448 return;
13450 Texture* texture = group_->mailbox_manager()->ConsumeTexture(mailbox);
13451 if (!texture) {
13452 EnsureTextureForClientId(target, client_id);
13453 LOCAL_SET_GL_ERROR(
13454 GL_INVALID_OPERATION,
13455 "glCreateAndConsumeTextureCHROMIUM", "invalid mailbox name");
13456 return;
13459 if (texture->target() != target) {
13460 EnsureTextureForClientId(target, client_id);
13461 LOCAL_SET_GL_ERROR(
13462 GL_INVALID_OPERATION,
13463 "glCreateAndConsumeTextureCHROMIUM", "invalid target");
13464 return;
13467 texture_ref = texture_manager()->Consume(client_id, texture);
13470 bool GLES2DecoderImpl::DoIsValuebufferCHROMIUM(GLuint client_id) {
13471 const Valuebuffer* valuebuffer = GetValuebuffer(client_id);
13472 return valuebuffer && valuebuffer->IsValid();
13475 void GLES2DecoderImpl::DoBindValueBufferCHROMIUM(GLenum target,
13476 GLuint client_id) {
13477 Valuebuffer* valuebuffer = NULL;
13478 if (client_id != 0) {
13479 valuebuffer = GetValuebuffer(client_id);
13480 if (!valuebuffer) {
13481 if (!group_->bind_generates_resource()) {
13482 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindValuebufferCHROMIUM",
13483 "id not generated by glBindValuebufferCHROMIUM");
13484 return;
13487 // It's a new id so make a valuebuffer for it.
13488 CreateValuebuffer(client_id);
13489 valuebuffer = GetValuebuffer(client_id);
13491 valuebuffer->MarkAsValid();
13493 state_.bound_valuebuffer = valuebuffer;
13496 void GLES2DecoderImpl::DoSubscribeValueCHROMIUM(GLenum target,
13497 GLenum subscription) {
13498 if (!CheckCurrentValuebuffer("glSubscribeValueCHROMIUM")) {
13499 return;
13501 state_.bound_valuebuffer.get()->AddSubscription(subscription);
13504 void GLES2DecoderImpl::DoPopulateSubscribedValuesCHROMIUM(GLenum target) {
13505 if (!CheckCurrentValuebuffer("glPopulateSubscribedValuesCHROMIUM")) {
13506 return;
13508 valuebuffer_manager()->UpdateValuebufferState(state_.bound_valuebuffer.get());
13511 void GLES2DecoderImpl::DoUniformValueBufferCHROMIUM(GLint location,
13512 GLenum target,
13513 GLenum subscription) {
13514 if (!CheckCurrentValuebufferForSubscription(
13515 subscription, "glPopulateSubscribedValuesCHROMIUM")) {
13516 return;
13518 if (!CheckSubscriptionTarget(location, subscription,
13519 "glPopulateSubscribedValuesCHROMIUM")) {
13520 return;
13522 const ValueState* state =
13523 state_.bound_valuebuffer.get()->GetState(subscription);
13524 if (state) {
13525 switch (subscription) {
13526 case GL_MOUSE_POSITION_CHROMIUM:
13527 DoUniform2iv(location, 1, state->int_value);
13528 break;
13529 default:
13530 NOTREACHED() << "Unhandled uniform subscription target "
13531 << subscription;
13532 break;
13537 void GLES2DecoderImpl::DoInsertEventMarkerEXT(
13538 GLsizei length, const GLchar* marker) {
13539 if (!marker) {
13540 marker = "";
13542 debug_marker_manager_.SetMarker(
13543 length ? std::string(marker, length) : std::string(marker));
13546 void GLES2DecoderImpl::DoPushGroupMarkerEXT(
13547 GLsizei /*length*/, const GLchar* /*marker*/) {
13550 void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
13553 void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
13554 GLenum target, GLint image_id) {
13555 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
13557 if (target == GL_TEXTURE_CUBE_MAP) {
13558 LOCAL_SET_GL_ERROR(
13559 GL_INVALID_ENUM,
13560 "glBindTexImage2DCHROMIUM", "invalid target");
13561 return;
13564 // Default target might be conceptually valid, but disallow it to avoid
13565 // accidents.
13566 TextureRef* texture_ref =
13567 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13568 if (!texture_ref) {
13569 LOCAL_SET_GL_ERROR(
13570 GL_INVALID_OPERATION,
13571 "glBindTexImage2DCHROMIUM", "no texture bound");
13572 return;
13575 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
13576 if (!gl_image) {
13577 LOCAL_SET_GL_ERROR(
13578 GL_INVALID_OPERATION,
13579 "glBindTexImage2DCHROMIUM", "no image found with the given ID");
13580 return;
13584 ScopedGLErrorSuppressor suppressor(
13585 "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
13586 if (!gl_image->BindTexImage(target)) {
13587 LOCAL_SET_GL_ERROR(
13588 GL_INVALID_OPERATION,
13589 "glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
13590 return;
13594 gfx::Size size = gl_image->GetSize();
13595 texture_manager()->SetLevelInfo(
13596 texture_ref, target, 0, gl_image->GetInternalFormat(), size.width(),
13597 size.height(), 1, 0, gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE,
13598 gfx::Rect(size));
13599 texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image);
13602 void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
13603 GLenum target, GLint image_id) {
13604 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
13606 // Default target might be conceptually valid, but disallow it to avoid
13607 // accidents.
13608 TextureRef* texture_ref =
13609 texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
13610 if (!texture_ref) {
13611 LOCAL_SET_GL_ERROR(
13612 GL_INVALID_OPERATION,
13613 "glReleaseTexImage2DCHROMIUM", "no texture bound");
13614 return;
13617 gfx::GLImage* gl_image = image_manager()->LookupImage(image_id);
13618 if (!gl_image) {
13619 LOCAL_SET_GL_ERROR(
13620 GL_INVALID_OPERATION,
13621 "glReleaseTexImage2DCHROMIUM", "no image found with the given ID");
13622 return;
13625 // Do nothing when image is not currently bound.
13626 if (texture_ref->texture()->GetLevelImage(target, 0) != gl_image)
13627 return;
13630 ScopedGLErrorSuppressor suppressor(
13631 "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
13632 gl_image->ReleaseTexImage(target);
13635 texture_manager()->SetLevelInfo(
13636 texture_ref, target, 0, gl_image->GetInternalFormat(), 0, 0, 1, 0,
13637 gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, gfx::Rect());
13640 error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM(
13641 uint32 immediate_data_size,
13642 const void* cmd_data) {
13643 const gles2::cmds::TraceBeginCHROMIUM& c =
13644 *static_cast<const gles2::cmds::TraceBeginCHROMIUM*>(cmd_data);
13645 Bucket* category_bucket = GetBucket(c.category_bucket_id);
13646 Bucket* name_bucket = GetBucket(c.name_bucket_id);
13647 if (!category_bucket || category_bucket->size() == 0 ||
13648 !name_bucket || name_bucket->size() == 0) {
13649 return error::kInvalidArguments;
13652 std::string category_name;
13653 std::string trace_name;
13654 if (!category_bucket->GetAsString(&category_name) ||
13655 !name_bucket->GetAsString(&trace_name)) {
13656 return error::kInvalidArguments;
13659 debug_marker_manager_.PushGroup(trace_name);
13660 if (!gpu_tracer_->Begin(category_name, trace_name, kTraceCHROMIUM)) {
13661 LOCAL_SET_GL_ERROR(
13662 GL_INVALID_OPERATION,
13663 "glTraceBeginCHROMIUM", "unable to create begin trace");
13664 return error::kNoError;
13666 return error::kNoError;
13669 void GLES2DecoderImpl::DoTraceEndCHROMIUM() {
13670 debug_marker_manager_.PopGroup();
13671 if (!gpu_tracer_->End(kTraceCHROMIUM)) {
13672 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13673 "glTraceEndCHROMIUM", "no trace begin found");
13674 return;
13678 void GLES2DecoderImpl::DoDrawBuffersEXT(
13679 GLsizei count, const GLenum* bufs) {
13680 if (count > static_cast<GLsizei>(group_->max_draw_buffers())) {
13681 LOCAL_SET_GL_ERROR(
13682 GL_INVALID_VALUE,
13683 "glDrawBuffersEXT", "greater than GL_MAX_DRAW_BUFFERS_EXT");
13684 return;
13687 Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
13688 if (framebuffer) {
13689 for (GLsizei i = 0; i < count; ++i) {
13690 if (bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i) &&
13691 bufs[i] != GL_NONE) {
13692 LOCAL_SET_GL_ERROR(
13693 GL_INVALID_OPERATION,
13694 "glDrawBuffersEXT",
13695 "bufs[i] not GL_NONE or GL_COLOR_ATTACHMENTi_EXT");
13696 return;
13699 glDrawBuffersARB(count, bufs);
13700 framebuffer->SetDrawBuffers(count, bufs);
13701 } else { // backbuffer
13702 if (count > 1 ||
13703 (bufs[0] != GL_BACK && bufs[0] != GL_NONE)) {
13704 LOCAL_SET_GL_ERROR(
13705 GL_INVALID_OPERATION,
13706 "glDrawBuffersEXT",
13707 "more than one buffer or bufs not GL_NONE or GL_BACK");
13708 return;
13710 GLenum mapped_buf = bufs[0];
13711 if (GetBackbufferServiceId() != 0 && // emulated backbuffer
13712 bufs[0] == GL_BACK) {
13713 mapped_buf = GL_COLOR_ATTACHMENT0;
13715 glDrawBuffersARB(count, &mapped_buf);
13716 back_buffer_draw_buffer_ = bufs[0];
13720 void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) {
13721 MarkContextLost(GetContextLostReasonFromResetStatus(current));
13722 group_->LoseContexts(GetContextLostReasonFromResetStatus(other));
13723 reset_by_robustness_extension_ = true;
13726 void GLES2DecoderImpl::DoFlushDriverCachesCHROMIUM(void) {
13727 // On Adreno Android devices we need to use a workaround to force caches to
13728 // clear.
13729 if (feature_info_->workarounds().unbind_egl_context_to_flush_driver_caches) {
13730 context_->ReleaseCurrent(nullptr);
13731 context_->MakeCurrent(surface_.get());
13735 void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode,
13736 const GLfloat* matrix) {
13737 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
13738 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
13739 if (!features().chromium_path_rendering) {
13740 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13741 "glMatrixLoadfCHROMIUM",
13742 "function not available");
13743 return;
13746 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
13747 ? state_.projection_matrix
13748 : state_.modelview_matrix;
13749 memcpy(target_matrix, matrix, sizeof(GLfloat) * 16);
13750 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13751 // since the values of the _NV and _CHROMIUM tokens match.
13752 glMatrixLoadfEXT(matrix_mode, matrix);
13755 void GLES2DecoderImpl::DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode) {
13756 DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
13757 matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
13759 if (!features().chromium_path_rendering) {
13760 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
13761 "glMatrixLoadIdentityCHROMIUM",
13762 "function not available");
13763 return;
13766 GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
13767 ? state_.projection_matrix
13768 : state_.modelview_matrix;
13769 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix));
13770 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV
13771 // since the values of the _NV and _CHROMIUM tokens match.
13772 glMatrixLoadIdentityEXT(matrix_mode);
13775 bool GLES2DecoderImpl::ValidateAsyncTransfer(
13776 const char* function_name,
13777 TextureRef* texture_ref,
13778 GLenum target,
13779 GLint level,
13780 const void * data) {
13781 // We only support async uploads to 2D textures for now.
13782 if (GL_TEXTURE_2D != target) {
13783 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
13784 return false;
13786 // We only support uploads to level zero for now.
13787 if (level != 0) {
13788 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "level != 0");
13789 return false;
13791 // A transfer buffer must be bound, even for asyncTexImage2D.
13792 if (data == NULL) {
13793 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "buffer == 0");
13794 return false;
13796 // We only support one async transfer in progress.
13797 if (!texture_ref ||
13798 async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
13799 LOCAL_SET_GL_ERROR(
13800 GL_INVALID_OPERATION,
13801 function_name, "transfer already in progress");
13802 return false;
13804 return true;
13807 base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
13808 uint32 async_upload_token,
13809 uint32 sync_data_shm_id,
13810 uint32 sync_data_shm_offset) {
13811 scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
13812 if (!buffer.get() ||
13813 !buffer->GetDataAddress(sync_data_shm_offset, sizeof(AsyncUploadSync)))
13814 return base::Closure();
13816 AsyncMemoryParams mem_params(buffer,
13817 sync_data_shm_offset,
13818 sizeof(AsyncUploadSync));
13820 scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
13821 new AsyncUploadTokenCompletionObserver(async_upload_token));
13823 return base::Bind(
13824 &AsyncPixelTransferManager::AsyncNotifyCompletion,
13825 base::Unretained(GetAsyncPixelTransferManager()),
13826 mem_params,
13827 observer);
13830 error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
13831 uint32 immediate_data_size,
13832 const void* cmd_data) {
13833 const gles2::cmds::AsyncTexImage2DCHROMIUM& c =
13834 *static_cast<const gles2::cmds::AsyncTexImage2DCHROMIUM*>(cmd_data);
13835 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
13836 GLenum target = static_cast<GLenum>(c.target);
13837 GLint level = static_cast<GLint>(c.level);
13838 GLenum internal_format = static_cast<GLenum>(c.internalformat);
13839 GLsizei width = static_cast<GLsizei>(c.width);
13840 GLsizei height = static_cast<GLsizei>(c.height);
13841 GLint border = static_cast<GLint>(c.border);
13842 GLenum format = static_cast<GLenum>(c.format);
13843 GLenum type = static_cast<GLenum>(c.type);
13844 uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
13845 uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
13846 uint32 pixels_size;
13847 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
13848 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
13849 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
13851 base::ScopedClosureRunner scoped_completion_callback;
13852 if (async_upload_token) {
13853 base::Closure completion_closure =
13854 AsyncUploadTokenCompletionClosure(async_upload_token,
13855 sync_data_shm_id,
13856 sync_data_shm_offset);
13857 if (completion_closure.is_null())
13858 return error::kInvalidArguments;
13860 scoped_completion_callback.Reset(completion_closure);
13863 // TODO(epenner): Move this and copies of this memory validation
13864 // into ValidateTexImage2D step.
13865 if (!GLES2Util::ComputeImageDataSizes(
13866 width, height, 1, format, type, state_.unpack_alignment, &pixels_size,
13867 NULL, NULL)) {
13868 return error::kOutOfBounds;
13870 const void* pixels = NULL;
13871 if (pixels_shm_id != 0 || pixels_shm_offset != 0) {
13872 pixels = GetSharedMemoryAs<const void*>(
13873 pixels_shm_id, pixels_shm_offset, pixels_size);
13874 if (!pixels) {
13875 return error::kOutOfBounds;
13879 TextureManager::DoTexImageArguments args = {
13880 target, level, internal_format, width, height, 1, border, format, type,
13881 pixels, pixels_size, TextureManager::DoTexImageArguments::kTexImage2D };
13882 TextureRef* texture_ref;
13883 // All the normal glTexSubImage2D validation.
13884 if (!texture_manager()->ValidateTexImage(
13885 &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
13886 return error::kNoError;
13889 // Extra async validation.
13890 Texture* texture = texture_ref->texture();
13891 if (!ValidateAsyncTransfer(
13892 "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
13893 return error::kNoError;
13895 // Don't allow async redefinition of a textures.
13896 if (texture->IsDefined()) {
13897 LOCAL_SET_GL_ERROR(
13898 GL_INVALID_OPERATION,
13899 "glAsyncTexImage2DCHROMIUM", "already defined");
13900 return error::kNoError;
13903 if (!EnsureGPUMemoryAvailable(pixels_size)) {
13904 LOCAL_SET_GL_ERROR(
13905 GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory");
13906 return error::kNoError;
13909 // Setup the parameters.
13910 AsyncTexImage2DParams tex_params = {
13911 target, level, static_cast<GLenum>(internal_format),
13912 width, height, border, format, type};
13913 AsyncMemoryParams mem_params(
13914 GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
13916 // Set up the async state if needed, and make the texture
13917 // immutable so the async state stays valid. The level info
13918 // is set up lazily when the transfer completes.
13919 AsyncPixelTransferDelegate* delegate =
13920 async_pixel_transfer_manager_->CreatePixelTransferDelegate(texture_ref,
13921 tex_params);
13922 texture->SetImmutable(true);
13924 delegate->AsyncTexImage2D(
13925 tex_params,
13926 mem_params,
13927 base::Bind(&TextureManager::SetLevelInfoFromParams,
13928 // The callback is only invoked if the transfer delegate still
13929 // exists, which implies through manager->texture_ref->state
13930 // ownership that both of these pointers are valid.
13931 base::Unretained(texture_manager()),
13932 base::Unretained(texture_ref),
13933 tex_params));
13934 return error::kNoError;
13937 error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
13938 uint32 immediate_data_size,
13939 const void* cmd_data) {
13940 const gles2::cmds::AsyncTexSubImage2DCHROMIUM& c =
13941 *static_cast<const gles2::cmds::AsyncTexSubImage2DCHROMIUM*>(cmd_data);
13942 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM");
13943 GLenum target = static_cast<GLenum>(c.target);
13944 GLint level = static_cast<GLint>(c.level);
13945 GLint xoffset = static_cast<GLint>(c.xoffset);
13946 GLint yoffset = static_cast<GLint>(c.yoffset);
13947 GLsizei width = static_cast<GLsizei>(c.width);
13948 GLsizei height = static_cast<GLsizei>(c.height);
13949 GLenum format = static_cast<GLenum>(c.format);
13950 GLenum type = static_cast<GLenum>(c.type);
13951 uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
13952 uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
13953 uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
13955 base::ScopedClosureRunner scoped_completion_callback;
13956 if (async_upload_token) {
13957 base::Closure completion_closure =
13958 AsyncUploadTokenCompletionClosure(async_upload_token,
13959 sync_data_shm_id,
13960 sync_data_shm_offset);
13961 if (completion_closure.is_null())
13962 return error::kInvalidArguments;
13964 scoped_completion_callback.Reset(completion_closure);
13967 // TODO(epenner): Move this and copies of this memory validation
13968 // into ValidateTexSubImage2D step.
13969 uint32 data_size;
13970 if (!GLES2Util::ComputeImageDataSizes(
13971 width, height, 1, format, type, state_.unpack_alignment, &data_size,
13972 NULL, NULL)) {
13973 return error::kOutOfBounds;
13975 const void* pixels = GetSharedMemoryAs<const void*>(
13976 c.data_shm_id, c.data_shm_offset, data_size);
13978 // All the normal glTexSubImage2D validation.
13979 error::Error error = error::kNoError;
13980 if (!ValidateTexSubImage2D(&error, "glAsyncTexSubImage2DCHROMIUM",
13981 target, level, xoffset, yoffset, width, height, format, type, pixels)) {
13982 return error;
13985 // Extra async validation.
13986 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
13987 &state_, target);
13988 Texture* texture = texture_ref->texture();
13989 if (!ValidateAsyncTransfer(
13990 "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
13991 return error::kNoError;
13993 // Guarantee async textures are always 'cleared' as follows:
13994 // - AsyncTexImage2D can not redefine an existing texture
13995 // - AsyncTexImage2D must initialize the entire image via non-null buffer.
13996 // - AsyncTexSubImage2D clears synchronously if not already cleared.
13997 // - Textures become immutable after an async call.
13998 // This way we know in all cases that an async texture is always clear.
13999 if (!texture->SafeToRenderFrom()) {
14000 if (!texture_manager()->ClearTextureLevel(this, texture_ref,
14001 target, level)) {
14002 LOCAL_SET_GL_ERROR(
14003 GL_OUT_OF_MEMORY,
14004 "glAsyncTexSubImage2DCHROMIUM", "dimensions too big");
14005 return error::kNoError;
14009 // Setup the parameters.
14010 AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
14011 width, height, format, type};
14012 AsyncMemoryParams mem_params(
14013 GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
14014 AsyncPixelTransferDelegate* delegate =
14015 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
14016 if (!delegate) {
14017 // TODO(epenner): We may want to enforce exclusive use
14018 // of async APIs in which case this should become an error,
14019 // (the texture should have been async defined).
14020 AsyncTexImage2DParams define_params = {target, level,
14021 0, 0, 0, 0, 0, 0};
14022 texture->GetLevelSize(
14023 target, level, &define_params.width, &define_params.height, nullptr);
14024 texture->GetLevelType(
14025 target, level, &define_params.type, &define_params.internal_format);
14026 // Set up the async state if needed, and make the texture
14027 // immutable so the async state stays valid.
14028 delegate = async_pixel_transfer_manager_->CreatePixelTransferDelegate(
14029 texture_ref, define_params);
14030 texture->SetImmutable(true);
14033 delegate->AsyncTexSubImage2D(tex_params, mem_params);
14034 return error::kNoError;
14037 error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
14038 uint32 immediate_data_size,
14039 const void* cmd_data) {
14040 const gles2::cmds::WaitAsyncTexImage2DCHROMIUM& c =
14041 *static_cast<const gles2::cmds::WaitAsyncTexImage2DCHROMIUM*>(cmd_data);
14042 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
14043 GLenum target = static_cast<GLenum>(c.target);
14045 if (GL_TEXTURE_2D != target) {
14046 LOCAL_SET_GL_ERROR(
14047 GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
14048 return error::kNoError;
14050 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
14051 &state_, target);
14052 if (!texture_ref) {
14053 LOCAL_SET_GL_ERROR(
14054 GL_INVALID_OPERATION,
14055 "glWaitAsyncTexImage2DCHROMIUM", "unknown texture");
14056 return error::kNoError;
14058 AsyncPixelTransferDelegate* delegate =
14059 async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
14060 if (!delegate) {
14061 LOCAL_SET_GL_ERROR(
14062 GL_INVALID_OPERATION,
14063 "glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
14064 return error::kNoError;
14066 delegate->WaitForTransferCompletion();
14067 ProcessFinishedAsyncTransfers();
14068 return error::kNoError;
14071 error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
14072 uint32 immediate_data_size,
14073 const void* data) {
14074 TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
14076 GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
14077 ProcessFinishedAsyncTransfers();
14078 return error::kNoError;
14081 error::Error GLES2DecoderImpl::HandleUniformBlockBinding(
14082 uint32_t immediate_data_size, const void* cmd_data) {
14083 if (!unsafe_es3_apis_enabled())
14084 return error::kUnknownCommand;
14085 const gles2::cmds::UniformBlockBinding& c =
14086 *static_cast<const gles2::cmds::UniformBlockBinding*>(cmd_data);
14087 GLuint client_id = c.program;
14088 GLuint index = static_cast<GLuint>(c.index);
14089 GLuint binding = static_cast<GLuint>(c.binding);
14090 Program* program = GetProgramInfoNotShader(
14091 client_id, "glUniformBlockBinding");
14092 if (!program) {
14093 return error::kNoError;
14095 GLuint service_id = program->service_id();
14096 glUniformBlockBinding(service_id, index, binding);
14097 return error::kNoError;
14100 error::Error GLES2DecoderImpl::HandleClientWaitSync(
14101 uint32_t immediate_data_size, const void* cmd_data) {
14102 if (!unsafe_es3_apis_enabled())
14103 return error::kUnknownCommand;
14104 const gles2::cmds::ClientWaitSync& c =
14105 *static_cast<const gles2::cmds::ClientWaitSync*>(cmd_data);
14106 GLuint sync = static_cast<GLuint>(c.sync);
14107 GLbitfield flags = static_cast<GLbitfield>(c.flags);
14108 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
14109 typedef cmds::ClientWaitSync::Result Result;
14110 Result* result_dst = GetSharedMemoryAs<Result*>(
14111 c.result_shm_id, c.result_shm_offset, sizeof(*result_dst));
14112 if (!result_dst) {
14113 return error::kOutOfBounds;
14115 if (*result_dst != GL_WAIT_FAILED) {
14116 return error::kInvalidArguments;
14118 GLsync service_sync = 0;
14119 if (!group_->GetSyncServiceId(sync, &service_sync)) {
14120 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "ClientWaitSync", "invalid sync");
14121 return error::kNoError;
14123 *result_dst = glClientWaitSync(service_sync, flags, timeout);
14124 return error::kNoError;
14127 error::Error GLES2DecoderImpl::HandleWaitSync(
14128 uint32_t immediate_data_size, const void* cmd_data) {
14129 if (!unsafe_es3_apis_enabled())
14130 return error::kUnknownCommand;
14131 const gles2::cmds::WaitSync& c =
14132 *static_cast<const gles2::cmds::WaitSync*>(cmd_data);
14133 GLuint sync = static_cast<GLuint>(c.sync);
14134 GLbitfield flags = static_cast<GLbitfield>(c.flags);
14135 GLuint64 timeout = GLES2Util::MapTwoUint32ToUint64(c.timeout_0, c.timeout_1);
14136 GLsync service_sync = 0;
14137 if (!group_->GetSyncServiceId(sync, &service_sync)) {
14138 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "WaitSync", "invalid sync");
14139 return error::kNoError;
14141 glWaitSync(service_sync, flags, timeout);
14142 return error::kNoError;
14145 error::Error GLES2DecoderImpl::HandleGetInternalformativ(
14146 uint32_t immediate_data_size, const void* cmd_data) {
14147 if (!unsafe_es3_apis_enabled())
14148 return error::kUnknownCommand;
14149 const gles2::cmds::GetInternalformativ& c =
14150 *static_cast<const gles2::cmds::GetInternalformativ*>(cmd_data);
14151 GLenum target = static_cast<GLenum>(c.target);
14152 GLenum format = static_cast<GLenum>(c.format);
14153 GLenum pname = static_cast<GLenum>(c.pname);
14154 if (!validators_->render_buffer_target.IsValid(target)) {
14155 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", target, "target");
14156 return error::kNoError;
14158 if (!validators_->render_buffer_format.IsValid(format)) {
14159 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", format, "format");
14160 return error::kNoError;
14162 if (!validators_->internal_format_parameter.IsValid(pname)) {
14163 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetInternalformativ", pname, "pname");
14164 return error::kNoError;
14166 typedef cmds::GetInternalformativ::Result Result;
14167 GLsizei num_values = 0;
14168 switch (pname) {
14169 case GL_NUM_SAMPLE_COUNTS:
14170 num_values = 1;
14171 break;
14172 case GL_SAMPLES:
14174 GLint value = 0;
14175 glGetInternalformativ(target, format, GL_NUM_SAMPLE_COUNTS, 1, &value);
14176 num_values = static_cast<GLsizei>(value);
14178 break;
14179 default:
14180 NOTREACHED();
14181 break;
14183 Result* result = GetSharedMemoryAs<Result*>(
14184 c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
14185 GLint* params = result ? result->GetData() : NULL;
14186 if (params == NULL) {
14187 return error::kOutOfBounds;
14189 // Check that the client initialized the result.
14190 if (result->size != 0) {
14191 return error::kInvalidArguments;
14193 glGetInternalformativ(target, format, pname, num_values, params);
14194 result->SetNumResults(num_values);
14195 return error::kNoError;
14198 error::Error GLES2DecoderImpl::HandleMapBufferRange(
14199 uint32_t immediate_data_size, const void* cmd_data) {
14200 if (!unsafe_es3_apis_enabled()) {
14201 return error::kUnknownCommand;
14203 const gles2::cmds::MapBufferRange& c =
14204 *static_cast<const gles2::cmds::MapBufferRange*>(cmd_data);
14205 GLenum target = static_cast<GLenum>(c.target);
14206 GLbitfield access = static_cast<GLbitfield>(c.access);
14207 GLintptr offset = static_cast<GLintptr>(c.offset);
14208 GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
14210 typedef cmds::MapBufferRange::Result Result;
14211 Result* result = GetSharedMemoryAs<Result*>(
14212 c.result_shm_id, c.result_shm_offset, sizeof(*result));
14213 if (!result) {
14214 return error::kOutOfBounds;
14216 if (*result != 0) {
14217 *result = 0;
14218 return error::kInvalidArguments;
14220 int8_t* mem =
14221 GetSharedMemoryAs<int8_t*>(c.data_shm_id, c.data_shm_offset, size);
14222 if (!mem) {
14223 return error::kOutOfBounds;
14226 GLbitfield mask = GL_MAP_INVALIDATE_BUFFER_BIT;
14227 if ((access & mask) == mask) {
14228 // TODO(zmo): To be on the safe side, always map
14229 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT.
14230 access = (access & ~GL_MAP_INVALIDATE_BUFFER_BIT);
14231 access = (access | GL_MAP_INVALIDATE_RANGE_BIT);
14233 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of
14234 // undefined behaviors.
14235 mask = GL_MAP_READ_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
14236 if ((access & mask) == mask) {
14237 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "MapBufferRange",
14238 "incompatible access bits");
14239 return error::kNoError;
14241 access = (access & ~GL_MAP_UNSYNCHRONIZED_BIT);
14242 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT &&
14243 (access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
14244 access = (access | GL_MAP_READ_BIT);
14246 void* ptr = glMapBufferRange(target, offset, size, access);
14247 if (ptr == nullptr) {
14248 return error::kNoError;
14250 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
14251 DCHECK(buffer);
14252 buffer->SetMappedRange(offset, size, access, ptr,
14253 GetSharedMemoryBuffer(c.data_shm_id));
14254 if ((access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) {
14255 memcpy(mem, ptr, size);
14257 *result = 1;
14258 return error::kNoError;
14261 error::Error GLES2DecoderImpl::HandleUnmapBuffer(
14262 uint32_t immediate_data_size, const void* cmd_data) {
14263 if (!unsafe_es3_apis_enabled()) {
14264 return error::kUnknownCommand;
14266 const gles2::cmds::UnmapBuffer& c =
14267 *static_cast<const gles2::cmds::UnmapBuffer*>(cmd_data);
14268 GLenum target = static_cast<GLenum>(c.target);
14270 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target);
14271 if (!buffer) {
14272 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", "no buffer bound");
14273 return error::kNoError;
14275 const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
14276 if (!mapped_range) {
14277 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer",
14278 "buffer is unmapped");
14279 return error::kNoError;
14281 if ((mapped_range->access & GL_MAP_WRITE_BIT) == 0 ||
14282 (mapped_range->access & GL_MAP_FLUSH_EXPLICIT_BIT) ==
14283 GL_MAP_FLUSH_EXPLICIT_BIT) {
14284 // If we don't need to write back, or explict flush is required, no copying
14285 // back is needed.
14286 } else {
14287 void* mem = mapped_range->GetShmPointer();
14288 if (!mem) {
14289 return error::kOutOfBounds;
14291 DCHECK(mapped_range->pointer);
14292 memcpy(mapped_range->pointer, mem, mapped_range->size);
14294 buffer->RemoveMappedRange();
14295 GLboolean rt = glUnmapBuffer(target);
14296 if (rt == GL_FALSE) {
14297 // At this point, we have already done the necessary validation, so
14298 // GL_FALSE indicates data corruption.
14299 // TODO(zmo): We could redo the map / copy data / unmap to recover, but
14300 // the second unmap could still return GL_FALSE. For now, we simply lose
14301 // the contexts in the share group.
14302 LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE";
14303 // Need to lose current context before broadcasting!
14304 MarkContextLost(error::kGuilty);
14305 group_->LoseContexts(error::kInnocent);
14306 return error::kLostContext;
14308 return error::kNoError;
14311 void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
14312 TextureRef* texture_ref) {
14313 Texture* texture = texture_ref->texture();
14314 DoDidUseTexImageIfNeeded(texture, texture->target());
14317 // Note that GL_LOST_CONTEXT is specific to GLES.
14318 // For desktop GL we have to query the reset status proactively.
14319 void GLES2DecoderImpl::OnContextLostError() {
14320 if (!WasContextLost()) {
14321 // Need to lose current context before broadcasting!
14322 CheckResetStatus();
14323 group_->LoseContexts(error::kUnknown);
14324 reset_by_robustness_extension_ = true;
14328 void GLES2DecoderImpl::OnOutOfMemoryError() {
14329 if (lose_context_when_out_of_memory_ && !WasContextLost()) {
14330 error::ContextLostReason other = error::kOutOfMemory;
14331 if (CheckResetStatus()) {
14332 other = error::kUnknown;
14333 } else {
14334 // Need to lose current context before broadcasting!
14335 MarkContextLost(error::kOutOfMemory);
14337 group_->LoseContexts(other);
14341 error::Error GLES2DecoderImpl::HandleGenPathsCHROMIUM(
14342 uint32 immediate_data_size,
14343 const void* cmd_data) {
14344 static const char kFunctionName[] = "glGenPathsCHROMIUM";
14345 const gles2::cmds::GenPathsCHROMIUM& c =
14346 *static_cast<const gles2::cmds::GenPathsCHROMIUM*>(cmd_data);
14347 if (!features().chromium_path_rendering) {
14348 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14349 "function not available");
14350 return error::kNoError;
14353 GLsizei range = static_cast<GLsizei>(c.range);
14354 if (range < 0) {
14355 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "range < 0");
14356 return error::kNoError;
14359 GLuint first_client_id = static_cast<GLuint>(c.first_client_id);
14360 if (first_client_id == 0)
14361 return error::kInvalidArguments;
14363 if (range == 0)
14364 return error::kNoError;
14366 if (!GenPathsCHROMIUMHelper(first_client_id, range))
14367 return error::kInvalidArguments;
14369 return error::kNoError;
14371 error::Error GLES2DecoderImpl::HandleDeletePathsCHROMIUM(
14372 uint32_t immediate_data_size,
14373 const void* cmd_data) {
14374 static const char kFunctionName[] = "glDeletePathsCHROMIUM";
14375 const gles2::cmds::DeletePathsCHROMIUM& c =
14376 *static_cast<const gles2::cmds::DeletePathsCHROMIUM*>(cmd_data);
14377 if (!features().chromium_path_rendering) {
14378 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14379 "function not available");
14380 return error::kNoError;
14383 GLsizei range = static_cast<GLsizei>(c.range);
14384 if (range < 0) {
14385 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "range < 0");
14386 return error::kNoError;
14389 if (range == 0)
14390 return error::kNoError;
14392 GLuint first_client_id = c.first_client_id;
14393 // first_client_id can be 0, because non-existing path ids are skipped.
14395 if (!DeletePathsCHROMIUMHelper(first_client_id, range))
14396 return error::kInvalidArguments;
14398 return error::kNoError;
14401 error::Error GLES2DecoderImpl::HandlePathCommandsCHROMIUM(
14402 uint32 immediate_data_size,
14403 const void* cmd_data) {
14404 static const char kFunctionName[] = "glPathCommandsCHROMIUM";
14405 const gles2::cmds::PathCommandsCHROMIUM& c =
14406 *static_cast<const gles2::cmds::PathCommandsCHROMIUM*>(cmd_data);
14407 if (!features().chromium_path_rendering) {
14408 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14409 "function not available");
14410 return error::kNoError;
14413 GLuint service_id = 0;
14414 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14415 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14416 "invalid path name");
14417 return error::kNoError;
14420 GLsizei num_commands = static_cast<GLsizei>(c.numCommands);
14421 if (num_commands < 0) {
14422 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numCommands < 0");
14423 return error::kNoError;
14426 GLsizei num_coords = static_cast<uint32>(c.numCoords);
14427 if (num_coords < 0) {
14428 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "numCoords < 0");
14429 return error::kNoError;
14432 GLenum coord_type = static_cast<uint32>(c.coordType);
14433 if (!validators_->path_coord_type.IsValid(static_cast<GLint>(coord_type))) {
14434 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName, "invalid coordType");
14435 return error::kNoError;
14438 const GLubyte* commands = NULL;
14439 base::CheckedNumeric<GLsizei> num_coords_expected = 0;
14441 if (num_commands > 0) {
14442 uint32 commands_shm_id = static_cast<uint32>(c.commands_shm_id);
14443 uint32 commands_shm_offset = static_cast<uint32>(c.commands_shm_offset);
14444 if (commands_shm_id != 0 || commands_shm_offset != 0)
14445 commands = GetSharedMemoryAs<const GLubyte*>(
14446 commands_shm_id, commands_shm_offset, num_commands);
14448 if (!commands)
14449 return error::kOutOfBounds;
14451 for (GLsizei i = 0; i < num_commands; ++i) {
14452 switch (commands[i]) {
14453 case GL_CLOSE_PATH_CHROMIUM:
14454 // Close has no coords.
14455 break;
14456 case GL_MOVE_TO_CHROMIUM:
14457 // Fallthrough.
14458 case GL_LINE_TO_CHROMIUM:
14459 num_coords_expected += 2;
14460 break;
14461 case GL_QUADRATIC_CURVE_TO_CHROMIUM:
14462 num_coords_expected += 4;
14463 break;
14464 case GL_CUBIC_CURVE_TO_CHROMIUM:
14465 num_coords_expected += 6;
14466 break;
14467 case GL_CONIC_CURVE_TO_CHROMIUM:
14468 num_coords_expected += 5;
14469 break;
14470 default:
14471 LOCAL_SET_GL_ERROR(GL_INVALID_ENUM, kFunctionName, "invalid command");
14472 return error::kNoError;
14477 if (!num_coords_expected.IsValid() ||
14478 num_coords != num_coords_expected.ValueOrDie()) {
14479 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14480 "numCoords does not match commands");
14481 return error::kNoError;
14484 const void* coords = NULL;
14486 if (num_coords > 0) {
14487 uint32 coords_size = 0;
14488 uint32 coord_type_size =
14489 GLES2Util::GetGLTypeSizeForPathCoordType(coord_type);
14490 if (!SafeMultiplyUint32(num_coords, coord_type_size, &coords_size))
14491 return error::kOutOfBounds;
14493 uint32 coords_shm_id = static_cast<uint32>(c.coords_shm_id);
14494 uint32 coords_shm_offset = static_cast<uint32>(c.coords_shm_offset);
14495 if (coords_shm_id != 0 || coords_shm_offset != 0)
14496 coords = GetSharedMemoryAs<const void*>(coords_shm_id, coords_shm_offset,
14497 coords_size);
14499 if (!coords)
14500 return error::kOutOfBounds;
14503 glPathCommandsNV(service_id, num_commands, commands, num_coords, coord_type,
14504 coords);
14506 return error::kNoError;
14509 error::Error GLES2DecoderImpl::HandlePathParameterfCHROMIUM(
14510 uint32 immediate_data_size,
14511 const void* cmd_data) {
14512 static const char kFunctionName[] = "glPathParameterfCHROMIUM";
14513 const gles2::cmds::PathParameterfCHROMIUM& c =
14514 *static_cast<const gles2::cmds::PathParameterfCHROMIUM*>(cmd_data);
14515 if (!features().chromium_path_rendering) {
14516 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14517 "function not available");
14518 return error::kNoError;
14520 GLuint service_id = 0;
14521 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14522 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14523 "invalid path name");
14524 return error::kNoError;
14527 GLenum pname = static_cast<GLenum>(c.pname);
14528 GLfloat value = static_cast<GLfloat>(c.value);
14529 bool hasValueError = false;
14531 switch (pname) {
14532 case GL_PATH_STROKE_WIDTH_CHROMIUM:
14533 case GL_PATH_MITER_LIMIT_CHROMIUM:
14534 hasValueError = std::isnan(value) || !std::isfinite(value) || value < 0;
14535 break;
14536 case GL_PATH_STROKE_BOUND_CHROMIUM:
14537 value = std::max(std::min(1.0f, value), 0.0f);
14538 break;
14539 case GL_PATH_END_CAPS_CHROMIUM:
14540 hasValueError = !validators_->path_parameter_cap_values.IsValid(
14541 static_cast<GLint>(value));
14542 break;
14543 case GL_PATH_JOIN_STYLE_CHROMIUM:
14544 hasValueError = !validators_->path_parameter_join_values.IsValid(
14545 static_cast<GLint>(value));
14546 break;
14547 default:
14548 DCHECK(!validators_->path_parameter.IsValid(pname));
14549 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, pname, "pname");
14550 return error::kNoError;
14552 DCHECK(validators_->path_parameter.IsValid(pname));
14554 if (hasValueError) {
14555 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "value not correct");
14556 return error::kNoError;
14559 glPathParameterfNV(service_id, pname, value);
14560 return error::kNoError;
14563 error::Error GLES2DecoderImpl::HandlePathParameteriCHROMIUM(
14564 uint32 immediate_data_size,
14565 const void* cmd_data) {
14566 static const char kFunctionName[] = "glPathParameteriCHROMIUM";
14567 const gles2::cmds::PathParameteriCHROMIUM& c =
14568 *static_cast<const gles2::cmds::PathParameteriCHROMIUM*>(cmd_data);
14569 if (!features().chromium_path_rendering) {
14570 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14571 "function not available");
14572 return error::kNoError;
14574 GLuint service_id = 0;
14575 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14576 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14577 "invalid path name");
14578 return error::kNoError;
14581 GLenum pname = static_cast<GLenum>(c.pname);
14582 GLint value = static_cast<GLint>(c.value);
14583 bool hasValueError = false;
14585 switch (pname) {
14586 case GL_PATH_STROKE_WIDTH_CHROMIUM:
14587 case GL_PATH_MITER_LIMIT_CHROMIUM:
14588 hasValueError = value < 0;
14589 break;
14590 case GL_PATH_STROKE_BOUND_CHROMIUM:
14591 value = std::max(std::min(1, value), 0);
14592 break;
14593 case GL_PATH_END_CAPS_CHROMIUM:
14594 hasValueError = !validators_->path_parameter_cap_values.IsValid(value);
14595 break;
14596 case GL_PATH_JOIN_STYLE_CHROMIUM:
14597 hasValueError = !validators_->path_parameter_join_values.IsValid(value);
14598 break;
14599 default:
14600 DCHECK(!validators_->path_parameter.IsValid(pname));
14601 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, pname, "pname");
14602 return error::kNoError;
14604 DCHECK(validators_->path_parameter.IsValid(pname));
14606 if (hasValueError) {
14607 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "value not correct");
14608 return error::kNoError;
14611 glPathParameteriNV(service_id, pname, value);
14612 return error::kNoError;
14615 error::Error GLES2DecoderImpl::HandleStencilFillPathCHROMIUM(
14616 uint32 immediate_data_size,
14617 const void* cmd_data) {
14618 static const char kFunctionName[] = "glStencilFillPathCHROMIUM";
14619 const gles2::cmds::StencilFillPathCHROMIUM& c =
14620 *static_cast<const gles2::cmds::StencilFillPathCHROMIUM*>(cmd_data);
14621 if (!features().chromium_path_rendering) {
14622 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14623 "function not available");
14624 return error::kNoError;
14626 GLenum fill_mode = static_cast<GLenum>(c.fillMode);
14627 if (!validators_->path_fill_mode.IsValid(fill_mode)) {
14628 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, fill_mode, "fillMode");
14629 return error::kNoError;
14631 GLuint mask = static_cast<GLuint>(c.mask);
14632 if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
14633 fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
14634 GLES2Util::IsNPOT(mask + 1)) {
14635 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
14636 "mask + 1 is not power of two");
14637 return error::kNoError;
14639 GLuint service_id = 0;
14640 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14641 // "If /path/ does not name an existing path object, the command does
14642 // nothing (and no error is generated)."
14643 // This holds for other rendering functions, too.
14644 return error::kNoError;
14646 ApplyDirtyState();
14647 glStencilFillPathNV(service_id, fill_mode, mask);
14648 return error::kNoError;
14651 error::Error GLES2DecoderImpl::HandleStencilStrokePathCHROMIUM(
14652 uint32 immediate_data_size,
14653 const void* cmd_data) {
14654 static const char kFunctionName[] = "glStencilStrokePathCHROMIUM";
14655 const gles2::cmds::StencilStrokePathCHROMIUM& c =
14656 *static_cast<const gles2::cmds::StencilStrokePathCHROMIUM*>(cmd_data);
14657 if (!features().chromium_path_rendering) {
14658 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14659 "function not available");
14660 return error::kNoError;
14662 GLuint service_id = 0;
14663 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id)) {
14664 return error::kNoError;
14666 GLint reference = static_cast<GLint>(c.reference);
14667 GLuint mask = static_cast<GLuint>(c.mask);
14668 ApplyDirtyState();
14669 glStencilStrokePathNV(service_id, reference, mask);
14670 return error::kNoError;
14673 error::Error GLES2DecoderImpl::HandleCoverFillPathCHROMIUM(
14674 uint32 immediate_data_size,
14675 const void* cmd_data) {
14676 static const char kFunctionName[] = "glCoverFillPathCHROMIUM";
14677 const gles2::cmds::CoverFillPathCHROMIUM& c =
14678 *static_cast<const gles2::cmds::CoverFillPathCHROMIUM*>(cmd_data);
14679 if (!features().chromium_path_rendering) {
14680 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14681 "function not available");
14682 return error::kNoError;
14684 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14685 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14686 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14687 return error::kNoError;
14689 GLuint service_id = 0;
14690 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14691 return error::kNoError;
14693 ApplyDirtyState();
14694 glCoverFillPathNV(service_id, cover_mode);
14695 return error::kNoError;
14698 error::Error GLES2DecoderImpl::HandleCoverStrokePathCHROMIUM(
14699 uint32 immediate_data_size,
14700 const void* cmd_data) {
14701 static const char kFunctionName[] = "glCoverStrokePathCHROMIUM";
14702 const gles2::cmds::CoverStrokePathCHROMIUM& c =
14703 *static_cast<const gles2::cmds::CoverStrokePathCHROMIUM*>(cmd_data);
14704 if (!features().chromium_path_rendering) {
14705 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14706 "function not available");
14707 return error::kNoError;
14709 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14710 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14711 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14712 return error::kNoError;
14714 GLuint service_id = 0;
14715 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14716 return error::kNoError;
14718 ApplyDirtyState();
14719 glCoverStrokePathNV(service_id, cover_mode);
14720 return error::kNoError;
14723 error::Error GLES2DecoderImpl::HandleStencilThenCoverFillPathCHROMIUM(
14724 uint32 immediate_data_size,
14725 const void* cmd_data) {
14726 static const char kFunctionName[] = "glStencilThenCoverFillPathCHROMIUM";
14727 const gles2::cmds::StencilThenCoverFillPathCHROMIUM& c =
14728 *static_cast<const gles2::cmds::StencilThenCoverFillPathCHROMIUM*>(
14729 cmd_data);
14730 if (!features().chromium_path_rendering) {
14731 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14732 "function not available");
14733 return error::kNoError;
14735 GLenum fill_mode = static_cast<GLenum>(c.fillMode);
14736 if (!validators_->path_fill_mode.IsValid(fill_mode)) {
14737 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, fill_mode, "fillMode");
14738 return error::kNoError;
14740 GLuint mask = static_cast<GLuint>(c.mask);
14741 if ((fill_mode == GL_COUNT_UP_CHROMIUM ||
14742 fill_mode == GL_COUNT_DOWN_CHROMIUM) &&
14743 GLES2Util::IsNPOT(mask + 1)) {
14744 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName,
14745 "mask + 1 is not power of two");
14746 return error::kNoError;
14748 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14749 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14750 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14751 return error::kNoError;
14753 GLuint service_id = 0;
14754 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14755 return error::kNoError;
14757 ApplyDirtyState();
14758 glStencilThenCoverFillPathNV(service_id, fill_mode, mask, cover_mode);
14759 return error::kNoError;
14762 error::Error GLES2DecoderImpl::HandleStencilThenCoverStrokePathCHROMIUM(
14763 uint32 immediate_data_size,
14764 const void* cmd_data) {
14765 static const char kFunctionName[] = "glStencilThenCoverStrokePathCHROMIUM";
14766 const gles2::cmds::StencilThenCoverStrokePathCHROMIUM& c =
14767 *static_cast<const gles2::cmds::StencilThenCoverStrokePathCHROMIUM*>(
14768 cmd_data);
14769 if (!features().chromium_path_rendering) {
14770 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName,
14771 "function not available");
14772 return error::kNoError;
14774 GLenum cover_mode = static_cast<GLenum>(c.coverMode);
14775 if (!validators_->path_cover_mode.IsValid(cover_mode)) {
14776 LOCAL_SET_GL_ERROR_INVALID_ENUM(kFunctionName, cover_mode, "coverMode");
14777 return error::kNoError;
14779 GLuint service_id = 0;
14780 if (!path_manager()->GetPath(static_cast<GLuint>(c.path), &service_id))
14781 return error::kNoError;
14783 GLint reference = static_cast<GLint>(c.reference);
14784 GLuint mask = static_cast<GLuint>(c.mask);
14785 ApplyDirtyState();
14786 glStencilThenCoverStrokePathNV(service_id, reference, mask, cover_mode);
14787 return error::kNoError;
14790 // Include the auto-generated part of this file. We split this because it means
14791 // we can easily edit the non-auto generated parts right here in this file
14792 // instead of having to edit some template or the code generator.
14793 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h"
14795 } // namespace gles2
14796 } // namespace gpu